X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fmutators%2Fmutator_overkill.qc;h=c975cda155a09ae5b75bc913d17b8ebf7a1ccbe0;hp=e2b1fb92d8e36938f27773d71b26026b606bb63a;hb=ae2c1407ec9a05e4f501a6604a7cce8e1030df9f;hpb=6d2af068b59d5dbc605112aabb81fe503b101d65 diff --git a/qcsrc/server/mutators/mutator_overkill.qc b/qcsrc/server/mutators/mutator_overkill.qc index e2b1fb92d8..c975cda155 100644 --- a/qcsrc/server/mutators/mutator_overkill.qc +++ b/qcsrc/server/mutators/mutator_overkill.qc @@ -1,144 +1,177 @@ -void ok_DecreaseCharge(entity ent, float wep) +#include "mutator_overkill.qh" +#include "../_all.qh" + +#include "mutator.qh" + +void W_Blaster_Attack(float, float, float, float, float, float, float, float, float, float); +void spawnfunc_weapon_hmg(); +void spawnfunc_weapon_rpc(); + +void ok_DecreaseCharge(entity ent, int wep) { - if not(autocvar_g_overkill_ammo_charge) return; + if(!ent.ok_use_ammocharge) return; entity wepent = get_weaponinfo(wep); - if(wepent.netname == "") + if(wepent.weapon == 0) return; // dummy - ent.ammo_charge[wep] -= cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname)); + ent.ammo_charge[wep] -= max(0, cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname))); } -void ok_IncreaseCharge(entity ent, float wep) +void ok_IncreaseCharge(entity ent, int wep) { entity wepent = get_weaponinfo(wep); - if(wepent.netname == "") + if(wepent.weapon == 0) return; // dummy - if(autocvar_g_overkill_ammo_charge) - if not(ent.BUTTON_ATCK) - if(ent.ammo_charge[wep] <= autocvar_g_overkill_ammo_charge_limit) + if(ent.ok_use_ammocharge) + if(!ent.BUTTON_ATCK) // not while attacking? ent.ammo_charge[wep] = min(autocvar_g_overkill_ammo_charge_limit, ent.ammo_charge[wep] + cvar(sprintf("g_overkill_ammo_charge_rate_%s", wepent.netname)) * frametime / W_TICSPERFRAME); } -float ok_CheckWeaponCharge(entity ent, float wep, float swep) +float ok_CheckWeaponCharge(entity ent, int wep) { - if not(autocvar_g_overkill_ammo_charge) return TRUE; - //if(wep != swep) return TRUE; // switching, don't even bother checking + if(!ent.ok_use_ammocharge) return true; entity wepent = get_weaponinfo(wep); - if(wepent.netname == "") + if(wepent.weapon == 0) return 0; // dummy - return !(ent.ammo_charge[wep] < cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname))); + return (ent.ammo_charge[wep] >= cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname))); } MUTATOR_HOOKFUNCTION(ok_PlayerDamage_Calculate) { - if(DEATH_ISWEAPON(frag_deathtype, WEP_LASER) && frag_target == frag_attacker) + if(IS_PLAYER(frag_attacker) && IS_PLAYER(frag_target)) + if(DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER.m_id)) + { frag_damage = 0; - if(!IS_PLAYER(frag_target) || frag_target == frag_attacker) - return FALSE; - - if not (DEATH_ISWEAPON(frag_deathtype, WEP_LASER)) - return FALSE; - - frag_damage = 0; - if(frag_target.health >= 1 && !frag_target.freezetag_frozen) - Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_MINSTA_SECONDARY); - - frag_force = '0 0 0'; + if(frag_attacker != frag_target) + if(frag_target.health > 0) + if(frag_target.frozen == 0) + if(frag_target.deadflag == DEAD_NO) + { + Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_SECONDARY_NODAMAGE); + frag_force = '0 0 0'; + } + } - return FALSE; + return false; } -MUTATOR_HOOKFUNCTION(ok_BuildMutatorsString) +MUTATOR_HOOKFUNCTION(ok_PlayerDamage_SplitHealthArmor) { - ret_string = strcat(ret_string, ":OK"); - return FALSE; + if(damage_take) + self.ok_pauseregen_finished = max(self.ok_pauseregen_finished, time + 2); + return false; } -MUTATOR_HOOKFUNCTION(ok_BuildMutatorsPrettyString) +MUTATOR_HOOKFUNCTION(ok_PlayerDies) { - ret_string = strcat(ret_string, ", Overkill"); - return FALSE; -} + entity oldself = self; + entity targ = ((frag_attacker) ? frag_attacker : frag_target); -void ok_Item_Touch() -{ - if(IS_PLAYER(other) && other.deadflag == DEAD_NO && !other.freezetag_frozen) + if(IS_MONSTER(self)) { - Item_Touch(); - remove(self); + remove(other); // remove default item + other = world; } -} - -MUTATOR_HOOKFUNCTION(ok_PlayerDies) -{ - self.ok_lastwep = self.weapon; - self.ok_deathloc = self.origin; - entity oldself = self; - float gpi = autocvar_g_pickup_items; - - cvar_set("g_pickup_items", "1"); self = spawn(); - self.ok_item = TRUE; - self.noalign = TRUE; + self.ok_item = true; + self.noalign = true; + self.pickup_anyway = true; spawnfunc_item_armor_small(); self.movetype = MOVETYPE_TOSS; self.gravity = 1; + self.reset = SUB_Remove; setorigin(self, frag_target.origin + '0 0 32'); - self.velocity = '0 0 200' + normalize(frag_attacker.origin - self.origin) * 500; - self.touch = ok_Item_Touch; + self.velocity = '0 0 200' + normalize(targ.origin - self.origin) * 500; + self.classname = "droppedweapon"; // hax SUB_SetFade(self, time + 5, 1); self = oldself; - cvar_set("g_pickup_items", ftos(gpi)); - return FALSE; + self.ok_lastwep = self.switchweapon; + + return false; +} + +MUTATOR_HOOKFUNCTION(ok_PlayerRegen) +{ + // overkill's values are different, so use custom regen + if(!self.frozen) + { + self.armorvalue = CalcRotRegen(self.armorvalue, autocvar_g_balance_armor_regenstable, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear, 1 * frametime * (time > self.ok_pauseregen_finished), 0, 0, 1, 1 * frametime * (time > self.pauserotarmor_finished), autocvar_g_balance_armor_limit); + self.health = CalcRotRegen(self.health, autocvar_g_balance_health_regenstable, 0, 100, 1 * frametime * (time > self.ok_pauseregen_finished), 200, 0, autocvar_g_balance_health_rotlinear, 1 * frametime * (time > self.pauserothealth_finished), autocvar_g_balance_health_limit); + + float minf, maxf, limitf; + + maxf = autocvar_g_balance_fuel_rotstable; + minf = autocvar_g_balance_fuel_regenstable; + limitf = autocvar_g_balance_fuel_limit; + + self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > self.pauseregen_finished) * ((self.items & ITEM_JetpackRegen.m_itemid) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > self.pauserotfuel_finished), limitf); + } + return true; // return true anyway, as frozen uses no regen } MUTATOR_HOOKFUNCTION(ok_ForbidThrowCurrentWeapon) { - return TRUE; + return true; } MUTATOR_HOOKFUNCTION(ok_PlayerPreThink) { if(intermission_running || gameover) - return FALSE; + return false; - if(self.deadflag != DEAD_NO || !IS_PLAYER(self)) - return FALSE; + if(self.deadflag != DEAD_NO || !IS_PLAYER(self) || self.frozen) + return false; - if(self.freezetag_frozen) - return FALSE; + if(self.ok_lastwep) + { + self.switchweapon = self.ok_lastwep; + self.ok_lastwep = 0; + } ok_IncreaseCharge(self, self.weapon); if(self.BUTTON_ATCK2) - if(self.jump_interval <= time) - { - self.jump_interval = time + autocvar_g_balance_laser_primary_refire * W_WeaponRateFactor(); - makevectors(self.v_angle); - float w = self.weapon; - self.weapon = WEP_LASER; - W_Laser_Attack(3); - self.weapon = w; - } + if(!forbidWeaponUse(self) || self.weapon_blocked) // allow if weapon is blocked + if(time >= self.jump_interval) + { + self.jump_interval = time + WEP_CVAR_PRI(blaster, refire) * W_WeaponRateFactor(); + makevectors(self.v_angle); + + int oldwep = self.weapon; + self.weapon = WEP_BLASTER.m_id; + W_Blaster_Attack( + WEP_BLASTER.m_id | HITTYPE_SECONDARY, + WEP_CVAR_SEC(vaporizer, shotangle), + WEP_CVAR_SEC(vaporizer, damage), + WEP_CVAR_SEC(vaporizer, edgedamage), + WEP_CVAR_SEC(vaporizer, radius), + WEP_CVAR_SEC(vaporizer, force), + WEP_CVAR_SEC(vaporizer, speed), + WEP_CVAR_SEC(vaporizer, spread), + WEP_CVAR_SEC(vaporizer, delay), + WEP_CVAR_SEC(vaporizer, lifetime) + ); + self.weapon = oldwep; + } - self.weapon_blocked = FALSE; + self.weapon_blocked = false; self.ok_ammo_charge = self.ammo_charge[self.weapon]; - if(autocvar_g_overkill_ammo_charge) - if(!ok_CheckWeaponCharge(self, self.weapon, self.switchweapon)) + if(self.ok_use_ammocharge) + if(!ok_CheckWeaponCharge(self, self.weapon)) { - if(autocvar_g_overkill_ammo_charge_notice && time > self.ok_notice_time && self.BUTTON_ATCK && IS_REAL_CLIENT(self)) + if(autocvar_g_overkill_ammo_charge_notice && time > self.ok_notice_time && self.BUTTON_ATCK && IS_REAL_CLIENT(self) && self.weapon == self.switchweapon) { //Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_OVERKILL_CHARGE); self.ok_notice_time = time + 2; @@ -147,21 +180,19 @@ MUTATOR_HOOKFUNCTION(ok_PlayerPreThink) if(self.weaponentity.state != WS_CLEAR) w_ready(); - self.weapon_blocked = TRUE; + self.weapon_blocked = true; } self.BUTTON_ATCK2 = 0; - return FALSE; + return false; } MUTATOR_HOOKFUNCTION(ok_PlayerSpawn) { if(autocvar_g_overkill_ammo_charge) { - float i; - - for(i = WEP_FIRST; i <= WEP_LAST; ++i) + for(int i = WEP_FIRST; i <= WEP_LAST; ++i) self.ammo_charge[i] = autocvar_g_overkill_ammo_charge_limit; self.ok_use_ammocharge = 1; @@ -170,97 +201,66 @@ MUTATOR_HOOKFUNCTION(ok_PlayerSpawn) else self.ok_use_ammocharge = 0; - return FALSE; -} - -void start_hmg() -{ - float gpi = autocvar_g_pickup_items; - cvar_set("g_pickup_items", "1"); - self.classname = "weapon_hmg"; - self.ok_item = TRUE; - //self.weapons = WEP_HMG; - //self.flags |= FL_POWERUP; - self.respawntime = autocvar_g_overkill_superguns_respawn_time; - setmodel(self, "models/weapons/g_ok_hmg.md3"); - spawnfunc_weapon_hmg(); - - cvar_set("g_pickup_items", ftos(gpi)); -} - -void start_rpc() -{ - float gpi = autocvar_g_pickup_items; - cvar_set("g_pickup_items", "1"); - self.classname = "weapon_rpc"; - self.respawntime = autocvar_g_overkill_superguns_respawn_time; - self.ok_item = TRUE; - //self.weapons = WEP_RPC; - //self.flags |= FL_POWERUP; - setmodel(self, "models/weapons/g_ok_rl.md3"); - spawnfunc_weapon_rpc(); - cvar_set("g_pickup_items", ftos(gpi)); -} - -void start_mh_anyway() -{ - cvar_set("g_pickup_items", "1"); - self.classname = "item_health_mega"; - self.ok_item = TRUE; - spawnfunc_item_health_mega(); - cvar_set("g_pickup_items", "0"); -} + self.ok_pauseregen_finished = time + 2; -void start_ma_anyway() -{ - cvar_set("g_pickup_items", "1"); - self.classname = "item_armor_large"; - self.ok_item = TRUE; - spawnfunc_item_armor_large(); - cvar_set("g_pickup_items", "0"); + return false; } MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn) { if(autocvar_g_powerups) if(autocvar_g_overkill_powerups_replace) - if(self.classname == "item_strength") { - entity wep = spawn(); - setorigin(wep, self.origin); - wep.ok_item = TRUE; - wep.think = start_hmg; - wep.nextthink = time + 0.1; - return TRUE; - } + if(self.classname == "item_strength") + { + entity wep = spawn(); + setorigin(wep, self.origin); + setmodel(wep, "models/weapons/g_ok_hmg.md3"); + wep.classname = "weapon_hmg"; + wep.ok_item = true; + wep.noalign = self.noalign; + wep.cnt = self.cnt; + wep.team = self.team; + wep.respawntime = autocvar_g_overkill_superguns_respawn_time; + wep.pickup_anyway = true; + wep.think = spawnfunc_weapon_hmg; + wep.nextthink = time + 0.1; + return true; + } - if(autocvar_g_powerups) - if(autocvar_g_overkill_powerups_replace) - if(self.classname == "item_invincible") - { - entity wep = spawn(); - setorigin(wep, self.origin); - wep.ok_item = TRUE; - wep.think = start_rpc; - wep.nextthink = time + 0.1; - return TRUE; + if(self.classname == "item_invincible") + { + entity wep = spawn(); + setorigin(wep, self.origin); + setmodel(wep, "models/weapons/g_ok_rl.md3"); + wep.classname = "weapon_rpc"; + wep.ok_item = true; + wep.noalign = self.noalign; + wep.cnt = self.cnt; + wep.team = self.team; + wep.respawntime = autocvar_g_overkill_superguns_respawn_time; + wep.pickup_anyway = true; + wep.think = spawnfunc_weapon_rpc; + wep.nextthink = time + 0.1; + return true; + } } - return FALSE; + return false; } MUTATOR_HOOKFUNCTION(ok_ItemRemove) { if(self.ok_item) - return FALSE; + return false; switch(self.items) { - case IT_HEALTH: return !(autocvar_g_overkill_100h_anyway); - case IT_ARMOR: return !(autocvar_g_overkill_100a_anyway); + case ITEM_HealthMega.m_itemid: return !(autocvar_g_overkill_100h_anyway); + case ITEM_ArmorMega.m_itemid: return !(autocvar_g_overkill_100a_anyway); } - - return TRUE; + + return true; } MUTATOR_HOOKFUNCTION(ok_SpectateCopy) @@ -268,43 +268,59 @@ MUTATOR_HOOKFUNCTION(ok_SpectateCopy) self.ammo_charge[self.weapon] = other.ammo_charge[other.weapon]; self.ok_use_ammocharge = other.ok_use_ammocharge; - return FALSE; + return false; } -MUTATOR_HOOKFUNCTION(ok_SetModname) +MUTATOR_HOOKFUNCTION(ok_StartItems) { - modname = "Overkill"; - return TRUE; + WepSet ok_start_items = (WEPSET_MACHINEGUN | WEPSET_VORTEX | WEPSET_SHOTGUN); + + if(WEP_RPC.weaponstart > 0) { ok_start_items |= WEPSET_RPC; } + if(WEP_HMG.weaponstart > 0) { ok_start_items |= WEPSET_HMG; } + + start_items |= IT_UNLIMITED_WEAPON_AMMO; + start_weapons = warmup_start_weapons = ok_start_items; + + return false; } -MUTATOR_HOOKFUNCTION(ok_StartItems) +MUTATOR_HOOKFUNCTION(ok_BuildMutatorsString) { - start_items |= IT_UNLIMITED_WEAPON_AMMO; - start_weapons = (WEPSET_UZI | WEPSET_NEX | WEPSET_SHOTGUN); + ret_string = strcat(ret_string, ":OK"); + return false; +} + +MUTATOR_HOOKFUNCTION(ok_BuildMutatorsPrettyString) +{ + ret_string = strcat(ret_string, ", Overkill"); + return false; +} - start_ammo_nails = start_ammo_cells = start_ammo_shells = start_ammo_rockets = - warmup_start_ammo_nails = warmup_start_ammo_cells = warmup_start_ammo_shells = warmup_start_ammo_rockets = autocvar_g_overkill_ammo_start; +MUTATOR_HOOKFUNCTION(ok_SetModname) +{ + modname = "Overkill"; + return true; +} - return FALSE; +void ok_SetCvars() +{ + // hack to force overkill playermodels + cvar_settemp("sv_defaultcharacter", "1"); + cvar_settemp("sv_defaultplayermodel", "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"); + cvar_settemp("sv_defaultplayermodel_red", "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"); + cvar_settemp("sv_defaultplayermodel_blue", "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"); } void ok_Initialize() { - precache_all_playermodels("models/ok_player/*.dpm"); + ok_SetCvars(); - precache_model("models/weapons/h_ok_rl.iqm"); - precache_model("models/weapons/v_ok_rl.md3"); - precache_model("models/weapons/g_ok_rl.md3"); - precache_model("models/weapons/ok_rocket.md3"); + precache_all_playermodels("models/ok_player/*.dpm"); precache_model("models/weapons/h_ok_mg.iqm"); precache_model("models/weapons/v_ok_mg.md3"); precache_model("models/weapons/g_ok_mg.md3"); - precache_model("models/weapons/h_ok_hmg.iqm"); - precache_model("models/weapons/v_ok_hmg.md3"); - precache_model("models/weapons/g_ok_hmg.md3"); - precache_model("models/weapons/h_ok_shotgun.iqm"); precache_model("models/weapons/v_ok_shotgun.md3"); precache_model("models/weapons/g_ok_shotgun.md3"); @@ -314,52 +330,35 @@ void ok_Initialize() precache_model("models/weapons/g_ok_sniper.md3"); precache_sound("weapons/dryfire.wav"); - - addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge); - addstat(STAT_OK_AMMO_CHARGEPOOl, AS_FLOAT, ok_ammo_charge); - - w_uzi(WR_PRECACHE); - w_nex(WR_PRECACHE); - w_shotgun(WR_PRECACHE); - w_laser(WR_PRECACHE); - (get_weaponinfo(WEP_RPC)).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED; - (get_weaponinfo(WEP_HMG)).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED; + addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge); + addstat(STAT_OK_AMMO_CHARGEPOOL, AS_FLOAT, ok_ammo_charge); - (get_weaponinfo(WEP_SHOTGUN)).mdl = "ok_shotgun"; - (get_weaponinfo(WEP_UZI)).mdl = "ok_mg"; - (get_weaponinfo(WEP_NEX)).mdl = "ok_sniper"; + WEP_RPC.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED; + WEP_HMG.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED; - string s; - float fh = fopen("overkill.cfg", FILE_READ); - if(fh >= 0) - { - while((s = fgets(fh))) - { - tokenize_console(s); - if not(argv(0) == "" || argv(1) == "//" || argv(1) == "") - cvar_settemp(argv(0), argv(1)); - } - fclose(fh); - } - else - dprint("^1Mutator Overkill: WARNING! overkill.cfg NOT found, things will be strange!\n"); + WEP_SHOTGUN.mdl = "ok_shotgun"; + WEP_MACHINEGUN.mdl = "ok_mg"; + WEP_VORTEX.mdl = "ok_sniper"; } MUTATOR_DEFINITION(mutator_overkill) { MUTATOR_HOOK(ForbidThrowCurrentWeapon, ok_ForbidThrowCurrentWeapon, CBC_ORDER_ANY); - MUTATOR_HOOK(BuildMutatorsString, ok_BuildMutatorsString, CBC_ORDER_ANY); - MUTATOR_HOOK(BuildMutatorsPrettyString, ok_BuildMutatorsPrettyString, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerPreThink, ok_PlayerPreThink, CBC_ORDER_LAST); - MUTATOR_HOOK(PlayerSpawn, ok_PlayerSpawn, CBC_ORDER_LAST); + MUTATOR_HOOK(PlayerSpawn, ok_PlayerSpawn, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerDamage_Calculate, ok_PlayerDamage_Calculate, CBC_ORDER_LAST); + MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, ok_PlayerDamage_SplitHealthArmor, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerDies, ok_PlayerDies, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerRegen, ok_PlayerRegen, CBC_ORDER_ANY); MUTATOR_HOOK(OnEntityPreSpawn, ok_OnEntityPreSpawn, CBC_ORDER_ANY); - MUTATOR_HOOK(SetModname, ok_SetModname, CBC_ORDER_ANY); MUTATOR_HOOK(FilterItem, ok_ItemRemove, CBC_ORDER_ANY); + MUTATOR_HOOK(MonsterDropItem, ok_PlayerDies, CBC_ORDER_ANY); MUTATOR_HOOK(SpectateCopy, ok_SpectateCopy, CBC_ORDER_ANY); MUTATOR_HOOK(SetStartItems, ok_StartItems, CBC_ORDER_ANY); + MUTATOR_HOOK(BuildMutatorsString, ok_BuildMutatorsString, CBC_ORDER_ANY); + MUTATOR_HOOK(BuildMutatorsPrettyString, ok_BuildMutatorsPrettyString, CBC_ORDER_ANY); + MUTATOR_HOOK(SetModname, ok_SetModname, CBC_ORDER_ANY); MUTATOR_ONADD { @@ -368,9 +367,9 @@ MUTATOR_DEFINITION(mutator_overkill) MUTATOR_ONREMOVE { - (get_weaponinfo(WEP_RPC)).spawnflags |= WEP_FLAG_MUTATORBLOCKED; - (get_weaponinfo(WEP_HMG)).spawnflags |= WEP_FLAG_MUTATORBLOCKED; + WEP_RPC.spawnflags |= WEP_FLAG_MUTATORBLOCKED; + WEP_HMG.spawnflags |= WEP_FLAG_MUTATORBLOCKED; } - return FALSE; + return false; }