X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Fmutators%2Fmutator%2Fbuffs%2Fbuffs.qc;h=de32df9683483ab1f9d4280f558e20b30cdd5ef2;hp=37a0573dcf56accbd31d630f2cd280ee842b864e;hb=a7f33b244c92e082d828e763ac1789f9b0a6c219;hpb=f3b08f163992b7be4e597cdd2297ed193d96dc1c diff --git a/qcsrc/common/mutators/mutator/buffs/buffs.qc b/qcsrc/common/mutators/mutator/buffs/buffs.qc index 37a0573dc..de32df968 100644 --- a/qcsrc/common/mutators/mutator/buffs/buffs.qc +++ b/qcsrc/common/mutators/mutator/buffs/buffs.qc @@ -19,6 +19,9 @@ float autocvar_g_buffs_medic_survive_health; float autocvar_g_buffs_medic_rot; float autocvar_g_buffs_medic_max; float autocvar_g_buffs_medic_regen; +float autocvar_g_buffs_medic_heal_amount = 15; +float autocvar_g_buffs_medic_heal_delay = 1; +float autocvar_g_buffs_medic_heal_range = 400; float autocvar_g_buffs_vengeance_damage_multiplier; float autocvar_g_buffs_bash_force; float autocvar_g_buffs_bash_force_self; @@ -33,7 +36,6 @@ float autocvar_g_buffs_speed_damage_take; float autocvar_g_buffs_speed_regen; float autocvar_g_buffs_vampire_damage_steal; float autocvar_g_buffs_invisible_alpha; -float autocvar_g_buffs_flight_gravity; float autocvar_g_buffs_jump_height; float autocvar_g_buffs_inferno_burntime_factor; float autocvar_g_buffs_inferno_burntime_min_time; @@ -42,14 +44,17 @@ float autocvar_g_buffs_inferno_burntime_target_time; float autocvar_g_buffs_inferno_damagemultiplier; float autocvar_g_buffs_swapper_range; float autocvar_g_buffs_magnet_range_item; +float autocvar_g_buffs_magnet_range_buff = 200; +float autocvar_g_buffs_luck_chance = 0.15; +float autocvar_g_buffs_luck_damagemultiplier = 3; // ammo .float buff_ammo_prev_infitems; .int buff_ammo_prev_clipload; // invisible .float buff_invisible_prev_alpha; -// flight -.float buff_flight_prev_gravity; +// medic +.float buff_medic_healtime; // disability .float buff_disability_time; .float buff_disability_effect_time; @@ -73,54 +78,45 @@ const vector BUFF_MAX = ('16 16 20'); #ifdef IMPLEMENTATION -#include "../../../triggers/target/music.qh" -#include "../../../gamemodes/all.qh" +#include +#include .float buff_time = _STAT(BUFF_TIME); -void buffs_DelayedInit(); +void buffs_DelayedInit(entity this); REGISTER_MUTATOR(buffs, cvar("g_buffs")) { MUTATOR_ONADD { - InitializeEntity(world, buffs_DelayedInit, INITPRIO_FINDTARGET); + InitializeEntity(NULL, buffs_DelayedInit, INITPRIO_FINDTARGET); } } -entity buff_FirstFromFlags(int _buffs) +bool buffs_BuffModel_Customize(entity this, entity client) { - if (flags) - { - FOREACH(Buffs, it.m_itemid & _buffs, LAMBDA(return it)); - } - return BUFF_Null; -} - -bool buffs_BuffModel_Customize() -{SELFPARAM(); entity player, myowner; bool same_team; - player = WaypointSprite_getviewentity(other); - myowner = self.owner; + player = WaypointSprite_getviewentity(client); + myowner = this.owner; same_team = (SAME_TEAM(player, myowner) || SAME_TEAM(player, myowner)); if(myowner.alpha <= 0.5 && !same_team && myowner.alpha != 0) return false; - if(MUTATOR_CALLHOOK(BuffModel_Customize, self, player)) + if(MUTATOR_CALLHOOK(BuffModel_Customize, this, player)) return false; - if(player == myowner || (IS_SPEC(other) && other.enemy == myowner)) + if(player == myowner || (IS_SPEC(client) && client.enemy == myowner)) { // somewhat hide the model, but keep the glow - self.effects = 0; - self.alpha = -1; + this.effects = 0; + this.alpha = -1; } else { - self.effects = EF_FULLBRIGHT | EF_LOWPRECISION; - self.alpha = 1; + this.effects = EF_FULLBRIGHT | EF_LOWPRECISION; + this.alpha = 1; } return true; } @@ -136,7 +132,7 @@ void buffs_BuffModel_Spawn(entity player) player.buff_model.scale = 0.7; player.buff_model.pflags = PFLAGS_FULLDYNAMIC; player.buff_model.light_lev = 200; - player.buff_model.customizeentityforclient = buffs_BuffModel_Customize; + setcefc(player.buff_model, buffs_BuffModel_Customize); } vector buff_GlowColor(entity buff) @@ -146,134 +142,137 @@ vector buff_GlowColor(entity buff) } void buff_Effect(entity player, string eff) -{SELFPARAM(); +{ if(!autocvar_g_buffs_effects) { return; } - if(time >= self.buff_effect_delay) + if(time >= player.buff_effect_delay) { Send_Effect_(eff, player.origin + ((player.mins + player.maxs) * 0.5), '0 0 0', 1); - self.buff_effect_delay = time + 0.05; // prevent spam + player.buff_effect_delay = time + 0.05; // prevent spam } } // buff item -float buff_Waypoint_visible_for_player(entity plr) -{SELFPARAM(); - if(!self.owner.buff_active && !self.owner.buff_activetime) +bool buff_Waypoint_visible_for_player(entity this, entity player, entity view) +{ + if(!this.owner.buff_active && !this.owner.buff_activetime) return false; - if (plr.buffs) + if (view.buffs) { - return plr.cvar_cl_buffs_autoreplace == false || plr.buffs != self.owner.buffs; + return view.cvar_cl_buffs_autoreplace == false || view.buffs != this.owner.buffs; } - return WaypointSprite_visible_for_player(plr); + return WaypointSprite_visible_for_player(this, player, view); } void buff_Waypoint_Spawn(entity e) { entity buff = buff_FirstFromFlags(e.buffs); - entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_Buff); + entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, NULL, e.team, e, buff_waypoint, true, RADARICON_Buff); wp.wp_extra = buff.m_id; WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_Buff, e.glowmod); e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player; } -void buff_SetCooldown(float cd) -{SELFPARAM(); +void buff_SetCooldown(entity this, float cd) +{ cd = max(0, cd); - if(!self.buff_waypoint) - buff_Waypoint_Spawn(self); + if(!this.buff_waypoint) + buff_Waypoint_Spawn(this); - WaypointSprite_UpdateBuildFinished(self.buff_waypoint, time + cd); - self.buff_activetime = cd; - self.buff_active = !cd; + WaypointSprite_UpdateBuildFinished(this.buff_waypoint, time + cd); + this.buff_activetime = cd; + this.buff_active = !cd; } -void buff_Respawn(entity ent) -{SELFPARAM(); +void buff_Respawn(entity this) +{ if(gameover) { return; } - vector oldbufforigin = ent.origin; + vector oldbufforigin = this.origin; + this.velocity = '0 0 200'; - if(!MoveToRandomMapLocation(ent, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, ((autocvar_g_buffs_random_location_attempts > 0) ? autocvar_g_buffs_random_location_attempts : 10), 1024, 256)) + if(!MoveToRandomMapLocation(this, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, + ((autocvar_g_buffs_random_location_attempts > 0) ? autocvar_g_buffs_random_location_attempts : 10), 1024, 256)) { - entity spot = SelectSpawnPoint(true); - setorigin(ent, spot.origin + '0 0 200'); - ent.angles = spot.angles; + entity spot = SelectSpawnPoint(this, true); + setorigin(this, spot.origin); + this.velocity = ((randomvec() * 100) + '0 0 200'); + this.angles = spot.angles; } - tracebox(ent.origin, ent.mins * 1.5, self.maxs * 1.5, ent.origin, MOVE_NOMONSTERS, ent); + tracebox(this.origin, this.mins * 1.5, this.maxs * 1.5, this.origin, MOVE_NOMONSTERS, this); - setorigin(ent, trace_endpos); // attempt to unstick + setorigin(this, trace_endpos); // attempt to unstick - ent.movetype = MOVETYPE_TOSS; + this.movetype = MOVETYPE_TOSS; - makevectors(ent.angles); - ent.velocity = '0 0 200'; - ent.angles = '0 0 0'; + makevectors(this.angles); + this.angles = '0 0 0'; if(autocvar_g_buffs_random_lifetime > 0) - ent.lifetime = time + autocvar_g_buffs_random_lifetime; + this.lifetime = time + autocvar_g_buffs_random_lifetime; - Send_Effect(EFFECT_ELECTRO_COMBO, oldbufforigin + ((ent.mins + ent.maxs) * 0.5), '0 0 0', 1); - Send_Effect(EFFECT_ELECTRO_COMBO, CENTER_OR_VIEWOFS(ent), '0 0 0', 1); + Send_Effect(EFFECT_ELECTRO_COMBO, oldbufforigin + ((this.mins + this.maxs) * 0.5), '0 0 0', 1); + Send_Effect(EFFECT_ELECTRO_COMBO, CENTER_OR_VIEWOFS(this), '0 0 0', 1); - WaypointSprite_Ping(ent.buff_waypoint); + WaypointSprite_Ping(this.buff_waypoint); - sound(ent, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere) + sound(this, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere) } -void buff_Touch() -{SELFPARAM(); +void buff_Touch(entity this, entity toucher) +{ if(gameover) { return; } if(ITEM_TOUCH_NEEDKILL()) { - buff_Respawn(self); + buff_Respawn(this); return; } - if((self.team && DIFF_TEAM(other, self)) - || (other.frozen) - || (other.vehicle) - || (!self.buff_active) + if((this.team && DIFF_TEAM(toucher, this)) + || (STAT(FROZEN, toucher)) + || (toucher.vehicle) + || (!this.buff_active) ) { // can't touch this return; } - if(MUTATOR_CALLHOOK(BuffTouch, self, other)) + if(MUTATOR_CALLHOOK(BuffTouch, this, toucher)) return; + toucher = M_ARGV(1, entity); - if(!IS_PLAYER(other)) - return; // incase mutator changed other + if(!IS_PLAYER(toucher)) + return; // incase mutator changed toucher - if (other.buffs) + if (toucher.buffs) { - if (other.cvar_cl_buffs_autoreplace && other.buffs != self.buffs) + if (toucher.cvar_cl_buffs_autoreplace && toucher.buffs != this.buffs) { - int buffid = buff_FirstFromFlags(other.buffs).m_id; - //Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_BUFF_DROP, other.buffs); - Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ITEM_BUFF_LOST, other.netname, buffid); + int buffid = buff_FirstFromFlags(toucher.buffs).m_id; + //Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_DROP, toucher.buffs); + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ITEM_BUFF_LOST, toucher.netname, buffid); - other.buffs = 0; - //sound(other, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM); + toucher.buffs = 0; + //sound(toucher, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM); } else { return; } // do nothing } - self.owner = other; - self.buff_active = false; - self.lifetime = 0; - int buffid = buff_FirstFromFlags(self.buffs).m_id; - Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_BUFF_GOT, buffid); - Send_Notification(NOTIF_ALL_EXCEPT, other, MSG_INFO, INFO_ITEM_BUFF, other.netname, buffid); + this.owner = toucher; + this.buff_active = false; + this.lifetime = 0; + int buffid = buff_FirstFromFlags(this.buffs).m_id; + Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_GOT, buffid); + Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_INFO, INFO_ITEM_BUFF, toucher.netname, buffid); - Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(self), '0 0 0', 1); - sound(other, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTN_NORM); - other.buffs |= (self.buffs); + Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1); + sound(toucher, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTN_NORM); + toucher.buffs |= (this.buffs); } float buff_Available(entity buff) @@ -295,167 +294,164 @@ void buff_NewType(entity ent, float cb) FOREACH(Buffs, buff_Available(it), LAMBDA( it.buff_seencount += 1; // if it's already been chosen, give it a lower priority - RandomSelection_Add(world, it.m_itemid, string_null, 1, max(0.2, 1 / it.buff_seencount)); + RandomSelection_Add(NULL, it.m_itemid, string_null, 1, max(0.2, 1 / it.buff_seencount)); )); ent.buffs = RandomSelection_chosen_float; } -void buff_Think() -{SELFPARAM(); - if(self.buffs != self.oldbuffs) +void buff_Think(entity this) +{ + if(this.buffs != this.oldbuffs) { - entity buff = buff_FirstFromFlags(self.buffs); - self.color = buff.m_color; - self.glowmod = buff_GlowColor(buff); - self.skin = buff.m_skin; + entity buff = buff_FirstFromFlags(this.buffs); + this.color = buff.m_color; + this.glowmod = buff_GlowColor(buff); + this.skin = buff.m_skin; - setmodel(self, MDL_BUFF); + setmodel(this, MDL_BUFF); - if(self.buff_waypoint) + if(this.buff_waypoint) { - //WaypointSprite_Disown(self.buff_waypoint, 1); - WaypointSprite_Kill(self.buff_waypoint); - buff_Waypoint_Spawn(self); - if(self.buff_activetime) - WaypointSprite_UpdateBuildFinished(self.buff_waypoint, time + self.buff_activetime - frametime); + //WaypointSprite_Disown(this.buff_waypoint, 1); + WaypointSprite_Kill(this.buff_waypoint); + buff_Waypoint_Spawn(this); + if(this.buff_activetime) + WaypointSprite_UpdateBuildFinished(this.buff_waypoint, time + this.buff_activetime - frametime); } - self.oldbuffs = self.buffs; + this.oldbuffs = this.buffs; } if(!gameover) if((round_handler_IsActive() && !round_handler_IsRoundStarted()) || time >= game_starttime) - if(!self.buff_activetime_updated) + if(!this.buff_activetime_updated) { - buff_SetCooldown(self.buff_activetime); - self.buff_activetime_updated = true; + buff_SetCooldown(this, this.buff_activetime); + this.buff_activetime_updated = true; } - if(!self.buff_active && !self.buff_activetime) - if(!self.owner || self.owner.frozen || self.owner.deadflag != DEAD_NO || !self.owner.iscreature || !(self.owner.buffs & self.buffs)) + if(!this.buff_active && !this.buff_activetime) + if(!this.owner || STAT(FROZEN, this.owner) || IS_DEAD(this.owner) || !this.owner.iscreature || !(this.owner.buffs & this.buffs)) { - buff_SetCooldown(autocvar_g_buffs_cooldown_respawn + frametime); - self.owner = world; + buff_SetCooldown(this, autocvar_g_buffs_cooldown_respawn + frametime); + this.owner = NULL; if(autocvar_g_buffs_randomize) - buff_NewType(self, self.buffs); + buff_NewType(this, this.buffs); - if(autocvar_g_buffs_random_location || (self.spawnflags & 64)) - buff_Respawn(self); + if(autocvar_g_buffs_random_location || (this.spawnflags & 64)) + buff_Respawn(this); } - if(self.buff_activetime) + if(this.buff_activetime) if(!gameover) if((round_handler_IsActive() && !round_handler_IsRoundStarted()) || time >= game_starttime) { - self.buff_activetime = max(0, self.buff_activetime - frametime); + this.buff_activetime = max(0, this.buff_activetime - frametime); - if(!self.buff_activetime) + if(!this.buff_activetime) { - self.buff_active = true; - sound(self, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTN_NORM); - Send_Effect(EFFECT_ITEM_RESPAWN, CENTER_OR_VIEWOFS(self), '0 0 0', 1); + this.buff_active = true; + sound(this, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTN_NORM); + Send_Effect(EFFECT_ITEM_RESPAWN, CENTER_OR_VIEWOFS(this), '0 0 0', 1); } } - if(self.buff_active) + if(this.buff_active) { - if(self.team && !self.buff_waypoint) - buff_Waypoint_Spawn(self); + if(this.team && !this.buff_waypoint) + buff_Waypoint_Spawn(this); - if(self.lifetime) - if(time >= self.lifetime) - buff_Respawn(self); + if(this.lifetime) + if(time >= this.lifetime) + buff_Respawn(this); } - self.nextthink = time; - //self.angles_y = time * 110.1; + this.nextthink = time; + //this.angles_y = time * 110.1; } -void buff_Waypoint_Reset() -{SELFPARAM(); - WaypointSprite_Kill(self.buff_waypoint); +void buff_Waypoint_Reset(entity this) +{ + WaypointSprite_Kill(this.buff_waypoint); - if(self.buff_activetime) { buff_Waypoint_Spawn(self); } + if(this.buff_activetime) { buff_Waypoint_Spawn(this); } } void buff_Reset(entity this) { if(autocvar_g_buffs_randomize) buff_NewType(this, this.buffs); - this.owner = world; - buff_SetCooldown(autocvar_g_buffs_cooldown_activate); - buff_Waypoint_Reset(); + this.owner = NULL; + buff_SetCooldown(this, autocvar_g_buffs_cooldown_activate); + buff_Waypoint_Reset(this); this.buff_activetime_updated = false; if(autocvar_g_buffs_random_location || (this.spawnflags & 64)) buff_Respawn(this); } -float buff_Customize() -{SELFPARAM(); - entity player = WaypointSprite_getviewentity(other); - if(!self.buff_active || (self.team && DIFF_TEAM(player, self))) +bool buff_Customize(entity this, entity client) +{ + entity player = WaypointSprite_getviewentity(client); + if(!this.buff_active || (this.team && DIFF_TEAM(player, this))) { - self.alpha = 0.3; - if(self.effects & EF_FULLBRIGHT) { self.effects &= ~(EF_FULLBRIGHT); } - self.pflags = 0; + this.alpha = 0.3; + if(this.effects & EF_FULLBRIGHT) { this.effects &= ~(EF_FULLBRIGHT); } + this.pflags = 0; } else { - self.alpha = 1; - if(!(self.effects & EF_FULLBRIGHT)) { self.effects |= EF_FULLBRIGHT; } - self.light_lev = 220 + 36 * sin(time); - self.pflags = PFLAGS_FULLDYNAMIC; + this.alpha = 1; + if(!(this.effects & EF_FULLBRIGHT)) { this.effects |= EF_FULLBRIGHT; } + this.light_lev = 220 + 36 * sin(time); + this.pflags = PFLAGS_FULLDYNAMIC; } return true; } -void buff_Init(entity ent) -{SELFPARAM(); - if(!cvar("g_buffs")) { remove(ent); return; } - - if(!teamplay && ent.team) { ent.team = 0; } - - entity buff = buff_FirstFromFlags(self.buffs); - - setself(ent); - if(!self.buffs || buff_Available(buff)) - buff_NewType(self, 0); - - self.classname = "item_buff"; - self.solid = SOLID_TRIGGER; - self.flags = FL_ITEM; - self.think = buff_Think; - self.touch = buff_Touch; - self.reset = buff_Reset; - self.nextthink = time + 0.1; - self.gravity = 1; - self.movetype = MOVETYPE_TOSS; - self.scale = 1; - self.skin = buff.m_skin; - self.effects = EF_FULLBRIGHT | EF_STARDUST | EF_NOSHADOW; - self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY; - self.customizeentityforclient = buff_Customize; - //self.gravity = 100; - self.color = buff.m_color; - self.glowmod = buff_GlowColor(self); - buff_SetCooldown(autocvar_g_buffs_cooldown_activate + game_starttime); - self.buff_active = !self.buff_activetime; - self.pflags = PFLAGS_FULLDYNAMIC; - - if(self.spawnflags & 1) - self.noalign = true; - - if(self.noalign) - self.movetype = MOVETYPE_NONE; // reset by random location - - setmodel(self, MDL_BUFF); - setsize(self, BUFF_MIN, BUFF_MAX); - - if(cvar("g_buffs_random_location") || (self.spawnflags & 64)) - buff_Respawn(self); - - setself(this); +void buff_Init(entity this) +{ + if(!cvar("g_buffs")) { remove(this); return; } + + if(!teamplay && this.team) { this.team = 0; } + + entity buff = buff_FirstFromFlags(this.buffs); + + if(!this.buffs || buff_Available(buff)) + buff_NewType(this, 0); + + this.classname = "item_buff"; + this.solid = SOLID_TRIGGER; + this.flags = FL_ITEM; + setthink(this, buff_Think); + settouch(this, buff_Touch); + this.reset = buff_Reset; + this.nextthink = time + 0.1; + this.gravity = 1; + this.movetype = MOVETYPE_TOSS; + this.scale = 1; + this.skin = buff.m_skin; + this.effects = EF_FULLBRIGHT | EF_STARDUST | EF_NOSHADOW; + this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY; + setcefc(this, buff_Customize); + //this.gravity = 100; + this.color = buff.m_color; + this.glowmod = buff_GlowColor(this); + buff_SetCooldown(this, autocvar_g_buffs_cooldown_activate + game_starttime); + this.buff_active = !this.buff_activetime; + this.pflags = PFLAGS_FULLDYNAMIC; + + if(this.spawnflags & 1) + this.noalign = true; + + if(this.noalign) + this.movetype = MOVETYPE_NONE; // reset by random location + + setmodel(this, MDL_BUFF); + setsize(this, BUFF_MIN, BUFF_MAX); + + if(cvar("g_buffs_random_location") || (this.spawnflags & 64)) + buff_Respawn(this); } void buff_Init_Compat(entity ent, entity replacement) @@ -479,15 +475,29 @@ void buff_SpawnReplacement(entity ent, entity old) buff_Init(ent); } -void buff_Vengeance_DelayedDamage() -{SELFPARAM(); - if(self.enemy) - Damage(self.enemy, self.owner, self.owner, self.dmg, DEATH_BUFF.m_id, self.enemy.origin, '0 0 0'); +void buff_Vengeance_DelayedDamage(entity this) +{ + if(this.enemy) + Damage(this.enemy, this.owner, this.owner, this.dmg, DEATH_BUFF.m_id, this.enemy.origin, '0 0 0'); - remove(self); + remove(this); return; } +// note: only really useful in teamplay +void buff_Medic_Heal(entity this) +{ + FOREACH_CLIENT(IS_PLAYER(it) && it != this && vdist(it.origin - this.origin, <=, autocvar_g_buffs_medic_heal_range), + { + if(SAME_TEAM(it, this)) + if(it.health < autocvar_g_balance_health_regenstable) + { + Send_Effect(EFFECT_HEALING, it.origin, '0 0 0', 1); + it.health = bound(0, it.health + autocvar_g_buffs_medic_heal_amount, autocvar_g_balance_health_regenstable); + } + }); +} + float buff_Inferno_CalculateTime(float x, float offset_x, float offset_y, float intersect_x, float intersect_y, float base) { return offset_y + (intersect_y - offset_y) * logn(((x - offset_x) * ((base - 1) / intersect_x)) + 1, base); @@ -496,21 +506,29 @@ float buff_Inferno_CalculateTime(float x, float offset_x, float offset_y, float // mutator hooks MUTATOR_HOOKFUNCTION(buffs, PlayerDamage_SplitHealthArmor) { - if(frag_deathtype == DEATH_BUFF.m_id) { return false; } + entity frag_target = M_ARGV(2, entity); + float frag_deathtype = M_ARGV(6, float); + float frag_damage = M_ARGV(7, float); + + if(frag_deathtype == DEATH_BUFF.m_id) { return; } if(frag_target.buffs & BUFF_RESISTANCE.m_itemid) { vector v = healtharmor_applydamage(50, autocvar_g_buffs_resistance_blockpercent, frag_deathtype, frag_damage); - damage_take = v.x; - damage_save = v.y; + M_ARGV(4, float) = v.x; // take + M_ARGV(5, float) = v.y; // save } - - return false; } MUTATOR_HOOKFUNCTION(buffs, PlayerDamage_Calculate) { - if(frag_deathtype == DEATH_BUFF.m_id) { return false; } + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + float frag_deathtype = M_ARGV(3, float); + float frag_damage = M_ARGV(4, float); + vector frag_force = M_ARGV(6, vector); + + if(frag_deathtype == DEATH_BUFF.m_id) { return; } if(frag_target.buffs & BUFF_SPEED.m_itemid) if(frag_target != frag_attacker) @@ -537,17 +555,16 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerDamage_Calculate) dmgent.dmg = frag_damage * autocvar_g_buffs_vengeance_damage_multiplier; dmgent.enemy = frag_attacker; dmgent.owner = frag_target; - dmgent.think = buff_Vengeance_DelayedDamage; + setthink(dmgent, buff_Vengeance_DelayedDamage); dmgent.nextthink = time + 0.1; } if(frag_target.buffs & BUFF_BASH.m_itemid) if(frag_attacker != frag_target) - if(vlen(frag_force)) frag_force = '0 0 0'; if(frag_attacker.buffs & BUFF_BASH.m_itemid) - if(vlen(frag_force)) + if(frag_force) if(frag_attacker == frag_target) frag_force *= autocvar_g_buffs_bash_force_self; else @@ -557,18 +574,23 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerDamage_Calculate) if(frag_target != frag_attacker) frag_target.buff_disability_time = time + autocvar_g_buffs_disability_slowtime; - if(frag_attacker.buffs & BUFF_MEDIC.m_itemid) - if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC) - if(SAME_TEAM(frag_attacker, frag_target)) - if(frag_attacker != frag_target) + if(frag_target.buffs & BUFF_INFERNO.m_itemid) { - frag_target.health = min(g_pickup_healthmega_max, frag_target.health + frag_damage); - frag_damage = 0; + if(frag_deathtype == DEATH_FIRE.m_id) + frag_damage = 0; + if(frag_deathtype == DEATH_LAVA.m_id) + frag_damage *= 0.5; // TODO: cvarize? } + if(frag_attacker.buffs & BUFF_LUCK.m_itemid) + if(frag_attacker != frag_target) + if(autocvar_g_buffs_luck_damagemultiplier > 0) + if(random() <= autocvar_g_buffs_luck_chance) + frag_damage *= autocvar_g_buffs_luck_damagemultiplier; + if(frag_attacker.buffs & BUFF_INFERNO.m_itemid) if(frag_target != frag_attacker) { - float time = buff_Inferno_CalculateTime( + float btime = buff_Inferno_CalculateTime( frag_damage, 0, autocvar_g_buffs_inferno_burntime_min_time, @@ -576,18 +598,17 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerDamage_Calculate) autocvar_g_buffs_inferno_burntime_target_time, autocvar_g_buffs_inferno_burntime_factor ); - Fire_AddDamage(frag_target, frag_attacker, (frag_damage * autocvar_g_buffs_inferno_damagemultiplier) * time, time, DEATH_BUFF.m_id); + Fire_AddDamage(frag_target, frag_attacker, (frag_damage * autocvar_g_buffs_inferno_damagemultiplier), btime, DEATH_BUFF.m_id); } // this... is ridiculous (TODO: fix!) if(frag_attacker.buffs & BUFF_VAMPIRE.m_itemid) if(!frag_target.vehicle) - if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC) if(!ITEM_DAMAGE_NEEDKILL(frag_deathtype)) - if(frag_target.deadflag == DEAD_NO) + if(!IS_DEAD(frag_target)) if(IS_PLAYER(frag_target) || IS_MONSTER(frag_target)) if(frag_attacker != frag_target) - if(!frag_target.frozen) + if(!STAT(FROZEN, frag_target)) if(frag_target.takedamage) if(DIFF_TEAM(frag_attacker, frag_target)) { @@ -596,16 +617,18 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerDamage_Calculate) frag_attacker.armorvalue = bound(0, frag_attacker.armorvalue + bound(0, frag_damage * autocvar_g_buffs_vampire_damage_steal, frag_target.armorvalue), g_pickup_armorsmall_max); } - return false; + M_ARGV(4, float) = frag_damage; + M_ARGV(6, vector) = frag_force; } -MUTATOR_HOOKFUNCTION(buffs,PlayerSpawn) -{SELFPARAM(); - self.buffs = 0; +MUTATOR_HOOKFUNCTION(buffs, PlayerSpawn) +{ + entity player = M_ARGV(0, entity); + + player.buffs = 0; // reset timers here to prevent them continuing after re-spawn - self.buff_disability_time = 0; - self.buff_disability_effect_time = 0; - return false; + player.buff_disability_time = 0; + player.buff_disability_effect_time = 0; } .float stat_sv_maxspeed; @@ -613,114 +636,121 @@ MUTATOR_HOOKFUNCTION(buffs,PlayerSpawn) .float stat_sv_jumpvelocity; MUTATOR_HOOKFUNCTION(buffs, PlayerPhysics) -{SELFPARAM(); - if(self.buffs & BUFF_SPEED.m_itemid) +{ + entity player = M_ARGV(0, entity); + + if(player.buffs & BUFF_SPEED.m_itemid) { - self.stat_sv_maxspeed *= autocvar_g_buffs_speed_speed; - self.stat_sv_airspeedlimit_nonqw *= autocvar_g_buffs_speed_speed; + player.stat_sv_maxspeed *= autocvar_g_buffs_speed_speed; + player.stat_sv_airspeedlimit_nonqw *= autocvar_g_buffs_speed_speed; } - if(time < self.buff_disability_time) + if(time < player.buff_disability_time) { - self.stat_sv_maxspeed *= autocvar_g_buffs_disability_speed; - self.stat_sv_airspeedlimit_nonqw *= autocvar_g_buffs_disability_speed; + player.stat_sv_maxspeed *= autocvar_g_buffs_disability_speed; + player.stat_sv_airspeedlimit_nonqw *= autocvar_g_buffs_disability_speed; } - if(self.buffs & BUFF_JUMP.m_itemid) + if(player.buffs & BUFF_JUMP.m_itemid) { // automatically reset, no need to worry - self.stat_sv_jumpvelocity = autocvar_g_buffs_jump_height; + player.stat_sv_jumpvelocity = autocvar_g_buffs_jump_height; } - - return false; } MUTATOR_HOOKFUNCTION(buffs, PlayerJump) -{SELFPARAM(); - if(self.buffs & BUFF_JUMP.m_itemid) - player_jumpheight = autocvar_g_buffs_jump_height; +{ + entity player = M_ARGV(0, entity); - return false; + if(player.buffs & BUFF_JUMP.m_itemid) + M_ARGV(1, float) = autocvar_g_buffs_jump_height; } MUTATOR_HOOKFUNCTION(buffs, MonsterMove) -{SELFPARAM(); - if(time < self.buff_disability_time) +{ + entity mon = M_ARGV(0, entity); + + if(time < mon.buff_disability_time) { - monster_speed_walk *= autocvar_g_buffs_disability_speed; - monster_speed_run *= autocvar_g_buffs_disability_speed; + M_ARGV(1, float) *= autocvar_g_buffs_disability_speed; // run speed + M_ARGV(2, float) *= autocvar_g_buffs_disability_speed; // walk speed } - - return false; } MUTATOR_HOOKFUNCTION(buffs, PlayerDies) -{SELFPARAM(); - if(self.buffs) +{ + entity frag_target = M_ARGV(2, entity); + + if(frag_target.buffs) { - int buffid = buff_FirstFromFlags(self.buffs).m_id; - Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, buffid); - self.buffs = 0; + int buffid = buff_FirstFromFlags(frag_target.buffs).m_id; + Send_Notification(NOTIF_ALL_EXCEPT, frag_target, MSG_INFO, INFO_ITEM_BUFF_LOST, frag_target.netname, buffid); + frag_target.buffs = 0; - if(self.buff_model) + if(frag_target.buff_model) { - remove(self.buff_model); - self.buff_model = world; + remove(frag_target.buff_model); + frag_target.buff_model = NULL; } } - return false; } MUTATOR_HOOKFUNCTION(buffs, PlayerUseKey, CBC_ORDER_FIRST) -{SELFPARAM(); - if(MUTATOR_RETURNVALUE || gameover) { return false; } - if(self.buffs) +{ + if(MUTATOR_RETURNVALUE || gameover) { return; } + + entity player = M_ARGV(0, entity); + + if(player.buffs) { - int buffid = buff_FirstFromFlags(self.buffs).m_id; - Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_BUFF_DROP, buffid); - Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, buffid); + int buffid = buff_FirstFromFlags(player.buffs).m_id; + Send_Notification(NOTIF_ONE, player, MSG_MULTI, ITEM_BUFF_DROP, buffid); + Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid); - self.buffs = 0; - sound(self, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM); + player.buffs = 0; + sound(player, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM); return true; } - return false; } MUTATOR_HOOKFUNCTION(buffs, ForbidThrowCurrentWeapon) -{SELFPARAM(); - if(MUTATOR_RETURNVALUE || gameover) { return false; } +{ + if(MUTATOR_RETURNVALUE || gameover) { return; } + entity player = M_ARGV(0, entity); - if(self.buffs & BUFF_SWAPPER.m_itemid) + if(player.buffs & BUFF_SWAPPER.m_itemid) { float best_distance = autocvar_g_buffs_swapper_range; - entity closest = world; - entity player; - FOR_EACH_PLAYER(player) - if(DIFF_TEAM(self, player)) - if(player.deadflag == DEAD_NO && !player.frozen && !player.vehicle) - if(vlen(self.origin - player.origin) <= best_distance) - { - best_distance = vlen(self.origin - player.origin); - closest = player; - } + entity closest = NULL; + FOREACH_CLIENT(IS_PLAYER(it), LAMBDA( + if(!IS_DEAD(it) && !STAT(FROZEN, it) && !it.vehicle) + if(DIFF_TEAM(it, player)) + { + float test = vlen2(player.origin - it.origin); + if(test <= best_distance * best_distance) + { + best_distance = sqrt(test); + closest = it; + } + } + )); if(closest) { vector my_org, my_vel, my_ang, their_org, their_vel, their_ang; - my_org = self.origin; - my_vel = self.velocity; - my_ang = self.angles; + my_org = player.origin; + my_vel = player.velocity; + my_ang = player.angles; their_org = closest.origin; their_vel = closest.velocity; their_ang = closest.angles; Drop_Special_Items(closest); - MUTATOR_CALLHOOK(PortalTeleport, self); // initiate flag dropper + MUTATOR_CALLHOOK(PortalTeleport, player); // initiate flag dropper - setorigin(self, their_org); + setorigin(player, their_org); setorigin(closest, my_org); closest.velocity = my_vel; @@ -728,29 +758,28 @@ MUTATOR_HOOKFUNCTION(buffs, ForbidThrowCurrentWeapon) closest.fixangle = true; closest.oldorigin = my_org; closest.oldvelocity = my_vel; - self.velocity = their_vel; - self.angles = their_ang; - self.fixangle = true; - self.oldorigin = their_org; - self.oldvelocity = their_vel; - - // set pusher so self gets the kill if they fall into void - closest.pusher = self; + player.velocity = their_vel; + player.angles = their_ang; + player.fixangle = true; + player.oldorigin = their_org; + player.oldvelocity = their_vel; + + // set pusher so player gets the kill if they fall into void + closest.pusher = player; closest.pushltime = time + autocvar_g_maxpushtime; - closest.istypefrag = closest.BUTTON_CHAT; + closest.istypefrag = PHYS_INPUT_BUTTON_CHAT(closest); Send_Effect(EFFECT_ELECTRO_COMBO, their_org, '0 0 0', 1); Send_Effect(EFFECT_ELECTRO_COMBO, my_org, '0 0 0', 1); - sound(self, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM); + sound(player, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM); sound(closest, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM); // TODO: add a counter to handle how many times one can teleport, and a delay to prevent spam - self.buffs = 0; + player.buffs = 0; return true; } } - return false; } bool buffs_RemovePlayer(entity player) @@ -758,7 +787,7 @@ bool buffs_RemovePlayer(entity player) if(player.buff_model) { remove(player.buff_model); - player.buff_model = world; + player.buff_model = NULL; } // also reset timers here to prevent them continuing after spectating @@ -767,74 +796,73 @@ bool buffs_RemovePlayer(entity player) return false; } -MUTATOR_HOOKFUNCTION(buffs, MakePlayerObserver) { return buffs_RemovePlayer(self); } -MUTATOR_HOOKFUNCTION(buffs, ClientDisconnect) { return buffs_RemovePlayer(self); } +MUTATOR_HOOKFUNCTION(buffs, MakePlayerObserver) { entity player = M_ARGV(0, entity); return buffs_RemovePlayer(player); } +MUTATOR_HOOKFUNCTION(buffs, ClientDisconnect) { entity player = M_ARGV(0, entity); return buffs_RemovePlayer(player); } MUTATOR_HOOKFUNCTION(buffs, CustomizeWaypoint) -{SELFPARAM(); - entity e = WaypointSprite_getviewentity(other); +{ + entity wp = M_ARGV(0, entity); + entity player = M_ARGV(1, entity); + + entity e = WaypointSprite_getviewentity(player); // if you have the invisibility powerup, sprites ALWAYS are restricted to your team // but only apply this to real players, not to spectators - if((self.owner.flags & FL_CLIENT) && (self.owner.buffs & BUFF_INVISIBLE.m_itemid) && (e == other)) - if(DIFF_TEAM(self.owner, e)) + if((wp.owner.flags & FL_CLIENT) && (wp.owner.buffs & BUFF_INVISIBLE.m_itemid) && (e == player)) + if(DIFF_TEAM(wp.owner, e)) return true; - - return false; } MUTATOR_HOOKFUNCTION(buffs, OnEntityPreSpawn, CBC_ORDER_LAST) -{SELFPARAM(); - if (self.classname == "item_flight" && cvar("g_buffs") && cvar("g_buffs_flight")) - { - buff_Init_Compat(self, BUFF_FLIGHT); - return true; - } +{ + entity ent = M_ARGV(0, entity); + if(autocvar_g_buffs_replace_powerups) - switch(self.classname) + switch(ent.classname) { case "item_strength": case "item_invincible": { entity e = spawn(); - buff_SpawnReplacement(e, self); + buff_SpawnReplacement(e, ent); return true; } } - return false; } MUTATOR_HOOKFUNCTION(buffs, WeaponRateFactor) -{SELFPARAM(); - if(self.buffs & BUFF_SPEED.m_itemid) - weapon_rate *= autocvar_g_buffs_speed_rate; +{ + entity player = M_ARGV(1, entity); - if(time < self.buff_disability_time) - weapon_rate *= autocvar_g_buffs_disability_rate; + if(player.buffs & BUFF_SPEED.m_itemid) + M_ARGV(0, float) *= autocvar_g_buffs_speed_rate; - return false; + if(time < player.buff_disability_time) + M_ARGV(0, float) *= autocvar_g_buffs_disability_rate; } MUTATOR_HOOKFUNCTION(buffs, WeaponSpeedFactor) -{SELFPARAM(); - if(self.buffs & BUFF_SPEED.m_itemid) - ret_float *= autocvar_g_buffs_speed_weaponspeed; +{ + entity player = M_ARGV(1, entity); - if(time < self.buff_disability_time) - ret_float *= autocvar_g_buffs_disability_weaponspeed; + if(player.buffs & BUFF_SPEED.m_itemid) + M_ARGV(0, float) *= autocvar_g_buffs_speed_weaponspeed; - return false; + if(time < player.buff_disability_time) + M_ARGV(0, float) *= autocvar_g_buffs_disability_weaponspeed; } MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink) -{SELFPARAM(); - if(gameover || self.deadflag != DEAD_NO) { return false; } +{ + entity player = M_ARGV(0, entity); + + if(gameover || IS_DEAD(player)) { return; } - if(time < self.buff_disability_time) - if(time >= self.buff_disability_effect_time) + if(time < player.buff_disability_time) + if(time >= player.buff_disability_effect_time) { - Send_Effect(EFFECT_SMOKING, self.origin + ((self.mins + self.maxs) * 0.5), '0 0 0', 1); - self.buff_disability_effect_time = time + 0.5; + Send_Effect(EFFECT_SMOKING, player.origin + ((player.mins + player.maxs) * 0.5), '0 0 0', 1); + player.buff_disability_effect_time = time + 0.5; } // handle buff lost status @@ -842,197 +870,200 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink) // 2: notify carrier as well int buff_lost = 0; - if(self.buff_time) - if(time >= self.buff_time) + if(player.buff_time) + if(time >= player.buff_time) + { + player.buff_time = 0; buff_lost = 2; + } - if(self.frozen) { buff_lost = 1; } + if(STAT(FROZEN, player)) { buff_lost = 1; } if(buff_lost) { - if(self.buffs) + if(player.buffs) { - int buffid = buff_FirstFromFlags(self.buffs).m_id; - Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, buffid); + int buffid = buff_FirstFromFlags(player.buffs).m_id; + Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid); if(buff_lost >= 2) { - Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_BUFF_DROP, buffid); // TODO: special timeout message? - sound(self, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM); + Send_Notification(NOTIF_ONE, player, MSG_MULTI, ITEM_BUFF_DROP, buffid); // TODO: special timeout message? + sound(player, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM); } - self.buffs = 0; + player.buffs = 0; } } - if(self.buffs & BUFF_MAGNET.m_itemid) + if(player.buffs & BUFF_MAGNET.m_itemid) { - vector pickup_size = '1 1 1' * autocvar_g_buffs_magnet_range_item; - for(other = world; (other = findflags(other, flags, FL_ITEM)); ) - if(boxesoverlap(self.absmin - pickup_size, self.absmax + pickup_size, other.absmin, other.absmax)) + vector pickup_size; + FOREACH_ENTITY_FLAGS(flags, FL_ITEM, { - setself(other); - other = this; - if(self.touch) - self.touch(); - other = self; - setself(this); - } + if(it.buffs) + pickup_size = '1 1 1' * autocvar_g_buffs_magnet_range_buff; + else + pickup_size = '1 1 1' * autocvar_g_buffs_magnet_range_item; + + if(boxesoverlap(player.absmin - pickup_size, player.absmax + pickup_size, it.absmin, it.absmax)) + { + if(gettouch(it)) + gettouch(it)(it, player); + } + }); } - if(self.buffs & BUFF_AMMO.m_itemid) - if(self.clip_size) - self.clip_load = self.(weapon_load[PS(self).m_switchweapon.m_id]) = self.clip_size; + if(player.buffs & BUFF_AMMO.m_itemid) + if(player.clip_size) + player.clip_load = player.(weapon_load[PS(player).m_switchweapon.m_id]) = player.clip_size; + + if((player.buffs & BUFF_INVISIBLE.m_itemid) && (player.oldbuffs & BUFF_INVISIBLE.m_itemid)) + if(player.alpha != autocvar_g_buffs_invisible_alpha) + player.alpha = autocvar_g_buffs_invisible_alpha; // powerups reset alpha, so we must enforce this (TODO) - if((self.buffs & BUFF_INVISIBLE.m_itemid) && (self.oldbuffs & BUFF_INVISIBLE.m_itemid)) - if(self.alpha != autocvar_g_buffs_invisible_alpha) - self.alpha = autocvar_g_buffs_invisible_alpha; // powerups reset alpha, so we must enforce this (TODO) + if(player.buffs & BUFF_MEDIC.m_itemid) + if(time >= player.buff_medic_healtime) + { + buff_Medic_Heal(player); + player.buff_medic_healtime = time + autocvar_g_buffs_medic_heal_delay; + } -#define BUFF_ONADD(b) if ( (self.buffs & (b).m_itemid) && !(self.oldbuffs & (b).m_itemid)) -#define BUFF_ONREM(b) if (!(self.buffs & (b).m_itemid) && (self.oldbuffs & (b).m_itemid)) +#define BUFF_ONADD(b) if ( (player.buffs & (b).m_itemid) && !(player.oldbuffs & (b).m_itemid)) +#define BUFF_ONREM(b) if (!(player.buffs & (b).m_itemid) && (player.oldbuffs & (b).m_itemid)) - if(self.buffs != self.oldbuffs) + if(player.buffs != player.oldbuffs) { - entity buff = buff_FirstFromFlags(self.buffs); + entity buff = buff_FirstFromFlags(player.buffs); float bufftime = buff != BUFF_Null ? buff.m_time(buff) : 0; - self.buff_time = (bufftime) ? time + bufftime : 0; + player.buff_time = (bufftime) ? time + bufftime : 0; BUFF_ONADD(BUFF_AMMO) { - self.buff_ammo_prev_infitems = (self.items & IT_UNLIMITED_WEAPON_AMMO); - self.items |= IT_UNLIMITED_WEAPON_AMMO; + player.buff_ammo_prev_infitems = (player.items & IT_UNLIMITED_WEAPON_AMMO); + player.items |= IT_UNLIMITED_WEAPON_AMMO; - if(self.clip_load) - self.buff_ammo_prev_clipload = self.clip_load; - self.clip_load = self.(weapon_load[PS(self).m_switchweapon.m_id]) = self.clip_size; + if(player.clip_load) + player.buff_ammo_prev_clipload = player.clip_load; + player.clip_load = player.(weapon_load[PS(player).m_switchweapon.m_id]) = player.clip_size; } BUFF_ONREM(BUFF_AMMO) { - if(self.buff_ammo_prev_infitems) - self.items |= IT_UNLIMITED_WEAPON_AMMO; + if(player.buff_ammo_prev_infitems) + player.items |= IT_UNLIMITED_WEAPON_AMMO; else - self.items &= ~IT_UNLIMITED_WEAPON_AMMO; + player.items &= ~IT_UNLIMITED_WEAPON_AMMO; - if(self.buff_ammo_prev_clipload) - self.clip_load = self.buff_ammo_prev_clipload; + if(player.buff_ammo_prev_clipload) + player.clip_load = player.buff_ammo_prev_clipload; } BUFF_ONADD(BUFF_INVISIBLE) { - if(time < self.strength_finished && g_instagib) - self.alpha = autocvar_g_instagib_invis_alpha; + if(time < player.strength_finished && g_instagib) + player.alpha = autocvar_g_instagib_invis_alpha; else - self.alpha = self.buff_invisible_prev_alpha; - self.alpha = autocvar_g_buffs_invisible_alpha; + player.alpha = player.buff_invisible_prev_alpha; + player.alpha = autocvar_g_buffs_invisible_alpha; } BUFF_ONREM(BUFF_INVISIBLE) - self.alpha = self.buff_invisible_prev_alpha; + player.alpha = player.buff_invisible_prev_alpha; - BUFF_ONADD(BUFF_FLIGHT) + player.oldbuffs = player.buffs; + if(player.buffs) { - self.buff_flight_prev_gravity = self.gravity; - self.gravity = autocvar_g_buffs_flight_gravity; - } - - BUFF_ONREM(BUFF_FLIGHT) - self.gravity = self.buff_flight_prev_gravity; + if(!player.buff_model) + buffs_BuffModel_Spawn(player); - self.oldbuffs = self.buffs; - if(self.buffs) - { - if(!self.buff_model) - buffs_BuffModel_Spawn(self); + player.buff_model.color = buff.m_color; + player.buff_model.glowmod = buff_GlowColor(player.buff_model); + player.buff_model.skin = buff.m_skin; - self.buff_model.color = buff.m_color; - self.buff_model.glowmod = buff_GlowColor(self.buff_model); - self.buff_model.skin = buff.m_skin; - - self.effects |= EF_NOSHADOW; + player.effects |= EF_NOSHADOW; } else { - remove(self.buff_model); - self.buff_model = world; + remove(player.buff_model); + player.buff_model = NULL; - self.effects &= ~(EF_NOSHADOW); + player.effects &= ~(EF_NOSHADOW); } } - if(self.buff_model) + if(player.buff_model) { - self.buff_model.effects = self.effects; - self.buff_model.effects |= EF_LOWPRECISION; - self.buff_model.effects = self.buff_model.effects & EFMASK_CHEAP; // eat performance + player.buff_model.effects = player.effects; + player.buff_model.effects |= EF_LOWPRECISION; + player.buff_model.effects = player.buff_model.effects & EFMASK_CHEAP; // eat performance - self.buff_model.alpha = self.alpha; + player.buff_model.alpha = player.alpha; } #undef BUFF_ONADD #undef BUFF_ONREM - return false; } MUTATOR_HOOKFUNCTION(buffs, SpectateCopy) -{SELFPARAM(); - self.buffs = other.buffs; - return false; +{ + entity spectatee = M_ARGV(0, entity); + entity client = M_ARGV(1, entity); + + client.buffs = spectatee.buffs; } MUTATOR_HOOKFUNCTION(buffs, VehicleEnter) { - vh_vehicle.buffs = vh_player.buffs; - vh_player.buffs = 0; - vh_vehicle.buff_time = max(0, time - vh_player.buff_time); - vh_player.buff_time = 0; - return false; + entity player = M_ARGV(0, entity); + entity veh = M_ARGV(1, entity); + + veh.buffs = player.buffs; + player.buffs = 0; + veh.buff_time = max(0, player.buff_time - time); + player.buff_time = 0; } MUTATOR_HOOKFUNCTION(buffs, VehicleExit) { - vh_player.buffs = vh_player.oldbuffs = vh_vehicle.buffs; - vh_vehicle.buffs = 0; - vh_player.buff_time = time + vh_vehicle.buff_time; - vh_vehicle.buff_time = 0; - return false; + entity player = M_ARGV(0, entity); + entity veh = M_ARGV(1, entity); + + player.buffs = player.oldbuffs = veh.buffs; + veh.buffs = 0; + player.buff_time = time + veh.buff_time; + veh.buff_time = 0; } MUTATOR_HOOKFUNCTION(buffs, PlayerRegen) -{SELFPARAM(); - if(self.buffs & BUFF_MEDIC.m_itemid) +{ + entity player = M_ARGV(0, entity); + + if(player.buffs & BUFF_MEDIC.m_itemid) { - regen_mod_rot = autocvar_g_buffs_medic_rot; - regen_mod_limit = regen_mod_max = autocvar_g_buffs_medic_max; - regen_mod_regen = autocvar_g_buffs_medic_regen; + M_ARGV(2, float) = autocvar_g_buffs_medic_rot; // rot_mod + M_ARGV(4, float) = M_ARGV(1, float) = autocvar_g_buffs_medic_max; // limit_mod = max_mod + M_ARGV(2, float) = autocvar_g_buffs_medic_regen; // regen_mod } - if(self.buffs & BUFF_SPEED.m_itemid) - regen_mod_regen = autocvar_g_buffs_speed_regen; - - return false; + if(player.buffs & BUFF_SPEED.m_itemid) + M_ARGV(2, float) = autocvar_g_buffs_speed_regen; // regen_mod } -MUTATOR_HOOKFUNCTION(buffs, GetCvars) -{ - GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_buffs_autoreplace, "cl_buffs_autoreplace"); - return false; -} +REPLICATE(cvar_cl_buffs_autoreplace, bool, "cl_buffs_autoreplace"); MUTATOR_HOOKFUNCTION(buffs, BuildMutatorsString) { - ret_string = strcat(ret_string, ":Buffs"); - return false; + M_ARGV(0, string) = strcat(M_ARGV(0, string), ":Buffs"); } MUTATOR_HOOKFUNCTION(buffs, BuildMutatorsPrettyString) { - ret_string = strcat(ret_string, ", Buffs"); - return false; + M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Buffs"); } -void buffs_DelayedInit() +void buffs_DelayedInit(entity this) { if(autocvar_g_buffs_spawn_count > 0) - if(find(world, classname, "item_buff") == world) + if(find(NULL, classname, "item_buff") == NULL) { float i; for(i = 0; i < autocvar_g_buffs_spawn_count; ++i)