From 5eea97bc262bfaf271817ca034439ad551f691d4 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 10 Jun 2016 14:10:00 +1000 Subject: [PATCH] Purge self from the damage/death mutator hooks --- .../gamemodes/gamemode/nexball/nexball.qc | 5 +- .../gamemodes/gamemode/onslaught/onslaught.qc | 68 +++---- qcsrc/common/monsters/monster.qh | 2 +- qcsrc/common/monsters/monster/mage.qc | 4 +- qcsrc/common/monsters/monster/shambler.qc | 4 +- qcsrc/common/monsters/monster/spider.qc | 4 +- qcsrc/common/monsters/monster/wyvern.qc | 4 +- qcsrc/common/monsters/monster/zombie.qc | 4 +- qcsrc/common/monsters/sv_monsters.qc | 16 +- qcsrc/common/mutators/mutator/buffs/buffs.qc | 10 +- .../mutators/mutator/campcheck/campcheck.qc | 2 + .../mutators/mutator/instagib/instagib.qc | 13 +- qcsrc/common/mutators/mutator/nades/nades.qc | 20 ++- .../mutators/mutator/overkill/overkill.qc | 44 +++-- .../common/mutators/mutator/pinata/pinata.qc | 2 + .../mutator/rocketminsta/rocketminsta.qc | 3 + .../mutators/mutator/sandbox/sandbox.qc | 169 +++++++++--------- .../spawn_near_teammate.qc | 17 +- .../mutators/mutator/superspec/superspec.qc | 85 +++++---- .../mutators/mutator/vampire/vampire.qc | 4 + qcsrc/server/cl_player.qc | 11 +- qcsrc/server/command/cmd.qc | 2 +- qcsrc/server/g_damage.qc | 6 +- qcsrc/server/mutators/events.qh | 99 +++++----- qcsrc/server/mutators/mutator/gamemode_ca.qc | 14 +- qcsrc/server/mutators/mutator/gamemode_ctf.qc | 18 +- qcsrc/server/mutators/mutator/gamemode_cts.qc | 2 + .../mutators/mutator/gamemode_freezetag.qc | 6 +- .../mutators/mutator/gamemode_invasion.qc | 24 ++- .../mutators/mutator/gamemode_keepaway.qc | 9 +- .../mutators/mutator/gamemode_keyhunt.qc | 16 +- qcsrc/server/mutators/mutator/gamemode_lms.qc | 6 +- .../server/mutators/mutator/gamemode_race.qc | 2 + qcsrc/server/spawnpoints.qc | 6 +- 34 files changed, 400 insertions(+), 301 deletions(-) diff --git a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc index 57539be68..7d10f5d47 100644 --- a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc +++ b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc @@ -929,8 +929,9 @@ MUTATOR_HOOKFUNCTION(nb, ClientDisconnect) MUTATOR_HOOKFUNCTION(nb, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + nb_DropBall(frag_target); - return false; } MUTATOR_HOOKFUNCTION(nb, MakePlayerObserver) @@ -1074,6 +1075,8 @@ MUTATOR_HOOKFUNCTION(nb, WantWeapon) MUTATOR_HOOKFUNCTION(nb, DropSpecialItems) { + entity frag_target = M_ARGV(0, entity); + if(frag_target.ballcarried) DropBall(frag_target.ballcarried, frag_target.origin, frag_target.velocity); diff --git a/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc b/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc index 617af7c76..1f9c88780 100644 --- a/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc +++ b/qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc @@ -1596,13 +1596,13 @@ void havocbot_ons_reset_role(entity this) * Find control point or generator owned by the same team self which is nearest to pos * if max_dist is positive, only control points within this range will be considered */ -entity ons_Nearest_ControlPoint(vector pos, float max_dist) -{SELFPARAM(); +entity ons_Nearest_ControlPoint(entity this, vector pos, float max_dist) +{ entity tmp_entity, closest_target = world; tmp_entity = findchain(classname, "onslaught_controlpoint"); while(tmp_entity) { - if(SAME_TEAM(tmp_entity, self)) + if(SAME_TEAM(tmp_entity, this)) if(tmp_entity.iscaptured) if(max_dist <= 0 || vdist(tmp_entity.origin - pos, <=, max_dist)) if(vlen2(tmp_entity.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == world) @@ -1612,7 +1612,7 @@ entity ons_Nearest_ControlPoint(vector pos, float max_dist) tmp_entity = findchain(classname, "onslaught_generator"); while(tmp_entity) { - if(SAME_TEAM(tmp_entity, self)) + if(SAME_TEAM(tmp_entity, this)) if(max_dist <= 0 || vdist(tmp_entity.origin - pos, <, max_dist)) if(vlen2(tmp_entity.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == world) closest_target = tmp_entity; @@ -1627,8 +1627,8 @@ entity ons_Nearest_ControlPoint(vector pos, float max_dist) * if max_dist is positive, only control points within this range will be considered * This function only check distances on the XY plane, disregarding Z */ -entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist) -{SELFPARAM(); +entity ons_Nearest_ControlPoint_2D(entity this, vector pos, float max_dist) +{ entity tmp_entity, closest_target = world; vector delta; float smallest_distance = 0, distance; @@ -1640,7 +1640,7 @@ entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist) delta_z = 0; distance = vlen(delta); - if(SAME_TEAM(tmp_entity, self)) + if(SAME_TEAM(tmp_entity, this)) if(tmp_entity.iscaptured) if(max_dist <= 0 || distance <= max_dist) if(closest_target == world || distance <= smallest_distance ) @@ -1658,7 +1658,7 @@ entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist) delta_z = 0; distance = vlen(delta); - if(SAME_TEAM(tmp_entity, self)) + if(SAME_TEAM(tmp_entity, this)) if(max_dist <= 0 || distance <= max_dist) if(closest_target == world || distance <= smallest_distance ) { @@ -1910,6 +1910,8 @@ MUTATOR_HOOKFUNCTION(ons, PlayerSpawn) MUTATOR_HOOKFUNCTION(ons, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + frag_target.ons_deathloc = frag_target.origin; entity l; for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext) @@ -2026,13 +2028,17 @@ MUTATOR_HOOKFUNCTION(ons, SpectateCopy) } MUTATOR_HOOKFUNCTION(ons, SV_ParseClientCommand) -{SELFPARAM(); +{ if(MUTATOR_RETURNVALUE) // command was already handled? return false; + entity player = M_ARGV(0, entity); + string cmd_name = M_ARGV(1, string); + int cmd_argc = M_ARGV(2, int); + if ( cmd_name == "ons_spawn" ) { - vector pos = self.origin; + vector pos = player.origin; if(cmd_argc > 1) pos_x = stof(argv(1)); if(cmd_argc > 2) @@ -2040,53 +2046,53 @@ MUTATOR_HOOKFUNCTION(ons, SV_ParseClientCommand) if(cmd_argc > 3) pos_z = stof(argv(3)); - if ( IS_PLAYER(self) ) + if ( IS_PLAYER(player) ) { - if ( !STAT(FROZEN, self) ) + if ( !STAT(FROZEN, player) ) { - entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius); + entity source_point = ons_Nearest_ControlPoint(player, player.origin, autocvar_g_onslaught_teleport_radius); - if ( !source_point && self.health > 0 ) + if ( !source_point && player.health > 0 ) { - sprint(self, "\nYou need to be next to a control point\n"); - return 1; + sprint(player, "\nYou need to be next to a control point\n"); + return true; } - entity closest_target = ons_Nearest_ControlPoint_2D(pos, autocvar_g_onslaught_click_radius); + entity closest_target = ons_Nearest_ControlPoint_2D(player, pos, autocvar_g_onslaught_click_radius); if ( closest_target == world ) { - sprint(self, "\nNo control point found\n"); - return 1; + sprint(player, "\nNo control point found\n"); + return true; } - if ( self.health <= 0 ) + if ( player.health <= 0 ) { - self.ons_spawn_by = closest_target; - self.respawn_flags = self.respawn_flags | RESPAWN_FORCE; + player.ons_spawn_by = closest_target; + player.respawn_flags = player.respawn_flags | RESPAWN_FORCE; } else { if ( source_point == closest_target ) { - sprint(self, "\nTeleporting to the same point\n"); - return 1; + sprint(player, "\nTeleporting to the same point\n"); + return true; } - if ( !ons_Teleport(self,closest_target,autocvar_g_onslaught_teleport_radius,true) ) - sprint(self, "\nUnable to teleport there\n"); + if ( !ons_Teleport(player,closest_target,autocvar_g_onslaught_teleport_radius,true) ) + sprint(player, "\nUnable to teleport there\n"); } - return 1; + return true; } - sprint(self, "\nNo teleportation for you\n"); + sprint(player, "\nNo teleportation for you\n"); } - return 1; + return true; } - return 0; + return false; } MUTATOR_HOOKFUNCTION(ons, PlayerUseKey) @@ -2095,7 +2101,7 @@ MUTATOR_HOOKFUNCTION(ons, PlayerUseKey) if((time > self.teleport_antispam) && (!IS_DEAD(self)) && !self.vehicle) { - entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius); + entity source_point = ons_Nearest_ControlPoint(self, self.origin, autocvar_g_onslaught_teleport_radius); if ( source_point ) { stuffcmd(self, "qc_cmd_cl hud clickradar\n"); diff --git a/qcsrc/common/monsters/monster.qh b/qcsrc/common/monsters/monster.qh index 9ba1cde12..de24caa01 100644 --- a/qcsrc/common/monsters/monster.qh +++ b/qcsrc/common/monsters/monster.qh @@ -69,7 +69,7 @@ CLASS(Monster, Object) /** (BOTH) precaches models/sounds used by this monster */ METHOD(Monster, mr_precache, bool(Monster this)) { TC(Monster, this); return false; } /** (SERVER) called when monster is damaged */ - METHOD(Monster, mr_pain, bool(Monster this, entity actor)) { TC(Monster, this); return false; } + METHOD(Monster, mr_pain, float(Monster this, entity actor, float damage_take, entity attacker, float deathtype)) { TC(Monster, this); return damage_take; } /** (BOTH?) sets animations for monster */ METHOD(Monster, mr_anim, bool(Monster this, entity actor)) { TC(Monster, this); return false; } diff --git a/qcsrc/common/monsters/monster/mage.qc b/qcsrc/common/monsters/monster/mage.qc index 5b7bf3a56..2401c9011 100644 --- a/qcsrc/common/monsters/monster/mage.qc +++ b/qcsrc/common/monsters/monster/mage.qc @@ -445,10 +445,10 @@ METHOD(Mage, mr_think, bool(Mage thismon, entity actor)) return true; } -METHOD(Mage, mr_pain, bool(Mage this, entity actor)) +METHOD(Mage, mr_pain, float(Mage this, entity actor, float damage_take, entity attacker, float deathtype)) { TC(Mage, this); - return true; + return damage_take; } METHOD(Mage, mr_death, bool(Mage this, entity actor)) diff --git a/qcsrc/common/monsters/monster/shambler.qc b/qcsrc/common/monsters/monster/shambler.qc index 2e9384dc2..e98c372c2 100644 --- a/qcsrc/common/monsters/monster/shambler.qc +++ b/qcsrc/common/monsters/monster/shambler.qc @@ -236,12 +236,12 @@ METHOD(Shambler, mr_think, bool(Shambler this, entity actor)) return true; } -METHOD(Shambler, mr_pain, bool(Shambler this, entity actor)) +METHOD(Shambler, mr_pain, float(Shambler this, entity actor, float damage_take, entity attacker, float deathtype)) { TC(Shambler, this); actor.pain_finished = time + 0.5; setanim(actor, actor.anim_pain1, true, true, false); - return true; + return damage_take; } METHOD(Shambler, mr_death, bool(Shambler this, entity actor)) diff --git a/qcsrc/common/monsters/monster/spider.qc b/qcsrc/common/monsters/monster/spider.qc index a3651812b..8727b798d 100644 --- a/qcsrc/common/monsters/monster/spider.qc +++ b/qcsrc/common/monsters/monster/spider.qc @@ -234,10 +234,10 @@ METHOD(Spider, mr_think, bool(Spider this, entity actor)) return true; } -METHOD(Spider, mr_pain, bool(Spider this, entity actor)) +METHOD(Spider, mr_pain, float(Spider this, entity actor, float damage_take, entity attacker, float deathtype)) { TC(Spider, this); - return true; + return damage_take; } METHOD(Spider, mr_death, bool(Spider this, entity actor)) diff --git a/qcsrc/common/monsters/monster/wyvern.qc b/qcsrc/common/monsters/monster/wyvern.qc index ae8e8751d..edfc92ba5 100644 --- a/qcsrc/common/monsters/monster/wyvern.qc +++ b/qcsrc/common/monsters/monster/wyvern.qc @@ -151,12 +151,12 @@ METHOD(Wyvern, mr_think, bool(Wyvern this, entity actor)) return true; } -METHOD(Wyvern, mr_pain, bool(Wyvern this, entity actor)) +METHOD(Wyvern, mr_pain, float(Wyvern this, entity actor, float damage_take, entity attacker, float deathtype)) { TC(Wyvern, this); actor.pain_finished = time + 0.5; setanim(actor, actor.anim_pain1, true, true, false); - return true; + return damage_take; } METHOD(Wyvern, mr_death, bool(Wyvern this, entity actor)) diff --git a/qcsrc/common/monsters/monster/zombie.qc b/qcsrc/common/monsters/monster/zombie.qc index ec84bb948..578cf4c59 100644 --- a/qcsrc/common/monsters/monster/zombie.qc +++ b/qcsrc/common/monsters/monster/zombie.qc @@ -163,12 +163,12 @@ METHOD(Zombie, mr_think, bool(Zombie this, entity actor)) return true; } -METHOD(Zombie, mr_pain, bool(Zombie this, entity actor)) +METHOD(Zombie, mr_pain, float(Zombie this, entity actor, float damage_take, entity attacker, float deathtype)) { TC(Zombie, this); actor.pain_finished = time + 0.34; setanim(actor, ((random() > 0.5) ? actor.anim_pain1 : actor.anim_pain2), true, true, false); - return true; + return damage_take; } METHOD(Zombie, mr_death, bool(Zombie this, entity actor)) diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index 2e7281bc2..f641d7944 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -31,7 +31,7 @@ void monsters_setstatus(entity this) this.stat_monsters_killed = monsters_killed; } -void monster_dropitem(entity this) +void monster_dropitem(entity this, entity attacker) { if(!this.candrop || !this.monster_loot) return; @@ -42,8 +42,8 @@ void monster_dropitem(entity this) e.monster_loot = this.monster_loot; - MUTATOR_CALLHOOK(MonsterDropItem, e); - e = other; + MUTATOR_CALLHOOK(MonsterDropItem, this, e, attacker); + e = M_ARGV(1, entity); if(e && e.monster_loot) { @@ -991,7 +991,7 @@ void Monster_Dead(entity this, entity attacker, float gibbed) this.health = 0; // reset by Unfreeze } - monster_dropitem(this); + monster_dropitem(this, attacker); Monster_Sound(this, monstersound_death, 0, false, CH_VOICE); @@ -1057,12 +1057,8 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage take = v_x; save = v_y; - damage_take = take; - frag_attacker = attacker; - frag_deathtype = deathtype; Monster mon = get_monsterinfo(this.monsterid); - mon.mr_pain(mon, this); - take = damage_take; + take = mon.mr_pain(mon, this, take, attacker, deathtype); if(take) { @@ -1102,7 +1098,7 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage WaypointSprite_Kill(this.sprite); - MUTATOR_CALLHOOK(MonsterDies, this, attacker); + MUTATOR_CALLHOOK(MonsterDies, this, attacker, deathtype); if(this.health <= -100 || deathtype == DEATH_KILL.m_id) // check if we're already gibbed { diff --git a/qcsrc/common/mutators/mutator/buffs/buffs.qc b/qcsrc/common/mutators/mutator/buffs/buffs.qc index 869dbcb62..01e7f31bb 100644 --- a/qcsrc/common/mutators/mutator/buffs/buffs.qc +++ b/qcsrc/common/mutators/mutator/buffs/buffs.qc @@ -505,13 +505,17 @@ float buff_Inferno_CalculateTime(float x, float offset_x, float offset_y, float // mutator hooks MUTATOR_HOOKFUNCTION(buffs, PlayerDamage_SplitHealthArmor) { + 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 false; } 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; @@ -679,6 +683,8 @@ MUTATOR_HOOKFUNCTION(buffs, MonsterMove) MUTATOR_HOOKFUNCTION(buffs, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + if(frag_target.buffs) { int buffid = buff_FirstFromFlags(frag_target.buffs).m_id; diff --git a/qcsrc/common/mutators/mutator/campcheck/campcheck.qc b/qcsrc/common/mutators/mutator/campcheck/campcheck.qc index b6d17a3ee..183eac3cd 100644 --- a/qcsrc/common/mutators/mutator/campcheck/campcheck.qc +++ b/qcsrc/common/mutators/mutator/campcheck/campcheck.qc @@ -10,6 +10,8 @@ REGISTER_MUTATOR(campcheck, cvar("g_campcheck")); MUTATOR_HOOKFUNCTION(campcheck, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + Kill_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CPID_CAMPCHECK); return false; } diff --git a/qcsrc/common/mutators/mutator/instagib/instagib.qc b/qcsrc/common/mutators/mutator/instagib/instagib.qc index fa8ce9734..34836ab3d 100644 --- a/qcsrc/common/mutators/mutator/instagib/instagib.qc +++ b/qcsrc/common/mutators/mutator/instagib/instagib.qc @@ -145,7 +145,9 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, MatchEnd) MUTATOR_HOOKFUNCTION(mutator_instagib, MonsterDropItem) { - other.monster_loot = spawnfunc_item_minst_cells; + entity item = M_ARGV(1, entity); + + item.monster_loot = spawnfunc_item_minst_cells; return false; } @@ -253,10 +255,8 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerPhysics) MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerDamage_SplitHealthArmor) { - damage_save = 0; - damage_take = frag_damage; - - return false; + M_ARGV(4, float) = M_ARGV(7, float); // take = damage + M_ARGV(5, float) = 0; // save } MUTATOR_HOOKFUNCTION(mutator_instagib, ForbidThrowCurrentWeapon) @@ -423,6 +423,9 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, CustomizeWaypoint) MUTATOR_HOOKFUNCTION(mutator_instagib, PlayerDies) { + float frag_deathtype = M_ARGV(3, float); + float frag_damage = M_ARGV(4, float); + if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER)) frag_damage = 1000; // always gib if it was a vaporizer death diff --git a/qcsrc/common/mutators/mutator/nades/nades.qc b/qcsrc/common/mutators/mutator/nades/nades.qc index 6b2782286..999bd4ada 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.qc +++ b/qcsrc/common/mutators/mutator/nades/nades.qc @@ -1270,6 +1270,9 @@ MUTATOR_HOOKFUNCTION(nades, PlayerSpawn) MUTATOR_HOOKFUNCTION(nades, PlayerDies, CBC_ORDER_LAST) { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + if(frag_target.nade) if(!STAT(FROZEN, frag_target) || !autocvar_g_freezetag_revive_nade) toss_nade(frag_target, true, '0 0 100', max(frag_target.nade.wait, time + 0.05)); @@ -1298,17 +1301,14 @@ MUTATOR_HOOKFUNCTION(nades, PlayerDies, CBC_ORDER_LAST) } nades_RemoveBonus(frag_target); - - return false; } MUTATOR_HOOKFUNCTION(nades, PlayerDamage_Calculate) { + entity frag_inflictor = M_ARGV(0, entity); 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(STAT(FROZEN, frag_target)) if(autocvar_g_freezetag_revive_nade) @@ -1319,13 +1319,10 @@ MUTATOR_HOOKFUNCTION(nades, PlayerDamage_Calculate) Unfreeze(frag_target); frag_target.health = autocvar_g_freezetag_revive_nade_health; Send_Effect(EFFECT_ICEORGLASS, frag_target.origin, '0 0 0', 3); - frag_damage = 0; - frag_force = '0 0 0'; + M_ARGV(4, float) = 0; + M_ARGV(6, vector) = '0 0 0'; Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_REVIVED_NADE, frag_target.netname); Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF); - - M_ARGV(4, float) = frag_damage; - M_ARGV(6, vector) = frag_force; } return false; @@ -1333,6 +1330,9 @@ MUTATOR_HOOKFUNCTION(nades, PlayerDamage_Calculate) MUTATOR_HOOKFUNCTION(nades, MonsterDies) { + entity frag_target = M_ARGV(0, entity); + entity frag_attacker = M_ARGV(1, entity); + if(IS_PLAYER(frag_attacker)) if(DIFF_TEAM(frag_attacker, frag_target)) if(!(frag_target.spawnflags & MONSTERFLAG_SPAWNED)) @@ -1343,6 +1343,8 @@ MUTATOR_HOOKFUNCTION(nades, MonsterDies) MUTATOR_HOOKFUNCTION(nades, DropSpecialItems) { + entity frag_target = M_ARGV(0, entity); + if(frag_target.nade) toss_nade(frag_target, true, '0 0 0', time + 0.05); diff --git a/qcsrc/common/mutators/mutator/overkill/overkill.qc b/qcsrc/common/mutators/mutator/overkill/overkill.qc index b8a203990..71b111476 100644 --- a/qcsrc/common/mutators/mutator/overkill/overkill.qc +++ b/qcsrc/common/mutators/mutator/overkill/overkill.qc @@ -123,41 +123,55 @@ MUTATOR_HOOKFUNCTION(ok, PlayerDamage_Calculate, CBC_ORDER_LAST) MUTATOR_HOOKFUNCTION(ok, PlayerDamage_SplitHealthArmor) { + entity frag_target = M_ARGV(2, entity); + float damage_take = M_ARGV(4, float); + if(damage_take) frag_target.ok_pauseregen_finished = max(frag_target.ok_pauseregen_finished, time + 2); - return false; } -MUTATOR_HOOKFUNCTION(ok, PlayerDies) +void ok_DropItem(entity this, entity targ) { - entity targ = ((frag_attacker) ? frag_attacker : frag_target); - - if(IS_MONSTER(frag_target)) - { - remove(other); // remove default item - other = NULL; - } - entity e = new(droppedweapon); // hax e.ok_item = true; e.noalign = true; e.pickup_anyway = true; e.spawnfunc_checked = true; - spawnfunc_item_armor_small(e); + WITHSELF(e, spawnfunc_item_armor_small(e)); if (!wasfreed(e)) { // might have been blocked by a mutator e.movetype = MOVETYPE_TOSS; e.gravity = 1; e.reset = SUB_Remove; - setorigin(e, frag_target.origin + '0 0 32'); - e.velocity = '0 0 200' + normalize(targ.origin - frag_target.origin) * 500; + setorigin(e, this.origin + '0 0 32'); + e.velocity = '0 0 200' + normalize(targ.origin - this.origin) * 500; SUB_SetFade(e, time + 5, 1); } +} + +MUTATOR_HOOKFUNCTION(ok, PlayerDies) +{ + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + + entity targ = ((frag_attacker) ? frag_attacker : frag_target); + + ok_DropItem(frag_target, targ); frag_target.ok_lastwep = PS(frag_target).m_switchweapon.m_id; +} - return false; +MUTATOR_HOOKFUNCTION(ok, MonsterDropItem) +{ + entity mon = M_ARGV(0, entity); + entity olditem = M_ARGV(1, entity); + entity frag_attacker = M_ARGV(2, entity); + + remove(olditem); + + M_ARGV(1, entity) = NULL; + + ok_DropItem(mon, frag_attacker); } -MUTATOR_HOOKFUNCTION(ok, MonsterDropItem) { ok_PlayerDies(); } MUTATOR_HOOKFUNCTION(ok, PlayerRegen) {SELFPARAM(); diff --git a/qcsrc/common/mutators/mutator/pinata/pinata.qc b/qcsrc/common/mutators/mutator/pinata/pinata.qc index 62dd19e4f..b9b4b6c4c 100644 --- a/qcsrc/common/mutators/mutator/pinata/pinata.qc +++ b/qcsrc/common/mutators/mutator/pinata/pinata.qc @@ -3,6 +3,8 @@ REGISTER_MUTATOR(pinata, cvar("g_pinata") && !cvar("g_instagib") && !cvar("g_ove MUTATOR_HOOKFUNCTION(pinata, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + FOREACH(Weapons, it != WEP_Null, LAMBDA( if(frag_target.weapons & WepSet_FromWeapon(it)) if(PS(frag_target).m_switchweapon != it) diff --git a/qcsrc/common/mutators/mutator/rocketminsta/rocketminsta.qc b/qcsrc/common/mutators/mutator/rocketminsta/rocketminsta.qc index b6264647c..143c985f6 100644 --- a/qcsrc/common/mutators/mutator/rocketminsta/rocketminsta.qc +++ b/qcsrc/common/mutators/mutator/rocketminsta/rocketminsta.qc @@ -33,6 +33,9 @@ MUTATOR_HOOKFUNCTION(rm, PlayerDies) // we do it this way, so rm can be toggled during the match if(!autocvar_g_rm) { return false; } + float frag_deathtype = M_ARGV(3, float); + float frag_damage = M_ARGV(4, float); + if(DEATH_ISWEAPON(frag_deathtype, WEP_DEVASTATOR) || DEATH_ISWEAPON(frag_deathtype, WEP_ELECTRO)) frag_damage = 1000; // always gib if it was a vaporizer death diff --git a/qcsrc/common/mutators/mutator/sandbox/sandbox.qc b/qcsrc/common/mutators/mutator/sandbox/sandbox.qc index b3e9ea15a..1ab693512 100644 --- a/qcsrc/common/mutators/mutator/sandbox/sandbox.qc +++ b/qcsrc/common/mutators/mutator/sandbox/sandbox.qc @@ -450,19 +450,24 @@ void sandbox_Database_Load() } MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) -{SELFPARAM(); +{ if(MUTATOR_RETURNVALUE) // command was already handled? return false; + + entity player = M_ARGV(0, entity); + string cmd_name = M_ARGV(1, string); + int cmd_argc = M_ARGV(2, int); + if(cmd_name == "g_sandbox") { if(autocvar_g_sandbox_readonly) { - print_to(self, "^2SANDBOX - INFO: ^7Sandbox mode is active, but in read-only mode. Sandbox commands cannot be used"); + print_to(player, "^2SANDBOX - INFO: ^7Sandbox mode is active, but in read-only mode. Sandbox commands cannot be used"); return true; } if(cmd_argc < 2) { - print_to(self, "^2SANDBOX - INFO: ^7Sandbox mode is active. For usage information, type 'sandbox help'"); + print_to(player, "^2SANDBOX - INFO: ^7Sandbox mode is active. For usage information, type 'sandbox help'"); return true; } @@ -474,56 +479,56 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) // ---------------- COMMAND: HELP ---------------- case "help": - print_to(self, "You can use the following sandbox commands:"); - print_to(self, "^7\"^2object_spawn ^3models/foo/bar.md3^7\" spawns a new object in front of the player, and gives it the specified model"); - print_to(self, "^7\"^2object_remove^7\" removes the object the player is looking at. Players can only remove their own objects"); - print_to(self, "^7\"^2object_duplicate ^3value^7\" duplicates the object, if the player has copying rights over the original"); - print_to(self, "^3copy value ^7- copies the properties of the object to the specified client cvar"); - print_to(self, "^3paste value ^7- spawns an object with the given properties. Properties or cvars must be specified as follows; eg1: \"0 1 2 ...\", eg2: \"$cl_cvar\""); - print_to(self, "^7\"^2object_attach ^3property value^7\" attaches one object to another. Players can only attach their own objects"); - print_to(self, "^3get ^7- selects the object you are facing as the object to be attached"); - print_to(self, "^3set value ^7- attaches the previously selected object to the object you are facing, on the specified bone"); - print_to(self, "^3remove ^7- detaches all objects from the object you are facing"); - print_to(self, "^7\"^2object_edit ^3property value^7\" edits the given property of the object. Players can only edit their own objects"); - print_to(self, "^3skin value ^7- changes the skin of the object"); - print_to(self, "^3alpha value ^7- sets object transparency"); - print_to(self, "^3colormod \"value_x value_y value_z\" ^7- main object color"); - print_to(self, "^3glowmod \"value_x value_y value_z\" ^7- glow object color"); - print_to(self, "^3frame value ^7- object animation frame, for self-animated models"); - print_to(self, "^3scale value ^7- changes object scale. 0.5 is half size and 2 is double size"); - print_to(self, "^3solidity value ^7- object collisions, 0 = non-solid, 1 = solid"); - print_to(self, "^3physics value ^7- object physics, 0 = static, 1 = movable, 2 = physical"); - print_to(self, "^3force value ^7- amount of force applied to objects that are shot"); - print_to(self, "^3material value ^7- sets the material of the object. Default materials are: metal, stone, wood, flesh"); - print_to(self, "^7\"^2object_claim^7\" sets the player as the owner of the object, if he has the right to edit it"); - print_to(self, "^7\"^2object_info ^3value^7\" shows public information about the object"); - print_to(self, "^3object ^7- prints general information about the object, such as owner and creation / editing date"); - print_to(self, "^3mesh ^7- prints information about the object's mesh, including skeletal bones"); - print_to(self, "^3attachments ^7- prints information about the object's attachments"); - print_to(self, "^7The ^1drag object ^7key can be used to grab and carry objects. Players can only grab their own objects"); + print_to(player, "You can use the following sandbox commands:"); + print_to(player, "^7\"^2object_spawn ^3models/foo/bar.md3^7\" spawns a new object in front of the player, and gives it the specified model"); + print_to(player, "^7\"^2object_remove^7\" removes the object the player is looking at. Players can only remove their own objects"); + print_to(player, "^7\"^2object_duplicate ^3value^7\" duplicates the object, if the player has copying rights over the original"); + print_to(player, "^3copy value ^7- copies the properties of the object to the specified client cvar"); + print_to(player, "^3paste value ^7- spawns an object with the given properties. Properties or cvars must be specified as follows; eg1: \"0 1 2 ...\", eg2: \"$cl_cvar\""); + print_to(player, "^7\"^2object_attach ^3property value^7\" attaches one object to another. Players can only attach their own objects"); + print_to(player, "^3get ^7- selects the object you are facing as the object to be attached"); + print_to(player, "^3set value ^7- attaches the previously selected object to the object you are facing, on the specified bone"); + print_to(player, "^3remove ^7- detaches all objects from the object you are facing"); + print_to(player, "^7\"^2object_edit ^3property value^7\" edits the given property of the object. Players can only edit their own objects"); + print_to(player, "^3skin value ^7- changes the skin of the object"); + print_to(player, "^3alpha value ^7- sets object transparency"); + print_to(player, "^3colormod \"value_x value_y value_z\" ^7- main object color"); + print_to(player, "^3glowmod \"value_x value_y value_z\" ^7- glow object color"); + print_to(player, "^3frame value ^7- object animation frame, for self-animated models"); + print_to(player, "^3scale value ^7- changes object scale. 0.5 is half size and 2 is double size"); + print_to(player, "^3solidity value ^7- object collisions, 0 = non-solid, 1 = solid"); + print_to(player, "^3physics value ^7- object physics, 0 = static, 1 = movable, 2 = physical"); + print_to(player, "^3force value ^7- amount of force applied to objects that are shot"); + print_to(player, "^3material value ^7- sets the material of the object. Default materials are: metal, stone, wood, flesh"); + print_to(player, "^7\"^2object_claim^7\" sets the player as the owner of the object, if he has the right to edit it"); + print_to(player, "^7\"^2object_info ^3value^7\" shows public information about the object"); + print_to(player, "^3object ^7- prints general information about the object, such as owner and creation / editing date"); + print_to(player, "^3mesh ^7- prints information about the object's mesh, including skeletal bones"); + print_to(player, "^3attachments ^7- prints information about the object's attachments"); + print_to(player, "^7The ^1drag object ^7key can be used to grab and carry objects. Players can only grab their own objects"); return true; // ---------------- COMMAND: OBJECT, SPAWN ---------------- case "object_spawn": - if(time < self.object_flood) + if(time < player.object_flood) { - print_to(self, strcat("^1SANDBOX - WARNING: ^7Flood protection active. Please wait ^3", ftos(self.object_flood - time), " ^7seconds beofore spawning another object")); + print_to(player, strcat("^1SANDBOX - WARNING: ^7Flood protection active. Please wait ^3", ftos(player.object_flood - time), " ^7seconds beofore spawning another object")); return true; } - self.object_flood = time + autocvar_g_sandbox_editor_flood; + player.object_flood = time + autocvar_g_sandbox_editor_flood; if(object_count >= autocvar_g_sandbox_editor_maxobjects) { - print_to(self, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time")); + print_to(player, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time")); return true; } if(cmd_argc < 3) { - print_to(self, "^1SANDBOX - WARNING: ^7Attempted to spawn an object without specifying a model. Please specify the path to your model file after the 'object_spawn' command"); + print_to(player, "^1SANDBOX - WARNING: ^7Attempted to spawn an object without specifying a model. Please specify the path to your model file after the 'object_spawn' command"); return true; } if (!(fexists(argv(2)))) { - print_to(self, "^1SANDBOX - WARNING: ^7Attempted to spawn an object with a non-existent model. Make sure the path to your model file is correct"); + print_to(player, "^1SANDBOX - WARNING: ^7Attempted to spawn an object with a non-existent model. Make sure the path to your model file is correct"); return true; } @@ -531,7 +536,7 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) _setmodel(e, argv(2)); if(autocvar_g_sandbox_info > 0) - LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", self.netname, " spawned an object at origin ^3", vtos(e.origin), "\n")); + LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", player.netname, " spawned an object at origin ^3", vtos(e.origin), "\n")); return true; // ---------------- COMMAND: OBJECT, REMOVE ---------------- @@ -540,12 +545,12 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) if(e != world) { if(autocvar_g_sandbox_info > 0) - LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", self.netname, " removed an object at origin ^3", vtos(e.origin), "\n")); + LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", player.netname, " removed an object at origin ^3", vtos(e.origin), "\n")); sandbox_ObjectRemove(e); return true; } - print_to(self, "^1SANDBOX - WARNING: ^7Object could not be removed. Make sure you are facing an object that you have edit rights over"); + print_to(player, "^1SANDBOX - WARNING: ^7Object could not be removed. Make sure you are facing an object that you have edit rights over"); return true; // ---------------- COMMAND: OBJECT, DUPLICATE ---------------- @@ -559,37 +564,37 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) { s = sandbox_ObjectPort_Save(e, false); s = strreplace("\"", "\\\"", s); - stuffcmd(self, strcat("set ", argv(3), " \"", s, "\"")); + stuffcmd(player, strcat("set ", argv(3), " \"", s, "\"")); - print_to(self, "^2SANDBOX - INFO: ^7Object copied to clipboard"); + print_to(player, "^2SANDBOX - INFO: ^7Object copied to clipboard"); return true; } - print_to(self, "^1SANDBOX - WARNING: ^7Object could not be copied. Make sure you are facing an object that you have copy rights over"); + print_to(player, "^1SANDBOX - WARNING: ^7Object could not be copied. Make sure you are facing an object that you have copy rights over"); return true; case "paste": // spawns a new object using the properties in the player's clipboard cvar - if(time < self.object_flood) + if(time < player.object_flood) { - print_to(self, strcat("^1SANDBOX - WARNING: ^7Flood protection active. Please wait ^3", ftos(self.object_flood - time), " ^7seconds beofore spawning another object")); + print_to(player, strcat("^1SANDBOX - WARNING: ^7Flood protection active. Please wait ^3", ftos(player.object_flood - time), " ^7seconds beofore spawning another object")); return true; } - self.object_flood = time + autocvar_g_sandbox_editor_flood; + player.object_flood = time + autocvar_g_sandbox_editor_flood; if(argv(3) == "") // no object in clipboard { - print_to(self, "^1SANDBOX - WARNING: ^7No object in clipboard. You must copy an object before you can paste it"); + print_to(player, "^1SANDBOX - WARNING: ^7No object in clipboard. You must copy an object before you can paste it"); return true; } if(object_count >= autocvar_g_sandbox_editor_maxobjects) { - print_to(self, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time")); + print_to(player, strcat("^1SANDBOX - WARNING: ^7Cannot spawn any more objects. Up to ^3", ftos(autocvar_g_sandbox_editor_maxobjects), " ^7objects may exist at a time")); return true; } e = sandbox_ObjectPort_Load(argv(3), false); - print_to(self, "^2SANDBOX - INFO: ^7Object pasted successfully"); + print_to(player, "^2SANDBOX - INFO: ^7Object pasted successfully"); if(autocvar_g_sandbox_info > 0) - LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", self.netname, " pasted an object at origin ^3", vtos(e.origin), "\n")); + LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", player.netname, " pasted an object at origin ^3", vtos(e.origin), "\n")); return true; } return true; @@ -603,16 +608,16 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) e = sandbox_ObjectEdit_Get(true); if(e != world) { - self.object_attach = e; - print_to(self, "^2SANDBOX - INFO: ^7Object selected for attachment"); + player.object_attach = e; + print_to(player, "^2SANDBOX - INFO: ^7Object selected for attachment"); return true; } - print_to(self, "^1SANDBOX - WARNING: ^7Object could not be selected for attachment. Make sure you are facing an object that you have edit rights over"); + print_to(player, "^1SANDBOX - WARNING: ^7Object could not be selected for attachment. Make sure you are facing an object that you have edit rights over"); return true; case "set": - if(self.object_attach == world) + if(player.object_attach == world) { - print_to(self, "^1SANDBOX - WARNING: ^7No object selected for attachment. Please select an object to be attached first."); + print_to(player, "^1SANDBOX - WARNING: ^7No object selected for attachment. Please select an object to be attached first."); return true; } @@ -620,14 +625,14 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) e = sandbox_ObjectEdit_Get(true); if(e != world) { - sandbox_ObjectAttach_Set(self.object_attach, e, argv(3)); - self.object_attach = world; // object was attached, no longer keep it scheduled for attachment - print_to(self, "^2SANDBOX - INFO: ^7Object attached successfully"); + sandbox_ObjectAttach_Set(player.object_attach, e, argv(3)); + player.object_attach = world; // object was attached, no longer keep it scheduled for attachment + print_to(player, "^2SANDBOX - INFO: ^7Object attached successfully"); if(autocvar_g_sandbox_info > 1) - LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", self.netname, " attached objects at origin ^3", vtos(e.origin), "\n")); + LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", player.netname, " attached objects at origin ^3", vtos(e.origin), "\n")); return true; } - print_to(self, "^1SANDBOX - WARNING: ^7Object could not be attached to the parent. Make sure you are facing an object that you have edit rights over"); + print_to(player, "^1SANDBOX - WARNING: ^7Object could not be attached to the parent. Make sure you are facing an object that you have edit rights over"); return true; case "remove": // removes e if it was attached @@ -635,12 +640,12 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) if(e != world) { sandbox_ObjectAttach_Remove(e); - print_to(self, "^2SANDBOX - INFO: ^7Child objects detached successfully"); + print_to(player, "^2SANDBOX - INFO: ^7Child objects detached successfully"); if(autocvar_g_sandbox_info > 1) - LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", self.netname, " detached objects at origin ^3", vtos(e.origin), "\n")); + LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", player.netname, " detached objects at origin ^3", vtos(e.origin), "\n")); return true; } - print_to(self, "^1SANDBOX - WARNING: ^7Child objects could not be detached. Make sure you are facing an object that you have edit rights over"); + print_to(player, "^1SANDBOX - WARNING: ^7Child objects could not be detached. Make sure you are facing an object that you have edit rights over"); return true; } return true; @@ -649,7 +654,7 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) case "object_edit": if(argv(2) == "") { - print_to(self, "^1SANDBOX - WARNING: ^7Too few parameters. You must specify a property to edit"); + print_to(player, "^1SANDBOX - WARNING: ^7Too few parameters. You must specify a property to edit"); return true; } @@ -719,7 +724,7 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) e.material = string_null; // no material break; default: - print_to(self, "^1SANDBOX - WARNING: ^7Invalid object property. For usage information, type 'sandbox help'"); + print_to(player, "^1SANDBOX - WARNING: ^7Invalid object property. For usage information, type 'sandbox help'"); return true; } @@ -728,19 +733,19 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) e.message2 = strzone(strftime(true, "%d-%m-%Y %H:%M:%S")); if(autocvar_g_sandbox_info > 1) - LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", self.netname, " edited property ^3", argv(2), " ^7of an object at origin ^3", vtos(e.origin), "\n")); + LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", player.netname, " edited property ^3", argv(2), " ^7of an object at origin ^3", vtos(e.origin), "\n")); return true; } - print_to(self, "^1SANDBOX - WARNING: ^7Object could not be edited. Make sure you are facing an object that you have edit rights over"); + print_to(player, "^1SANDBOX - WARNING: ^7Object could not be edited. Make sure you are facing an object that you have edit rights over"); return true; // ---------------- COMMAND: OBJECT, CLAIM ---------------- case "object_claim": // if the player can edit an object but is not its owner, this can be used to claim that object - if(self.crypto_idfp == "") + if(player.crypto_idfp == "") { - print_to(self, "^1SANDBOX - WARNING: ^7You do not have a player UID, and cannot claim objects"); + print_to(player, "^1SANDBOX - WARNING: ^7You do not have a player UID, and cannot claim objects"); return true; } e = sandbox_ObjectEdit_Get(true); @@ -749,25 +754,25 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) // update the owner's name // Do this before checking if you're already the owner and skipping if such, so we // also update the player's nickname if he changed it (but has the same player UID) - if(e.netname != self.netname) + if(e.netname != player.netname) { if(e.netname) strunzone(e.netname); - e.netname = strzone(self.netname); - print_to(self, "^2SANDBOX - INFO: ^7Object owner name updated"); + e.netname = strzone(player.netname); + print_to(player, "^2SANDBOX - INFO: ^7Object owner name updated"); } - if(e.crypto_idfp == self.crypto_idfp) + if(e.crypto_idfp == player.crypto_idfp) { - print_to(self, "^2SANDBOX - INFO: ^7Object is already yours, nothing to claim"); + print_to(player, "^2SANDBOX - INFO: ^7Object is already yours, nothing to claim"); return true; } if(e.crypto_idfp) strunzone(e.crypto_idfp); - e.crypto_idfp = strzone(self.crypto_idfp); + e.crypto_idfp = strzone(player.crypto_idfp); - print_to(self, "^2SANDBOX - INFO: ^7Object claimed successfully"); + print_to(player, "^2SANDBOX - INFO: ^7Object claimed successfully"); } - print_to(self, "^1SANDBOX - WARNING: ^7Object could not be claimed. Make sure you are facing an object that you have edit rights over"); + print_to(player, "^1SANDBOX - WARNING: ^7Object could not be claimed. Make sure you are facing an object that you have edit rights over"); return true; // ---------------- COMMAND: OBJECT, INFO ---------------- @@ -779,13 +784,13 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) switch(argv(2)) { case "object": - print_to(self, strcat("^2SANDBOX - INFO: ^7Object is owned by \"^7", e.netname, "^7\", created \"^3", e.message, "^7\", last edited \"^3", e.message2, "^7\"")); + print_to(player, strcat("^2SANDBOX - INFO: ^7Object is owned by \"^7", e.netname, "^7\", created \"^3", e.message, "^7\", last edited \"^3", e.message2, "^7\"")); return true; case "mesh": s = ""; FOR_EACH_TAG(e) s = strcat(s, "^7\"^5", gettaginfo_name, "^7\", "); - print_to(self, strcat("^2SANDBOX - INFO: ^7Object mesh is \"^3", e.model, "^7\" at animation frame ^3", ftos(e.frame), " ^7containing the following tags: ", s)); + print_to(player, strcat("^2SANDBOX - INFO: ^7Object mesh is \"^3", e.model, "^7\" at animation frame ^3", ftos(e.frame), " ^7containing the following tags: ", s)); return true; case "attachments": // this should show the same info as 'mesh' but for attachments @@ -803,18 +808,18 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand) } } if(i) // object contains attachments - print_to(self, strcat("^2SANDBOX - INFO: ^7Object contains the following ^1", ftos(i), "^7 attachment(s): ", s)); + print_to(player, strcat("^2SANDBOX - INFO: ^7Object contains the following ^1", ftos(i), "^7 attachment(s): ", s)); else - print_to(self, "^2SANDBOX - INFO: ^7Object contains no attachments"); + print_to(player, "^2SANDBOX - INFO: ^7Object contains no attachments"); return true; } } - print_to(self, "^1SANDBOX - WARNING: ^7No information could be found. Make sure you are facing an object"); + print_to(player, "^1SANDBOX - WARNING: ^7No information could be found. Make sure you are facing an object"); return true; // ---------------- COMMAND: DEFAULT ---------------- default: - print_to(self, "Invalid command. For usage information, type 'sandbox help'"); + print_to(player, "Invalid command. For usage information, type 'sandbox help'"); return true; } } diff --git a/qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc b/qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc index 3d2c17f33..038548399 100644 --- a/qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc +++ b/qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc @@ -17,8 +17,12 @@ REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate")); .float cvar_cl_spawn_near_teammate; MUTATOR_HOOKFUNCTION(spawn_near_teammate, Spawn_Score) -{SELFPARAM(); - if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate)) +{ + entity player = M_ARGV(0, entity); + entity spawn_spot = M_ARGV(1, entity); + vector spawn_score = M_ARGV(2, vector); + + if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && player.cvar_cl_spawn_near_teammate)) return false; spawn_spot.msnt_lookat = world; @@ -27,7 +31,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, Spawn_Score) return false; RandomSelection_Init(); - FOREACH_CLIENT(IS_PLAYER(it) && it != self && SAME_TEAM(it, self) && !IS_DEAD(it), LAMBDA( + FOREACH_CLIENT(IS_PLAYER(it) && it != player && SAME_TEAM(it, player) && !IS_DEAD(it), LAMBDA( if(vdist(spawn_spot.origin - it.origin, >, autocvar_g_spawn_near_teammate_distance)) continue; if(vdist(spawn_spot.origin - it.origin, <, 48)) @@ -42,9 +46,11 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, Spawn_Score) spawn_spot.msnt_lookat = RandomSelection_chosen_ent; spawn_score.x += SPAWN_PRIO_NEAR_TEAMMATE_FOUND; } - else if(self.team == spawn_spot.team) + else if(player.team == spawn_spot.team) spawn_score.x += SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM; // prefer same team, if we can't find a spawn near teammate + M_ARGV(2, vector) = spawn_score; + return false; } @@ -52,6 +58,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) { if(!teamplay) { return false; } entity player = M_ARGV(0, entity); + entity spawn_spot = M_ARGV(1, entity); int num_red = 0, num_blue = 0, num_yellow = 0, num_pink = 0; FOREACH_CLIENT(IS_PLAYER(it), @@ -176,6 +183,8 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerDies) { + entity frag_target = M_ARGV(0, entity); + frag_target.msnt_deathloc = frag_target.origin; return false; } diff --git a/qcsrc/common/mutators/mutator/superspec/superspec.qc b/qcsrc/common/mutators/mutator/superspec/superspec.qc index 142f9d9ba..c3ce2d27d 100644 --- a/qcsrc/common/mutators/mutator/superspec/superspec.qc +++ b/qcsrc/common/mutators/mutator/superspec/superspec.qc @@ -147,7 +147,7 @@ MUTATOR_HOOKFUNCTION(superspec, ItemTouch) } MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) -{SELFPARAM(); +{ #define OPTIONINFO(flag,var,test,text,long,short) \ var = strcat(var, ((flag & test) ? "^2[ON] ^7" : "^1[OFF] ^7")); \ var = strcat(var, text," ^7(^3 ", long, "^7 | ^3", short, " ^7)\n") @@ -155,7 +155,11 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) if(MUTATOR_RETURNVALUE) // command was already handled? return false; - if(IS_PLAYER(self)) + entity player = M_ARGV(0, entity); + string cmd_name = M_ARGV(1, string); + int cmd_argc = M_ARGV(2, int); + + if(IS_PLAYER(player)) return false; if(cmd_name == "superspec_itemfilter") @@ -166,24 +170,24 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) _aspeco = "^7 superspec_itemfilter ^3\"item_classname1 item_classname2\"^7 only show thise items when ^2superspec ^3item_message^7 is on\n"; _aspeco = strcat(_aspeco, "^3 clear^7 Remove the filter (show all pickups)\n"); _aspeco = strcat(_aspeco, "^3 show ^7 Display current filter\n"); - superspec_msg("^3superspec_itemfilter help:\n\n\n", "\n^3superspec_itemfilter help:\n", self, _aspeco, 1); + superspec_msg("^3superspec_itemfilter help:\n\n\n", "\n^3superspec_itemfilter help:\n", player, _aspeco, 1); } else if(argv(1) == "clear") { - if(self.superspec_itemfilter != "") - strunzone(self.superspec_itemfilter); + if(player.superspec_itemfilter != "") + strunzone(player.superspec_itemfilter); - self.superspec_itemfilter = ""; + player.superspec_itemfilter = ""; } else if(argv(1) == "show" || argv(1) == "") { - if(self.superspec_itemfilter == "") + if(player.superspec_itemfilter == "") { - superspec_msg("^3superspec_itemfilter^7 is ^1not^7 set", "\n^3superspec_itemfilter^7 is ^1not^7 set\n", self, "", 1); + superspec_msg("^3superspec_itemfilter^7 is ^1not^7 set", "\n^3superspec_itemfilter^7 is ^1not^7 set\n", player, "", 1); return true; } float i; - float l = tokenize_console(self.superspec_itemfilter); + float l = tokenize_console(player.superspec_itemfilter); string _msg = ""; for(i = 0; i < l; ++i) _msg = strcat(_msg, "^3#", ftos(i), " ^7", argv(i), "\n"); @@ -191,14 +195,14 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) _msg = strcat(_msg,"\n"); - superspec_msg("^3superspec_itemfilter is:\n\n\n", "\n^3superspec_itemfilter is:\n", self, _msg, 1); + superspec_msg("^3superspec_itemfilter is:\n\n\n", "\n^3superspec_itemfilter is:\n", player, _msg, 1); } else { - if(self.superspec_itemfilter != "") - strunzone(self.superspec_itemfilter); + if(player.superspec_itemfilter != "") + strunzone(player.superspec_itemfilter); - self.superspec_itemfilter = strzone(argv(1)); + player.superspec_itemfilter = strzone(argv(1)); } return true; @@ -218,13 +222,13 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) _aspeco = strcat(_aspeco, "^3 verbose ^7(short^5 ve^7) makes superspectate print some additional information.\n"); _aspeco = strcat(_aspeco, "^3 item_message ^7(short^5 im^7) makes superspectate print items that were picked up.\n"); _aspeco = strcat(_aspeco, "^7 Use cmd superspec_itemfilter \"item_class1 item_class2\" to set up a filter of what to show with ^3item_message.\n"); - superspec_msg("^2Available Super Spectate ^3options:\n\n\n", "\n^2Available Super Spectate ^3options:\n", self, _aspeco, 1); + superspec_msg("^2Available Super Spectate ^3options:\n\n\n", "\n^2Available Super Spectate ^3options:\n", player, _aspeco, 1); return true; } if(argv(1) == "clear") { - self.superspec_flags = 0; + player.superspec_flags = 0; _start = 2; } @@ -232,13 +236,13 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) { if(argv(i) == "on" || argv(i) == "1") { - self.superspec_flags |= _bits; + player.superspec_flags |= _bits; _bits = 0; } else if(argv(i) == "off" || argv(i) == "0") { if(_start == 1) - self.superspec_flags &= ~_bits; + player.superspec_flags &= ~_bits; _bits = 0; } @@ -252,11 +256,11 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) } _aspeco = ""; - OPTIONINFO(self.superspec_flags, _aspeco, SSF_SILENT, "Silent", "silent", "si"); - OPTIONINFO(self.superspec_flags, _aspeco, SSF_VERBOSE, "Verbose", "verbose", "ve"); - OPTIONINFO(self.superspec_flags, _aspeco, SSF_ITEMMSG, "Item pickup messages", "item_message", "im"); + OPTIONINFO(player.superspec_flags, _aspeco, SSF_SILENT, "Silent", "silent", "si"); + OPTIONINFO(player.superspec_flags, _aspeco, SSF_VERBOSE, "Verbose", "verbose", "ve"); + OPTIONINFO(player.superspec_flags, _aspeco, SSF_ITEMMSG, "Item pickup messages", "item_message", "im"); - superspec_msg("^3Current Super Spectate options are:\n\n\n\n\n", "\n^3Current Super Spectate options are:\n", self, _aspeco, 1); + superspec_msg("^3Current Super Spectate options are:\n\n\n\n\n", "\n^3Current Super Spectate options are:\n", player, _aspeco, 1); return true; } @@ -281,14 +285,14 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) _aspeco = strcat(_aspeco, "^3 item_msg ^7(short^5 im^7) to autospec when item_message in superspectate is triggered\n"); _aspeco = strcat(_aspeco, "^3 followkiller ^7(short ^5fk^7) to autospec the killer/off\n"); _aspeco = strcat(_aspeco, "^3 all ^7(short ^5aa^7) to turn everything on/off\n"); - superspec_msg("^2Available Auto Spectate ^3options:\n\n\n", "\n^2Available Auto Spectate ^3options:\n", self, _aspeco, 1); + superspec_msg("^2Available Auto Spectate ^3options:\n\n\n", "\n^2Available Auto Spectate ^3options:\n", player, _aspeco, 1); return true; } float i, _bits = 0, _start = 1; if(argv(1) == "clear") { - self.autospec_flags = 0; + player.autospec_flags = 0; _start = 2; } @@ -296,13 +300,13 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) { if(argv(i) == "on" || argv(i) == "1") { - self.autospec_flags |= _bits; + player.autospec_flags |= _bits; _bits = 0; } else if(argv(i) == "off" || argv(i) == "0") { if(_start == 1) - self.autospec_flags &= ~_bits; + player.autospec_flags &= ~_bits; _bits = 0; } @@ -323,17 +327,17 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) } _aspeco = ""; - OPTIONINFO(self.autospec_flags, _aspeco, ASF_STRENGTH, "Strength", "strength", "st"); - OPTIONINFO(self.autospec_flags, _aspeco, ASF_SHIELD, "Shield", "shield", "sh"); - OPTIONINFO(self.autospec_flags, _aspeco, ASF_MEGA_HP, "Mega Health", "mega_health", "mh"); - OPTIONINFO(self.autospec_flags, _aspeco, ASF_MEGA_AR, "Mega Armor", "mega_armor", "ma"); - OPTIONINFO(self.autospec_flags, _aspeco, ASF_FLAG_GRAB, "Flag grab", "flag_grab","fg"); - OPTIONINFO(self.autospec_flags, _aspeco, ASF_OBSERVER_ONLY, "Only switch if observer", "observer_only", "oo"); - OPTIONINFO(self.autospec_flags, _aspeco, ASF_SHOWWHAT, "Show what item triggered spectate", "show_what", "sw"); - OPTIONINFO(self.autospec_flags, _aspeco, ASF_SSIM, "Switch on superspec item message", "item_msg", "im"); - OPTIONINFO(self.autospec_flags, _aspeco, ASF_FOLLOWKILLER, "Followkiller", "followkiller", "fk"); - - superspec_msg("^3Current auto spectate options are:\n\n\n\n\n", "\n^3Current auto spectate options are:\n", self, _aspeco, 1); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_STRENGTH, "Strength", "strength", "st"); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_SHIELD, "Shield", "shield", "sh"); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_MEGA_HP, "Mega Health", "mega_health", "mh"); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_MEGA_AR, "Mega Armor", "mega_armor", "ma"); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_FLAG_GRAB, "Flag grab", "flag_grab","fg"); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_OBSERVER_ONLY, "Only switch if observer", "observer_only", "oo"); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_SHOWWHAT, "Show what item triggered spectate", "show_what", "sw"); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_SSIM, "Switch on superspec item message", "item_msg", "im"); + OPTIONINFO(player.autospec_flags, _aspeco, ASF_FOLLOWKILLER, "Followkiller", "followkiller", "fk"); + + superspec_msg("^3Current auto spectate options are:\n\n\n\n\n", "\n^3Current auto spectate options are:\n", player, _aspeco, 1); return true; } @@ -341,7 +345,7 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) { FOREACH_CLIENT(IS_PLAYER(it) && (it.strength_finished > time || it.invincible_finished > time), LAMBDA(return superspec_Spectate(it))); - superspec_msg("", "", self, "No active powerup\n", 1); + superspec_msg("", "", player, "No active powerup\n", 1); return true; } @@ -349,7 +353,7 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) { FOREACH_CLIENT(IS_PLAYER(it) && it.strength_finished > time, LAMBDA(return superspec_Spectate(it))); - superspec_msg("", "", self, "No active Strength\n", 1); + superspec_msg("", "", player, "No active Strength\n", 1); return true; } @@ -357,7 +361,7 @@ MUTATOR_HOOKFUNCTION(superspec, SV_ParseClientCommand) { FOREACH_CLIENT(IS_PLAYER(it) && it.invincible_finished > time, LAMBDA(return superspec_Spectate(it))); - superspec_msg("", "", self, "No active Shield\n", 1); + superspec_msg("", "", player, "No active Shield\n", 1); return true; } @@ -435,6 +439,9 @@ MUTATOR_HOOKFUNCTION(superspec, ClientConnect) MUTATOR_HOOKFUNCTION(superspec, PlayerDies) { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + FOREACH_CLIENT(IS_SPEC(it), LAMBDA( if(it.autospec_flags & ASF_FOLLOWKILLER && IS_PLAYER(frag_attacker) && it.enemy == frag_target) { diff --git a/qcsrc/common/mutators/mutator/vampire/vampire.qc b/qcsrc/common/mutators/mutator/vampire/vampire.qc index 6a2e1fdb7..9eb7e0046 100644 --- a/qcsrc/common/mutators/mutator/vampire/vampire.qc +++ b/qcsrc/common/mutators/mutator/vampire/vampire.qc @@ -3,6 +3,10 @@ REGISTER_MUTATOR(vampire, cvar("g_vampire") && !cvar("g_instagib")); MUTATOR_HOOKFUNCTION(vampire, PlayerDamage_SplitHealthArmor) { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + float damage_take = M_ARGV(4, float); + if(time >= frag_target.spawnshieldtime) if(frag_target != frag_attacker) if(!IS_DEAD(frag_target)) diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 1c17abdd3..3b04a4922 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -384,10 +384,9 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, save = v.y; } - frag_damage = damage; - MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor, inflictor, attacker, this, force, take, save); - take = bound(0, damage_take, this.health); - save = bound(0, damage_save, this.armorvalue); + MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor, inflictor, attacker, this, force, take, save, deathtype, damage); + take = bound(0, M_ARGV(4, float), this.health); + save = bound(0, M_ARGV(5, float), this.armorvalue); excess = max(0, damage - take - save); if(sound_allowed(MSG_BROADCAST, attacker)) @@ -552,8 +551,8 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, if(accuracy_isgooddamage(attacker, this)) attacker.accuracy.(accuracy_frags[w.m_id-1]) += 1; - MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, this, deathtype); - excess = frag_damage; + MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, this, deathtype, excess); + excess = M_ARGV(4, float); Weapon wep = PS(this).m_weapon; WITHSELF(this, wep.wr_playerdeath(wep, this)); diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 6c3c942a7..d681535a2 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -784,7 +784,7 @@ void SV_ParseClientCommand(string command) return; } } - else if (MUTATOR_CALLHOOK(SV_ParseClientCommand, strtolower(argv(0)), argc, command)) + else if (MUTATOR_CALLHOOK(SV_ParseClientCommand, this, strtolower(argv(0)), argc, command)) { return; // handled by a mutator } diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 92710cc58..adfd5ddd8 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -31,7 +31,7 @@ void UpdateFrags(entity player, float f) } void GiveFrags (entity attacker, entity targ, float f, int deathtype) -{SELFPARAM(); +{ // TODO route through PlayerScores instead if(gameover) return; @@ -102,9 +102,9 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype) } // FIXME fix the mess this is (we have REAL points now!) - if(MUTATOR_CALLHOOK(GiveFragsForKill, self, attacker, targ, f)) + if(MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f)) { - f = frag_score; + f = M_ARGV(2, float); } attacker.totalfrags += f; diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index 91b74335d..eaef39ae8 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -44,15 +44,13 @@ MUTATOR_HOOKABLE(ClientDisconnect, EV_ClientDisconnect); /** called when a player dies to e.g. remove stuff he was carrying. */ #define EV_PlayerDies(i, o) \ - /**/ i(entity, frag_inflictor) \ - /**/ i(entity, frag_attacker) \ - /** same as self */ i(entity, frag_target) \ - /**/ i(int, frag_deathtype) \ - /**/ -entity frag_inflictor; -entity frag_attacker; -entity frag_target; -int frag_deathtype; + /** inflictor */ i(entity, MUTATOR_ARGV_0_entity) \ + /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \ + /** target */ i(entity, MUTATOR_ARGV_2_entity) \ + /** deathtype */ i(float, MUTATOR_ARGV_3_float) \ + /** damage */ i(float, MUTATOR_ARGV_4_float) \ + /** damage */ o(float, MUTATOR_ARGV_4_float) \ + /**/ MUTATOR_HOOKABLE(PlayerDies, EV_PlayerDies); /** called when a player dies to e.g. remove stuff he was carrying */ @@ -84,13 +82,11 @@ MUTATOR_HOOKABLE(ItemModel, EV_ItemModel); /** called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill */ #define EV_GiveFragsForKill(i, o) \ - /**/ i(entity, __self) \ - /** same as self */ i(entity, frag_attacker) \ - /**/ i(entity, frag_target) \ - /**/ i(float, frag_score) \ - /**/ o(float, frag_score) \ + /** attacker */ i(entity, MUTATOR_ARGV_0_entity) \ + /** target */ i(entity, MUTATOR_ARGV_1_entity) \ + /** frag score */ i(float, MUTATOR_ARGV_2_float) \ + /** */ o(float, MUTATOR_ARGV_2_float) \ /**/ -float frag_score; MUTATOR_HOOKABLE(GiveFragsForKill, EV_GiveFragsForKill); /** called when the match ends */ @@ -231,8 +227,9 @@ MUTATOR_HOOKABLE(MonsterSpawn, EV_MonsterSpawn); /** called when a monster dies */ #define EV_MonsterDies(i, o) \ - /**/ i(entity, frag_target) \ - /**/ i(entity, frag_attacker) \ + /** target */ i(entity, MUTATOR_ARGV_0_entity) \ + /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \ + /** deathtype */ i(float, MUTATOR_ARGV_2_float) \ /**/ MUTATOR_HOOKABLE(MonsterDies, EV_MonsterDies); @@ -251,8 +248,10 @@ MUTATOR_HOOKABLE(MonsterRespawn, EV_MonsterRespawn); /** called when a monster is dropping loot */ #define EV_MonsterDropItem(i, o) \ - /**/ i(entity, other) \ - /**/ o(entity, other) \ + /* monster */ i(entity, MUTATOR_ARGV_0_entity) \ + /* item (can be removed or changed) */ i(entity, MUTATOR_ARGV_1_entity) \ + /**/ o(entity, MUTATOR_ARGV_1_entity) \ + /* attacker */ i(entity, MUTATOR_ARGV_2_entity) \ /**/ .void(entity this) monster_loot; MUTATOR_HOOKABLE(MonsterDropItem, EV_MonsterDropItem); @@ -291,18 +290,17 @@ MUTATOR_HOOKABLE(AllowMobSpawning, EV_NO_ARGS); /** called when a player gets damaged to e.g. remove stuff he was carrying. */ #define EV_PlayerDamage_SplitHealthArmor(i, o) \ - /**/ i(entity, frag_inflictor) \ - /**/ i(entity, frag_attacker) \ - /** same as self */ i(entity, frag_target) \ - /** NOTE: this force already HAS been applied */ i(vector, damage_force) \ - /**/ i(float, damage_take) \ - /**/ o(float, damage_take) \ - /**/ i(float, damage_save) \ - /**/ o(float, damage_save) \ - /**/ -vector damage_force; -float damage_take; -float damage_save; + /** inflictor */ i(entity, MUTATOR_ARGV_0_entity) \ + /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \ + /** target */ i(entity, MUTATOR_ARGV_2_entity) \ + /** force (no out) */ i(vector, MUTATOR_ARGV_3_vector) \ + /** damage take */ i(float, MUTATOR_ARGV_4_float) \ + /** damage take */ o(float, MUTATOR_ARGV_4_float) \ + /** damage save */ i(float, MUTATOR_ARGV_5_float) \ + /** damage save */ o(float, MUTATOR_ARGV_5_float) \ + /** deathtype */ i(float, MUTATOR_ARGV_6_float) \ + /** damage */ i(float, MUTATOR_ARGV_7_float) \ + /**/ MUTATOR_HOOKABLE(PlayerDamage_SplitHealthArmor, EV_PlayerDamage_SplitHealthArmor); /** @@ -407,24 +405,19 @@ MUTATOR_HOOKABLE(PlayerUseKey, EV_NO_ARGS); * } */ #define EV_SV_ParseClientCommand(i, o) \ - /** command name */ i(string, cmd_name) \ - /** also, argv() can be used */ i(int, cmd_argc) \ - /** whole command, use only if you really have to */ i(string, cmd_string) \ + /** client sending the command */ i(entity, MUTATOR_ARGV_0_entity) \ + /** command name */ i(string, MUTATOR_ARGV_1_string) \ + /** argc (also, argv() can be used) */ i(int, MUTATOR_ARGV_2_int) \ + /** whole command, use only if you really have to */ i(string, MUTATOR_ARGV_3_string) \ /**/ -string cmd_name; -int cmd_argc; -string cmd_string; MUTATOR_HOOKABLE(SV_ParseClientCommand, EV_SV_ParseClientCommand); /** please read EV_SV_ParseClientCommand description before using */ #define EV_SV_ParseServerCommand(i, o) \ - /** command name */ i(string, cmd_name) \ - /** also, argv() can be used */ i(int, cmd_argc) \ - /** whole command, use only if you really have to */ i(string, cmd_string) \ + /** command name */ i(string, MUTATOR_ARGV_0_string) \ + /** argc (also, argv() can be used) */ i(int, MUTATOR_ARGV_1_int) \ + /** whole command, use only if you really have to */ i(string, MUTATOR_ARGV_2_string) \ /**/ -//string cmd_name; -//int cmd_argc; -//string cmd_string; MUTATOR_HOOKABLE(SV_ParseServerCommand, EV_SV_ParseServerCommand); /** @@ -432,13 +425,11 @@ MUTATOR_HOOKABLE(SV_ParseServerCommand, EV_SV_ParseServerCommand); * return 1 to make the spawnpoint unusable */ #define EV_Spawn_Score(i, o) \ - /** player wanting to spawn */ i(entity, __self) \ - /** spot to be evaluated */ i(entity, spawn_spot) \ - /** _x is priority, _y is "distance" */ i(vector, spawn_score) \ - /**/ o(vector, spawn_score) \ + /** player wanting to spawn */ i(entity, MUTATOR_ARGV_0_entity) \ + /** spot to be evaluated */ i(entity, MUTATOR_ARGV_1_entity) \ + /** spot score, _x is priority, _y is "distance" */ i(vector, MUTATOR_ARGV_0_vector) \ + /**/ o(vector, MUTATOR_ARGV_0_vector) \ /**/ -entity spawn_spot; -vector spawn_score; MUTATOR_HOOKABLE(Spawn_Score, EV_Spawn_Score); /** runs globally each server frame */ @@ -579,8 +570,8 @@ MUTATOR_HOOKABLE(HavocBot_ChooseRole, EV_HavocBot_ChooseRole); /** called when a target is checked for accuracy */ #define EV_AccuracyTargetValid(i, o) \ - /** attacker */ i(entity, frag_attacker) \ - /** target */ i(entity, frag_target) \ + /** attacker */ i(entity, MUTATOR_ARGV_0_entity) \ + /** target */ i(entity, MUTATOR_ARGV_1_entity) \ /**/ MUTATOR_HOOKABLE(AccuracyTargetValid, EV_AccuracyTargetValid); enum { @@ -789,7 +780,7 @@ MUTATOR_HOOKABLE(GetPlayerStatus, EV_GetPlayerStatus); MUTATOR_HOOKABLE(SetWeaponArena, EV_SetWeaponArena); #define EV_DropSpecialItems(i, o) \ - /**/ i(entity, frag_target) \ + /** target */ i(entity, MUTATOR_ARGV_0_entity) \ /**/ MUTATOR_HOOKABLE(DropSpecialItems, EV_DropSpecialItems); @@ -833,8 +824,8 @@ MUTATOR_HOOKABLE(Ent_Init, EV_NO_ARGS); /** */ #define EV_PrepareExplosionByDamage(i, o) \ - /**/ i(entity, __self) \ - /**/ i(entity, frag_attacker) \ + /** projectile */ i(entity, MUTATOR_ARGV_0_entity) \ + /** attacker */ i(entity, MUTATOR_ARGV_1_entity) \ /**/ MUTATOR_HOOKABLE(PrepareExplosionByDamage, EV_PrepareExplosionByDamage); diff --git a/qcsrc/server/mutators/mutator/gamemode_ca.qc b/qcsrc/server/mutators/mutator/gamemode_ca.qc index c7c1c7e83..32c69096c 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ca.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ca.qc @@ -308,6 +308,8 @@ void ca_LastPlayerForTeam_Notify() MUTATOR_HOOKFUNCTION(ca, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + ca_LastPlayerForTeam_Notify(); if (!allowed_to_spawn) frag_target.respawn_flags = RESPAWN_SILENT; @@ -350,8 +352,8 @@ MUTATOR_HOOKFUNCTION(ca, ForbidThrowCurrentWeapon) MUTATOR_HOOKFUNCTION(ca, GiveFragsForKill, CBC_ORDER_FIRST) { - frag_score = 0; // score will be given to the winner team when the round ends - return 1; + M_ARGV(2, float) = 0; // score will be given to the winner team when the round ends + return true; } MUTATOR_HOOKFUNCTION(ca, SetStartItems) @@ -405,12 +407,16 @@ MUTATOR_HOOKFUNCTION(ca, FilterItem) MUTATOR_HOOKFUNCTION(ca, PlayerDamage_SplitHealthArmor) { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + float frag_damage = M_ARGV(7, float); + float damage_take = M_ARGV(4, float); + float damage_save = M_ARGV(5, float); + float excess = max(0, frag_damage - damage_take - damage_save); if (frag_target != frag_attacker && IS_PLAYER(frag_attacker)) PlayerTeamScore_Add(frag_attacker, SP_SCORE, ST_SCORE, (frag_damage - excess) * autocvar_g_ca_damage2score_multiplier); - - return false; } MUTATOR_HOOKFUNCTION(ca, PlayerRegen) diff --git a/qcsrc/server/mutators/mutator/gamemode_ctf.qc b/qcsrc/server/mutators/mutator/gamemode_ctf.qc index ed9dc1fbd..1d8ad402f 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ctf.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ctf.qc @@ -2065,6 +2065,9 @@ MUTATOR_HOOKFUNCTION(ctf, PlayerDamage_Calculate) // for changing damage and for MUTATOR_HOOKFUNCTION(ctf, PlayerDies) { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker)) && (frag_target.flagcarried)) { PlayerTeamScore_AddScore(frag_attacker, ((SAME_TEAM(frag_attacker, frag_target)) ? -autocvar_g_ctf_score_kill : autocvar_g_ctf_score_kill)); @@ -2083,7 +2086,7 @@ MUTATOR_HOOKFUNCTION(ctf, PlayerDies) MUTATOR_HOOKFUNCTION(ctf, GiveFragsForKill) { - frag_score = 0; + M_ARGV(2, float) = 0; // frag score return (autocvar_g_ctf_ignore_frags); // no frags counted in ctf if this is true } @@ -2357,8 +2360,11 @@ bool superspec_Spectate(entity _player); // TODO void superspec_msg(string _center_title, string _con_title, entity _to, string _msg, float _spamlevel); // TODO MUTATOR_HOOKFUNCTION(ctf, SV_ParseClientCommand) { - SELFPARAM(); - if(IS_PLAYER(self) || MUTATOR_RETURNVALUE || !cvar("g_superspectate")) { return false; } + entity player = M_ARGV(0, entity); + string cmd_name = M_ARGV(1, string); + int cmd_argc = M_ARGV(2, int); + + if(IS_PLAYER(player) || MUTATOR_RETURNVALUE || !cvar("g_superspectate")) { return false; } if(cmd_name == "followfc") { @@ -2383,14 +2389,14 @@ MUTATOR_HOOKFUNCTION(ctf, SV_ParseClientCommand) if(it.flagcarried && (it.team == _team || _team == 0)) { found = true; - if(_team == 0 && IS_SPEC(self) && self.enemy == it) + if(_team == 0 && IS_SPEC(player) && player.enemy == it) continue; // already spectating this fc, try another return superspec_Spectate(it); } )); if(!found) - superspec_msg("", "", self, "No active flag carrier\n", 1); + superspec_msg("", "", player, "No active flag carrier\n", 1); return true; } @@ -2399,6 +2405,8 @@ MUTATOR_HOOKFUNCTION(ctf, SV_ParseClientCommand) MUTATOR_HOOKFUNCTION(ctf, DropSpecialItems) { + entity frag_target = M_ARGV(0, entity); + if(frag_target.flagcarried) ctf_Handle_Throw(frag_target, world, DROP_THROW); diff --git a/qcsrc/server/mutators/mutator/gamemode_cts.qc b/qcsrc/server/mutators/mutator/gamemode_cts.qc index 777cf1fa0..65376b78d 100644 --- a/qcsrc/server/mutators/mutator/gamemode_cts.qc +++ b/qcsrc/server/mutators/mutator/gamemode_cts.qc @@ -289,6 +289,8 @@ MUTATOR_HOOKFUNCTION(cts, PutClientInServer) MUTATOR_HOOKFUNCTION(cts, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + frag_target.respawn_flags |= RESPAWN_FORCE; race_AbandonRaceCheck(frag_target); return false; diff --git a/qcsrc/server/mutators/mutator/gamemode_freezetag.qc b/qcsrc/server/mutators/mutator/gamemode_freezetag.qc index 7700e074a..86b8d1336 100644 --- a/qcsrc/server/mutators/mutator/gamemode_freezetag.qc +++ b/qcsrc/server/mutators/mutator/gamemode_freezetag.qc @@ -375,6 +375,10 @@ MUTATOR_HOOKFUNCTION(ft, MakePlayerObserver) MUTATOR_HOOKFUNCTION(ft, PlayerDies) { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + float frag_deathtype = M_ARGV(2, float); + if(round_handler_IsActive()) if(round_handler_CountdownRunning()) { @@ -466,7 +470,7 @@ MUTATOR_HOOKFUNCTION(ft, reset_map_players) MUTATOR_HOOKFUNCTION(ft, GiveFragsForKill, CBC_ORDER_FIRST) { - frag_score = 0; // no frags counted in Freeze Tag + M_ARGV(2, float) = 0; // no frags counted in Freeze Tag return 1; } diff --git a/qcsrc/server/mutators/mutator/gamemode_invasion.qc b/qcsrc/server/mutators/mutator/gamemode_invasion.qc index db4f85731..ea2ed6e1d 100644 --- a/qcsrc/server/mutators/mutator/gamemode_invasion.qc +++ b/qcsrc/server/mutators/mutator/gamemode_invasion.qc @@ -331,6 +331,9 @@ void Invasion_RoundStart() MUTATOR_HOOKFUNCTION(inv, MonsterDies) { + entity frag_target = M_ARGV(0, entity); + entity frag_attacker = M_ARGV(1, entity); + if(!(frag_target.spawnflags & MONSTERFLAG_RESPAWNED)) { inv_numkilled += 1; @@ -423,19 +426,22 @@ MUTATOR_HOOKFUNCTION(inv, PlayerDamage_Calculate) } MUTATOR_HOOKFUNCTION(inv, SV_ParseClientCommand) -{SELFPARAM(); +{ if(MUTATOR_RETURNVALUE) // command was already handled? return false; + entity player = M_ARGV(0, entity); + string cmd_name = M_ARGV(1, string); + if(cmd_name == "debuginvasion") { - sprint(self, strcat("inv_maxspawned = ", ftos(inv_maxspawned), "\n")); - sprint(self, strcat("inv_numspawned = ", ftos(inv_numspawned), "\n")); - sprint(self, strcat("inv_numkilled = ", ftos(inv_numkilled), "\n")); - sprint(self, strcat("inv_roundcnt = ", ftos(inv_roundcnt), "\n")); - sprint(self, strcat("monsters_total = ", ftos(monsters_total), "\n")); - sprint(self, strcat("monsters_killed = ", ftos(monsters_killed), "\n")); - sprint(self, strcat("inv_monsterskill = ", ftos(inv_monsterskill), "\n")); + sprint(player, strcat("inv_maxspawned = ", ftos(inv_maxspawned), "\n")); + sprint(player, strcat("inv_numspawned = ", ftos(inv_numspawned), "\n")); + sprint(player, strcat("inv_numkilled = ", ftos(inv_numkilled), "\n")); + sprint(player, strcat("inv_roundcnt = ", ftos(inv_roundcnt), "\n")); + sprint(player, strcat("monsters_total = ", ftos(monsters_total), "\n")); + sprint(player, strcat("monsters_killed = ", ftos(monsters_killed), "\n")); + sprint(player, strcat("inv_monsterskill = ", ftos(inv_monsterskill), "\n")); return true; } @@ -460,6 +466,8 @@ MUTATOR_HOOKFUNCTION(inv, SetStartItems) MUTATOR_HOOKFUNCTION(inv, AccuracyTargetValid) { + entity frag_target = M_ARGV(1, entity); + if(IS_MONSTER(frag_target)) return MUT_ACCADD_INVALID; return MUT_ACCADD_INDIFFERENT; diff --git a/qcsrc/server/mutators/mutator/gamemode_keepaway.qc b/qcsrc/server/mutators/mutator/gamemode_keepaway.qc index b12ddb4b3..0da0e3025 100644 --- a/qcsrc/server/mutators/mutator/gamemode_keepaway.qc +++ b/qcsrc/server/mutators/mutator/gamemode_keepaway.qc @@ -316,6 +316,9 @@ void havocbot_role_ka_collector(entity this) MUTATOR_HOOKFUNCTION(ka, PlayerDies) { + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker))) { if(frag_target.ballcarried) { // add to amount of times killing carrier @@ -337,8 +340,8 @@ MUTATOR_HOOKFUNCTION(ka, PlayerDies) MUTATOR_HOOKFUNCTION(ka, GiveFragsForKill) { - frag_score = 0; // no frags counted in keepaway - return 1; // you deceptive little bugger ;3 This needs to be true in order for this function to even count. + M_ARGV(2, float) = 0; // no frags counted in keepaway + return true; // you deceptive little bugger ;3 This needs to be true in order for this function to even count. } MUTATOR_HOOKFUNCTION(ka, PlayerPreThink) @@ -461,6 +464,8 @@ MUTATOR_HOOKFUNCTION(ka, HavocBot_ChooseRole) MUTATOR_HOOKFUNCTION(ka, DropSpecialItems) { + entity frag_target = M_ARGV(0, entity); + if(frag_target.ballcarried) ka_DropEvent(frag_target); diff --git a/qcsrc/server/mutators/mutator/gamemode_keyhunt.qc b/qcsrc/server/mutators/mutator/gamemode_keyhunt.qc index 4d65abf9e..ef23a9109 100644 --- a/qcsrc/server/mutators/mutator/gamemode_keyhunt.qc +++ b/qcsrc/server/mutators/mutator/gamemode_keyhunt.qc @@ -1303,9 +1303,12 @@ MUTATOR_HOOKFUNCTION(kh, MakePlayerObserver) MUTATOR_HOOKFUNCTION(kh, PlayerDies) { - if(frag_target == other) + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + + if(frag_target == frag_attacker) kh_Key_DropAll(frag_target, true); - else if(IS_PLAYER(other)) + else if(IS_PLAYER(frag_attacker)) kh_Key_DropAll(frag_target, false); else kh_Key_DropAll(frag_target, true); @@ -1314,8 +1317,11 @@ MUTATOR_HOOKFUNCTION(kh, PlayerDies) MUTATOR_HOOKFUNCTION(kh, GiveFragsForKill, CBC_ORDER_FIRST) { - frag_score = kh_HandleFrags(frag_attacker, frag_target, frag_score); - return 0; + entity frag_attacker = M_ARGV(0, entity); + entity frag_target = M_ARGV(1, entity); + float frag_score = M_ARGV(2, float); + M_ARGV(2, float) = kh_HandleFrags(frag_attacker, frag_target, frag_score); + return false; } MUTATOR_HOOKFUNCTION(kh, MatchEnd) @@ -1370,6 +1376,8 @@ MUTATOR_HOOKFUNCTION(kh, HavocBot_ChooseRole) MUTATOR_HOOKFUNCTION(kh, DropSpecialItems) { + entity frag_target = M_ARGV(0, entity); + kh_Key_DropAll(frag_target, false); return false; } diff --git a/qcsrc/server/mutators/mutator/gamemode_lms.qc b/qcsrc/server/mutators/mutator/gamemode_lms.qc index dac0e148a..8670bbbef 100644 --- a/qcsrc/server/mutators/mutator/gamemode_lms.qc +++ b/qcsrc/server/mutators/mutator/gamemode_lms.qc @@ -182,6 +182,8 @@ MUTATOR_HOOKFUNCTION(lms, PutClientInServer) MUTATOR_HOOKFUNCTION(lms, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + frag_target.respawn_flags |= RESPAWN_FORCE; return false; } @@ -251,6 +253,8 @@ MUTATOR_HOOKFUNCTION(lms, ForbidThrowCurrentWeapon) MUTATOR_HOOKFUNCTION(lms, GiveFragsForKill) { + entity frag_target = M_ARGV(1, entity); + // remove a life float tl; tl = PlayerScore_Add(frag_target, SP_LMS_LIVES, -1); @@ -265,7 +269,7 @@ MUTATOR_HOOKFUNCTION(lms, GiveFragsForKill) PlayerScore_Add(frag_target, SP_LMS_RANK, lms_next_place); // won't ever spawn again --lms_next_place; } - frag_score = 0; + M_ARGV(2, float) = 0; return true; } diff --git a/qcsrc/server/mutators/mutator/gamemode_race.qc b/qcsrc/server/mutators/mutator/gamemode_race.qc index 95a97db50..c3be9b247 100644 --- a/qcsrc/server/mutators/mutator/gamemode_race.qc +++ b/qcsrc/server/mutators/mutator/gamemode_race.qc @@ -322,6 +322,8 @@ MUTATOR_HOOKFUNCTION(rc, PutClientInServer) MUTATOR_HOOKFUNCTION(rc, PlayerDies) { + entity frag_target = M_ARGV(2, entity); + frag_target.respawn_flags |= RESPAWN_FORCE; race_AbandonRaceCheck(frag_target); return false; diff --git a/qcsrc/server/spawnpoints.qc b/qcsrc/server/spawnpoints.qc index 69c136085..6859b4849 100644 --- a/qcsrc/server/spawnpoints.qc +++ b/qcsrc/server/spawnpoints.qc @@ -246,8 +246,7 @@ vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck) if(shortest > mindist) prio += SPAWN_PRIO_GOOD_DISTANCE; - spawn_score = prio * '1 0 0' + shortest * '0 1 0'; - spawn_spot = spot; + vector spawn_score = prio * '1 0 0' + shortest * '0 1 0'; // filter out spots for assault if(spot.target != "") { @@ -273,7 +272,8 @@ vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck) } } - MUTATOR_CALLHOOK(Spawn_Score, this, spawn_spot, spawn_score); + MUTATOR_CALLHOOK(Spawn_Score, this, spot, spawn_score); + spawn_score = M_ARGV(2, vector); return spawn_score; } -- 2.39.2