From 1765dc0e71e6c32f246411cb6d417847b675f085 Mon Sep 17 00:00:00 2001 From: div0 Date: Wed, 3 Sep 2008 12:20:00 +0000 Subject: [PATCH] Porto (untested): secondary fire button "holds" the shooting angles, so you can turn the view and look where the portals go git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4307 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/Main.qc | 5 + data/qcsrc/client/View.qc | 25 ++++ data/qcsrc/common/constants.qh | 1 + data/qcsrc/server/portals.qc | 234 ++++++++++++++++----------------- data/qcsrc/server/w_porto.qc | 62 +++++++-- 5 files changed, 196 insertions(+), 131 deletions(-) diff --git a/data/qcsrc/client/Main.qc b/data/qcsrc/client/Main.qc index 3d5945aea..25b9d06c6 100644 --- a/data/qcsrc/client/Main.qc +++ b/data/qcsrc/client/Main.qc @@ -766,6 +766,7 @@ void Net_ReadSpawn() // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer. // You must ALWAYS first acquire the temporary ID, which is sent as a byte. // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event. +void Net_ReadHoldAngles(); float CSQC_Parse_TempEntity() { local float bHandled; @@ -817,6 +818,10 @@ float CSQC_Parse_TempEntity() Net_ReadZoomNotify(); bHandled = true; break; + case TE_CSQC_HOLDANGLES: + Net_ReadHoldAngles(); + bHandled = true; + break; default: // No special logic for this temporary entity; return 0 so the engine can handle it bHandled = false; diff --git a/data/qcsrc/client/View.qc b/data/qcsrc/client/View.qc index 544e3b3d9..77ba215b6 100644 --- a/data/qcsrc/client/View.qc +++ b/data/qcsrc/client/View.qc @@ -1,3 +1,21 @@ +float angles_held_status[24]; +vector angles_held[24]; +void Net_ReadHoldAngles() +{ + float wpn; + vector v; + wpn = ReadByte(); + --wpn; + angles_held_status[wpn] = ReadByte(); + if(angles_held_status[wpn]) + { + v_x = ReadCoord(); + v_y = ReadCoord(); + v_z = 0; + angles_held[wpn] = v; + } +} + entity porto; void Porto_Draw() { @@ -7,6 +25,13 @@ void Porto_Draw() return; dir = view_forward; + + if(angles_held_status[WEP_PORTO-1]) + { + makevectors(angles_held[WEP_PORTO-1]); + dir = v_forward; + } + v0 = view_origin; traceline(v0, v0 + 65536 * dir, TRUE, world); if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) diff --git a/data/qcsrc/common/constants.qh b/data/qcsrc/common/constants.qh index 8f94fe38a..1b11cd23d 100644 --- a/data/qcsrc/common/constants.qh +++ b/data/qcsrc/common/constants.qh @@ -201,6 +201,7 @@ const float TE_CSQC_FORCESCOREBOARD = 110; const float TE_CSQC_SPECTATING = 111; const float TE_CSQC_SPAWN = 112; const float TE_CSQC_ZOOMNOTIFY = 113; +const float TE_CSQC_HOLDANGLES = 114; const float STAT_KH_KEYS = 32; const float STAT_CTF_STATE = 33; diff --git a/data/qcsrc/server/portals.qc b/data/qcsrc/server/portals.qc index 93fbb95a3..4d9e5eb0d 100644 --- a/data/qcsrc/server/portals.qc +++ b/data/qcsrc/server/portals.qc @@ -175,6 +175,7 @@ void Portal_MakeBrokenPortal(entity portal) portal.touch = SUB_Null; portal.effects = 0; portal.colormod = '1 1 1'; + portal.nextthink = 0; } void Portal_MakeInPortal(entity portal) @@ -183,6 +184,7 @@ void Portal_MakeInPortal(entity portal) portal.touch = Portal_Touch; portal.effects = EF_RED; portal.colormod = '1 0 0'; + portal.nextthink = time; } void Portal_MakeOutPortal(entity portal) @@ -191,6 +193,7 @@ void Portal_MakeOutPortal(entity portal) portal.touch = SUB_Null; portal.effects = EF_STARDUST; portal.colormod = '0 0 1'; + portal.nextthink = 0; } void Portal_Disconnect(entity teleporter, entity destination) @@ -214,84 +217,116 @@ void Portal_Connect(entity teleporter, entity destination) destination.portal_wants_to_vanish = 0; } -void Portal_Think() +void Portal_Remove(entity portal) { - entity e, o; - float m; + entity e; + e = portal.enemy; - if(self.solid == SOLID_TRIGGER) + if(e) { - m = self.modelindex; - o = self.owner; - self.solid = SOLID_BBOX; - self.owner = world; - self.modelindex = 0; - FOR_EACH_PLAYER(e) - { - if(time < self.portal_activatetime) - if(e == o) - continue; - // if e would hit the portal in a frame... - // already teleport him - tracebox(e.origin, e.mins, e.maxs, e.origin + e.velocity * 3 * frametime, MOVE_NORMAL, e); - if(trace_ent == self) - Portal_TeleportPlayer(self, e); - } - self.solid = SOLID_TRIGGER; - self.owner = o; - self.modelindex = m; + Portal_Disconnect(portal, e); + Portal_Remove(e); } - self.nextthink = time; + if(portal == portal.owner.portal_in) + portal.owner.portal_in = world; + if(portal == portal.owner.portal_out) + portal.owner.portal_out = world; + portal.owner = world; - if(time < self.fade_time) - return; + // makes the portal vanish + Portal_MakeBrokenPortal(portal); + SUB_SetFade(portal, time, 0.5); +} - self.portal_wants_to_vanish = 1; +void Portal_Think() +{ + entity e, o; - if(self.enemy) - if(!self.enemy.portal_wants_to_vanish) - return; + if(self.solid != SOLID_TRIGGER) + error("Portal_Think called for a portal that should not be thinking"); - SUB_SetFade(self, time + 1, 1); - if(self.enemy) - { - SUB_SetFade(self.enemy, time + 1, 1); - Portal_Disconnect(self, self.enemy); - } - if(self.owner.portal_in == self) - { - self.owner.portal_in = world; - print("fixed in-portal ownership\n"); - } - if(self.owner.portal_out == self) + o = self.owner; + self.solid = SOLID_BBOX; + self.owner = world; + FOR_EACH_PLAYER(e) { - self.owner.portal_out = world; - print("fixed out-portal ownership\n"); + if(time < self.portal_activatetime) + if(e == o) + continue; + // if e would hit the portal in a frame... + // already teleport him + tracebox(e.origin, e.mins, e.maxs, e.origin + e.velocity * 3 * frametime, MOVE_NORMAL, e); + if(trace_ent == self) + Portal_TeleportPlayer(self, e); } + self.solid = SOLID_TRIGGER; + self.owner = o; + + self.nextthink = time; + + if(time > self.fade_time) + Portal_Remove(self); } -void Portal_RequestVanish(entity portal) + +// cleanup: +// when creating in-portal: +// disconnect +// clear existing out-portal +// make existing in-portal an out-portal and connect +// set as in-portal +// when creating out-portal: +// disconnect +// clear existing out-portal +// set as out-portal +// when player dies: +// disconnect portals +// clear both portals +// after timeout of in-portal: +// disconnect portals +// clear both portals +// TODO: ensure only one portal shot at once +float Portal_SetInPortal(entity own, entity portal) { - entity oldself; - oldself = self; - self = portal; - if(self.enemy) - { - self.enemy.portal_wants_to_vanish = 1; - self.enemy.fade_time = time; - } - self.fade_time = time; - Portal_Think(); - self = oldself; + if(own.portal_out) + Portal_Remove(own.portal_out); + if(own.portal_in) + own.portal_out = own.portal_in; + own.portal_in = portal; + if(own.portal_out) + Portal_Connect(own.portal_in, own.portal_out); + return 1; } - -entity Portal_Spawn(entity own, vector org, vector ang) +float Portal_SetOutPortal(entity own, entity portal) +{ + if(!own.portal_in) + return 0; + if(own.portal_out) + Portal_Remove(own.portal_out); + own.portal_out = portal; + Portal_Connect(own.portal_in, own.portal_out); + return 1; +} +void Portal_ClearAll(entity own) +{ + if(own.portal_in) + Portal_Remove(own.portal_in); + if(own.portal_out) + Portal_Remove(own.portal_out); +} +float Portal_VerifyPortalAtTrace(vector ang) { + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) + return 0; fixedmakevectors(ang); - if(!CheckWireframeBox(org - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 16 * v_forward)) - return world; + if(!CheckWireframeBox(trace_endpos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 16 * v_forward)) + return 0; + return 1; +} +entity Portal_Spawn(entity own, vector org, vector ang) +{ entity portal; portal = spawn(); portal.classname = "portal"; @@ -319,8 +354,8 @@ entity Portal_Spawn(entity own, vector org, vector ang) float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val) { - if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) - return 0; + entity portal; + vector ang; if(trace_ent.classname == "player") { @@ -329,85 +364,46 @@ float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val) trace_plane_normal = '0 0 1'; } - if(own.portal_in) - { - if(own.portal_out) - { - Portal_Disconnect(own.portal_in, own.portal_out); - Portal_RequestVanish(own.portal_out); - } - own.portal_out = own.portal_in; - own.portal_in = world; - own.portal_out.portal_id = portal_id_val; - } - else if(own.portal_out) - { - print("this DID happen, no idea why (1)\n"); - Portal_RequestVanish(own.portal_out); - own.portal_out = world; - } - - own.portal_in = Portal_Spawn(own, trace_endpos + trace_plane_normal, fixedvectoangles2(trace_plane_normal, dir)); - if(!own.portal_in) + if(!Portal_VerifyPortalAtTrace(dir)) { - if(own.portal_out) - { - Portal_RequestVanish(own.portal_out); - own.portal_out = world; - } + // cannot create a portal here + // clear all to make sure + Portal_ClearAll(own); return 0; } - own.portal_in.portal_id = portal_id_val; - if(own.portal_out) - Portal_Connect(own.portal_in, own.portal_out); + ang = fixedvectoangles2(trace_plane_normal, dir); + portal = Portal_Spawn(own, trace_endpos, ang); + Portal_SetInPortal(own, portal); return 1; } float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id_val) { - if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) - { - if(own.portal_in.portal_id == portal_id_val) - { - Portal_RequestVanish(own.portal_in); - own.portal_in = world; - } - return 0; - } + entity portal; + vector ang; if(trace_ent.classname == "player") { print("hit a player, adjusting...\n"); trace_endpos = trace_ent.origin + '0 0 1' * PL_MIN_z; trace_plane_normal = '0 0 1'; - dir = -1 * dir; // fix orientation } + else + dir = -1 * dir; // invert the sense of the second portal - if(!own.portal_in) - return 0; // sorry - - if(own.portal_in.portal_id != portal_id_val) - return 0; // we need MATCHING portals - - if(own.portal_out) + if(!Portal_VerifyPortalAtTrace(dir)) { - Portal_Disconnect(own.portal_in, own.portal_out); - Portal_RequestVanish(own.portal_out); - own.portal_out = world; - } - - own.portal_out = Portal_Spawn(own, trace_endpos + trace_plane_normal, fixedvectoangles2(trace_plane_normal, -1 * dir)); - if(!own.portal_out) - { - Portal_RequestVanish(own.portal_in); - own.portal_in = world; + // cannot create a portal here + // clear all to make sure + Portal_ClearAll(own); return 0; } - own.portal_out.portal_id = portal_id_val; - Portal_Connect(own.portal_in, own.portal_out); + ang = fixedvectoangles2(trace_plane_normal, dir); + portal = Portal_Spawn(own, trace_endpos, ang); + Portal_SetOutPortal(own, portal); return 1; } diff --git a/data/qcsrc/server/w_porto.qc b/data/qcsrc/server/w_porto.qc index b1a979839..2fc2946df 100644 --- a/data/qcsrc/server/w_porto.qc +++ b/data/qcsrc/server/w_porto.qc @@ -1,26 +1,29 @@ .float porto_grenade_id; +.vector porto_v_angle; // holds "held" view angles +.float porto_v_angle_held; void W_Porto_Explode (void) { + self.owner.porto_grenade_id = 0; remove(self); } void W_Porto_Touch1 (void) { - if(self.porto_grenade_id == 0) + if(self.owner.playerid != self.playerid) { - self.porto_grenade_id = time; + remove(self); + } + else if(self.cnt == 0) + { + self.cnt = 1; if(!Portal_SpawnInPortalAtTrace(self.owner, self.velocity, self.porto_grenade_id)) - { - self.porto_grenade_id = 0; - remove(self); - } + W_Porto_Explode(); } else { Portal_SpawnOutPortalAtTrace(self.owner, self.velocity, self.porto_grenade_id); - self.porto_grenade_id = 0; - remove(self); + W_Porto_Explode(); } } @@ -55,11 +58,8 @@ void W_Porto_Attack (void) gren.angles = vectoangles (gren.velocity); gren.flags = FL_PROJECTILE; -} -void W_Porto_Attack2 (void) -{ - // nothing yet (maybe find the last one and detonate it?) + self.porto_grenade_id = gren.porto_grenade_id = time; } void spawnfunc_weapon_porto (void) @@ -69,6 +69,8 @@ void spawnfunc_weapon_porto (void) float w_porto(float req) { + vector v_angle_save; + if (req == WR_AIM) { self.BUTTON_ATCK = FALSE; @@ -78,12 +80,48 @@ float w_porto(float req) } else if (req == WR_THINK) { + if(self.porto_v_angle_held) + { + if(!self.BUTTON_ATCK2) + { + msg_entity = self; + WRITESPECTATABLE_MSG_ONE({ + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_HOLDANGLES); + WriteByte(MSG_ONE, WEP_PORTO); + WriteByte(MSG_ONE, 0); + }); + self.porto_v_angle_held = 0; + } + } + else + { + if(self.BUTTON_ATCK2) + { + self.porto_v_angle = self.v_angle; + msg_entity = self; + WRITESPECTATABLE_MSG_ONE({ + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_HOLDANGLES); + WriteByte(MSG_ONE, WEP_PORTO); + WriteByte(MSG_ONE, 1); + WriteCoord(MSG_ONE, self.v_angle_x); + WriteCoord(MSG_ONE, self.v_angle_y); + }); + self.porto_v_angle_held = 1; + } + } + v_angle_save = self.v_angle; + if(self.porto_v_angle_held) + self.v_angle = self.porto_v_angle; if (self.BUTTON_ATCK) + if (!self.porto_grenade_id) if (weapon_prepareattack(0, cvar("g_balance_porto_primary_refire"))) { W_Porto_Attack(); weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_porto_primary_animtime"), w_ready); } + self.v_angle = v_angle_save; } else if (req == WR_PRECACHE) { -- 2.39.2