X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fmonsters%2Fsv_monsters.qc;h=c707f8c38e5ede6509fd6620456bbbd7288468e7;hb=a568545ed787883224aa1cff980bd5b50a661edc;hp=ccd10ee4532dcc911ad001862fa0866178f886fc;hpb=0b6694545ba935bbac13c20fc11842ba1850d972;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index ccd10ee45..c707f8c38 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -1,6 +1,5 @@ #include "sv_monsters.qh" -#include #include #include "../constants.qh" #include "../teams.qh" @@ -18,7 +17,7 @@ #include "../vehicles/all.qh" #include #include -#include "../triggers/triggers.qh" +#include "../mapobjects/triggers.qh" #include #include #include @@ -85,7 +84,7 @@ bool Monster_ValidTarget(entity this, entity targ) || (game_stopped) || (targ.items & IT_INVISIBILITY) || (IS_SPEC(targ) || IS_OBSERVER(targ)) // don't attack spectators - || (!IS_VEHICLE(targ) && (IS_DEAD(targ) || IS_DEAD(this) || targ.health <= 0 || this.health <= 0)) + || (!IS_VEHICLE(targ) && (IS_DEAD(targ) || IS_DEAD(this) || GetResource(targ, RES_HEALTH) <= 0 || GetResource(this, RES_HEALTH) <= 0)) || (this.monster_follow == targ || targ.monster_follow == this) || (!IS_VEHICLE(targ) && (targ.flags & FL_NOTARGET)) || (!autocvar_g_monsters_typefrag && PHYS_INPUT_BUTTON_CHAT(targ)) @@ -376,7 +375,7 @@ bool Monster_Attack_Leap_Check(entity this, vector vel) return false; // already attacking if(!IS_ONGROUND(this)) return false; // not on the ground - if(this.health <= 0 || IS_DEAD(this)) + if(GetResource(this, RES_HEALTH) <= 0 || IS_DEAD(this)) return false; // called when dead? if(time < this.attack_finished_single[0]) return false; // still attacking @@ -487,7 +486,7 @@ void Monster_Miniboss_Check(entity this) // g_monsters_miniboss_chance cvar or spawnflags 64 causes a monster to be a miniboss if ((this.spawnflags & MONSTERFLAG_MINIBOSS) || (chance < autocvar_g_monsters_miniboss_chance)) { - this.health += autocvar_g_monsters_miniboss_healthboost; + GiveResource(this, RES_HEALTH, autocvar_g_monsters_miniboss_healthboost); this.effects |= EF_RED; if(!this.weapon) this.weapon = WEP_VORTEX.m_id; @@ -528,10 +527,11 @@ void Monster_Dead_Fade(entity this) this.pos2 = this.angles; } this.event_damage = func_null; + this.event_heal = func_null; this.takedamage = DAMAGE_NO; setorigin(this, this.pos1); this.angles = this.pos2; - this.health = this.max_health; + SetResourceExplicit(this, RES_HEALTH, this.max_health); setmodel(this, MDL_Null); } else @@ -560,7 +560,7 @@ vector Monster_Move_Target(entity this, entity targ) // cases where the enemy may have changed their state (don't need to check everything here) if((!this.enemy) - || (IS_DEAD(this.enemy) || this.enemy.health < 1) + || (IS_DEAD(this.enemy) || GetResource(this.enemy, RES_HEALTH) < 1) || (STAT(FROZEN, this.enemy)) || (this.enemy.flags & FL_NOTARGET) || (this.enemy.alpha < 0.5 && this.enemy.alpha != 0) @@ -695,7 +695,6 @@ void Monster_CalculateVelocity(entity this, vector to, vector from, float turnra } .entity draggedby; -.entity target2; void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) { @@ -804,10 +803,12 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) if(time > this.pain_finished && time > this.anim_finished) // TODO: use anim_finished instead!? if(!this.state) - if(vdist(this.velocity, >, 10)) - setanim(this, ((do_run) ? this.anim_run : this.anim_walk), true, false, false); - else - setanim(this, this.anim_idle, true, false, false); + { + if(vdist(this.velocity, >, 10)) + setanim(this, ((do_run) ? this.anim_run : this.anim_walk), true, false, false); + else + setanim(this, this.anim_idle, true, false, false); + } } else { @@ -895,9 +896,9 @@ void Monster_Reset(entity this) setorigin(this, this.pos1); this.angles = this.pos2; - Unfreeze(this); // remove any icy remains + Unfreeze(this, false); // remove any icy remains - this.health = this.max_health; + SetResourceExplicit(this, RES_HEALTH, this.max_health); this.velocity = '0 0 0'; this.enemy = NULL; this.goalentity = NULL; @@ -907,11 +908,11 @@ void Monster_Reset(entity this) void Monster_Dead_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) { - this.health -= damage; + TakeResource(this, RES_HEALTH, damage); Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, this, attacker); - if(this.health <= -50) // 100 health until gone? + if(GetResource(this, RES_HEALTH) <= -50) // 100 health until gone? { Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, this, attacker); @@ -931,10 +932,7 @@ void Monster_Dead(entity this, entity attacker, float gibbed) this.monster_lifetime = time + 5; if(STAT(FROZEN, this)) - { - Unfreeze(this); // remove any icy remains - this.health = 0; // reset by Unfreeze - } + Unfreeze(this, false); // remove any icy remains monster_dropitem(this, attacker); @@ -957,6 +955,7 @@ void Monster_Dead(entity this, entity attacker, float gibbed) _setmodel(this, this.mdl_dead); this.event_damage = ((gibbed) ? func_null : Monster_Dead_Damage); + this.event_heal = func_null; this.solid = SOLID_CORPSE; this.takedamage = DAMAGE_AIM; this.deadflag = DEAD_DEAD; @@ -1001,7 +1000,7 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage if(deathtype == DEATH_FALL.m_id && this.draggedby != NULL) return; - vector v = healtharmor_applydamage(100, this.armorvalue / 100, deathtype, damage); + vector v = healtharmor_applydamage(100, GetResource(this, RES_ARMOR) / 100, deathtype, damage); float take = v.x; //float save = v.y; @@ -1010,12 +1009,12 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage if(take) { - this.health -= take; + TakeResource(this, RES_HEALTH, take); Monster_Sound(this, monstersound_pain, 1.2, true, CH_PAIN); } if(this.sprite) - WaypointSprite_UpdateHealth(this.sprite, this.health); + WaypointSprite_UpdateHealth(this.sprite, GetResource(this, RES_HEALTH)); this.dmg_time = time; @@ -1033,7 +1032,7 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, this, attacker); } - if(this.health <= 0) + if(GetResource(this, RES_HEALTH) <= 0) { if(deathtype == DEATH_KILL.m_id) this.candrop = false; // killed by mobkill command @@ -1042,13 +1041,13 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage SUB_UseTargets(this, attacker, this.enemy); this.target2 = this.oldtarget2; // reset to original target on death, incase we respawn - Monster_Dead(this, attacker, (this.health <= -100 || deathtype == DEATH_KILL.m_id)); + Monster_Dead(this, attacker, (GetResource(this, RES_HEALTH) <= -100 || deathtype == DEATH_KILL.m_id)); WaypointSprite_Kill(this.sprite); MUTATOR_CALLHOOK(MonsterDies, this, attacker, deathtype); - if(this.health <= -100 || deathtype == DEATH_KILL.m_id) // check if we're already gibbed + if(GetResource(this, RES_HEALTH) <= -100 || deathtype == DEATH_KILL.m_id) // check if we're already gibbed { Violence_GibSplash(this, 1, 0.5, attacker); @@ -1058,6 +1057,18 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage } } +bool Monster_Heal(entity targ, entity inflictor, float amount, float limit) +{ + float true_limit = ((limit != RES_LIMIT_NONE) ? limit : targ.max_health); + if(GetResource(targ, RES_HEALTH) <= 0 || GetResource(targ, RES_HEALTH) >= true_limit) + return false; + + GiveResourceWithLimit(targ, RES_HEALTH, amount, true_limit); + if(targ.sprite) + WaypointSprite_UpdateHealth(targ.sprite, GetResource(targ, RES_HEALTH)); + return true; +} + // don't check for enemies, just keep walking in a straight line void Monster_Move_2D(entity this, float mspeed, bool allow_jumpoff) { @@ -1084,15 +1095,12 @@ void Monster_Move_2D(entity this, float mspeed, bool allow_jumpoff) if(trace_ent && IS_MONSTER(trace_ent)) reverse = true; - // TODO: fix this... tracing is broken if the floor is thin - /* - if(!allow_jumpoff) + if(!allow_jumpoff && IS_ONGROUND(this)) { - a = b - '0 0 32'; - traceline(b, a, MOVE_WORLDONLY, this); + traceline(b, b - '0 0 32', MOVE_NORMAL, this); if(trace_fraction == 1.0) reverse = true; - } */ + } if(reverse) { @@ -1103,10 +1111,12 @@ void Monster_Move_2D(entity this, float mspeed, bool allow_jumpoff) movelib_move_simple_gravity(this, v_forward, mspeed, 1); if(time > this.pain_finished && time > this.attack_finished_single[0]) - if(vdist(this.velocity, >, 10)) - setanim(this, this.anim_walk, true, false, false); - else - setanim(this, this.anim_idle, true, false, false); + { + if(vdist(this.velocity, >, 10)) + setanim(this, this.anim_walk, true, false, false); + else + setanim(this, this.anim_idle, true, false, false); + } } void Monster_Anim(entity this) @@ -1148,36 +1158,34 @@ void Monster_Anim(entity this) void Monster_Frozen_Think(entity this) { - if(STAT(FROZEN, this) == 2) + if (STAT(FROZEN, this) == FROZEN_TEMP_REVIVING) { STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) + this.ticrate * this.revive_speed, 1); - this.health = max(1, STAT(REVIVE_PROGRESS, this) * this.max_health); + SetResourceExplicit(this, RES_HEALTH, max(1, STAT(REVIVE_PROGRESS, this) * this.max_health)); this.iceblock.alpha = bound(0.2, 1 - STAT(REVIVE_PROGRESS, this), 1); if(!(this.spawnflags & MONSTERFLAG_INVINCIBLE) && this.sprite) - WaypointSprite_UpdateHealth(this.sprite, this.health); + WaypointSprite_UpdateHealth(this.sprite, GetResource(this, RES_HEALTH)); if(STAT(REVIVE_PROGRESS, this) >= 1) - Unfreeze(this); + Unfreeze(this, false); } - else if(STAT(FROZEN, this) == 3) + else if (STAT(FROZEN, this) == FROZEN_TEMP_DYING) { STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) - this.ticrate * this.revive_speed, 1); - this.health = max(0, autocvar_g_nades_ice_health + (this.max_health-autocvar_g_nades_ice_health) * STAT(REVIVE_PROGRESS, this) ); + SetResourceExplicit(this, RES_HEALTH, max(0, autocvar_g_nades_ice_health + (this.max_health-autocvar_g_nades_ice_health) * STAT(REVIVE_PROGRESS, this))); if(!(this.spawnflags & MONSTERFLAG_INVINCIBLE) && this.sprite) - WaypointSprite_UpdateHealth(this.sprite, this.health); + WaypointSprite_UpdateHealth(this.sprite, GetResource(this, RES_HEALTH)); - if(this.health < 1) + if(GetResource(this, RES_HEALTH) < 1) { - Unfreeze(this); - this.health = 0; + Unfreeze(this, false); if(this.event_damage) this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, DMG_NOWEP, this.origin, '0 0 0'); } - else if ( STAT(REVIVE_PROGRESS, this) <= 0 ) - Unfreeze(this); + Unfreeze(this, false); } // otherwise, no revival! @@ -1211,7 +1219,7 @@ void Monster_Think(entity this) if(this.monster_lifetime && time >= this.monster_lifetime) { - Damage(this, this, this, this.health + this.max_health, DEATH_KILL.m_id, DMG_NOWEP, this.origin, this.origin); + Damage(this, this, this, GetResource(this, RES_HEALTH) + this.max_health, DEATH_KILL.m_id, DMG_NOWEP, this.origin, this.origin); return; } @@ -1243,8 +1251,8 @@ bool Monster_Spawn_Setup(entity this) mon.mr_setup(mon, this); // ensure some basic needs are met - if(!this.health) { this.health = 100; } - if(!this.armorvalue) { this.armorvalue = bound(0.2, 0.5 * MONSTER_SKILLMOD(this), 0.9); } + if(!GetResource(this, RES_HEALTH)) { SetResourceExplicit(this, RES_HEALTH, 100); } + if(!GetResource(this, RES_ARMOR)) { SetResourceExplicit(this, RES_ARMOR, bound(0.2, 0.5 * MONSTER_SKILLMOD(this), 0.9)); } if(!this.target_range) { this.target_range = autocvar_g_monsters_target_range; } if(!this.respawntime) { this.respawntime = autocvar_g_monsters_respawn_delay; } if(!this.monster_moveflags) { this.monster_moveflags = MONSTER_MOVE_WANDER; } @@ -1254,13 +1262,13 @@ bool Monster_Spawn_Setup(entity this) if(!(this.spawnflags & MONSTERFLAG_RESPAWNED)) { Monster_Miniboss_Check(this); - this.health *= MONSTER_SKILLMOD(this); + SetResourceExplicit(this, RES_HEALTH, GetResource(this, RES_HEALTH) * MONSTER_SKILLMOD(this)); if(!this.skin) this.skin = rint(random() * 4); } - this.max_health = this.health; + this.max_health = GetResource(this, RES_HEALTH); this.pain_finished = this.nextthink; if(IS_PLAYER(this.monster_follow)) @@ -1289,7 +1297,7 @@ bool Monster_Spawn_Setup(entity this) if(!(this.spawnflags & MONSTERFLAG_INVINCIBLE)) { WaypointSprite_UpdateMaxHealth(this.sprite, this.max_health); - WaypointSprite_UpdateHealth(this.sprite, this.health); + WaypointSprite_UpdateHealth(this.sprite, GetResource(this, RES_HEALTH)); } } @@ -1354,6 +1362,7 @@ bool Monster_Spawn(entity this, bool check_appear, int mon_id) this.damagedbycontents = true; this.monsterid = mon_id; this.event_damage = Monster_Damage; + this.event_heal = Monster_Heal; settouch(this, Monster_Touch); this.use = Monster_Use; this.solid = SOLID_BBOX;