X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Ft_plats.qc;h=3955442310817b537994f80d19d872ac6d65be3e;hb=3b2bc1bdee04f4c454279bf14ac8ed6b37c6ddb5;hp=d6b39768b8aa0ccc1f55754763b57d088f922290;hpb=778b291f050a48a6ccff737a2897be38ad3883cc;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/t_plats.qc b/qcsrc/server/t_plats.qc index d6b39768b..395544231 100644 --- a/qcsrc/server/t_plats.qc +++ b/qcsrc/server/t_plats.qc @@ -14,11 +14,6 @@ void generic_plat_blocked() } -float STATE_TOP = 0; -float STATE_BOTTOM = 1; -float STATE_UP = 2; -float STATE_DOWN = 3; - .entity trigger_field; void() plat_center_touch; @@ -27,7 +22,7 @@ void() plat_trigger_use; void() plat_go_up; void() plat_go_down; void() plat_crush; -float PLAT_LOW_TRIGGER = 1; +const float PLAT_LOW_TRIGGER = 1; void plat_spawn_inside_trigger() { @@ -72,7 +67,7 @@ void plat_spawn_inside_trigger() void plat_hit_top() { - sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); self.state = 1; self.think = plat_go_down; self.nextthink = self.ltime + 3; @@ -80,27 +75,27 @@ void plat_hit_top() void plat_hit_bottom() { - sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); self.state = 2; } void plat_go_down() { - sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM); self.state = 3; - SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom); + SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, plat_hit_bottom); } void plat_go_up() { - sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM); self.state = 4; - SUB_CalcMove (self.pos1, self.speed, plat_hit_top); + SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, plat_hit_top); } void plat_center_touch() { - if not(other.iscreature) + if (!other.iscreature) return; if (other.health <= 0) @@ -115,7 +110,7 @@ void plat_center_touch() void plat_outside_touch() { - if not(other.iscreature) + if (!other.iscreature) return; if (other.health <= 0) @@ -158,7 +153,7 @@ void plat_crush() void plat_use() { - self.use = SUB_Null; + self.use = func_null; if (self.state != 4) objerror ("plat_use: not in up state"); plat_go_down(); @@ -182,7 +177,43 @@ void plat_reset() } } -void spawnfunc_path_corner() { } +.float platmovetype_start_default, platmovetype_end_default; +float set_platmovetype(entity e, string s) +{ + // sets platmovetype_start and platmovetype_end based on a string consisting of two values + + float n; + n = tokenize_console(s); + if(n > 0) + e.platmovetype_start = stof(argv(0)); + else + e.platmovetype_start = 0; + + if(n > 1) + e.platmovetype_end = stof(argv(1)); + else + e.platmovetype_end = e.platmovetype_start; + + if(n > 2) + if(argv(2) == "force") + return TRUE; // no checking, return immediately + + if(!cubic_speedfunc_is_sane(e.platmovetype_start, e.platmovetype_end)) + { + objerror("Invalid platform move type; platform would go in reverse, which is not allowed."); + return FALSE; + } + + return TRUE; +} + +void spawnfunc_path_corner() +{ + // setup values for overriding train movement + // if a second value does not exist, both start and end speeds are the single value specified + if(!set_platmovetype(self, self.platmovetype)) + return; +} void spawnfunc_func_plat() { if (self.sounds == 0) @@ -191,9 +222,9 @@ void spawnfunc_func_plat() if(self.spawnflags & 4) self.dmg = 10000; - if(self.dmg && (!self.message)) + if(self.dmg && (self.message == "")) self.message = "was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message2 == "")) self.message2 = "was squished by"; if (self.sounds == 1) @@ -227,7 +258,7 @@ void spawnfunc_func_plat() self.angles = '0 0 0'; self.classname = "plat"; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.effects |= EF_LOWPRECISION; setsize (self, self.mins , self.maxs); @@ -255,13 +286,35 @@ void spawnfunc_func_plat() void() train_next; void train_wait() { - // if using bezier curves and turning is enabled, the train will turn toward the next point while waiting - if(!self.train_wait_turning) - if (self.spawnflags & 1 && self.bezier_turn && self.wait >= 0) + entity oldself; + oldself = self; + self = self.enemy; + SUB_UseTargets(); + self = oldself; + self.enemy = world; + + // if turning is enabled, the train will turn toward the next point while waiting + if(self.platmovetype_turn && !self.train_wait_turning) { - entity targ; + entity targ, cp; + vector ang; targ = find(world, targetname, self.target); - SUB_CalcAngleMove(targ.origin, self.ltime + self.wait, train_wait); + if((self.spawnflags & 1) && targ.curvetarget) + cp = find(world, targetname, targ.curvetarget); + else + cp = world; + + if(cp) // bezier curves movement + ang = cp.origin - (self.origin - self.view_ofs); // use the origin of the control point of the next path_corner + else // linear movement + ang = targ.origin - (self.origin - self.view_ofs); // use the origin of the next path_corner + ang = vectoangles(ang); + 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); + else // instant turning + SUB_CalcAngleMove(ang, TSPEED_TIME, 0.0000001, train_wait); self.train_wait_turning = TRUE; return; } @@ -269,8 +322,9 @@ void train_wait() if(self.noise != "") stopsoundto(MSG_BROADCAST, self, CH_TRIGGER_SINGLE); // send this as unreliable only, as the train will resume operation shortly anyway - if(self.wait < 0) + if(self.wait < 0 || self.train_wait_turning) // no waiting or we already waited while turning { + self.train_wait_turning = FALSE; train_next(); } else @@ -278,55 +332,59 @@ void train_wait() self.think = train_next; self.nextthink = self.ltime + self.wait; } - - entity oldself; - oldself = self; - self = self.enemy; - SUB_UseTargets(); - self = oldself; - self.enemy = world; - self.train_wait_turning = FALSE; } void train_next() { - entity targ, cp; - vector cp_org; + entity targ, cp = world; + vector cp_org = '0 0 0'; targ = find(world, targetname, self.target); self.target = targ.target; if (self.spawnflags & 1) { - cp = find(world, target, targ.targetname); // get the previous corner first - cp = find(world, targetname, cp.target2); // now get its second target (the control point) - if(cp.targetname == "") - cp_org = targ.origin - self.mins; // no control point found, assume a straight line to the destination - else - cp_org = cp.origin - self.mins; + if(targ.curvetarget) + { + cp = find(world, targetname, targ.curvetarget); // get its second target (the control point) + cp_org = cp.origin - self.view_ofs; // no control point found, assume a straight line to the destination + } } - if (!self.target) + if (self.target == "") objerror("train_next: no next target"); self.wait = targ.wait; if (!self.wait) self.wait = 0.1; + if(targ.platmovetype) + { + // this path_corner contains a movetype overrider, apply it + self.platmovetype_start = targ.platmovetype_start; + self.platmovetype_end = targ.platmovetype_end; + } + else + { + // this path_corner doesn't contain a movetype overrider, use the train's defaults + self.platmovetype_start = self.platmovetype_start_default; + self.platmovetype_end = self.platmovetype_end_default; + } + if (targ.speed) { - if (self.spawnflags & 1) - SUB_CalcMove_Bezier(cp_org, targ.origin - self.mins, targ.speed, train_wait); + if (cp) + SUB_CalcMove_Bezier(cp_org, targ.origin - self.view_ofs, TSPEED_LINEAR, targ.speed, train_wait); else - SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait); + SUB_CalcMove(targ.origin - self.view_ofs, TSPEED_LINEAR, targ.speed, train_wait); } else { - if (self.spawnflags & 1) - SUB_CalcMove_Bezier(cp_org, targ.origin - self.mins, self.speed, train_wait); + if (cp) + SUB_CalcMove_Bezier(cp_org, targ.origin - self.view_ofs, TSPEED_LINEAR, self.speed, train_wait); else - SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait); + SUB_CalcMove(targ.origin - self.view_ofs, TSPEED_LINEAR, self.speed, train_wait); } if(self.noise != "") - sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); + sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE); } void func_train_find() @@ -334,9 +392,9 @@ void func_train_find() entity targ; targ = find(world, targetname, self.target); self.target = targ.target; - if (!self.target) + if (self.target == "") objerror("func_train_find: no next target"); - setorigin(self, targ.origin - self.mins); + setorigin(self, targ.origin - self.view_ofs); self.nextthink = self.ltime + 1; self.think = train_next; } @@ -351,14 +409,20 @@ void spawnfunc_func_train() if (self.noise != "") precache_sound(self.noise); - if (!self.target) + if (self.target == "") objerror("func_train without a target"); if (!self.speed) self.speed = 100; + if (self.spawnflags & 2) - self.bezier_turn = TRUE; + { + self.platmovetype_turn = TRUE; + self.view_ofs = '0 0 0'; // don't offset a rotating train, origin works differently now + } + else + self.view_ofs = self.mins; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.effects |= EF_LOWPRECISION; @@ -366,22 +430,27 @@ void spawnfunc_func_train() InitializeEntity(self, func_train_find, INITPRIO_SETLOCATION); self.blocked = generic_plat_blocked; - if(self.dmg & (!self.message)) + if(self.dmg && (self.message == "")) self.message = " was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message2 == "")) self.message2 = "was squished by"; if(self.dmg && (!self.dmgtime)) self.dmgtime = 0.25; self.dmgtime2 = time; + if(!set_platmovetype(self, self.platmovetype)) + return; + self.platmovetype_start_default = self.platmovetype_start; + self.platmovetype_end_default = self.platmovetype_end; + // TODO make a reset function for this one } void func_rotating_setactive(float astate) { - + if (astate == ACTIVE_TOGGLE) - { + { if(self.active == ACTIVE_ACTIVE) self.active = ACTIVE_NOT; else @@ -389,8 +458,8 @@ void func_rotating_setactive(float astate) } else self.active = astate; - - if(self.active == ACTIVE_NOT) + + if(self.active == ACTIVE_NOT) self.avelocity = '0 0 0'; else self.avelocity = self.pos1; @@ -409,12 +478,12 @@ void spawnfunc_func_rotating() if (self.noise != "") { precache_sound(self.noise); - ambientsound(self.origin, self.noise, VOL_BASE, ATTN_IDLE); + ambientsound(self.origin, self.noise, VOL_BASE, ATTEN_IDLE); } - + self.active = ACTIVE_ACTIVE; self.setactive = func_rotating_setactive; - + if (!self.speed) self.speed = 100; // FIXME: test if this turns the right way, then remove this comment (negate as needed) @@ -426,12 +495,12 @@ void spawnfunc_func_rotating() // FIXME: test if this turns the right way, then remove this comment (negate as needed) else // Z self.avelocity = '0 1 0' * self.speed; - + self.pos1 = self.avelocity; - - if(self.dmg & (!self.message)) + + if(self.dmg && (self.message == "")) self.message = " was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message2 == "")) self.message2 = "was squished by"; @@ -440,7 +509,7 @@ void spawnfunc_func_rotating() self.dmgtime2 = time; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; // no EF_LOWPRECISION here, as rounding angles is bad @@ -448,7 +517,7 @@ void spawnfunc_func_rotating() // wait for targets to spawn self.nextthink = self.ltime + 999999999; - self.think = SUB_Null; + self.think = SUB_NullThink; // for PushMove // TODO make a reset function for this one } @@ -458,13 +527,13 @@ void func_bobbing_controller_think() { vector v; self.nextthink = time + 0.1; - - if not (self.owner.active == ACTIVE_ACTIVE) + + if (!(self.owner.active == ACTIVE_ACTIVE)) { - self.owner.velocity = '0 0 0'; + self.owner.velocity = '0 0 0'; return; } - + // calculate sinewave using makevectors makevectors((self.nextthink * self.owner.cnt + self.owner.phase * 360) * '0 1 0'); v = self.owner.destvec + self.owner.movedir * v_forward_y; @@ -488,7 +557,7 @@ void spawnfunc_func_bobbing() if (self.noise != "") { precache_sound(self.noise); - soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); + soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE); } if (!self.speed) self.speed = 4; @@ -503,9 +572,9 @@ void spawnfunc_func_bobbing() // damage when blocked self.blocked = generic_plat_blocked; - if(self.dmg & (!self.message)) + if(self.dmg && (self.message == "")) self.message = " was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message2 == "")) self.message2 = "was squished by"; if(self.dmg && (!self.dmgtime)) self.dmgtime = 0.25; @@ -519,7 +588,7 @@ void spawnfunc_func_bobbing() else // Z self.movedir = '0 0 1' * self.height; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; // wait for targets to spawn @@ -529,7 +598,7 @@ void spawnfunc_func_bobbing() controller.nextthink = time + 1; controller.think = func_bobbing_controller_think; self.nextthink = self.ltime + 999999999; - self.think = SUB_Null; + self.think = SUB_NullThink; // for PushMove // Savage: Reduce bandwith, critical on e.g. nexdm02 self.effects |= EF_LOWPRECISION; @@ -543,7 +612,7 @@ void func_pendulum_controller_think() float v; self.nextthink = time + 0.1; - if not (self.owner.active == ACTIVE_ACTIVE) + if (!(self.owner.active == ACTIVE_ACTIVE)) { self.owner.avelocity_x = 0; return; @@ -565,7 +634,7 @@ void spawnfunc_func_pendulum() if (self.noise != "") { precache_sound(self.noise); - soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); + soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE); } self.active = ACTIVE_ACTIVE; @@ -576,9 +645,9 @@ void spawnfunc_func_pendulum() self.speed = 30; // not initializing self.dmg to 2, to allow damageless pendulum - if(self.dmg & (!self.message)) + if(self.dmg && (self.message == "")) self.message = " was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message2 == "")) self.message2 = "was squished by"; if(self.dmg && (!self.dmgtime)) self.dmgtime = 0.25; @@ -587,7 +656,7 @@ void spawnfunc_func_pendulum() self.blocked = generic_plat_blocked; self.avelocity_z = 0.0000001; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; if(!self.freq) @@ -606,7 +675,7 @@ void spawnfunc_func_pendulum() controller.nextthink = time + 1; controller.think = func_pendulum_controller_think; self.nextthink = self.ltime + 999999999; - self.think = SUB_Null; + self.think = SUB_NullThink; // for PushMove //self.effects |= EF_LOWPRECISION; @@ -636,7 +705,7 @@ void button_done() void button_return() { self.state = STATE_DOWN; - SUB_CalcMove (self.pos1, self.speed, button_done); + SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, button_done); self.frame = 0; // use normal textures if (self.health) self.takedamage = DAMAGE_YES; // can be shot again @@ -658,10 +727,10 @@ void button_fire() return; if (self.noise != "") - sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM); self.state = STATE_UP; - SUB_CalcMove (self.pos2, self.speed, button_wait); + SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, button_wait); } void button_reset() @@ -676,13 +745,7 @@ void button_reset() void button_use() { -// if (activator.classname != "player") -// { -// dprint(activator.classname); -// dprint(" triggered a button\n"); -// } - - if not (self.active == ACTIVE_ACTIVE) + if (!(self.active == ACTIVE_ACTIVE)) return; self.enemy = activator; @@ -691,14 +754,9 @@ void button_use() void button_touch() { -// if (activator.classname != "player") -// { -// dprint(activator.classname); -// dprint(" touched a button\n"); -// } if (!other) return; - if not(other.iscreature) + if (!other.iscreature) return; if(other.velocity * self.movedir < 0) return; @@ -716,11 +774,6 @@ void button_damage(entity inflictor, entity attacker, float damage, float deatht self.health = self.health - damage; if (self.health <= 0) { - // if (activator.classname != "player") - // { - // dprint(activator.classname); - // dprint(" killed a button\n"); - // } self.enemy = damage_attacker; button_fire (); } @@ -746,7 +799,7 @@ void spawnfunc_func_button() { SetMovedir (); - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.effects |= EF_LOWPRECISION; @@ -784,9 +837,9 @@ void spawnfunc_func_button() } -float DOOR_START_OPEN = 1; -float DOOR_DONT_LINK = 4; -float DOOR_TOGGLE = 32; +const float DOOR_START_OPEN = 1; +const float DOOR_DONT_LINK = 4; +const float DOOR_TOGGLE = 32; /* @@ -869,7 +922,7 @@ void door_blocked() void door_hit_top() { if (self.noise1 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); self.state = STATE_TOP; if (self.spawnflags & DOOR_TOGGLE) return; // don't come down automatically @@ -886,14 +939,14 @@ void door_hit_top() void door_hit_bottom() { if (self.noise1 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); self.state = STATE_BOTTOM; } void door_go_down() { if (self.noise2 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); if (self.max_health) { self.takedamage = DAMAGE_YES; @@ -901,7 +954,7 @@ void door_go_down() } self.state = STATE_DOWN; - SUB_CalcMove (self.pos1, self.speed, door_hit_bottom); + SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, door_hit_bottom); } void door_go_up() @@ -916,9 +969,9 @@ void door_go_up() } if (self.noise2 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); self.state = STATE_UP; - SUB_CalcMove (self.pos2, self.speed, door_hit_top); + SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, door_hit_top); string oldmessage; oldmessage = self.message; @@ -939,22 +992,22 @@ ACTIVATION FUNCTIONS float door_check_keys(void) { local entity door; - - + + if (self.owner) door = self.owner; else door = self; - + // no key needed - if not(door.itemkeys) + if (!door.itemkeys) return TRUE; // this door require a key // only a player can have a key - if (other.classname != "player") + if (!IS_PLAYER(other)) return FALSE; - + if (item_keys_usekey(door, other)) { // some keys were used if (other.key_door_messagetime <= time) { @@ -1046,7 +1099,7 @@ void door_use() entity oself; //dprint("door_use (model: ");dprint(self.model);dprint(")\n"); - + if (self.owner) { oself = self; @@ -1060,16 +1113,16 @@ void door_use() void door_trigger_touch() { if (other.health < 1) - if not(other.iscreature && other.deadflag == DEAD_NO) + if (!(other.iscreature && other.deadflag == DEAD_NO)) return; if (time < self.attack_finished_single) return; - + // check if door is locked if (!door_check_keys()) return; - + self.attack_finished_single = time + 1; activator = other; @@ -1086,12 +1139,12 @@ void door_damage(entity inflictor, entity attacker, float damage, float deathtyp if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH)) return; self.health = self.health - damage; - + if (self.itemkeys) { // don't allow opening doors through damage if keys are required return; } - + if (self.health <= 0) { oself = self; @@ -1113,7 +1166,7 @@ Prints messages */ void door_touch() { - if(other.classname != "player") + if (!IS_PLAYER(other)) return; if (self.owner.attack_finished_single > time) return; @@ -1122,7 +1175,7 @@ void door_touch() if (!(self.owner.dmg) && (self.owner.message != "")) { - if (other.flags & FL_CLIENT) + if (IS_CLIENT(other)) centerprint (other, self.owner.message); play2(other, "misc/talk.wav"); } @@ -1172,7 +1225,7 @@ void door_generic_plat_blocked() void door_rotating_hit_top() { if (self.noise1 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); self.state = STATE_TOP; if (self.spawnflags & DOOR_TOGGLE) return; // don't come down automatically @@ -1183,7 +1236,7 @@ void door_rotating_hit_top() void door_rotating_hit_bottom() { if (self.noise1 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); if (self.lip==666) // self.lip is used to remember reverse opening direction for door_rotating { self.pos2 = '0 0 0' - self.pos2; @@ -1195,7 +1248,7 @@ void door_rotating_hit_bottom() void door_rotating_go_down() { if (self.noise2 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); if (self.max_health) { self.takedamage = DAMAGE_YES; @@ -1203,7 +1256,7 @@ void door_rotating_go_down() } self.state = STATE_DOWN; - SUB_CalcAngleMove (self.pos1, self.speed, door_rotating_hit_bottom); + SUB_CalcAngleMove (self.pos1, TSPEED_LINEAR, self.speed, door_rotating_hit_bottom); } void door_rotating_go_up() @@ -1217,9 +1270,9 @@ void door_rotating_go_up() return; } if (self.noise2 != "") - sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); self.state = STATE_UP; - SUB_CalcAngleMove (self.pos2, self.speed, door_rotating_hit_top); + SUB_CalcAngleMove (self.pos2, TSPEED_LINEAR, self.speed, door_rotating_hit_top); string oldmessage; oldmessage = self.message; @@ -1259,24 +1312,32 @@ entity spawn_field(vector fmins, vector fmaxs) } -float EntitiesTouching(entity e1, entity e2) +entity LinkDoors_nextent(entity cur, entity near, entity pass) +{ + while((cur = find(cur, classname, self.classname)) && ((cur.spawnflags & 4) || cur.enemy)) + { + } + return cur; +} + +float LinkDoors_isconnected(entity e1, entity e2, entity pass) { - if (e1.absmin_x > e2.absmax_x) + float DELTA = 4; + if (e1.absmin_x > e2.absmax_x + DELTA) return FALSE; - if (e1.absmin_y > e2.absmax_y) + if (e1.absmin_y > e2.absmax_y + DELTA) return FALSE; - if (e1.absmin_z > e2.absmax_z) + if (e1.absmin_z > e2.absmax_z + DELTA) return FALSE; - if (e1.absmax_x < e2.absmin_x) + if (e2.absmin_x > e1.absmax_x + DELTA) return FALSE; - if (e1.absmax_y < e2.absmin_y) + if (e2.absmin_y > e1.absmax_y + DELTA) return FALSE; - if (e1.absmax_z < e2.absmin_z) + if (e2.absmin_z > e1.absmax_z + DELTA) return FALSE; return TRUE; } - /* ============= LinkDoors @@ -1286,7 +1347,7 @@ LinkDoors */ void LinkDoors() { - entity t, starte; + entity t; vector cmins, cmaxs; if (self.enemy) @@ -1306,68 +1367,70 @@ void LinkDoors() return; // don't want to link this door } - cmins = self.absmin; - cmaxs = self.absmax; - - starte = self; - t = self; + FindConnectedComponent(self, enemy, LinkDoors_nextent, LinkDoors_isconnected, world); - do + // set owner, and make a loop of the chain + dprint("LinkDoors: linking doors:"); + for(t = self; ; t = t.enemy) { - self.owner = starte; // master door - - if (self.health) - starte.health = self.health; - IFTARGETED - starte.targetname = self.targetname; - if (self.message != "") - starte.message = self.message; - - t = find(t, classname, self.classname); - if (!t) + dprint(" ", etos(t)); + t.owner = self; + if(t.enemy == world) { - self.enemy = starte; // make the chain a loop - - // shootable, or triggered doors just needed the owner/enemy links, - // they don't spawn a field - - self = self.owner; + t.enemy = self; + break; + } + } + dprint("\n"); - if (self.health) - return; - IFTARGETED - return; - if (self.items) - return; + // collect health, targetname, message, size + cmins = self.absmin; + cmaxs = self.absmax; + for(t = self; ; t = t.enemy) + { + if(t.health && !self.health) + self.health = t.health; + if((t.targetname != "") && (self.targetname == "")) + self.targetname = t.targetname; + if((t.message != "") && (self.message == "")) + self.message = t.message; + if (t.absmin_x < cmins_x) + cmins_x = t.absmin_x; + if (t.absmin_y < cmins_y) + cmins_y = t.absmin_y; + if (t.absmin_z < cmins_z) + cmins_z = t.absmin_z; + if (t.absmax_x > cmaxs_x) + cmaxs_x = t.absmax_x; + if (t.absmax_y > cmaxs_y) + cmaxs_y = t.absmax_y; + if (t.absmax_z > cmaxs_z) + cmaxs_z = t.absmax_z; + if(t.enemy == self) + break; + } - self.owner.trigger_field = spawn_field(cmins, cmaxs); + // distribute health, targetname, message + for(t = self; t; t = t.enemy) + { + t.health = self.health; + t.targetname = self.targetname; + t.message = self.message; + if(t.enemy == self) + break; + } - return; - } + // shootable, or triggered doors just needed the owner/enemy links, + // they don't spawn a field - if (EntitiesTouching(self,t)) - { - if (t.enemy) - objerror ("cross connected doors"); - - self.enemy = t; - self = t; - - if (t.absmin_x < cmins_x) - cmins_x = t.absmin_x; - if (t.absmin_y < cmins_y) - cmins_y = t.absmin_y; - if (t.absmin_z < cmins_z) - cmins_z = t.absmin_z; - if (t.absmax_x > cmaxs_x) - cmaxs_x = t.absmax_x; - if (t.absmax_y > cmaxs_y) - cmaxs_y = t.absmax_y; - if (t.absmax_z > cmaxs_z) - cmaxs_z = t.absmax_z; - } - } while (1 ); + if (self.health) + return; + IFTARGETED + return; + if (self.items) + return; + self.trigger_field = spawn_field(cmins, cmaxs); } @@ -1412,7 +1475,8 @@ void door_reset() setorigin(self, self.pos1); self.velocity = '0 0 0'; self.state = STATE_BOTTOM; - self.think = SUB_Null; + self.think = func_null; + self.nextthink = 0; } // spawnflags require key (for now only func_door) @@ -1425,13 +1489,13 @@ void spawnfunc_func_door() self.itemkeys |= ITEM_KEY_BIT(0); if (self.spawnflags & SPAWNFLAGS_SILVER_KEY) self.itemkeys |= ITEM_KEY_BIT(1); - + //if (!self.deathtype) // map makers can override this // self.deathtype = " got in the way"; SetMovedir (); self.max_health = self.health; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.effects |= EF_LOWPRECISION; self.classname = "door"; @@ -1443,9 +1507,9 @@ void spawnfunc_func_door() // if(self.spawnflags & 8) // self.dmg = 10000; - if(self.dmg && (!self.message)) + if(self.dmg && (self.message == "")) self.message = "was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message2 == "")) self.message2 = "was squished by"; if (self.sounds > 0) @@ -1524,7 +1588,8 @@ void door_rotating_reset() self.angles = self.pos1; self.avelocity = '0 0 0'; self.state = STATE_BOTTOM; - self.think = SUB_Null; + self.think = func_null; + self.nextthink = 0; } void door_rotating_init_startopen() @@ -1556,7 +1621,7 @@ void spawnfunc_func_door_rotating() self.max_health = self.health; self.avelocity = self.movedir; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.velocity = '0 0 0'; //self.effects |= EF_LOWPRECISION; @@ -1568,9 +1633,9 @@ void spawnfunc_func_door_rotating() if(self.spawnflags & 8) self.dmg = 10000; - if(self.dmg && (!self.message)) + if(self.dmg && (self.message == "")) self.message = "was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message2 == "")) self.message2 = "was squished by"; if (self.sounds > 0) @@ -1631,12 +1696,11 @@ void() fd_secret_move5; void() fd_secret_move6; void() fd_secret_done; -float SECRET_OPEN_ONCE = 1; // stays open -float SECRET_1ST_LEFT = 2; // 1st move is left of arrow -float SECRET_1ST_DOWN = 4; // 1st move is down from arrow -float SECRET_NO_SHOOT = 8; // only opened by trigger -float SECRET_YES_SHOOT = 16; // shootable even if targeted - +const float SECRET_OPEN_ONCE = 1; // stays open +const float SECRET_1ST_LEFT = 2; // 1st move is left of arrow +const float SECRET_1ST_DOWN = 4; // 1st move is down from arrow +const float SECRET_NO_SHOOT = 8; // only opened by trigger +const float SECRET_YES_SHOOT = 16; // shootable even if targeted void fd_secret_use() { @@ -1660,7 +1724,7 @@ void fd_secret_use() // Make a sound, wait a little... if (self.noise1 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM); self.nextthink = self.ltime + 0.1; temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1 @@ -1683,9 +1747,14 @@ void fd_secret_use() self.dest1 = self.origin + v_right * (self.t_width * temp); self.dest2 = self.dest1 + v_forward * self.t_length; - SUB_CalcMove(self.dest1, self.speed, fd_secret_move1); + SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move1); if (self.noise2 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); +} + +void fd_secret_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + fd_secret_use(); } // Wait after first movement... @@ -1694,22 +1763,22 @@ void fd_secret_move1() self.nextthink = self.ltime + 1.0; self.think = fd_secret_move2; if (self.noise3 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM); } // Start moving sideways w/sound... void fd_secret_move2() { if (self.noise2 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); - SUB_CalcMove(self.dest2, self.speed, fd_secret_move3); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); + SUB_CalcMove(self.dest2, TSPEED_LINEAR, self.speed, fd_secret_move3); } // Wait here until time to go back... void fd_secret_move3() { if (self.noise3 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM); if (!(self.spawnflags & SECRET_OPEN_ONCE)) { self.nextthink = self.ltime + self.wait; @@ -1721,8 +1790,8 @@ void fd_secret_move3() void fd_secret_move4() { if (self.noise2 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); - SUB_CalcMove(self.dest1, self.speed, fd_secret_move5); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); + SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move5); } // Wait 1 second... @@ -1731,14 +1800,14 @@ void fd_secret_move5() self.nextthink = self.ltime + 1.0; self.think = fd_secret_move6; if (self.noise3 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM); } void fd_secret_move6() { if (self.noise2 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM); - SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done); + sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); + SUB_CalcMove(self.oldorigin, TSPEED_LINEAR, self.speed, fd_secret_done); } void fd_secret_done() @@ -1750,7 +1819,7 @@ void fd_secret_done() //self.th_pain = fd_secret_use; } if (self.noise3 != "") - sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); + sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM); } void secret_blocked() @@ -1770,7 +1839,7 @@ Prints messages */ void secret_touch() { - if not(other.iscreature) + if (!other.iscreature) return; if (self.attack_finished_single > time) return; @@ -1779,7 +1848,7 @@ void secret_touch() if (self.message) { - if (other.flags & FL_CLIENT) + if (IS_CLIENT(other)) centerprint (other, self.message); play2(other, "misc/talk.wav"); } @@ -1793,7 +1862,8 @@ void secret_reset() self.takedamage = DAMAGE_YES; } setorigin(self, self.oldorigin); - self.think = SUB_Null; + self.think = func_null; + self.nextthink = 0; } /*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot @@ -1825,7 +1895,7 @@ void spawnfunc_func_door_secret() self.mangle = self.angles; self.angles = '0 0 0'; self.classname = "door"; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.effects |= EF_LOWPRECISION; @@ -1843,7 +1913,7 @@ void spawnfunc_func_door_secret() { self.health = 10000; self.takedamage = DAMAGE_YES; - self.event_damage = fd_secret_use; + self.event_damage = fd_secret_damage; } self.oldorigin = self.origin; if (!self.wait) @@ -1870,9 +1940,9 @@ void func_fourier_controller_think() float n, i, t; self.nextthink = time + 0.1; - if not (self.owner.active == ACTIVE_ACTIVE) + if (!(self.owner.active == ACTIVE_ACTIVE)) { - self.owner.velocity = '0 0 0'; + self.owner.velocity = '0 0 0'; return; } @@ -1899,7 +1969,7 @@ void spawnfunc_func_fourier() if (self.noise != "") { precache_sound(self.noise); - soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); + soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE); } if (!self.speed) @@ -1910,9 +1980,9 @@ void spawnfunc_func_fourier() self.cnt = 360 / self.speed; self.blocked = generic_plat_blocked; - if(self.dmg & (!self.message)) + if(self.dmg && (self.message == "")) self.message = " was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message2 == "")) self.message2 = "was squished by"; if(self.dmg && (!self.dmgtime)) self.dmgtime = 0.25; @@ -1921,7 +1991,7 @@ void spawnfunc_func_fourier() if(self.netname == "") self.netname = "1 0 0 0 1"; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.active = ACTIVE_ACTIVE; @@ -1933,7 +2003,7 @@ void spawnfunc_func_fourier() controller.nextthink = time + 1; controller.think = func_fourier_controller_think; self.nextthink = self.ltime + 999999999; - self.think = SUB_Null; + self.think = SUB_NullThink; // for PushMove // Savage: Reduce bandwith, critical on e.g. nexdm02 self.effects |= EF_LOWPRECISION; @@ -2003,9 +2073,9 @@ void func_vectormamamam_controller_think() { self.nextthink = time + 0.1; - if not (self.owner.active == ACTIVE_ACTIVE) + if (!(self.owner.active == ACTIVE_ACTIVE)) { - self.owner.velocity = '0 0 0'; + self.owner.velocity = '0 0 0'; return; } @@ -2030,7 +2100,7 @@ void func_vectormamamam_findtarget() if(!self.wp00 && !self.wp01 && !self.wp02 && !self.wp03) objerror("No reference entity found, so there is nothing to move. Aborting."); - self.destvec = self.origin - func_vectormamamam_origin(self.owner, 0); + self.destvec = self.origin - func_vectormamamam_origin(self, 0); entity controller; controller = spawn(); @@ -2045,7 +2115,7 @@ void spawnfunc_func_vectormamamam() if (self.noise != "") { precache_sound(self.noise); - soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); + soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE); } if(!self.targetfactor) @@ -2073,9 +2143,9 @@ void spawnfunc_func_vectormamamam() self.target4normal = normalize(self.target4normal); self.blocked = generic_plat_blocked; - if(self.dmg & (!self.message)) + if(self.dmg && (self.message == "")) self.message = " was squished"; - if(self.dmg && (!self.message2)) + if(self.dmg && (self.message == "")) self.message2 = "was squished by"; if(self.dmg && (!self.dmgtime)) self.dmgtime = 0.25; @@ -2084,12 +2154,12 @@ void spawnfunc_func_vectormamamam() if(self.netname == "") self.netname = "1 0 0 0 1"; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; // wait for targets to spawn self.nextthink = self.ltime + 999999999; - self.think = SUB_Null; + self.think = SUB_NullThink; // for PushMove // Savage: Reduce bandwith, critical on e.g. nexdm02 self.effects |= EF_LOWPRECISION; @@ -2127,7 +2197,7 @@ void conveyor_think() for(e = world; (e = findentity(e, conveyor, self)); ) { - if(e.flags & FL_CLIENT) // doing it via velocity has quite some advantages + if(IS_CLIENT(e)) // doing it via velocity has quite some advantages continue; // done in SV_PlayerPhysics setorigin(e, e.origin + self.movedir * sys_frametime);