From 2860c33fe91a4fce1a7e66d21fed906c62a407c4 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 20 Feb 2015 11:02:05 +1100 Subject: [PATCH] Rough port of SV_PushMove to CSQC --- qcsrc/client/main.qc | 2 +- qcsrc/client/movetypes.qc | 240 ++++++-------------- qcsrc/client/movetypes.qh | 5 + qcsrc/client/player_skeleton.qc | 2 + qcsrc/common/constants.qh | 4 +- qcsrc/common/triggers/func/bobbing.qc | 6 +- qcsrc/common/triggers/func/button.qc | 4 +- qcsrc/common/triggers/func/door.qc | 94 +++----- qcsrc/common/triggers/func/door_secret.qc | 10 +- qcsrc/common/triggers/func/fourier.qc | 4 +- qcsrc/common/triggers/func/include.qh | 1 + qcsrc/common/triggers/func/pendulum.qc | 4 +- qcsrc/common/triggers/func/plat.qc | 16 +- qcsrc/common/triggers/func/rotating.qc | 4 +- qcsrc/common/triggers/func/train.qc | 164 ++++++++++++- qcsrc/common/triggers/func/train.qh | 4 + qcsrc/common/triggers/func/vectormamamam.qc | 4 +- qcsrc/common/triggers/misc/corner.qc | 13 +- qcsrc/common/triggers/platforms.qc | 65 ++---- qcsrc/common/triggers/platforms.qh | 4 - qcsrc/common/triggers/subs.qc | 102 ++++----- qcsrc/common/triggers/subs.qh | 36 +++ qcsrc/common/triggers/trigger/delay.qc | 2 +- qcsrc/common/triggers/triggers.qc | 11 - qcsrc/common/triggers/triggers.qh | 2 - 25 files changed, 419 insertions(+), 384 deletions(-) create mode 100644 qcsrc/common/triggers/func/train.qh diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index 791a6a046..0b75058b4 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -850,10 +850,10 @@ void CSQC_Ent_Update(float bIsNewEntity) case ENT_CLIENT_CONVEYOR: ent_conveyor(); break; case ENT_CLIENT_DOOR: ent_door(); break; case ENT_CLIENT_PLAT: ent_plat(); break; - case ENT_CLIENT_PLAT_TRIGGER: ent_plat_trigger(); break; case ENT_CLIENT_SWAMP: ent_swamp(); break; case ENT_CLIENT_CORNER: ent_corner(); break; case ENT_CLIENT_KEYLOCK: ent_keylock(); break; + case ENT_CLIENT_TRAIN: ent_train(); break; default: //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype)); diff --git a/qcsrc/client/movetypes.qc b/qcsrc/client/movetypes.qc index 2a46de112..2fa5f9122 100644 --- a/qcsrc/client/movetypes.qc +++ b/qcsrc/client/movetypes.qc @@ -291,6 +291,8 @@ void _Movetype_AngleVectorsFLU(vector myangles) // AngleVectorsFLU { float angle, sr, sp, sy, cr, cp, cy; + v_forward = v_right = v_up = '0 0 0'; + angle = myangles_y * (M_PI*2 / 360); sy = sin(angle); cy = cos(angle); @@ -343,23 +345,18 @@ void _Movetype_AngleVectorsFLU(vector myangles) // AngleVectorsFLU void _Movetype_PushMove(float dt) // SV_PushMove { - float pushltime; - //int pusherowner; - //int i; - //int num_moved; - //int numcheckentities; - int savesolid; bool rotated; - vector move1, moveangle; + int savesolid; + float movetime2, pushltime; + vector move, move1, moveangle, pushorig, pushang; vector a; - vector pushorig, pushang; - vector org; - vector move; + vector pivot; entity oldself; + entity check; - if(!vlen(self.move_velocity) && !vlen(self.move_avelocity)) + if(self.move_velocity == '0 0 0' && self.move_avelocity == '0 0 0') { - self.ltime += dt; + self.move_ltime += dt; return; } @@ -374,212 +371,117 @@ void _Movetype_PushMove(float dt) // SV_PushMove // LordHavoc: no collisions case SOLID_NOT: case SOLID_TRIGGER: - - self.move_origin = self.move_origin + self.move_velocity * dt; + self.move_origin = self.move_origin + dt * self.move_velocity; + self.move_angles = self.move_angles + dt * self.move_avelocity; self.move_angles_x -= 360.0 * floor(self.move_angles_x * (1.0 / 360.0)); self.move_angles_y -= 360.0 * floor(self.move_angles_y * (1.0 / 360.0)); self.move_angles_z -= 360.0 * floor(self.move_angles_z * (1.0 / 360.0)); - self.ltime += dt; + self.move_ltime += dt; _Movetype_LinkEdict(true); return; default: - printf("_Movetype_PushMove: entity %e with classname %s, unrecognized solid type %d\n", num_for_edict(self), self.classname, self.solid); - return; - } - if(!self.modelindex || self.model == "null") - { - printf("_Movetype_PushMove: entity %e with classname %s, unusable modelindex %f\n", num_for_edict(self), self.classname, self.modelindex); + dprintf("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", self, self.solid); return; } - //pusherowner = self.owner; - rotated = (self.move_angles * self.move_avelocity) > 0; + rotated = dotproduct(self.move_angles, self.move_angles) + dotproduct(self.move_avelocity, self.move_avelocity) > 0; - move1 = self.move_velocity * dt; - moveangle = self.move_avelocity * dt; + movetime2 = dt; - a = -moveangle; + move1 = self.move_velocity * movetime2; + moveangle = self.move_avelocity * movetime2; + a = -moveangle; // sets v_forward, v_right and v_up _Movetype_AngleVectorsFLU(a); pushorig = self.move_origin; pushang = self.move_angles; - pushltime = self.ltime; + pushltime = self.move_ltime; // move the pusher to its final position - self.move_origin = self.move_origin + self.move_velocity * dt; - self.move_angles = self.move_angles + self.move_avelocity * dt; - self.ltime += dt; + self.move_origin = self.move_origin + dt * self.move_velocity; + self.move_angles = self.move_angles + dt * self.move_avelocity; + + self.move_ltime += dt; _Movetype_LinkEdict(true); - //pushermodel = SV_GetModelFromEdict(pusher); - //Matrix4x4_CreateFromQuakeEntity(&pusherfinalmatrix, PRVM_serveredictvector(pusher, origin)[0], PRVM_serveredictvector(pusher, origin)[1], PRVM_serveredictvector(pusher, origin)[2], - //PRVM_serveredictvector(pusher, angles)[0], PRVM_serveredictvector(pusher, angles)[1], PRVM_serveredictvector(pusher, angles)[2], 1); - //Matrix4x4_Invert_Simple(&pusherfinalimatrix, &pusherfinalmatrix); - savesolid = self.solid; -// see if any solid entities are inside the final position - //num_moved = 0; - - entity e; - if(self.move_movetype != MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push... - for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain) + if(self.move_movetype != MOVETYPE_FAKEPUSH) + for(check = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); check; check = check.chain) { - if(e.owner == self) + switch(check.move_movetype) + { + case MOVETYPE_NONE: + case MOVETYPE_PUSH: + case MOVETYPE_FOLLOW: + case MOVETYPE_NOCLIP: + case MOVETYPE_FLY_WORLDONLY: continue; + default: + break; + } - if(self.owner == e) + if(check.owner == self) continue; - //Con_Printf("%i %s ", PRVM_NUM_FOR_EDICT(check), PRVM_GetString(PRVM_serveredictstring(check, classname))); - - // tell any MOVETYPE_STEP entity that it may need to check for water transitions - //check->priv.server->waterposition_forceupdate = true; - - //int checkcontents = pointcontents(e.move_origin); + if(self.owner == check) + continue; - // if the entity is standing on the pusher, it will definitely be moved - // if the entity is not standing on the pusher, but is in the pusher's - // final position, move it - if(!(e.move_flags & FL_ONGROUND) || e.move_groundentity != self) - { - //vector pushermins = self.mins; - //vector pushermaxs = self.maxs; - //vector checkorigin = e.origin; - //vector checkmins = e.mins; - //vector checkmaxs = e.maxs; - //Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pushermins, pushermaxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, - //&pusherfinalimatrix, checkorigin, checkmins, checkmaxs, checkorigin, checkcontents, collision_extendmovelength.value); - tracebox(e.move_origin, e.mins, e.maxs, self.move_origin, MOVE_NOMONSTERS, e); - if(!trace_startsolid) - { - //Con_Printf("- not in solid\n"); - continue; - } - } - vector pivot = e.mins + 0.5 * (e.maxs - e.mins); + pivot = check.mins + 0.5 * (check.maxs - check.mins); //VectorClear(pivot); - if(rotated) + if (rotated) { vector org2; - org = e.move_origin - self.move_origin; - org += pivot; - org2_x = (org * v_forward); - org2_y = (org * v_right); - org2_z = (org * v_up); + vector org = check.move_origin - self.move_origin; + org = org + pivot; + org2_x = dotproduct(org, v_forward); + org2_y = dotproduct(org, v_right); + org2_z = dotproduct(org, v_up); move = org2 - org; - move += move1; + move = move + move1; } else move = move1; - //Con_Printf("- pushing %f %f %f\n", move[0], move[1], move[2]); - - //VectorCopy (PRVM_serveredictvector(check, origin), check->priv.server->moved_from); - //VectorCopy (PRVM_serveredictvector(check, angles), check->priv.server->moved_fromangles); - //moved_edicts[num_moved++] = PRVM_NUM_FOR_EDICT(check); - // physics objects need better collisions than this code can do - /*if(e.move_movetype == MOVETYPE_PHYSICS) + if(check.move_movetype == 32) // MOVETYPE_PHYSICS { - e.move_origin += move; + check.move_origin = check.move_origin + move; oldself = self; - self = e; - _Movetype_LinkEdict(false); - _Movetype_LinkEdict_TouchAreaGrid(); + self = check; + _Movetype_LinkEdict(true); self = oldself; continue; - }*/ + } // try moving the contacted entity self.solid = SOLID_NOT; oldself = self; - self = e; + self = check; if(!_Movetype_PushEntity(move, true)) { + self = oldself; // entity "check" got teleported - self.angles_y += trace_fraction * moveangle_y; - oldself.solid = savesolid; + check.move_angles_y += trace_fraction * moveangle_y; + self.solid = savesolid; continue; // pushed enough } self = oldself; // FIXME: turn players specially - e.angles_y += trace_fraction * moveangle_y; + check.move_angles_y += trace_fraction * moveangle_y; self.solid = savesolid; - //Con_Printf("%s:%d frac %f startsolid %d bmodelstartsolid %d allsolid %d\n", __FILE__, __LINE__, trace.fraction, trace.startsolid, trace.bmodelstartsolid, trace.allsolid); // this trace.fraction < 1 check causes items to fall off of pushers // if they pass under or through a wall // the groundentity check causes items to fall off of ledges - if(e.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || e.move_groundentity != self)) - e.move_flags &= ~FL_ONGROUND; - - // if it is still inside the pusher, block - //vector pushermins = self.mins; - //vector pushermaxs = self.maxs; - //vector checkorigin = e.move_origin; - //vector checkmins = e.mins; - //vector checkmaxs = e.maxs; - //Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, pushermins, pushermaxs, SUPERCONTENTS_BODY, - //&pusherfinalmatrix, &pusherfinalimatrix, checkorigin, checkmins, checkmaxs, checkorigin, checkcontents, collision_extendmovelength.value); - tracebox(e.move_origin, e.mins, e.maxs, self.move_origin, MOVE_NOMONSTERS, e); - if(trace_startsolid) - { - /*vector move2; - if(SV_NudgeOutOfSolid_PivotIsKnownGood(check, pivot)) - { - // hack to invoke all necessary movement triggers - move2 = '0 0 0'; - if(!_Movetype_PushEntity(move2, true)) - { - // entity "check" got teleported - continue; - } - // we could fix it - continue; - }*/ - - // still inside pusher, so it's really blocked - - // fail the move - if(e.mins_x == e.maxs_x) - continue; - if(e.solid == SOLID_NOT || e.solid == SOLID_TRIGGER) - { - // corpse - e.mins_x = e.mins_y = 0; - e.maxs = e.mins; - continue; - } - - self.move_origin = pushorig; - self.move_angles = pushang; - self.ltime = pushltime; - _Movetype_LinkEdict(true); - - // move back any entities we already moved - /*for (i = 0;i < num_moved;i++) - { - prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]); - VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin)); - VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles)); - SV_LinkEdict(ed); - }*/ - - // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone - if(self.blocked) - { - self.move_time = time; - other = e; - self.blocked(); - } - break; - } + if(check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.move_groundentity != self)) + check.move_flags &= ~FL_ONGROUND; } + self.move_angles_x -= 360.0 * floor(self.move_angles_x * (1.0 / 360.0)); self.move_angles_y -= 360.0 * floor(self.move_angles_y * (1.0 / 360.0)); self.move_angles_z -= 360.0 * floor(self.move_angles_z * (1.0 / 360.0)); @@ -587,31 +489,31 @@ void _Movetype_PushMove(float dt) // SV_PushMove void _Movetype_Physics_Pusher(float dt) // SV_Physics_Pusher { - float oldltime, movetime; + float thinktime, oldltime, movetime; - oldltime = self.ltime; + oldltime = self.move_ltime; - if (self.nextthink < self.ltime + dt) + thinktime = self.move_nextthink; + if(thinktime < self.move_ltime + dt) { - movetime = self.nextthink - self.ltime; - if (movetime < 0) + movetime = thinktime - self.move_ltime; + if(movetime < 0) movetime = 0; } else movetime = dt; - if (movetime) - // advances PRVM_serveredictfloat(ent, ltime) if not blocked + if(movetime) + // advances self.move_ltime if not blocked _Movetype_PushMove(movetime); - if (self.nextthink > oldltime && self.nextthink <= self.ltime) + if(thinktime > oldltime && thinktime <= self.move_ltime) { - self.nextthink = 0; - //time = dt; + self.move_nextthink = 0; self.move_time = time; other = world; - if(self.think) - self.think(); + if(self.move_think) + self.move_think(); } } diff --git a/qcsrc/client/movetypes.qh b/qcsrc/client/movetypes.qh index b4dea1de1..41f0bb064 100644 --- a/qcsrc/client/movetypes.qh +++ b/qcsrc/client/movetypes.qh @@ -1,6 +1,11 @@ #ifndef MOVETYPES_H #define MOVETYPES_H +.float move_ltime; +.void(void) move_think; +.float move_nextthink; +.void(void) move_blocked; + .float move_movetype; .float move_time; .vector move_origin; diff --git a/qcsrc/client/player_skeleton.qc b/qcsrc/client/player_skeleton.qc index 0a9ac8cac..d8b0aaad4 100644 --- a/qcsrc/client/player_skeleton.qc +++ b/qcsrc/client/player_skeleton.qc @@ -170,6 +170,8 @@ void skeleton_from_frames(entity e, float is_dead) if(!is_dead) { + if(self == csqcplayer) + self.v_angle_x = input_angles_x; int i; for(i = 0; i < MAX_AIM_BONES; ++i) { diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 47f0381f5..4c8d448dd 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -108,9 +108,9 @@ const int ENT_CLIENT_TRIGGER_PUSH = 62; const int ENT_CLIENT_TARGET_PUSH = 63; const int ENT_CLIENT_CONVEYOR = 64; const int ENT_CLIENT_DOOR = 65; -// 66 +const int ENT_CLIENT_TRAIN = 66; const int ENT_CLIENT_PLAT = 67; -const int ENT_CLIENT_PLAT_TRIGGER = 68; +// 68 const int ENT_CLIENT_SWAMP = 69; const int ENT_CLIENT_CORNER = 70; const int ENT_CLIENT_KEYLOCK = 71; diff --git a/qcsrc/common/triggers/func/bobbing.qc b/qcsrc/common/triggers/func/bobbing.qc index 35a37508b..9fb2f56c9 100644 --- a/qcsrc/common/triggers/func/bobbing.qc +++ b/qcsrc/common/triggers/func/bobbing.qc @@ -16,7 +16,7 @@ void func_bobbing_controller_think() v = self.owner.destvec + self.owner.movedir * v_forward_y; if(self.owner.classname == "func_bobbing") // don't brake stuff if the func_bobbing was killtarget'ed // * 10 so it will arrive in 0.1 sec - self.owner.velocity = (v - self.owner.origin) * 10; + self.owner.velocity = (v - self.owner.SUB_ORIGIN) * 10; } /*QUAKED spawnfunc_func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS @@ -74,8 +74,8 @@ void spawnfunc_func_bobbing() controller.owner = self; controller.nextthink = time + 1; controller.think = func_bobbing_controller_think; - trigger_setnextthink(self, self.ltime + 999999999); - self.think = SUB_NullThink; // for PushMove + self.SUB_NEXTTHINK = self.SUB_LTIME + 999999999; + self.SUB_THINK = SUB_NullThink; // Savage: Reduce bandwith, critical on e.g. nexdm02 self.effects |= EF_LOWPRECISION; diff --git a/qcsrc/common/triggers/func/button.qc b/qcsrc/common/triggers/func/button.qc index 0ccd118e9..0ed374a33 100644 --- a/qcsrc/common/triggers/func/button.qc +++ b/qcsrc/common/triggers/func/button.qc @@ -7,8 +7,8 @@ void() button_return; void button_wait() { self.state = STATE_TOP; - trigger_setnextthink(self, self.ltime + self.wait); - self.think = button_return; + self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait; + self.SUB_THINK = button_return; activator = self.enemy; SUB_UseTargets(); self.frame = 1; // use alternate textures diff --git a/qcsrc/common/triggers/func/door.qc b/qcsrc/common/triggers/func/door.qc index d08fb84fb..1a1c82b9a 100644 --- a/qcsrc/common/triggers/func/door.qc +++ b/qcsrc/common/triggers/func/door.qc @@ -93,12 +93,12 @@ void door_hit_top() return; // don't come down automatically if (self.classname == "door") { - self.think = door_go_down; + self.SUB_THINK = door_go_down; } else { - self.think = door_rotating_go_down; + self.SUB_THINK = door_rotating_go_down; } - trigger_setnextthink(self, self.ltime + self.wait); + self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait; } void door_hit_bottom() @@ -129,7 +129,7 @@ void door_go_up() if (self.state == STATE_TOP) { // reset top wait time - trigger_setnextthink(self, self.ltime + self.wait); + self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait; return; } @@ -383,8 +383,8 @@ void door_rotating_hit_top() self.state = STATE_TOP; if (self.spawnflags & DOOR_TOGGLE) return; // don't come down automatically - self.think = door_rotating_go_down; - self.nextthink = self.ltime + self.wait; + self.SUB_THINK = door_rotating_go_down; + self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait; } void door_rotating_hit_bottom() @@ -420,7 +420,7 @@ void door_rotating_go_up() if (self.state == STATE_TOP) { // reset top wait time - trigger_setnextthink(self, self.ltime + self.wait); + self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait; return; } if (self.noise2 != "") @@ -656,28 +656,9 @@ float door_send(entity to, float sf) WriteString(MSG_ENTITY, self.classname); WriteByte(MSG_ENTITY, self.spawnflags); - WriteByte(MSG_ENTITY, self.scale); - - WriteCoord(MSG_ENTITY, self.origin_x); - WriteCoord(MSG_ENTITY, self.origin_y); - WriteCoord(MSG_ENTITY, self.origin_z); - WriteString(MSG_ENTITY, self.model); - WriteCoord(MSG_ENTITY, self.mins_x); - WriteCoord(MSG_ENTITY, self.mins_y); - WriteCoord(MSG_ENTITY, self.mins_z); - WriteCoord(MSG_ENTITY, self.maxs_x); - WriteCoord(MSG_ENTITY, self.maxs_y); - WriteCoord(MSG_ENTITY, self.maxs_z); - - WriteCoord(MSG_ENTITY, self.movedir_x); - WriteCoord(MSG_ENTITY, self.movedir_y); - WriteCoord(MSG_ENTITY, self.movedir_z); - - WriteAngle(MSG_ENTITY, self.angles_x); - WriteAngle(MSG_ENTITY, self.angles_y); - WriteAngle(MSG_ENTITY, self.angles_z); + trigger_common_write(true); WriteCoord(MSG_ENTITY, self.pos1_x); WriteCoord(MSG_ENTITY, self.pos1_y); @@ -694,7 +675,7 @@ float door_send(entity to, float sf) WriteShort(MSG_ENTITY, self.speed); WriteByte(MSG_ENTITY, self.lip); WriteByte(MSG_ENTITY, self.state); - WriteCoord(MSG_ENTITY, self.ltime); + WriteCoord(MSG_ENTITY, self.SUB_LTIME); } if(sf & SF_TRIGGER_RESET) @@ -729,7 +710,7 @@ void door_link() void door_init_startopen() { - setorigin (self, self.pos2); + SUB_SETORIGIN(self, self.pos2); self.pos2 = self.pos1; self.pos1 = self.origin; @@ -740,11 +721,11 @@ void door_init_startopen() void door_reset() { - setorigin(self, self.pos1); - self.velocity = '0 0 0'; + SUB_SETORIGIN(self, self.pos1); + self.SUB_VELOCITY = '0 0 0'; self.state = STATE_BOTTOM; - self.think = func_null; - self.nextthink = 0; + self.SUB_THINK = func_null; + self.SUB_NEXTTHINK = 0; #ifdef SVQC self.SendFlags |= SF_TRIGGER_RESET; @@ -793,7 +774,7 @@ void spawnfunc_func_door() if (!self.lip) self.lip = 8; - self.pos1 = self.origin; + self.pos1 = self.SUB_ORIGIN; self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip); // DOOR_START_OPEN is to allow an entity to be lighted in the closed position @@ -823,6 +804,13 @@ void spawnfunc_func_door() #elif defined(CSQC) +void door_draw() +{ + Movetype_Physics_NoMatchServer(); + + trigger_draw_generic(); +} + void ent_door() { float sf = ReadByte(); @@ -832,31 +820,10 @@ void ent_door() self.classname = strzone(ReadString()); self.spawnflags = ReadByte(); - self.scale = ReadByte(); - - self.origin_x = ReadCoord(); - self.origin_y = ReadCoord(); - self.origin_z = ReadCoord(); - setorigin(self, self.origin); - self.mdl = strzone(ReadString()); setmodel(self, self.mdl); - self.mins_x = ReadCoord(); - self.mins_y = ReadCoord(); - self.mins_z = ReadCoord(); - self.maxs_x = ReadCoord(); - self.maxs_y = ReadCoord(); - self.maxs_z = ReadCoord(); - setsize(self, self.mins, self.maxs); - - self.movedir_x = ReadCoord(); - self.movedir_y = ReadCoord(); - self.movedir_z = ReadCoord(); - - self.angles_x = ReadAngle(); - self.angles_y = ReadAngle(); - self.angles_z = ReadAngle(); + trigger_common_read(true); self.pos1_x = ReadCoord(); self.pos1_y = ReadCoord(); @@ -873,21 +840,25 @@ void ent_door() self.speed = ReadShort(); self.lip = ReadByte(); self.state = ReadByte(); - self.ltime = ReadCoord(); + self.SUB_LTIME = ReadCoord(); - self.movetype = MOVETYPE_PUSH; self.solid = SOLID_BSP; + self.movetype = MOVETYPE_PUSH; self.trigger_touch = door_touch; - self.draw = trigger_draw_generic; + self.draw = door_draw; self.drawmask = MASK_NORMAL; - self.move_time = time; self.use = door_use; - self.blocked = door_blocked; LinkDoors(); if(self.spawnflags & DOOR_START_OPEN) door_init_startopen(); + + self.move_time = time; + self.move_origin = self.origin; + self.move_movetype = MOVETYPE_PUSH; + self.move_angles = self.angles; + self.move_blocked = door_blocked; } if(sf & SF_TRIGGER_RESET) @@ -901,6 +872,7 @@ void ent_door() self.origin_y = ReadCoord(); self.origin_z = ReadCoord(); setorigin(self, self.origin); + self.move_origin = self.origin; self.pos1_x = ReadCoord(); self.pos1_y = ReadCoord(); diff --git a/qcsrc/common/triggers/func/door_secret.qc b/qcsrc/common/triggers/func/door_secret.qc index d507fe144..b188f83f0 100644 --- a/qcsrc/common/triggers/func/door_secret.qc +++ b/qcsrc/common/triggers/func/door_secret.qc @@ -36,7 +36,7 @@ void fd_secret_use() if (self.noise1 != "") sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); - trigger_setnextthink(self, self.ltime + 0.1); + self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1; temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1 makevectors(self.mangle); @@ -71,7 +71,7 @@ void fd_secret_damage(entity inflictor, entity attacker, float damage, float dea // Wait after first movement... void fd_secret_move1() { - trigger_setnextthink(self, self.ltime + 1.0); + self.SUB_NEXTTHINK = self.SUB_LTIME + 1.0; self.think = fd_secret_move2; if (self.noise3 != "") sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM); @@ -92,7 +92,7 @@ void fd_secret_move3() sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM); if (!(self.spawnflags & SECRET_OPEN_ONCE)) { - trigger_setnextthink(self, self.ltime + self.wait); + self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait; self.think = fd_secret_move4; } } @@ -108,7 +108,7 @@ void fd_secret_move4() // Wait 1 second... void fd_secret_move5() { - trigger_setnextthink(self, self.ltime + 1.0); + self.SUB_NEXTTHINK = self.SUB_LTIME + 1.0; self.think = fd_secret_move6; if (self.noise3 != "") sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM); @@ -174,7 +174,7 @@ void secret_reset() } setorigin(self, self.oldorigin); self.think = func_null; - self.nextthink = 0; + self.SUB_NEXTTHINK = 0; } /*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot diff --git a/qcsrc/common/triggers/func/fourier.qc b/qcsrc/common/triggers/func/fourier.qc index 1e8d791e1..19dceef25 100644 --- a/qcsrc/common/triggers/func/fourier.qc +++ b/qcsrc/common/triggers/func/fourier.qc @@ -78,8 +78,8 @@ void spawnfunc_func_fourier() controller.owner = self; controller.nextthink = time + 1; controller.think = func_fourier_controller_think; - trigger_setnextthink(self, self.ltime + 999999999); - self.think = SUB_NullThink; // for PushMove + self.SUB_NEXTTHINK = self.SUB_LTIME + 999999999; + self.SUB_THINK = SUB_NullThink; // for PushMove // Savage: Reduce bandwith, critical on e.g. nexdm02 self.effects |= EF_LOWPRECISION; diff --git a/qcsrc/common/triggers/func/include.qh b/qcsrc/common/triggers/func/include.qh index e49a9671e..624c0b5c8 100644 --- a/qcsrc/common/triggers/func/include.qh +++ b/qcsrc/common/triggers/func/include.qh @@ -7,5 +7,6 @@ #include "plat.qh" #include "rainsnow.qh" #include "pointparticles.qh" +#include "train.qh" #endif diff --git a/qcsrc/common/triggers/func/pendulum.qc b/qcsrc/common/triggers/func/pendulum.qc index 83cbbbad1..7d3eff7c9 100644 --- a/qcsrc/common/triggers/func/pendulum.qc +++ b/qcsrc/common/triggers/func/pendulum.qc @@ -67,8 +67,8 @@ void spawnfunc_func_pendulum() controller.owner = self; controller.nextthink = time + 1; controller.think = func_pendulum_controller_think; - trigger_setnextthink(self, self.ltime + 999999999); - self.think = SUB_NullThink; // for PushMove + self.nextthink = self.SUB_LTIME + 999999999; + self.SUB_THINK = SUB_NullThink; // for PushMove //self.effects |= EF_LOWPRECISION; diff --git a/qcsrc/common/triggers/func/plat.qc b/qcsrc/common/triggers/func/plat.qc index 4c4e5049d..198083f0a 100644 --- a/qcsrc/common/triggers/func/plat.qc +++ b/qcsrc/common/triggers/func/plat.qc @@ -1,6 +1,9 @@ #ifdef SVQC +void plat_link(); + void plat_delayedinit() { + plat_link(); plat_spawn_inside_trigger(); // the "start moving" trigger } @@ -11,11 +14,10 @@ float plat_send(entity to, float sf) if(sf & SF_TRIGGER_INIT) { - WriteShort(MSG_ENTITY, num_for_edict(self)); - WriteByte(MSG_ENTITY, self.platmovetype_start); WriteByte(MSG_ENTITY, self.platmovetype_turn); WriteByte(MSG_ENTITY, self.platmovetype_end); + WriteByte(MSG_ENTITY, self.spawnflags); WriteString(MSG_ENTITY, self.model); @@ -122,14 +124,13 @@ void spawnfunc_func_plat() self.reset = plat_reset; plat_reset(); - plat_link(); - InitializeEntity(self, plat_delayedinit, INITPRIO_FINDTARGET); } #elif defined(CSQC) void plat_draw() { Movetype_Physics_NoMatchServer(); + //Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); } void ent_plat() @@ -138,11 +139,10 @@ void ent_plat() if(sf & SF_TRIGGER_INIT) { - self.sv_entnum = ReadShort(); - self.platmovetype_start = ReadByte(); self.platmovetype_turn = ReadByte(); self.platmovetype_end = ReadByte(); + self.spawnflags = ReadByte(); self.model = strzone(ReadString()); setmodel(self, self.model); @@ -171,6 +171,7 @@ void ent_plat() self.dmg = ReadShort(); + self.classname = "plat"; self.solid = SOLID_BSP; self.movetype = MOVETYPE_PUSH; self.drawmask = MASK_NORMAL; @@ -180,9 +181,12 @@ void ent_plat() plat_reset(); // also called here + self.move_movetype = MOVETYPE_PUSH; self.move_origin = self.origin; self.move_angles = self.angles; self.move_time = time; + + plat_spawn_inside_trigger(); } if(sf & SF_TRIGGER_RESET) diff --git a/qcsrc/common/triggers/func/rotating.qc b/qcsrc/common/triggers/func/rotating.qc index 2aaec0f06..93d4a30ce 100644 --- a/qcsrc/common/triggers/func/rotating.qc +++ b/qcsrc/common/triggers/func/rotating.qc @@ -69,8 +69,8 @@ void spawnfunc_func_rotating() self.blocked = generic_plat_blocked; // wait for targets to spawn - trigger_setnextthink(self, self.ltime + 999999999); - self.think = SUB_NullThink; // for PushMove + self.SUB_NEXTTHINK = self.SUB_LTIME + 999999999; + self.SUB_THINK = SUB_NullThink; // for PushMove // TODO make a reset function for this one } diff --git a/qcsrc/common/triggers/func/train.qc b/qcsrc/common/triggers/func/train.qc index 61f16fea1..2b4f67cd0 100644 --- a/qcsrc/common/triggers/func/train.qc +++ b/qcsrc/common/triggers/func/train.qc @@ -1,4 +1,3 @@ -#ifdef SVQC .float train_wait_turning; void() train_next; void train_wait() @@ -29,15 +28,17 @@ void train_wait() ang_x = -ang_x; // flip up / down orientation if(self.wait > 0) // slow turning - SUB_CalcAngleMove(ang, TSPEED_TIME, self.ltime - time + self.wait, train_wait); + SUB_CalcAngleMove(ang, TSPEED_TIME, self.SUB_LTIME - time + self.wait, train_wait); else // instant turning SUB_CalcAngleMove(ang, TSPEED_TIME, 0.0000001, train_wait); self.train_wait_turning = true; return; } +#ifdef SVQC if(self.noise != "") stopsoundto(MSG_BROADCAST, self, CH_TRIGGER_SINGLE); // send this as unreliable only, as the train will resume operation shortly anyway +#endif if(self.wait < 0 || self.train_wait_turning) // no waiting or we already waited while turning { @@ -46,8 +47,8 @@ void train_wait() } else { - self.think = train_next; - trigger_setnextthink(self, self.ltime + self.wait); + self.SUB_THINK = train_next; + self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait; } } @@ -104,6 +105,66 @@ void train_next() sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE); } +#ifdef SVQC +float train_send(entity to, float sf) +{ + WriteByte(MSG_ENTITY, ENT_CLIENT_TRAIN); + WriteByte(MSG_ENTITY, sf); + + if(sf & SF_TRIGGER_INIT) + { + WriteString(MSG_ENTITY, self.platmovetype); + WriteByte(MSG_ENTITY, self.platmovetype_turn); + WriteByte(MSG_ENTITY, self.spawnflags); + + WriteString(MSG_ENTITY, self.model); + + trigger_common_write(true); + + WriteString(MSG_ENTITY, self.curvetarget); + + WriteCoord(MSG_ENTITY, self.pos1_x); + WriteCoord(MSG_ENTITY, self.pos1_y); + WriteCoord(MSG_ENTITY, self.pos1_z); + WriteCoord(MSG_ENTITY, self.pos2_x); + WriteCoord(MSG_ENTITY, self.pos2_y); + WriteCoord(MSG_ENTITY, self.pos2_z); + + WriteCoord(MSG_ENTITY, self.size_x); + WriteCoord(MSG_ENTITY, self.size_y); + WriteCoord(MSG_ENTITY, self.size_z); + + WriteCoord(MSG_ENTITY, self.view_ofs_x); + WriteCoord(MSG_ENTITY, self.view_ofs_y); + WriteCoord(MSG_ENTITY, self.view_ofs_z); + + WriteAngle(MSG_ENTITY, self.mangle_x); + WriteAngle(MSG_ENTITY, self.mangle_y); + WriteAngle(MSG_ENTITY, self.mangle_z); + + WriteShort(MSG_ENTITY, self.speed); + WriteShort(MSG_ENTITY, self.height); + WriteByte(MSG_ENTITY, self.lip); + WriteByte(MSG_ENTITY, self.state); + WriteByte(MSG_ENTITY, self.wait); + + WriteShort(MSG_ENTITY, self.dmg); + WriteByte(MSG_ENTITY, self.dmgtime); + } + + if(sf & SF_TRIGGER_RESET) + { + // used on client + } + + return true; +} + +void train_link() +{ + Net_LinkEntity(self, 0, false, train_send); +} + void func_train_find() { entity targ; @@ -111,16 +172,21 @@ void func_train_find() self.target = targ.target; if (self.target == "") objerror("func_train_find: no next target"); - setorigin(self, targ.origin - self.view_ofs); - trigger_setnextthink(self, self.ltime + 1); - self.think = train_next; + SUB_SETORIGIN(self, targ.origin - self.view_ofs); + self.SUB_NEXTTHINK = self.SUB_LTIME + 1; + self.SUB_THINK = train_next; + + train_link(); } +#endif + /*QUAKED spawnfunc_func_train (0 .5 .8) ? Ridable platform, targets spawnfunc_path_corner path to follow. speed : speed the train moves (can be overridden by each spawnfunc_path_corner) target : targetname of first spawnfunc_path_corner (starts here) */ +#ifdef SVQC void spawnfunc_func_train() { if (self.noise != "") @@ -162,4 +228,88 @@ void spawnfunc_func_train() // TODO make a reset function for this one } +#elif defined(CSQC) +void train_draw() +{ + //Movetype_Physics_NoMatchServer(); + Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); +} + +void ent_train() +{ + float sf = ReadByte(); + + if(sf & SF_TRIGGER_INIT) + { + self.platmovetype = strzone(ReadString()); + self.platmovetype_turn = ReadByte(); + self.spawnflags = ReadByte(); + + self.model = strzone(ReadString()); + setmodel(self, self.model); + + trigger_common_read(true); + + self.curvetarget = strzone(ReadString()); + + self.pos1_x = ReadCoord(); + self.pos1_y = ReadCoord(); + self.pos1_z = ReadCoord(); + self.pos2_x = ReadCoord(); + self.pos2_y = ReadCoord(); + self.pos2_z = ReadCoord(); + + self.size_x = ReadCoord(); + self.size_y = ReadCoord(); + self.size_z = ReadCoord(); + + self.view_ofs_x = ReadCoord(); + self.view_ofs_y = ReadCoord(); + self.view_ofs_z = ReadCoord(); + + self.mangle_x = ReadAngle(); + self.mangle_y = ReadAngle(); + self.mangle_z = ReadAngle(); + + self.speed = ReadShort(); + self.height = ReadShort(); + self.lip = ReadByte(); + self.state = ReadByte(); + self.wait = ReadByte(); + + self.dmg = ReadShort(); + self.dmgtime = ReadByte(); + + self.classname = "func_train"; + self.solid = SOLID_BSP; + self.movetype = MOVETYPE_PUSH; + self.drawmask = MASK_NORMAL; + self.draw = train_draw; + self.entremove = trigger_remove_generic; + + if(set_platmovetype(self, self.platmovetype)) + { + self.platmovetype_start_default = self.platmovetype_start; + self.platmovetype_end_default = self.platmovetype_end; + } + + // everything is set up by the time the train is linked, we shouldn't need this + //func_train_find(); + + // but we will need these + self.move_nextthink = self.move_ltime + 0.1; + self.move_think = train_next; + + self.move_movetype = MOVETYPE_PUSH; + self.move_origin = self.origin; + self.move_angles = self.angles; + self.move_time = time; + } + + if(sf & SF_TRIGGER_RESET) + { + // TODO: make a reset function for trains + } +} + #endif diff --git a/qcsrc/common/triggers/func/train.qh b/qcsrc/common/triggers/func/train.qh new file mode 100644 index 000000000..f69515f5a --- /dev/null +++ b/qcsrc/common/triggers/func/train.qh @@ -0,0 +1,4 @@ +#ifdef CSQC +.float dmgtime; +void ent_train(); +#endif diff --git a/qcsrc/common/triggers/func/vectormamamam.qc b/qcsrc/common/triggers/func/vectormamamam.qc index 171c8ecb2..521ac8780 100644 --- a/qcsrc/common/triggers/func/vectormamamam.qc +++ b/qcsrc/common/triggers/func/vectormamamam.qc @@ -146,8 +146,8 @@ void spawnfunc_func_vectormamamam() return; // wait for targets to spawn - trigger_setnextthink(self, self.ltime + 999999999); - self.think = SUB_NullThink; // for PushMove + self.SUB_NEXTTHINK = self.SUB_LTIME + 999999999; + self.SUB_THINK = SUB_NullThink; // for PushMove // Savage: Reduce bandwith, critical on e.g. nexdm02 self.effects |= EF_LOWPRECISION; diff --git a/qcsrc/common/triggers/misc/corner.qc b/qcsrc/common/triggers/misc/corner.qc index 5b2d8fcff..35ad2ceb4 100644 --- a/qcsrc/common/triggers/misc/corner.qc +++ b/qcsrc/common/triggers/misc/corner.qc @@ -14,6 +14,9 @@ bool corner_send(entity to, int sf) WriteString(MSG_ENTITY, self.target3); WriteString(MSG_ENTITY, self.target4); WriteString(MSG_ENTITY, self.targetname); + WriteByte(MSG_ENTITY, self.target_random); + + WriteByte(MSG_ENTITY, self.wait); return true; } @@ -25,11 +28,11 @@ void corner_link() void spawnfunc_path_corner() { - corner_link(); - // setup values for overriding train movement // if a second value does not exist, both start and end speeds are the single value specified set_platmovetype(self, self.platmovetype); + + corner_link(); } #elif defined(CSQC) @@ -51,7 +54,7 @@ void corner_remove() self.targetname = string_null; if(self.platmovetype) { strunzone(self.platmovetype); } - self.targetname = string_null; + self.platmovetype = string_null; } void ent_corner() @@ -61,12 +64,16 @@ void ent_corner() self.origin_x = ReadCoord(); self.origin_y = ReadCoord(); self.origin_z = ReadCoord(); + setorigin(self, self.origin); self.target = strzone(ReadString()); self.target2 = strzone(ReadString()); self.target3 = strzone(ReadString()); self.target4 = strzone(ReadString()); self.targetname = strzone(ReadString()); + self.target_random = ReadByte(); + + self.wait = ReadByte(); self.classname = "path_corner"; self.drawmask = MASK_NORMAL; diff --git a/qcsrc/common/triggers/platforms.qc b/qcsrc/common/triggers/platforms.qc index c5f50c46e..b837d7c5a 100644 --- a/qcsrc/common/triggers/platforms.qc +++ b/qcsrc/common/triggers/platforms.qc @@ -16,25 +16,6 @@ void generic_plat_blocked() #endif } -#ifdef SVQC -float plat_trigger_send(entity to, float sf) -{ - WriteByte(MSG_ENTITY, ENT_CLIENT_PLAT_TRIGGER); - WriteShort(MSG_ENTITY, num_for_edict(self.enemy)); - - WriteCoord(MSG_ENTITY, self.origin_x); - WriteCoord(MSG_ENTITY, self.origin_y); - WriteCoord(MSG_ENTITY, self.origin_z); - - WriteCoord(MSG_ENTITY, self.mins_x); - WriteCoord(MSG_ENTITY, self.mins_y); - WriteCoord(MSG_ENTITY, self.mins_z); - WriteCoord(MSG_ENTITY, self.maxs_x); - WriteCoord(MSG_ENTITY, self.maxs_y); - WriteCoord(MSG_ENTITY, self.maxs_z); - return true; -} - void plat_spawn_inside_trigger() { entity trigger; @@ -46,6 +27,12 @@ void plat_spawn_inside_trigger() trigger.solid = SOLID_TRIGGER; trigger.enemy = self; +#ifdef CSQC + trigger.drawmask = MASK_NORMAL; + trigger.trigger_touch = plat_center_touch; + trigger.draw = trigger_draw_generic; +#endif + tmin = self.absmin + '25 25 0'; tmax = self.absmax - '25 25 -8'; tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8); @@ -68,7 +55,6 @@ void plat_spawn_inside_trigger() if(tmin_z < tmax_z) { setsize (trigger, tmin, tmax); - Net_LinkEntity(trigger, false, 0, plat_trigger_send); return; } @@ -76,38 +62,14 @@ void plat_spawn_inside_trigger() remove(trigger); objerror("plat_spawn_inside_trigger: platform has odd size or lip, can't spawn"); } -#elif defined(CSQC) -void ent_plat_trigger() -{ - float myenemy = ReadShort(); - self.origin_x = ReadCoord(); - self.origin_y = ReadCoord(); - self.origin_z = ReadCoord(); - setorigin(self, self.origin); - - self.mins_x = ReadCoord(); - self.mins_y = ReadCoord(); - self.mins_z = ReadCoord(); - self.maxs_x = ReadCoord(); - self.maxs_y = ReadCoord(); - self.maxs_z = ReadCoord(); - setsize(self, self.mins, self.maxs); - - self.enemy = findfloat(world, sv_entnum, myenemy); - if(!self.enemy) { print("^1BAD BAD BAD!!!\n"); } - self.drawmask = MASK_NORMAL; - self.draw = trigger_draw_generic; - self.trigger_touch = plat_center_touch; - self.solid = SOLID_TRIGGER; -} -#endif void plat_hit_top() { sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); self.state = 1; - self.think = plat_go_down; - trigger_setnextthink(self, self.ltime + 3); + + self.SUB_THINK = plat_go_down; + self.SUB_NEXTTHINK = self.SUB_LTIME + 3; } void plat_hit_bottom() @@ -141,13 +103,15 @@ void plat_center_touch() #elif defined(CSQC) if (!IS_PLAYER(other)) return; + if(PHYS_DEAD(other)) + return; #endif self = self.enemy; if (self.state == 2) plat_go_up (); else if (self.state == 1) - trigger_setnextthink(self, self.ltime + 1); + self.SUB_NEXTTHINK = self.SUB_LTIME + 1; } void plat_outside_touch() @@ -170,8 +134,13 @@ void plat_outside_touch() void plat_trigger_use() { +#ifdef SVQC if (self.think) return; // already activated +#elif defined(CSQC) + if(self.move_think) + return; +#endif plat_go_down(); } diff --git a/qcsrc/common/triggers/platforms.qh b/qcsrc/common/triggers/platforms.qh index 69ad2fae5..e0a581b7c 100644 --- a/qcsrc/common/triggers/platforms.qh +++ b/qcsrc/common/triggers/platforms.qh @@ -13,8 +13,4 @@ const float PLAT_LOW_TRIGGER = 1; .float dmg; -#ifdef CSQC -void ent_plat_trigger(); -#endif - #endif diff --git a/qcsrc/common/triggers/subs.qc b/qcsrc/common/triggers/subs.qc index cf80384d4..f21455dc5 100644 --- a/qcsrc/common/triggers/subs.qc +++ b/qcsrc/common/triggers/subs.qc @@ -26,9 +26,9 @@ Applies some friction to self .float friction; void SUB_Friction (void) { - self.nextthink = time; - if(self.flags & FL_ONGROUND) - self.velocity = self.velocity * (1 - frametime * self.friction); + self.SUB_NEXTTHINK = time; + if(self.SUB_FLAGS & FL_ONGROUND) + self.SUB_VELOCITY = self.SUB_VELOCITY * (1 - frametime * self.friction); } /* @@ -61,13 +61,13 @@ void SUB_SetFade_Think (void) { if(self.alpha == 0) self.alpha = 1; - self.think = SUB_SetFade_Think; - self.nextthink = time; + self.SUB_THINK = SUB_SetFade_Think; + self.SUB_NEXTTHINK = time; self.alpha -= frametime * self.fade_rate; if (self.alpha < 0.01) SUB_VanishOrRemove(self); else - self.nextthink = time; + self.SUB_NEXTTHINK = time; } /* @@ -80,25 +80,25 @@ Fade 'ent' out when time >= 'when' void SUB_SetFade (entity ent, float when, float fading_time) { ent.fade_rate = 1/fading_time; - ent.think = SUB_SetFade_Think; - ent.nextthink = when; + ent.SUB_THINK = SUB_SetFade_Think; + ent.SUB_NEXTTHINK = when; } /* ============= SUB_CalcMove -calculate self.velocity and self.nextthink to reach dest from -self.origin traveling at speed +calculate self.SUB_VELOCITY and self.SUB_NEXTTHINK to reach dest from +self.SUB_ORIGIN traveling at speed =============== */ void SUB_CalcMoveDone (void) { // After moving, set origin to exact final destination - setorigin (self, self.finaldest); - self.velocity = '0 0 0'; - self.nextthink = -1; + SUB_SETORIGIN (self, self.finaldest); + self.SUB_VELOCITY = '0 0 0'; + self.SUB_NEXTTHINK = -1; if (self.think1) self.think1 (); } @@ -135,30 +135,30 @@ void SUB_CalcMove_controller_think (void) destangle_x = -destangle_x; // flip up / down orientation // take the shortest distance for the angles - self.owner.angles_x -= 360 * floor((self.owner.angles_x - destangle_x) / 360 + 0.5); - self.owner.angles_y -= 360 * floor((self.owner.angles_y - destangle_y) / 360 + 0.5); - self.owner.angles_z -= 360 * floor((self.owner.angles_z - destangle_z) / 360 + 0.5); - angloc = destangle - self.owner.angles; + SUB_ANGLES(self.owner)_x -= 360 * floor((SUB_ANGLES(self.owner)_x - destangle_x) / 360 + 0.5); + SUB_ANGLES(self.owner)_y -= 360 * floor((SUB_ANGLES(self.owner)_y - destangle_y) / 360 + 0.5); + SUB_ANGLES(self.owner)_z -= 360 * floor((SUB_ANGLES(self.owner)_z - destangle_z) / 360 + 0.5); + angloc = destangle - SUB_ANGLES(self.owner); angloc = angloc * (1 / PHYS_INPUT_FRAMETIME); // so it arrives for the next frame - self.owner.avelocity = angloc; + self.owner.SUB_AVELOCITY = angloc; } if(nexttick < self.animstate_endtime) - veloc = nextpos - self.owner.origin; + veloc = nextpos - self.owner.SUB_ORIGIN; else - veloc = self.finaldest - self.owner.origin; + veloc = self.finaldest - self.owner.SUB_ORIGIN; veloc = veloc * (1 / PHYS_INPUT_FRAMETIME); // so it arrives for the next frame - self.owner.velocity = veloc; + self.owner.SUB_VELOCITY = veloc; self.nextthink = nexttick; } else { // derivative: delta + 2 * delta2 (e.g. for angle positioning) oldself = self; - self.owner.think = self.think1; + self.owner.SUB_THINK = self.think1; self = self.owner; remove(oldself); - self.think(); + self.SUB_THINK(); } } @@ -168,7 +168,7 @@ void SUB_CalcMove_controller_setbezier (entity controller, vector org, vector co // 2 * control * t - 2 * control * t * t + destin * t * t // 2 * control * t + (destin - 2 * control) * t * t - controller.origin = org; // starting point + setorigin(controller, org); control -= org; destin -= org; @@ -183,7 +183,7 @@ void SUB_CalcMove_controller_setlinear (entity controller, vector org, vector de // 2 * control * t - 2 * control * t * t + destin * t * t // 2 * control * t + (destin - 2 * control) * t * t - controller.origin = org; // starting point + setorigin(controller, org); destin -= org; controller.destvec = destin; // end point @@ -206,19 +206,19 @@ void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float self.think1 = func; self.finaldest = tdest; - self.think = SUB_CalcMoveDone; + self.SUB_THINK = SUB_CalcMoveDone; switch(tspeedtype) { default: case TSPEED_START: - traveltime = 2 * vlen(tcontrol - self.origin) / tspeed; + traveltime = 2 * vlen(tcontrol - self.SUB_ORIGIN) / tspeed; break; case TSPEED_END: traveltime = 2 * vlen(tcontrol - tdest) / tspeed; break; case TSPEED_LINEAR: - traveltime = vlen(tdest - self.origin) / tspeed; + traveltime = vlen(tdest - self.SUB_ORIGIN) / tspeed; break; case TSPEED_TIME: traveltime = tspeed; @@ -227,8 +227,8 @@ void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float if (traveltime < 0.1) // useless anim { - self.velocity = '0 0 0'; - trigger_setnextthink(self, self.ltime + 0.1); + self.SUB_VELOCITY = '0 0 0'; + self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1; return; } @@ -238,16 +238,16 @@ void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float controller.platmovetype = self.platmovetype; controller.platmovetype_start = self.platmovetype_start; controller.platmovetype_end = self.platmovetype_end; - SUB_CalcMove_controller_setbezier(controller, self.origin, tcontrol, tdest); + SUB_CalcMove_controller_setbezier(controller, self.SUB_ORIGIN, tcontrol, tdest); controller.finaldest = (tdest + '0 0 0.125'); // where do we want to end? Offset to overshoot a bit. controller.animstate_starttime = time; controller.animstate_endtime = time + traveltime; controller.think = SUB_CalcMove_controller_think; - controller.think1 = self.think; + controller.think1 = self.SUB_THINK; // the thinking is now done by the controller - self.think = SUB_NullThink; // for PushMove - trigger_setnextthink(self, self.ltime + traveltime); + self.SUB_THINK = SUB_NullThink; // for PushMove + self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime; // invoke controller self = controller; @@ -265,16 +265,16 @@ void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func) self.think1 = func; self.finaldest = tdest; - self.think = SUB_CalcMoveDone; + self.SUB_THINK = SUB_CalcMoveDone; - if (tdest == self.origin) + if (tdest == self.SUB_ORIGIN) { - self.velocity = '0 0 0'; - trigger_setnextthink(self, self.ltime + 0.1); + self.SUB_VELOCITY = '0 0 0'; + self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1; return; } - delta = tdest - self.origin; + delta = tdest - self.SUB_ORIGIN; switch(tspeedtype) { @@ -295,13 +295,13 @@ void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func) // The only currently implemented alternative movement is linear (value 1) if (traveltime < 0.15 || (self.platmovetype_start == 1 && self.platmovetype_end == 1)) // is this correct? { - self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division - trigger_setnextthink(self, self.ltime + traveltime); + self.SUB_VELOCITY = delta * (1/traveltime); // QuakeC doesn't allow vector/float division + self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime; return; } // now just run like a bezier curve... - SUB_CalcMove_Bezier((self.origin + tdest) * 0.5, tdest, tspeedtype, tspeed, func); + SUB_CalcMove_Bezier((self.SUB_ORIGIN + tdest) * 0.5, tdest, tspeedtype, tspeed, func); } void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void() func) @@ -320,18 +320,18 @@ void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, ============= SUB_CalcAngleMove -calculate self.avelocity and self.nextthink to reach destangle from +calculate self.SUB_AVELOCITY and self.SUB_NEXTTHINK to reach destangle from self.angles rotating -The calling function should make sure self.think is valid +The calling function should make sure self.SUB_THINK is valid =============== */ void SUB_CalcAngleMoveDone (void) { // After rotating, set angle to exact final angle self.angles = self.finalangle; - self.avelocity = '0 0 0'; - self.nextthink = -1; + self.SUB_AVELOCITY = '0 0 0'; + self.SUB_NEXTTHINK = -1; if (self.think1) self.think1 (); } @@ -366,17 +366,17 @@ void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void() self.think1 = func; self.finalangle = destangle; - self.think = SUB_CalcAngleMoveDone; + self.SUB_THINK = SUB_CalcAngleMoveDone; if (traveltime < 0.1) { - self.avelocity = '0 0 0'; - trigger_setnextthink(self, self.ltime + 0.1); + self.SUB_AVELOCITY = '0 0 0'; + self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1; return; } - self.avelocity = delta * (1 / traveltime); - trigger_setnextthink(self, self.ltime + traveltime); + self.SUB_AVELOCITY = delta * (1 / traveltime); + self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime; } void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void() func) diff --git a/qcsrc/common/triggers/subs.qh b/qcsrc/common/triggers/subs.qh index bf0994897..ea8ef3057 100644 --- a/qcsrc/common/triggers/subs.qh +++ b/qcsrc/common/triggers/subs.qh @@ -1,6 +1,42 @@ #ifndef SUBS_H #define SUBS_H +#ifdef SVQC + + #define SUB_ANGLES(s) (s).angles + #define SUB_VELOCITY velocity + #define SUB_AVELOCITY avelocity + #define SUB_ORIGIN origin + #define SUB_SETORIGIN(s,v) setorigin((s), (v)) + #define SUB_NEXTTHINK nextthink + #define SUB_THINK think + #define SUB_LTIME ltime + #define SUB_FLAGS flags + +#elif defined(CSQC) + + void _Movetype_LinkEdict(float touch_triggers); + + #define SUB_ANGLES(s) (s).move_angles + #define SUB_VELOCITY move_velocity + #define SUB_AVELOCITY move_avelocity + #define SUB_ORIGIN move_origin + #define SUB_NEXTTHINK move_nextthink + #define SUB_THINK move_think + #define SUB_LTIME move_ltime + #define SUB_FLAGS move_flags + + void SUB_SETORIGIN(entity s, vector v) + { + s.move_origin = v; + entity oldself = self; + self = s; + _Movetype_LinkEdict(true); + self = oldself; + } + +#endif + void SUB_Remove(); void SUB_SetFade (entity ent, float when, float fading_time); void SUB_VanishOrRemove (entity ent); diff --git a/qcsrc/common/triggers/trigger/delay.qc b/qcsrc/common/triggers/trigger/delay.qc index f01845cf8..b01efe3bb 100644 --- a/qcsrc/common/triggers/trigger/delay.qc +++ b/qcsrc/common/triggers/trigger/delay.qc @@ -2,7 +2,7 @@ void delay_use() { self.think = SUB_UseTargets; - trigger_setnextthink(self, self.wait); + self.nextthink = self.wait; } void delay_reset() diff --git a/qcsrc/common/triggers/triggers.qc b/qcsrc/common/triggers/triggers.qc index a8a5a03c1..da0301778 100644 --- a/qcsrc/common/triggers/triggers.qc +++ b/qcsrc/common/triggers/triggers.qc @@ -20,15 +20,6 @@ void FixSize(entity e) e.maxs_z = rint(e.maxs_z); } -void trigger_setnextthink(entity e, float dtime) -{ -#ifdef CSQC - e.nextthink = time + dtime; -#else - e.nextthink = dtime; -#endif -} - #ifdef SVQC void trigger_common_write(bool withtarget) { @@ -276,8 +267,6 @@ void trigger_draw_generic() self.move_time = time; if(dt <= 0) { return; } - setorigin(self, self.origin + self.velocity * frametime); - if(self.trigger_touch) { trigger_touch_generic(self.trigger_touch); } } #endif diff --git a/qcsrc/common/triggers/triggers.qh b/qcsrc/common/triggers/triggers.qh index 9416f7a16..c50d95b89 100644 --- a/qcsrc/common/triggers/triggers.qh +++ b/qcsrc/common/triggers/triggers.qh @@ -23,8 +23,6 @@ const float SPAWNFLAG_NOTOUCH = 1; .float lip; -void trigger_setnextthink(entity e, float dtime); - // used elsewhere (will fix) #ifdef SVQC void trigger_common_write(bool withtarget); -- 2.39.2