X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Ft_plats.qc;h=fc31ad50ce3332d9027b557e0904aad1a01b8451;hb=cc12a5558fc68f65a18176eb88047ba4d64f61cc;hp=25a25cdd1b1cee8a19db00f097697750cf3a6a6c;hpb=2a396193296cf0b109fb33e7106ac6f4e1e0b799;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/t_plats.qc b/qcsrc/server/t_plats.qc index 25a25cdd1..fc31ad50c 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; @@ -58,7 +58,7 @@ void plat_spawn_inside_trigger() } setsize (trigger, tmin, tmax); -}; +} void plat_hit_top() { @@ -66,27 +66,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); -}; +} 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); -}; +} void plat_center_touch() { @@ -101,7 +101,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 +114,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 +144,7 @@ void plat_crush() // plat state already had changed // this isn't a bug per se! } -}; +} void plat_use() { @@ -152,7 +152,7 @@ void plat_use() if (self.state != 4) objerror ("plat_use: not in up state"); plat_go_down(); -}; +} .string sound1, sound2; @@ -172,14 +172,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,16 +226,20 @@ 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; + self.pos2_z = self.origin_z - self.height; plat_spawn_inside_trigger (); // the "start moving" trigger self.reset = plat_reset; plat_reset(); -}; +} void() train_next; @@ -265,11 +264,11 @@ void train_wait() SUB_UseTargets(); self = oldself; self.enemy = world; -}; +} void train_next() { - local entity targ; + entity targ; targ = find(world, targetname, self.target); self.enemy = targ; self.target = targ.target; @@ -286,11 +285,11 @@ void train_next() 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 +297,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. @@ -332,7 +331,7 @@ void spawnfunc_func_train() self.dmgtime2 = time; // TODO make a reset function for this one -}; +} void func_rotating_setactive(float astate) { @@ -408,12 +407,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 +427,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 +440,7 @@ dmgtime : See above. */ void spawnfunc_func_bobbing() { - local entity controller; + entity controller; if (self.noise != "") { precache_sound(self.noise); @@ -492,12 +491,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 +513,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 +567,7 @@ void spawnfunc_func_pendulum() //self.effects |= EF_LOWPRECISION; // TODO make a reset function for this one -}; +} // button and multiple button @@ -583,12 +582,12 @@ void button_wait() activator = self.enemy; SUB_UseTargets(); self.frame = 1; // use alternate textures -}; +} void button_done() { self.state = STATE_BOTTOM; -}; +} void button_return() { @@ -597,13 +596,13 @@ void button_return() 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() @@ -619,7 +618,7 @@ void button_fire() self.state = STATE_UP; SUB_CalcMove (self.pos2, self.speed, button_wait); -}; +} void button_reset() { @@ -644,7 +643,7 @@ void button_use() self.enemy = activator; button_fire (); -}; +} void button_touch() { @@ -663,7 +662,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 +680,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 +737,7 @@ void spawnfunc_func_button() self.flags |= FL_NOTARGET; button_reset(); -}; +} float DOOR_START_OPEN = 1; @@ -820,7 +819,7 @@ void door_blocked() door_go_down (); } */ -}; +} void door_hit_top() @@ -838,14 +837,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() { @@ -859,7 +858,7 @@ void door_go_down() self.state = STATE_DOWN; SUB_CalcMove (self.pos1, self.speed, door_hit_bottom); -}; +} void door_go_up() { @@ -882,7 +881,8 @@ void door_go_up() self.message = ""; SUB_UseTargets(); self.message = oldmessage; -}; +} + /* @@ -893,10 +893,54 @@ 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) + 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; + } + } 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; + } 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"); @@ -950,14 +994,15 @@ 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"); + if (self.owner) { oself = self; @@ -965,7 +1010,7 @@ void door_use() door_fire (); self = oself; } -}; +} void door_trigger_touch() @@ -977,26 +1022,9 @@ void door_trigger_touch() if (time < self.attack_finished_single) return; - if (self.spawnflags & (SPAWNFLAGS_GOLD_KEY | SPAWNFLAGS_SILVER_KEY)) { - // this door require a key - // only a player can have a key - if (other.classname != "player") - return; - - // check gold key - if (self.spawnflags & SPAWNFLAGS_GOLD_KEY) - if (!(other.itemkeys & KEYS_GOLD_KEY)) { - centerprint(other, "You don't have the gold key"); - return; - } - - // check silver key - if (self.spawnflags & SPAWNFLAGS_SILVER_KEY) - if (!(other.itemkeys & KEYS_SILVER_KEY)) { - centerprint(other, "You don't have the silver key"); - return; - } - } + // check if door is locked + if (!door_check_keys()) + return; self.attack_finished_single = time + 1; @@ -1004,18 +1032,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; } @@ -1029,7 +1057,7 @@ void door_damage(entity inflictor, entity attacker, float damage, float deathtyp door_use (); self = oself; } -}; +} /* @@ -1054,7 +1082,7 @@ void door_touch() centerprint (other, self.owner.message); play2(other, "misc/talk.wav"); } -}; +} void door_generic_plat_blocked() @@ -1094,7 +1122,7 @@ void door_generic_plat_blocked() door_rotating_go_down (); } */ -}; +} void door_rotating_hit_top() @@ -1106,7 +1134,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() { @@ -1118,7 +1146,7 @@ void door_rotating_hit_bottom() self.lip = 0; } self.state = STATE_BOTTOM; -}; +} void door_rotating_go_down() { @@ -1132,7 +1160,7 @@ void door_rotating_go_down() self.state = STATE_DOWN; SUB_CalcAngleMove (self.pos1, self.speed, door_rotating_hit_bottom); -}; +} void door_rotating_go_up() { @@ -1154,7 +1182,7 @@ void door_rotating_go_up() self.message = ""; SUB_UseTargets(); self.message = oldmessage; -}; +} @@ -1170,8 +1198,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"; @@ -1184,7 +1212,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) @@ -1202,7 +1230,7 @@ float EntitiesTouching(entity e1, entity e2) if (e1.absmax_z < e2.absmin_z) return FALSE; return TRUE; -}; +} /* @@ -1214,8 +1242,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 @@ -1296,7 +1324,7 @@ void LinkDoors() } } while (1 ); -}; +} /*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE @@ -1343,8 +1371,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() { + // 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 (); @@ -1358,8 +1395,9 @@ void spawnfunc_func_door() self.blocked = door_blocked; self.use = door_use; - if(self.spawnflags & 8) - self.dmg = 10000; + // FIXME: undocumented flag 8, originally (Q1) GOLD_KEY + // if(self.spawnflags & 8) + // self.dmg = 10000; if(self.dmg && (!self.message)) self.message = "was squished"; @@ -1407,7 +1445,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. @@ -1531,7 +1569,7 @@ void spawnfunc_func_door_rotating() InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS); self.reset = door_rotating_reset; -}; +} /* ============================================================================= @@ -1558,7 +1596,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; @@ -1604,7 +1642,7 @@ void fd_secret_use() SUB_CalcMove(self.dest1, 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() @@ -1613,7 +1651,7 @@ 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() @@ -1621,7 +1659,7 @@ 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); -}; +} // Wait here until time to go back... void fd_secret_move3() @@ -1633,7 +1671,7 @@ void fd_secret_move3() self.nextthink = self.ltime + self.wait; self.think = fd_secret_move4; } -}; +} // Move backward... void fd_secret_move4() @@ -1641,7 +1679,7 @@ 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); -}; +} // Wait 1 second... void fd_secret_move5() @@ -1650,14 +1688,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); -}; +} void fd_secret_done() { @@ -1669,7 +1707,7 @@ void fd_secret_done() } if (self.noise3 != "") sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM); -}; +} void secret_blocked() { @@ -1677,7 +1715,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); -}; +} /* ============== @@ -1701,7 +1739,7 @@ void secret_touch() centerprint (other, self.message); play2(other, "misc/talk.wav"); } -}; +} void secret_reset() { @@ -1769,7 +1807,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. @@ -1784,7 +1822,7 @@ dmgtime: See above. void func_fourier_controller_think() { - local vector v; + vector v; float n, i, t; self.nextthink = time + 0.1; @@ -1809,11 +1847,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); @@ -1857,7 +1895,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; @@ -1950,7 +1988,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; @@ -2016,3 +2054,85 @@ 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); e; e = e.chain) + if(!e.conveyor.state) + if(e.movetype != MOVETYPE_NONE) + { + 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 + + // 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() +{ + EXACTTRIGGER_INIT; + conveyor_init(); +} + +void spawnfunc_func_conveyor() +{ + SetMovedir(); + InitMovingBrushTrigger(); + self.movetype = MOVETYPE_NONE; + conveyor_init(); +}