X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Ft_plats.qc;h=de1243ecbba0ee11ae8c9658ff5310a9b2c5a115;hb=c4e5adb4a6ca7e6af370ec3b8a955eba0920868f;hp=8cb87678223c0c6348c875af14c4d773366997bb;hpb=0822ebd5f8367f4087ccf04129d22519c6ac93ac;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/t_plats.qc b/qcsrc/server/t_plats.qc index 8cb876782..de1243ecb 100644 --- a/qcsrc/server/t_plats.qc +++ b/qcsrc/server/t_plats.qc @@ -31,8 +31,8 @@ float PLAT_LOW_TRIGGER = 1; void plat_spawn_inside_trigger() { - local entity trigger; - local vector tmin, tmax; + entity trigger; + vector tmin, tmax; trigger = spawn(); trigger.touch = plat_center_touch; @@ -57,8 +57,18 @@ void plat_spawn_inside_trigger() tmax_y = tmin_y + 1; } - setsize (trigger, tmin, tmax); -}; + if(tmin_x < tmax_x) + if(tmin_y < tmax_y) + if(tmin_z < tmax_z) + { + setsize (trigger, tmin, tmax); + return; + } + + // otherwise, something is fishy... + remove(trigger); + objerror("plat_spawn_inside_trigger: platform has odd size or lip, can't spawn"); +} void plat_hit_top() { @@ -66,27 +76,27 @@ void plat_hit_top() self.state = 1; self.think = plat_go_down; self.nextthink = self.ltime + 3; -}; +} void plat_hit_bottom() { sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); self.state = 2; -}; +} void plat_go_down() { sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_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); 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() { @@ -101,7 +111,7 @@ void plat_center_touch() plat_go_up (); else if (self.state == 1) self.nextthink = self.ltime + 1; // delay going down -}; +} void plat_outside_touch() { @@ -114,14 +124,14 @@ void plat_outside_touch() self = self.enemy; if (self.state == 1) plat_go_down (); -}; +} void plat_trigger_use() { if (self.think) return; // already activated plat_go_down(); -}; +} void plat_crush() @@ -144,7 +154,7 @@ void plat_crush() // plat state already had changed // this isn't a bug per se! } -}; +} void plat_use() { @@ -152,7 +162,7 @@ void plat_use() if (self.state != 4) objerror ("plat_use: not in up state"); plat_go_down(); -}; +} .string sound1, sound2; @@ -172,14 +182,9 @@ void plat_reset() } } -void spawnfunc_path_corner() { }; +void spawnfunc_path_corner() { } void spawnfunc_func_plat() { - if (!self.t_length) - self.t_length = 80; - if (!self.t_width) - self.t_width = 10; - if (self.sounds == 0) self.sounds = 2; @@ -231,26 +236,51 @@ void spawnfunc_func_plat() if (!self.speed) self.speed = 150; + if (!self.lip) + self.lip = 16; + if (!self.height) + self.height = self.size_z - self.lip; self.pos1 = self.origin; self.pos2 = self.origin; - self.pos2_z = self.origin_z - self.size_z + 8; - - plat_spawn_inside_trigger (); // the "start moving" trigger + self.pos2_z = self.origin_z - self.height; self.reset = plat_reset; plat_reset(); -}; + 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 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 targ; + vector org; + targ = find(world, targetname, self.target); + org = vectoangles(targ.origin); + SUB_CalcAngleMove(org, TSPEED_TIME, self.ltime - time + self.wait, 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 @@ -258,21 +288,24 @@ 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() { - local entity targ; + entity targ, cp; + vector cp_org; + targ = find(world, targetname, self.target); - self.enemy = targ; self.target = targ.target; + if (self.spawnflags & 1) + { + cp = find(world, target, targ.targetname); // get the previous corner first + cp = find(world, targetname, cp.curve); // 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 (!self.target) objerror("train_next: no next target"); self.wait = targ.wait; @@ -280,17 +313,27 @@ void train_next() self.wait = 0.1; if (targ.speed) - SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait); + { + if (self.spawnflags & 1) + SUB_CalcMove_Bezier(cp_org, targ.origin - self.mins, TSPEED_LINEAR, targ.speed, train_wait); + else + SUB_CalcMove(targ.origin - self.mins, TSPEED_LINEAR, targ.speed, train_wait); + } else - SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait); + { + if (self.spawnflags & 1) + SUB_CalcMove_Bezier(cp_org, targ.origin - self.mins, TSPEED_LINEAR, self.speed, train_wait); + else + SUB_CalcMove(targ.origin - self.mins, TSPEED_LINEAR, self.speed, train_wait); + } if(self.noise != "") sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE); -}; +} void func_train_find() { - local entity targ; + entity targ; targ = find(world, targetname, self.target); self.target = targ.target; if (!self.target) @@ -298,7 +341,7 @@ void func_train_find() setorigin(self, targ.origin - self.mins); self.nextthink = self.ltime + 1; self.think = train_next; -}; +} /*QUAKED spawnfunc_func_train (0 .5 .8) ? Ridable platform, targets spawnfunc_path_corner path to follow. @@ -314,6 +357,8 @@ void spawnfunc_func_train() objerror("func_train without a target"); if (!self.speed) self.speed = 100; + if (self.spawnflags & 2) + self.bezier_turn = TRUE; if not(InitMovingBrushTrigger()) return; @@ -332,7 +377,7 @@ void spawnfunc_func_train() self.dmgtime2 = time; // TODO make a reset function for this one -}; +} void func_rotating_setactive(float astate) { @@ -408,12 +453,12 @@ void spawnfunc_func_rotating() self.think = SUB_Null; // TODO make a reset function for this one -}; +} .float height; void func_bobbing_controller_think() { - local vector v; + vector v; self.nextthink = time + 0.1; if not (self.owner.active == ACTIVE_ACTIVE) @@ -428,7 +473,7 @@ void func_bobbing_controller_think() 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; -}; +} /*QUAKED spawnfunc_func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS Brush model that moves back and forth on one axis (default Z). @@ -441,7 +486,7 @@ dmgtime : See above. */ void spawnfunc_func_bobbing() { - local entity controller; + entity controller; if (self.noise != "") { precache_sound(self.noise); @@ -492,12 +537,12 @@ void spawnfunc_func_bobbing() self.effects |= EF_LOWPRECISION; // TODO make a reset function for this one -}; +} .float freq; void func_pendulum_controller_think() { - local float v; + float v; self.nextthink = time + 0.1; if not (self.owner.active == ACTIVE_ACTIVE) @@ -514,11 +559,11 @@ void func_pendulum_controller_think() // * 10 so it will arrive in 0.1 sec self.owner.avelocity_z = (remainder(v - self.owner.angles_z, 360)) * 10; } -}; +} void spawnfunc_func_pendulum() { - local entity controller; + entity controller; if (self.noise != "") { precache_sound(self.noise); @@ -568,7 +613,7 @@ void spawnfunc_func_pendulum() //self.effects |= EF_LOWPRECISION; // TODO make a reset function for this one -}; +} // button and multiple button @@ -583,27 +628,27 @@ void button_wait() activator = self.enemy; SUB_UseTargets(); self.frame = 1; // use alternate textures -}; +} void button_done() { self.state = STATE_BOTTOM; -}; +} 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 -}; +} void button_blocked() { // do nothing, just don't come all the way back out -}; +} void button_fire() @@ -618,8 +663,8 @@ void button_fire() sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_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() { @@ -644,7 +689,7 @@ void button_use() self.enemy = activator; button_fire (); -}; +} void button_touch() { @@ -663,7 +708,7 @@ void button_touch() if (other.owner) self.enemy = other.owner; button_fire (); -}; +} void button_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { @@ -681,7 +726,7 @@ void button_damage(entity inflictor, entity attacker, float damage, float deatht self.enemy = damage_attacker; button_fire (); } -}; +} /*QUAKED spawnfunc_func_button (0 .5 .8) ? @@ -738,7 +783,7 @@ void spawnfunc_func_button() self.flags |= FL_NOTARGET; button_reset(); -}; +} float DOOR_START_OPEN = 1; @@ -820,7 +865,7 @@ void door_blocked() door_go_down (); } */ -}; +} void door_hit_top() @@ -838,14 +883,14 @@ void door_hit_top() self.think = door_rotating_go_down; } self.nextthink = self.ltime + self.wait; -}; +} void door_hit_bottom() { if (self.noise1 != "") sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM); self.state = STATE_BOTTOM; -}; +} void door_go_down() { @@ -858,8 +903,8 @@ 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() { @@ -875,14 +920,14 @@ void door_go_up() if (self.noise2 != "") sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_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; self.message = ""; SUB_UseTargets(); self.message = oldmessage; -}; +} @@ -895,7 +940,7 @@ ACTIVATION FUNCTIONS */ float door_check_keys(void) { - local entity door, p; + local entity door; if (self.owner) @@ -903,58 +948,45 @@ float door_check_keys(void) { else door = self; - if (other.owner) - p = other.owner; - else - p = other; - - if (door.spawnflags & (SPAWNFLAGS_GOLD_KEY | SPAWNFLAGS_SILVER_KEY)) { - // this door require a key - // only a player can have a key - if (p.classname != "player") - return FALSE; - - // check gold key - if (self.owner.spawnflags & SPAWNFLAGS_GOLD_KEY) { - if (!(other.itemkeys & KEYS_GOLD_KEY)) { - if (p.key_door_messagetime <= time) { - play2(other, "misc/talk.wav"); - centerprint(other, "You don't have the gold key!"); - p.key_door_messagetime = time + 2; - } - return FALSE; - } else { - self.owner.spawnflags &~= SPAWNFLAGS_GOLD_KEY; - } + // no key needed + if not(door.itemkeys) + return TRUE; + + // this door require a key + // only a player can have a key + if (other.classname != "player") + 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), "!")); + other.key_door_messagetime = time + 2; } - - // check silver key - if (self.owner.spawnflags & SPAWNFLAGS_SILVER_KEY) { - if (!(other.itemkeys & KEYS_SILVER_KEY)) { - if (p.key_door_messagetime <= time) { - play2(other, "misc/talk.wav"); - centerprint(other, "You don't have the silver key!"); - p.key_door_messagetime = time + 2; - } - return FALSE; - } else { - self.owner.spawnflags &~= SPAWNFLAGS_SILVER_KEY; - } + } 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), "!")); + other.key_door_messagetime = time + 2; } - + } + + if (door.itemkeys) { // door is now unlocked play2(other, "misc/talk.wav"); centerprint(other, "Door unlocked!"); - } - - return TRUE; + return TRUE; + } else + return FALSE; } void door_fire() { - local entity oself; - local entity starte; + entity oself; + entity starte; if (self.owner != self) objerror ("door_fire: self.owner != self"); @@ -1008,12 +1040,12 @@ void door_fire() self = self.enemy; } while ( (self != starte) && (self != world) ); self = oself; -}; +} void door_use() { - local entity oself; + entity oself; //dprint("door_use (model: ");dprint(self.model);dprint(")\n"); @@ -1024,7 +1056,7 @@ void door_use() door_fire (); self = oself; } -}; +} void door_trigger_touch() @@ -1046,18 +1078,18 @@ void door_trigger_touch() self = self.owner; door_use (); -}; +} void door_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { - local entity oself; + entity oself; if(self.spawnflags & DOOR_NOSPLASH) if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH)) return; self.health = self.health - damage; - if (self.spawnflags & SPAWNFLAGS_GOLD_KEY || self.spawnflags & SPAWNFLAGS_SILVER_KEY) { + if (self.itemkeys) { // don't allow opening doors through damage if keys are required return; } @@ -1071,7 +1103,7 @@ void door_damage(entity inflictor, entity attacker, float damage, float deathtyp door_use (); self = oself; } -}; +} /* @@ -1096,7 +1128,7 @@ void door_touch() centerprint (other, self.owner.message); play2(other, "misc/talk.wav"); } -}; +} void door_generic_plat_blocked() @@ -1136,7 +1168,7 @@ void door_generic_plat_blocked() door_rotating_go_down (); } */ -}; +} void door_rotating_hit_top() @@ -1148,7 +1180,7 @@ void door_rotating_hit_top() return; // don't come down automatically self.think = door_rotating_go_down; self.nextthink = self.ltime + self.wait; -}; +} void door_rotating_hit_bottom() { @@ -1160,7 +1192,7 @@ void door_rotating_hit_bottom() self.lip = 0; } self.state = STATE_BOTTOM; -}; +} void door_rotating_go_down() { @@ -1173,8 +1205,8 @@ 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() { @@ -1189,14 +1221,14 @@ void door_rotating_go_up() if (self.noise2 != "") sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_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; self.message = ""; SUB_UseTargets(); self.message = oldmessage; -}; +} @@ -1212,8 +1244,8 @@ SPAWNING FUNCTIONS entity spawn_field(vector fmins, vector fmaxs) { - local entity trigger; - local vector t1, t2; + entity trigger; + vector t1, t2; trigger = spawn(); trigger.classname = "doortriggerfield"; @@ -1226,7 +1258,7 @@ entity spawn_field(vector fmins, vector fmaxs) t2 = fmaxs; setsize (trigger, t1 - '60 60 8', t2 + '60 60 8'); return (trigger); -}; +} float EntitiesTouching(entity e1, entity e2) @@ -1244,7 +1276,7 @@ float EntitiesTouching(entity e1, entity e2) if (e1.absmax_z < e2.absmin_z) return FALSE; return TRUE; -}; +} /* @@ -1256,8 +1288,8 @@ LinkDoors */ void LinkDoors() { - local entity t, starte; - local vector cmins, cmaxs; + entity t, starte; + vector cmins, cmaxs; if (self.enemy) return; // already linked by another door @@ -1338,7 +1370,7 @@ void LinkDoors() } } while (1 ); -}; +} /*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE @@ -1385,12 +1417,17 @@ void door_reset() self.think = SUB_Null; } +// spawnflags require key (for now only func_door) +#define SPAWNFLAGS_GOLD_KEY 8 +#define SPAWNFLAGS_SILVER_KEY 16 void spawnfunc_func_door() { - print("spawnfunc_func_door() spawnflags=", ftos(self.spawnflags)); - print(", gold_key=", ftos(self.spawnflags & SPAWNFLAGS_GOLD_KEY)); - print(", silver_key=", ftos(self.spawnflags & SPAWNFLAGS_SILVER_KEY), "\n"); - + // Quake 1 keys compatibility + if (self.spawnflags & SPAWNFLAGS_GOLD_KEY) + 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 (); @@ -1454,7 +1491,7 @@ void spawnfunc_func_door() InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS); self.reset = door_reset; -}; +} /*QUAKED spawnfunc_func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN x TOGGLE X_AXIS Y_AXIS if two doors touch, they are assumed to be connected and operate as a unit. @@ -1578,7 +1615,7 @@ void spawnfunc_func_door_rotating() InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS); self.reset = door_rotating_reset; -}; +} /* ============================================================================= @@ -1605,7 +1642,7 @@ float SECRET_YES_SHOOT = 16; // shootable even if targeted void fd_secret_use() { - local float temp; + float temp; string message_save; self.health = 10000; @@ -1648,10 +1685,10 @@ 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); -}; +} // Wait after first movement... void fd_secret_move1() @@ -1660,15 +1697,15 @@ void fd_secret_move1() self.think = fd_secret_move2; if (self.noise3 != "") sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_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); -}; + SUB_CalcMove(self.dest2, TSPEED_LINEAR, self.speed, fd_secret_move3); +} // Wait here until time to go back... void fd_secret_move3() @@ -1680,15 +1717,15 @@ void fd_secret_move3() self.nextthink = self.ltime + self.wait; self.think = fd_secret_move4; } -}; +} // Move backward... 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); -}; + SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move5); +} // Wait 1 second... void fd_secret_move5() @@ -1697,14 +1734,14 @@ void fd_secret_move5() self.think = fd_secret_move6; if (self.noise3 != "") sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_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); -}; + SUB_CalcMove(self.oldorigin, TSPEED_LINEAR, self.speed, fd_secret_done); +} void fd_secret_done() { @@ -1716,7 +1753,7 @@ void fd_secret_done() } if (self.noise3 != "") sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); -}; +} void secret_blocked() { @@ -1724,7 +1761,7 @@ void secret_blocked() return; self.attack_finished_single = time + 0.5; //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic); -}; +} /* ============== @@ -1748,7 +1785,7 @@ void secret_touch() centerprint (other, self.message); play2(other, "misc/talk.wav"); } -}; +} void secret_reset() { @@ -1816,7 +1853,7 @@ void spawnfunc_func_door_secret() self.reset = secret_reset; secret_reset(); -}; +} /*QUAKED spawnfunc_func_fourier (0 .5 .8) ? Brush model that moves in a pattern of added up sine waves, can be used e.g. for circular motions. @@ -1831,7 +1868,7 @@ dmgtime: See above. void func_fourier_controller_think() { - local vector v; + vector v; float n, i, t; self.nextthink = time + 0.1; @@ -1856,11 +1893,11 @@ void func_fourier_controller_think() if(self.owner.classname == "func_fourier") // don't brake stuff if the func_fourier was killtarget'ed // * 10 so it will arrive in 0.1 sec self.owner.velocity = (v - self.owner.origin) * 10; -}; +} void spawnfunc_func_fourier() { - local entity controller; + entity controller; if (self.noise != "") { precache_sound(self.noise); @@ -1904,7 +1941,7 @@ void spawnfunc_func_fourier() self.effects |= EF_LOWPRECISION; // TODO make a reset function for this one -}; +} // reusing some fields havocbots declared .entity wp00, wp01, wp02, wp03; @@ -1997,7 +2034,7 @@ void func_vectormamamam_findtarget() self.destvec = self.origin - func_vectormamamam_origin(self.owner, 0); - local entity controller; + entity controller; controller = spawn(); controller.classname = "func_vectormamamam_controller"; controller.owner = self; @@ -2063,3 +2100,91 @@ void spawnfunc_func_vectormamamam() InitializeEntity(self, func_vectormamamam_findtarget, INITPRIO_FINDTARGET); } + +void conveyor_think() +{ + entity e; + + // set myself as current conveyor where possible + for(e = world; (e = findentity(e, conveyor, self)); ) + e.conveyor = world; + + if(self.state) + { + for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain) + if(!e.conveyor.state) + if(isPushable(e)) + { + vector emin = e.absmin; + vector emax = e.absmax; + if(self.solid == SOLID_BSP) + { + emin -= '1 1 1'; + emax += '1 1 1'; + } + if(boxesoverlap(emin, emax, self.absmin, self.absmax)) // quick + if(WarpZoneLib_BoxTouchesBrush(emin, emax, self, e)) // accurate + e.conveyor = self; + } + + for(e = world; (e = findentity(e, conveyor, self)); ) + { + if(e.flags & FL_CLIENT) // doing it via velocity has quite some advantages + continue; // done in SV_PlayerPhysics + + setorigin(e, e.origin + self.movedir * sys_frametime); + move_out_of_solid(e); + UpdateCSQCProjectile(e); + /* + // stupid conveyor code + tracebox(e.origin, e.mins, e.maxs, e.origin + self.movedir * sys_frametime, MOVE_NORMAL, e); + if(trace_fraction > 0) + setorigin(e, trace_endpos); + */ + } + } + + self.nextthink = time; +} + +void conveyor_use() +{ + self.state = !self.state; +} + +void conveyor_reset() +{ + self.state = (self.spawnflags & 1); +} + +void conveyor_init() +{ + if (!self.speed) + self.speed = 200; + self.movedir = self.movedir * self.speed; + self.think = conveyor_think; + self.nextthink = time; + IFTARGETED + { + self.use = conveyor_use; + self.reset = conveyor_reset; + conveyor_reset(); + } + else + self.state = 1; +} + +void spawnfunc_trigger_conveyor() +{ + SetMovedir(); + EXACTTRIGGER_INIT; + conveyor_init(); +} + +void spawnfunc_func_conveyor() +{ + SetMovedir(); + InitMovingBrushTrigger(); + self.movetype = MOVETYPE_NONE; + conveyor_init(); +}