X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Ft_plats.qc;h=29e57e49783406db480202b2b321c9412cd6b24e;hb=a6a3b0cebd6928e3678ee4e97de4093f1b61c58b;hp=24da476d72bad18cb5d19089a883492b98d392c5;hpb=39380aa9e45dbc545f5fe241c0002ce65a6f635e;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/t_plats.qc b/qcsrc/server/t_plats.qc index 24da476d7..29e57e497 100644 --- a/qcsrc/server/t_plats.qc +++ b/qcsrc/server/t_plats.qc @@ -83,19 +83,19 @@ void plat_go_down() { 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, 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) @@ -110,7 +110,7 @@ void plat_center_touch() void plat_outside_touch() { - if not(other.iscreature) + if (!other.iscreature) return; if (other.health <= 0) @@ -177,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) @@ -222,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); @@ -246,15 +282,49 @@ void spawnfunc_func_plat() plat_spawn_inside_trigger (); // the "start moving" trigger } - +.float train_wait_turning; void() train_next; void train_wait() { + 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, cp; + vector ang; + targ = find(world, targetname, self.target); + 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; + } + 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 @@ -262,31 +332,56 @@ 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; } void train_next() { - entity targ; + entity targ, cp = world; + vector cp_org = '0 0 0'; + targ = find(world, targetname, self.target); - self.enemy = targ; self.target = targ.target; + if (self.spawnflags & 1) + { + 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 == "") 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) - SUB_CalcMove(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.view_ofs, TSPEED_LINEAR, targ.speed, train_wait); + } else - SUB_CalcMove(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.view_ofs, TSPEED_LINEAR, self.speed, train_wait); + } if(self.noise != "") sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE); @@ -299,7 +394,7 @@ void func_train_find() self.target = targ.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; } @@ -319,9 +414,17 @@ void spawnfunc_func_train() if (!self.speed) self.speed = 100; - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.effects |= EF_LOWPRECISION; + + if (self.spawnflags & 2) + { + 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; // wait for targets to spawn InitializeEntity(self, func_train_find, INITPRIO_SETLOCATION); @@ -335,14 +438,19 @@ void spawnfunc_func_train() 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 @@ -350,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; @@ -372,10 +480,10 @@ void spawnfunc_func_rotating() precache_sound(self.noise); 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) @@ -387,9 +495,9 @@ 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 == "")) self.message = " was squished"; if(self.dmg && (self.message2 == "")) @@ -401,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 @@ -419,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; @@ -480,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 @@ -504,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; @@ -548,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) @@ -597,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 @@ -622,7 +730,7 @@ void button_fire() 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() @@ -637,7 +745,7 @@ void button_reset() void button_use() { - if not (self.active == ACTIVE_ACTIVE) + if(self.active != ACTIVE_ACTIVE) return; self.enemy = activator; @@ -648,7 +756,7 @@ void button_touch() { if (!other) return; - if not(other.iscreature) + if (!other.iscreature) return; if(other.velocity * self.movedir < 0) return; @@ -680,7 +788,7 @@ When a button is touched, it moves some distance in the direction of it's angle, "speed" override the default 40 speed "wait" override the default 1 second wait (-1 = never return) "lip" override the default 4 pixel lip remaining at end of move -"health" if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the MinstaGib laser +"health" if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the InstaGib laser "sounds" 0) steam metal 1) wooden clunk @@ -691,7 +799,7 @@ void spawnfunc_func_button() { SetMovedir (); - if not(InitMovingBrushTrigger()) + if (!InitMovingBrushTrigger()) return; self.effects |= EF_LOWPRECISION; @@ -846,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() @@ -863,7 +971,7 @@ void door_go_up() if (self.noise2 != "") 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; @@ -884,34 +992,34 @@ 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 not(IS_PLAYER(other)) + if (!IS_PLAYER(other)) return FALSE; - + if (item_keys_usekey(door, other)) { // some keys were used if (other.key_door_messagetime <= time) { play2(other, "misc/talk.wav"); - centerprint(other, strcat("You also need ", item_keys_keylist(door.itemkeys), "!")); + Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(door.itemkeys)); other.key_door_messagetime = time + 2; } } else { // no keys were used if (other.key_door_messagetime <= time) { play2(other, "misc/talk.wav"); - centerprint(other, strcat("You need ", item_keys_keylist(door.itemkeys), "!")); + Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(door.itemkeys)); other.key_door_messagetime = time + 2; } } @@ -919,7 +1027,7 @@ float door_check_keys(void) { if (door.itemkeys) { // door is now unlocked play2(other, "misc/talk.wav"); - centerprint(other, "Door unlocked!"); + Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_UNLOCKED); return TRUE; } else return FALSE; @@ -991,7 +1099,7 @@ void door_use() entity oself; //dprint("door_use (model: ");dprint(self.model);dprint(")\n"); - + if (self.owner) { oself = self; @@ -1005,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; @@ -1031,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; @@ -1058,7 +1166,7 @@ Prints messages */ void door_touch() { - if not(IS_PLAYER(other)) + if (!IS_PLAYER(other)) return; if (self.owner.attack_finished_single > time) return; @@ -1068,7 +1176,7 @@ void door_touch() if (!(self.owner.dmg) && (self.owner.message != "")) { if (IS_CLIENT(other)) - centerprint (other, self.owner.message); + centerprint(other, self.message); play2(other, "misc/talk.wav"); } } @@ -1148,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() @@ -1164,7 +1272,7 @@ void door_rotating_go_up() if (self.noise2 != "") 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; @@ -1381,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"; @@ -1513,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; @@ -1639,7 +1747,7 @@ 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, ATTEN_NORM); } @@ -1663,7 +1771,7 @@ void fd_secret_move2() { if (self.noise2 != "") sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); - SUB_CalcMove(self.dest2, self.speed, fd_secret_move3); + SUB_CalcMove(self.dest2, TSPEED_LINEAR, self.speed, fd_secret_move3); } // Wait here until time to go back... @@ -1683,7 +1791,7 @@ void fd_secret_move4() { if (self.noise2 != "") sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); - SUB_CalcMove(self.dest1, self.speed, fd_secret_move5); + SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move5); } // Wait 1 second... @@ -1699,7 +1807,7 @@ void fd_secret_move6() { if (self.noise2 != "") sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM); - SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done); + SUB_CalcMove(self.oldorigin, TSPEED_LINEAR, self.speed, fd_secret_done); } void fd_secret_done() @@ -1731,7 +1839,7 @@ Prints messages */ void secret_touch() { - if not(other.iscreature) + if (!other.iscreature) return; if (self.attack_finished_single > time) return; @@ -1741,7 +1849,7 @@ void secret_touch() if (self.message) { if (IS_CLIENT(other)) - centerprint (other, self.message); + centerprint(other, self.message); play2(other, "misc/talk.wav"); } } @@ -1787,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; @@ -1832,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; } @@ -1883,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; @@ -1965,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; } @@ -2046,7 +2154,7 @@ 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