From: Mario Date: Sun, 8 May 2016 18:29:54 +0000 (+1000) Subject: New nade type: Entrap (spawns a large orb for 10 seconds that slows down any enemies... X-Git-Tag: xonotic-v0.8.2~807^2~12 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=6b2d411ca49447dd972c6ae84b9b16818366930d;p=xonotic%2Fxonotic-data.pk3dir.git New nade type: Entrap (spawns a large orb for 10 seconds that slows down any enemies that enter it) --- diff --git a/gfx/hud/default/nade_entrap.tga b/gfx/hud/default/nade_entrap.tga new file mode 100644 index 000000000..358dc1a1f Binary files /dev/null and b/gfx/hud/default/nade_entrap.tga differ diff --git a/gfx/hud/luma/nade_entrap.tga b/gfx/hud/luma/nade_entrap.tga new file mode 100644 index 000000000..27287ad3f Binary files /dev/null and b/gfx/hud/luma/nade_entrap.tga differ diff --git a/models/ctf/orb.md3_0.skin b/models/ctf/orb.md3_0.skin new file mode 100644 index 000000000..89de3595c --- /dev/null +++ b/models/ctf/orb.md3_0.skin @@ -0,0 +1 @@ +ons_shield,nade_orb diff --git a/models/nades/orb.md3 b/models/nades/orb.md3 new file mode 100644 index 000000000..22d7bcc42 Binary files /dev/null and b/models/nades/orb.md3 differ diff --git a/models/nades/orb.md3_0.skin b/models/nades/orb.md3_0.skin new file mode 100644 index 000000000..bfeddf2f8 --- /dev/null +++ b/models/nades/orb.md3_0.skin @@ -0,0 +1 @@ +shield,nade_orb diff --git a/mutators.cfg b/mutators.cfg index 0f4966542..307837932 100644 --- a/mutators.cfg +++ b/mutators.cfg @@ -267,6 +267,12 @@ set g_nades_heal_foe -2 "Multiplier of health given to enemies" set g_nades_pokenade_monster_lifetime 150 "How long pokenade monster will survive" set g_nades_pokenade_monster_type "zombie" "Monster to spawn" +// Entrap (8) +set g_nades_entrap_strength 0.01 "Strength of the orb's movement slowing powers" +set g_nades_entrap_speed 0.5 "Running speed while entrapped" +set g_nades_entrap_time 10 "Life time of the orb" +set g_nades_entrap_radius 500 + // ============ // camp check diff --git a/qcsrc/common/models/all.inc b/qcsrc/common/models/all.inc index 08aeaaeb7..e2a278eb3 100644 --- a/qcsrc/common/models/all.inc +++ b/qcsrc/common/models/all.inc @@ -125,7 +125,7 @@ MODEL(PROJECTILE_ROCKETMINSTA_LASER, "models/elaser.mdl"); MODEL(PROJECTILE_NADE, W_Model("v_ok_grenade.md3")); MODEL(NADE_VIEW, W_Model("h_ok_grenade.iqm")); MODEL(NADE_TIMER, "models/ok_nade_counter/ok_nade_counter.md3"); -MODEL(NADE_HEAL, "models/ctf/shield.md3"); +MODEL(NADE_ORB, "models/nades/orb.md3"); MODEL(GIB_CHUNK, "models/gibs/chunk.mdl"); MODEL(GIB_LEG1, "models/gibs/leg1.md3"); diff --git a/qcsrc/common/mutators/mutator/nades/nades.inc b/qcsrc/common/mutators/mutator/nades/nades.inc index d2f350c5f..8a7337f61 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.inc +++ b/qcsrc/common/mutators/mutator/nades/nades.inc @@ -60,3 +60,11 @@ REGISTER_NADE(MONSTER) { NADE_PROJECTILE(0, PROJECTILE_NADE_MONSTER, EFFECT_NADE_TRAIL_RED); NADE_PROJECTILE(1, PROJECTILE_NADE_MONSTER_BURN, EFFECT_NADE_TRAIL_BURN_RED); } + +REGISTER_NADE(ENTRAP) { + this.m_color = '0.15 0.85 0'; + this.m_name = _("Entrap grenade"); + this.m_icon = "nade_entrap"; + NADE_PROJECTILE(0, PROJECTILE_NADE_ENTRAP, EFFECT_NADE_TRAIL_YELLOW); + NADE_PROJECTILE(1, PROJECTILE_NADE_ENTRAP_BURN, EFFECT_NADE_TRAIL_BURN_YELLOW); +} diff --git a/qcsrc/common/mutators/mutator/nades/nades.qc b/qcsrc/common/mutators/mutator/nades/nades.qc index cabfd31b8..ab4e2bc6d 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.qc +++ b/qcsrc/common/mutators/mutator/nades/nades.qc @@ -38,10 +38,19 @@ entity Nade_TrailEffect(int proj, int nade_team) REGISTER_MUTATOR(cl_nades, true); MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay) { - if (STAT(HEALING_ORB) <= time) return false; - MUTATOR_ARGV(0, vector) = NADE_TYPE_HEAL.m_color; - MUTATOR_ARGV(0, float) = STAT(HEALING_ORB_ALPHA); - return true; + if (STAT(HEALING_ORB) > time) + { + MUTATOR_ARGV(0, vector) = NADE_TYPE_HEAL.m_color; + MUTATOR_ARGV(0, float) = STAT(HEALING_ORB_ALPHA); + return true; + } + if (STAT(ENTRAP_ORB) > time) + { + MUTATOR_ARGV(0, vector) = NADE_TYPE_ENTRAP.m_color; + MUTATOR_ARGV(0, float) = STAT(ENTRAP_ORB_ALPHA); + return true; + } + return false; } MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile) { @@ -502,23 +511,91 @@ void nade_spawn_boom() self.realowner.nade_spawnloc = spawnloc; } -void nade_heal_think() +void nades_orb_think() {SELFPARAM(); - if(time >= self.ltime) + if(time >= this.ltime) { - remove(self); + remove(this); return; } - self.nextthink = time; + this.nextthink = time; - if(time >= self.nade_special_time) + if(time >= this.nade_special_time) { - self.nade_special_time = time+0.25; - self.nade_show_particles = 1; + this.nade_special_time = time+0.25; + this.nade_show_particles = 1; } else - self.nade_show_particles = 0; + this.nade_show_particles = 0; +} + +entity nades_spawn_orb(entity own, entity realown, vector org, float orb_ltime, float orb_rad) +{ + // NOTE: this function merely places an orb + // you must add a custom touch function to the returned entity if desired + // also set .colormod if you wish to have it colorized + entity orb = spawn(); // Net_LinkEntity sets the classname (TODO) + orb.owner = own; + orb.realowner = realown; + setorigin(orb, org); + + orb.orb_lifetime = orb_ltime; // required for timers + orb.ltime = time + orb.orb_lifetime; + orb.bot_dodge = false; + orb.team = realown.team; + orb.solid = SOLID_TRIGGER; + + setmodel(orb, MDL_NADE_ORB); + orb.orb_radius = orb_rad; // required for fading + vector size = '1 1 1' * orb.orb_radius / 2; + setsize(orb, -size, size); + + Net_LinkEntity(orb, true, 0, orb_send); + orb.SendFlags |= 1; + + orb.think = nades_orb_think; + orb.nextthink = time; + + return orb; +} + +void nade_entrap_touch() +{SELFPARAM(); + if(DIFF_TEAM(other, self.realowner)) // TODO: what if realowner changes team or disconnects? + { + if (!isPushable(other)) + return; + + float pushdeltatime = time - other.lastpushtime; + if (pushdeltatime > 0.15) pushdeltatime = 0; + other.lastpushtime = time; + if(!pushdeltatime) return; + + // div0: ticrate independent, 1 = identity (not 20) +#ifdef SVQC + other.velocity = other.velocity * pow(autocvar_g_nades_entrap_strength, pushdeltatime); + + UpdateCSQCProjectile(other); +#elif defined(CSQC) + other.move_velocity = other.move_velocity * pow(autocvar_g_nades_entrap_strength, pushdeltatime); +#endif + + if ( IS_REAL_CLIENT(other) || IS_VEHICLE(other) ) + { + entity show_tint = (IS_VEHICLE(other)) ? other.owner : other; + STAT(ENTRAP_ORB, show_tint) = time + 0.1; + STAT(ENTRAP_ORB_ALPHA, show_tint) = 0.75 * (self.ltime - time) / self.orb_lifetime; + } + } +} + +void nade_entrap_boom(entity this) +{ + entity healer = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_entrap_time, autocvar_g_nades_entrap_radius); + + healer.touch = nade_entrap_touch; + healer.colormod = NADE_TYPE_ENTRAP.m_color; } void nade_heal_touch() @@ -559,34 +636,16 @@ void nade_heal_touch() { entity show_red = (IS_VEHICLE(other)) ? other.owner : other; show_red.stat_healing_orb = time+0.1; - show_red.stat_healing_orb_alpha = 0.75 * (self.ltime - time) / self.healer_lifetime; + show_red.stat_healing_orb_alpha = 0.75 * (self.ltime - time) / self.orb_lifetime; } } -void nade_heal_boom() -{SELFPARAM(); - entity healer; - healer = spawn(); - healer.owner = self.owner; - healer.realowner = self.realowner; - setorigin(healer, self.origin); - healer.healer_lifetime = autocvar_g_nades_heal_time; // save the cvar - healer.ltime = time + healer.healer_lifetime; - healer.team = self.realowner.team; - healer.bot_dodge = false; - healer.solid = SOLID_TRIGGER; - healer.touch = nade_heal_touch; - - setmodel(healer, MDL_NADE_HEAL); - healer.healer_radius = autocvar_g_nades_nade_radius; - vector size = '1 1 1' * healer.healer_radius / 2; - setsize(healer,-size,size); - - Net_LinkEntity(healer, true, 0, healer_send); +void nade_heal_boom(entity this) +{ + entity healer = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_heal_time, autocvar_g_nades_nade_radius); - healer.think = nade_heal_think; - healer.nextthink = time; - healer.SendFlags |= 1; + healer.touch = nade_heal_touch; + healer.colormod = '1 0 0'; } void nade_monster_boom() @@ -633,6 +692,11 @@ void nade_boom() expef = EFFECT_SPAWN_RED; break; + case NADE_TYPE_ENTRAP: + nade_blast = false; + expef = EFFECT_SPAWN_YELLOW; + break; + default: case NADE_TYPE_NORMAL: expef = EFFECT_NADE_EXPLODE(self.realowner.team); @@ -661,8 +725,9 @@ void nade_boom() case NADE_TYPE_ICE: nade_ice_boom(); break; case NADE_TYPE_TRANSLOCATE: nade_translocate_boom(); break; case NADE_TYPE_SPAWN: nade_spawn_boom(); break; - case NADE_TYPE_HEAL: nade_heal_boom(); break; + case NADE_TYPE_HEAL: nade_heal_boom(self); break; case NADE_TYPE_MONSTER: nade_monster_boom(); break; + case NADE_TYPE_ENTRAP: nade_entrap_boom(self); break; } FOREACH_ENTITY_ENT(aiment, self, @@ -1234,6 +1299,16 @@ MUTATOR_HOOKFUNCTION(nades, PlayerPreThink) return false; } +MUTATOR_HOOKFUNCTION(nades, PlayerPhysics) +{SELFPARAM(); + if (STAT(ENTRAP_ORB, this) > time) + { + this.stat_sv_maxspeed *= autocvar_g_nades_entrap_speed; + this.stat_sv_airspeedlimit_nonqw *= autocvar_g_nades_entrap_speed; + } + return false; +} + MUTATOR_HOOKFUNCTION(nades, PlayerSpawn) {SELFPARAM(); if(autocvar_g_nades_spawn) @@ -1355,6 +1430,8 @@ MUTATOR_HOOKFUNCTION(nades, SpectateCopy) self.bonus_nade_score = other.bonus_nade_score; self.stat_healing_orb = other.stat_healing_orb; self.stat_healing_orb_alpha = other.stat_healing_orb_alpha; + STAT(ENTRAP_ORB, this) = STAT(ENTRAP_ORB, other); + STAT(ENTRAP_ORB_ALPHA, this) = STAT(ENTRAP_ORB_ALPHA, other); return false; } diff --git a/qcsrc/common/mutators/mutator/nades/nades.qh b/qcsrc/common/mutators/mutator/nades/nades.qh index da80327bb..2df711316 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.qh +++ b/qcsrc/common/mutators/mutator/nades/nades.qh @@ -17,6 +17,8 @@ const int PROJECTILE_NADE_HEAL = 80; const int PROJECTILE_NADE_HEAL_BURN = 81; const int PROJECTILE_NADE_MONSTER = 82; const int PROJECTILE_NADE_MONSTER_BURN = 83; +const int PROJECTILE_NADE_ENTRAP = 84; +const int PROJECTILE_NADE_ENTRAP_BURN = 85; REGISTRY(Nades, BITS(4)) #define Nades_from(i) _Nades_from(i, NADE_TYPE_Null) @@ -56,8 +58,8 @@ Nade Nade_FromProjectile(int proj) #include "nades.inc" -.float healer_lifetime; -.float healer_radius; +.float orb_lifetime; +.float orb_radius; #ifdef SVQC @@ -78,7 +80,7 @@ Nade Nade_FromProjectile(int proj) .float stat_healing_orb_alpha = _STAT(HEALING_ORB_ALPHA); .float nade_show_particles; -bool healer_send(entity this, entity to, int sf); +bool orb_send(entity this, entity to, int sf); // Remove nades that are being thrown void nades_Clear(entity player); diff --git a/qcsrc/common/mutators/mutator/nades/net.qc b/qcsrc/common/mutators/mutator/nades/net.qc index 70f2218e7..269574cda 100644 --- a/qcsrc/common/mutators/mutator/nades/net.qc +++ b/qcsrc/common/mutators/mutator/nades/net.qc @@ -4,76 +4,82 @@ #ifdef CSQC .float ltime; -void healer_draw(entity this) +void orb_draw(entity this) { float dt = time - this.move_time; this.move_time = time; if(dt <= 0) return; - this.alpha = (this.ltime - time) / this.healer_lifetime; - this.scale = min((1 - this.alpha)*this.healer_lifetime*4,1)*this.healer_radius; + this.alpha = (this.ltime - time) / this.orb_lifetime; + this.scale = min((1 - this.alpha)*this.orb_lifetime*4,1)*this.orb_radius; } -void healer_setup(entity e) +void orb_setup(entity e) { - setmodel(e, MDL_NADE_HEAL); + setmodel(e, MDL_NADE_ORB); setorigin(e, e.origin); float model_radius = e.maxs.x; - vector size = '1 1 1' * e.healer_radius / 2; + vector size = '1 1 1' * e.orb_radius / 2; setsize(e,-size,size); - e.healer_radius = e.healer_radius/model_radius*0.6; + e.orb_radius = e.orb_radius/model_radius*0.6; - e.draw = healer_draw; + e.draw = orb_draw; e.health = 255; e.movetype = MOVETYPE_NONE; e.solid = SOLID_NOT; e.drawmask = MASK_NORMAL; e.scale = 0.01; e.avelocity = e.move_avelocity = '7 0 11'; - e.colormod = '1 0 0'; e.renderflags |= RF_ADDITIVE; } #endif -REGISTER_NET_LINKED(Nade_Heal) +REGISTER_NET_LINKED(Nade_Orb) #ifdef CSQC -NET_HANDLE(Nade_Heal, bool isNew) +NET_HANDLE(Nade_Orb, bool isNew) { - Net_Accept(Nade_Heal); + Net_Accept(Nade_Orb); int sf = ReadByte(); if (sf & 1) { this.origin_x = ReadCoord(); this.origin_y = ReadCoord(); this.origin_z = ReadCoord(); setorigin(this, this.origin); - this.healer_lifetime = ReadByte(); - this.healer_radius = ReadShort(); + this.colormod_x = ReadCoord(); + this.colormod_y = ReadCoord(); + this.colormod_z = ReadCoord(); + this.orb_lifetime = ReadByte(); + this.orb_radius = ReadShort(); this.ltime = time + ReadByte()/10.0; - // this.ltime = time + this.healer_lifetime; - healer_setup(this); + // this.ltime = time + this.orb_lifetime; + orb_setup(this); } return true; } #endif #ifdef SVQC -bool healer_send(entity this, entity to, int sf) +bool orb_send(entity this, entity to, int sf) { int channel = MSG_ENTITY; - WriteHeader(channel, Nade_Heal); + WriteHeader(channel, Nade_Orb); WriteByte(channel, sf); if (sf & 1) { WriteCoord(channel, this.origin.x); WriteCoord(channel, this.origin.y); WriteCoord(channel, this.origin.z); - WriteByte(channel, this.healer_lifetime); + WriteCoord(channel, this.colormod.x); + WriteCoord(channel, this.colormod.y); + WriteCoord(channel, this.colormod.z); + + WriteByte(channel, this.orb_lifetime); //WriteByte(MSG_ENTITY, this.ltime - time + 1); - WriteShort(channel, this.healer_radius); + WriteShort(channel, this.orb_radius); // round time delta to a 1/10th of a second WriteByte(channel, (this.ltime - time)*10.0+0.5); } diff --git a/qcsrc/common/stats.qh b/qcsrc/common/stats.qh index e9828c69e..54a76b309 100644 --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@ -122,6 +122,8 @@ REGISTER_STAT(REVIVE_PROGRESS, float) REGISTER_STAT(ROUNDLOST, int) REGISTER_STAT(BUFF_TIME, float) REGISTER_STAT(CTF_FLAGSTATUS, int) +REGISTER_STAT(ENTRAP_ORB, float) +REGISTER_STAT(ENTRAP_ORB_ALPHA, float) #ifdef SVQC int autocvar_g_multijump; diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index c565298e8..d8345f64f 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -517,6 +517,10 @@ float autocvar_g_nades_heal_time; float autocvar_g_nades_heal_rate; float autocvar_g_nades_heal_friend; float autocvar_g_nades_heal_foe; +float autocvar_g_nades_entrap_strength; +float autocvar_g_nades_entrap_speed; +float autocvar_g_nades_entrap_radius; +float autocvar_g_nades_entrap_time; string autocvar_g_nades_pokenade_monster_type; float autocvar_g_nades_pokenade_monster_lifetime; bool autocvar_g_jump_grunt; diff --git a/textures/nade_orb.tga b/textures/nade_orb.tga new file mode 100644 index 000000000..45a97da4f Binary files /dev/null and b/textures/nade_orb.tga differ