From 069dc42609a4174a5375caa552cb489f7deeee3f Mon Sep 17 00:00:00 2001 From: div0 Date: Thu, 27 Nov 2008 08:06:32 +0000 Subject: [PATCH] breakable: add support for causing damage, and playing a sound seeker: allow following func_breakable assault: fixes git-svn-id: svn://svn.icculus.org/nexuiz/trunk@5113 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/server/arena.qc | 13 +++++++----- data/qcsrc/server/assault.qc | 18 ++++++++-------- data/qcsrc/server/func_breakable.qc | 32 +++++++++++++++++++++++------ data/qcsrc/server/g_damage.qc | 4 ++-- data/qcsrc/server/g_triggers.qc | 9 ++++---- data/qcsrc/server/w_seeker.qc | 9 ++++---- data/scripts/entities.def | 7 +++++++ 7 files changed, 61 insertions(+), 31 deletions(-) diff --git a/data/qcsrc/server/arena.qc b/data/qcsrc/server/arena.qc index affb384ad..972d5d9d2 100644 --- a/data/qcsrc/server/arena.qc +++ b/data/qcsrc/server/arena.qc @@ -126,19 +126,22 @@ void reset_map() { target_assault_roundend_reset(); } - else if(self.classname == "target_assault_roundstart") - { - self.use(); - } } - // Waypoints come LAST (keyhunt keys reference them) + // Waypoints and assault start come LAST for(self = world; (self = nextent(self)); ) + if(clienttype(self) == CLIENTTYPE_NOTACLIENT) + { if(self.classname == "sprite_waypoint") { if(self.health | g_keyhunt) WaypointSprite_Kill(self); } + else if(self.classname == "target_assault_roundstart") + { + self.use(); + } + } // Moving the player reset code here since the player-reset depends // on spawnpoint entities which have to be reset first --blub diff --git a/data/qcsrc/server/assault.qc b/data/qcsrc/server/assault.qc index d8c09c13e..2a6c5f583 100644 --- a/data/qcsrc/server/assault.qc +++ b/data/qcsrc/server/assault.qc @@ -1,7 +1,7 @@ void spawnfunc_func_breakable(); void target_objective_decrease_activate(); .entity assault_decreaser; -.entity sprite; +.entity assault_sprite; void spawnfunc_info_player_attacker() { if(!g_assault) @@ -64,8 +64,10 @@ void assault_objective_decrease_use() { return; } - if(other.sprite.classname == "assault_decreaser_sprite") - WaypointSprite_Disown(other.sprite, waypointsprite_deadlifetime); + if(other.assault_sprite.classname == "assault_decreaser_sprite") + WaypointSprite_Disown(other.assault_sprite, waypointsprite_deadlifetime); + else + return; // already activated! cannot activate again! if(self.enemy.health < ASSAULT_VALUE_INACTIVE) { @@ -129,10 +131,10 @@ void target_objective_decrease_activate() self.owner = world; for(ent = world; (ent = find(ent, target, self.targetname)); ) { - if(ent.sprite != world) - WaypointSprite_Disown(ent.sprite, waypointsprite_deadlifetime); + if(ent.assault_sprite != world) + WaypointSprite_Disown(ent.assault_sprite, waypointsprite_deadlifetime); - spr = WaypointSprite_SpawnFixed("", 0.5 * (ent.absmin + ent.absmax), ent, sprite); + spr = WaypointSprite_SpawnFixed("", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite); spr.assault_decreaser = self; spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible; spr.classname = "assault_decreaser_sprite"; @@ -156,10 +158,6 @@ void spawnfunc_target_objective_decrease() { self.classname = "target_objective_decrease"; - precache_model("models/sprites/defend.sp2"); - precache_model("models/sprites/destroy.sp2"); - precache_model("models/sprites/push.sp2"); - if(!self.dmg) { self.dmg = 101; } diff --git a/data/qcsrc/server/func_breakable.qc b/data/qcsrc/server/func_breakable.qc index f90e6395c..8aaada2e3 100644 --- a/data/qcsrc/server/func_breakable.qc +++ b/data/qcsrc/server/func_breakable.qc @@ -1,6 +1,9 @@ .entity sprite; -// TODO add the fields this uses to the entities.def when done +.float dmg; +.float dmg_edge; +.float dmg_radius; +.float dmg_force; .string mdl_dead; // or "" to hide when broken .string debris; // space separated list of debris models @@ -117,8 +120,16 @@ void func_breakable_restore() void func_breakable_destroy() { float n, i; + activator = self.owner; + func_breakable_destroyed(); + if(self.noise) + sound (self, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM); + + if(self.dmg) + RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, self.dmg_force, DEATH_HURTTRIGGER, world); + // now throw around the debris n = tokenize_sane(self.debris); for(i = 0; i < n; ++i) @@ -140,12 +151,10 @@ void func_breakable_damage(entity inflictor, entity attacker, float damage, floa if(self.sprite) WaypointSprite_Ping(self.sprite); self.health = self.health - damage; - if(self.health < 0) - { - activator = attacker; - func_breakable_destroy(); - } func_breakable_colormod(); + + if(self.health < 0) + W_PrepareExplosionByDamage(attacker, func_breakable_destroy); } void func_breakable_reset() @@ -169,6 +178,15 @@ void spawnfunc_func_breakable() { if(self.count == 0) self.count = 1; + if(!self.message) + self.message = "got too close to an explosion"; + if(!self.message2) + self.message2 = "was pushed into an explosion by"; + if(!self.dmg_radius) + self.dmg_radius = 150; + if(!self.dmg_force) + self.dmg_force = 200; + self.mdl = self.model; SetBrushEntityModel(); self.mins_save = self.mins; @@ -182,6 +200,8 @@ void spawnfunc_func_breakable() { n = tokenize_sane(self.debris); for(i = 0; i < n; ++i) precache_model(argv(i)); + if(self.noise) + precache_sound(self.noise); func_breakable_reset(); } diff --git a/data/qcsrc/server/g_damage.qc b/data/qcsrc/server/g_damage.qc index ccfc1f2d1..681501277 100644 --- a/data/qcsrc/server/g_damage.qc +++ b/data/qcsrc/server/g_damage.qc @@ -432,8 +432,8 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype) else { centerprint(targ, "^1Watch your step!\n\n\n"); - if (deathtype == DEATH_HURTTRIGGER && attacker.message != "") - bprint ("^1",s, "^1 ", attacker.message, "\n"); + if (deathtype == DEATH_HURTTRIGGER && inflictor.message != "") + bprint ("^1",s, "^1 ", inflictor.message, "\n"); else if (deathtype == DEATH_DROWN) if(sv_gentle) bprint ("^1",s, "^1 was in the water for too long\n"); diff --git a/data/qcsrc/server/g_triggers.qc b/data/qcsrc/server/g_triggers.qc index c0a543cbd..4c7e61a0e 100644 --- a/data/qcsrc/server/g_triggers.qc +++ b/data/qcsrc/server/g_triggers.qc @@ -86,16 +86,17 @@ void SUB_UseTargets() switch(i) { default: - case 0: s = self.target; break; - case 1: s = self.target2; break; - case 2: s = self.target3; break; - case 3: s = self.target4; break; + case 0: s = stemp.target; break; + case 1: s = stemp.target2; break; + case 2: s = stemp.target3; break; + case 3: s = stemp.target4; break; } if (s != "") { for(t = world; (t = find(t, targetname, s)); ) if(t.use) { + print(stemp.classname, " ", stemp.targetname, " -> ", t.classname, " ", t.targetname, "\n"); self = t; other = stemp; activator = act; diff --git a/data/qcsrc/server/w_seeker.qc b/data/qcsrc/server/w_seeker.qc index 5f84e8031..463521fae 100644 --- a/data/qcsrc/server/w_seeker.qc +++ b/data/qcsrc/server/w_seeker.qc @@ -33,7 +33,7 @@ void Seeker_Missile_Touch() void Seeker_Missile_Think() { entity e; - vector desireddir, olddir, newdir; + vector desireddir, olddir, newdir, eorg; float turnrate; float dist; @@ -56,10 +56,11 @@ void Seeker_Missile_Think() if (self.enemy != world) { e = self.enemy; + eorg = 0.5 * (e.absmin + e.absmax); turnrate = cvar("g_balance_seeker_missile_turnrate"); // how fast to turn - desireddir = normalize(e.origin - self.origin); + desireddir = normalize(eorg - self.origin); olddir = normalize(self.velocity); // get my current direction - dist = vlen(e.origin - self.origin); + dist = vlen(eorg - self.origin); // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P ) if (cvar("g_balance_seeker_missile_smart") && (dist > cvar("g_balance_seeker_missile_smart_mindist"))) @@ -68,7 +69,7 @@ void Seeker_Missile_Think() if ( vlen(self.origin + olddir * self.wait) < dist) traceline(self.origin, self.origin + olddir * self.wait, FALSE, self); else - traceline(self.origin, self.enemy.origin, FALSE, self); + traceline(self.origin, eorg, FALSE, self); // Setup adaptive tracelength self.wait = vlen(self.origin - trace_endpos); diff --git a/data/scripts/entities.def b/data/scripts/entities.def index 5463915b5..d6ba4dc64 100644 --- a/data/scripts/entities.def +++ b/data/scripts/entities.def @@ -1165,6 +1165,13 @@ mdl: particle effect name to show when destroyed count: particle effect multiplier mdl_dead: optional replacement model to show when destroyed debris: names of debris models to show when destroyed, separated by spaces +noise: sound to play when destroyed +dmg: damage to deal to the environment when destroyed +dmg_edge: edge damage to deal to the environment when destroyed +dmg_radius: damage radius +dmg_force: damage force +message: death message when a player gets hit by the explosion +message2: death message when someone gets pushed into this (default: "was pushed into an explosion by"). The # character is replaced by the attacker name if present (and it instead does not get appended to the end) -------- SPAWNFLAGS -------- DISABLED: do not allow damaging this until it is first activated INDICATE: indicate amount of damage already taken by coloring -- 2.39.2