X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fmonsters%2Fsv_monsters.qc;h=c1414bfd48ed95d9973780a08b383254eac07107;hb=931d24d4337e58557fa82a68aa8a740e523c2f22;hp=2e7281bc2c2d1f9b08bdccb6005da9c9b228a923;hpb=3d4a324cc2e15c1eb99209674942506eb998e2ec;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index 2e7281bc2..c1414bfd4 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -1,29 +1,27 @@ -#if defined(CSQC) -#elif defined(MENUQC) -#elif defined(SVQC) - #include - #include "../constants.qh" - #include "../teams.qh" - #include "../util.qh" - #include "all.qh" - #include "sv_monsters.qh" - #include "../physics/movelib.qh" - #include "../weapons/all.qh" - #include - #include - #include "../deathtypes/all.qh" - #include - #include - #include "../turrets/sv_turrets.qh" - #include "../turrets/util.qh" - #include "../vehicles/all.qh" - #include - #include - #include - #include "../triggers/triggers.qh" - #include - #include -#endif +#include "sv_monsters.qh" + +#include +#include +#include "../constants.qh" +#include "../teams.qh" +#include "../util.qh" +#include "all.qh" +#include "../physics/movelib.qh" +#include "../weapons/_mod.qh" +#include +#include +#include "../deathtypes/all.qh" +#include +#include +#include "../turrets/sv_turrets.qh" +#include "../turrets/util.qh" +#include "../vehicles/all.qh" +#include +#include +#include "../triggers/triggers.qh" +#include +#include +#include void monsters_setstatus(entity this) { @@ -31,7 +29,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,15 +40,15 @@ 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) { e.noalign = true; - WITHSELF(e, e.monster_loot(e)); + e.monster_loot(e); e.gravity = 1; - e.movetype = MOVETYPE_TOSS; + set_movetype(e, MOVETYPE_TOSS); e.reset = SUB_Remove; setorigin(e, org); e.velocity = randomvec() * 175 + '0 0 325'; @@ -94,16 +92,17 @@ bool Monster_ValidTarget(entity this, entity targ) || (SAME_TEAM(targ, this)) || (STAT(FROZEN, targ)) || (targ.alpha != 0 && targ.alpha < 0.5) + || (MUTATOR_CALLHOOK(MonsterValidTarget, this, targ)) ) { // if any of the above checks fail, target is not valid return false; } - traceline(this.origin + this.view_ofs, targ.origin, 0, this); + traceline(this.origin + this.view_ofs, targ.origin, MOVE_NOMONSTERS, this); - if((trace_fraction < 1) && (trace_ent != targ)) - return false; + if(trace_fraction < 1) + return false; // solid if(autocvar_g_monsters_target_infront || (this.spawnflags & MONSTERFLAG_INFRONT)) if(this.enemy != targ) @@ -123,29 +122,26 @@ entity Monster_FindTarget(entity mon) { if(MUTATOR_CALLHOOK(MonsterFindTarget)) { return mon.enemy; } // Handled by a mutator - entity head, closest_target = world; - head = findradius(mon.origin, mon.target_range); + entity closest_target = NULL; - while(head) // find the closest acceptable target to pass to + // find the closest acceptable target to pass to + FOREACH_ENTITY_RADIUS(mon.origin, mon.target_range, it.monster_attack, { - if(head.monster_attack) - if(Monster_ValidTarget(mon, head)) + if(Monster_ValidTarget(mon, it)) { // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc) - vector head_center = CENTER_OR_VIEWOFS(head); + vector head_center = CENTER_OR_VIEWOFS(it); vector ent_center = CENTER_OR_VIEWOFS(mon); if(closest_target) { vector closest_target_center = CENTER_OR_VIEWOFS(closest_target); if(vlen2(ent_center - head_center) < vlen2(ent_center - closest_target_center)) - { closest_target = head; } + { closest_target = it; } } - else { closest_target = head; } + else { closest_target = it; } } - - head = head.chain; - } + }); return closest_target; } @@ -250,7 +246,7 @@ void Monster_Sound_Precache(string f) { if(tokenize_console(s) != 3) { - LOG_TRACE("Invalid sound info line: ", s, "\n"); + LOG_TRACE("Invalid sound info line: ", s); continue; } PrecacheGlobalSound(strcat(argv(1), " ", argv(2))); @@ -305,7 +301,7 @@ bool Monster_Sounds_Load(entity this, string f, int first) fh = fopen(f, FILE_READ); if(fh < 0) { - LOG_TRACE("Monster sound file not found: ", f, "\n"); + LOG_TRACE("Monster sound file not found: ", f); return false; } while((s = fgets(fh))) @@ -341,7 +337,7 @@ void Monster_Sound(entity this, .string samplefield, float sound_delay, float de if(delaytoo) if(time < this.msound_delay) return; // too early - GlobalSound_string(this, this.(samplefield), chan, VOICETYPE_PLAYERSOUND); + GlobalSound_string(this, this.(samplefield), chan, VOL_BASE, VOICETYPE_PLAYERSOUND); this.msound_delay = time + sound_delay; } @@ -394,7 +390,7 @@ bool Monster_Attack_Leap_Check(entity this, vector vel) return true; } -bool Monster_Attack_Leap(entity this, vector anm, void(entity this) touchfunc, vector vel, float animtime) +bool Monster_Attack_Leap(entity this, vector anm, void(entity this, entity toucher) touchfunc, vector vel, float animtime) { if(!Monster_Attack_Leap_Check(this, vel)) return false; @@ -416,16 +412,18 @@ bool Monster_Attack_Leap(entity this, vector anm, void(entity this) touchfunc, v return true; } -void Monster_Attack_Check(entity this, entity targ) +void Monster_Attack_Check(entity this, entity targ, .entity weaponentity) { - if((this == world || targ == world) + int slot = weaponslot(weaponentity); + + if((this == NULL || targ == NULL) || (!this.monster_attackfunc) - || (time < this.attack_finished_single[0]) + || (time < this.attack_finished_single[slot]) ) { return; } if(vdist(targ.origin - this.origin, <=, this.attack_range)) { - bool attack_success = this.monster_attackfunc(MONSTER_ATTACK_MELEE, this, targ); + bool attack_success = this.monster_attackfunc(MONSTER_ATTACK_MELEE, this, targ, weaponentity); if(attack_success == 1) Monster_Sound(this, monstersound_melee, 0, false, CH_VOICE); else if(attack_success > 0) @@ -434,7 +432,7 @@ void Monster_Attack_Check(entity this, entity targ) if(vdist(targ.origin - this.origin, >, this.attack_range)) { - float attack_success = this.monster_attackfunc(MONSTER_ATTACK_RANGED, this, targ); + float attack_success = this.monster_attackfunc(MONSTER_ATTACK_RANGED, this, targ, weaponentity); if(attack_success == 1) Monster_Sound(this, monstersound_melee, 0, false, CH_VOICE); else if(attack_success > 0) @@ -466,15 +464,15 @@ void Monster_UpdateModel(entity this) mon.mr_anim(mon, this); } -void Monster_Touch(entity this) +void Monster_Touch(entity this, entity toucher) { - if(other == world) { return; } + if(toucher == NULL) { return; } - if(other.monster_attack) - if(this.enemy != other) - if(!IS_MONSTER(other)) - if(Monster_ValidTarget(this, other)) - this.enemy = other; + if(toucher.monster_attack) + if(this.enemy != toucher) + if(!IS_MONSTER(toucher)) + if(Monster_ValidTarget(this, toucher)) + this.enemy = toucher; } void Monster_Miniboss_Check(entity this) @@ -511,6 +509,8 @@ bool Monster_Respawn_Check(entity this) void Monster_Respawn(entity this) { Monster_Spawn(this, this.monsterid); } +.vector pos1, pos2; + void Monster_Dead_Fade(entity this) { if(Monster_Respawn_Check(this)) @@ -546,6 +546,7 @@ void Monster_Use(entity this, entity actor, entity trigger) if(Monster_ValidTarget(this, actor)) { this.enemy = actor; } } +.float pass_distance; vector Monster_Move_Target(entity this, entity targ) { // enemy is always preferred target @@ -555,7 +556,7 @@ vector Monster_Move_Target(entity this, entity targ) targ_origin = WarpZone_RefSys_TransformOrigin(this.enemy, this, targ_origin); // origin of target as seen by the monster (us) WarpZone_TraceLine(this.origin, targ_origin, MOVE_NOMONSTERS, this); - if((this.enemy == world) + if((this.enemy == NULL) || (IS_DEAD(this.enemy) || this.enemy.health < 1) || (STAT(FROZEN, this.enemy)) || (this.enemy.flags & FL_NOTARGET) @@ -564,13 +565,13 @@ vector Monster_Move_Target(entity this, entity targ) || (vdist(this.origin - targ_origin, >, this.target_range)) || ((trace_fraction < 1) && (trace_ent != this.enemy))) { - this.enemy = world; + this.enemy = NULL; this.pass_distance = 0; } if(this.enemy) { - /*WarpZone_TrailParticles(world, particleeffectnum(EFFECT_RED_PASS), this.origin, targ_origin); + /*WarpZone_TrailParticles(NULL, particleeffectnum(EFFECT_RED_PASS), this.origin, targ_origin); print("Trace origin: ", vtos(targ_origin), "\n"); print("Target origin: ", vtos(this.enemy.origin), "\n"); print("My origin: ", vtos(this.origin), "\n"); */ @@ -688,11 +689,15 @@ void Monster_CalculateVelocity(entity this, vector to, vector from, float turnra //this.angles = vectoangles(this.velocity); } +.entity draggedby; +.entity target2; + void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) { - if(this.target2) { this.goalentity = find(world, targetname, this.target2); } + // update goal entity if lost + if(this.target2 && this.goalentity.targetname != this.target2) { this.goalentity = find(NULL, targetname, this.target2); } - entity targ; + entity targ = this.goalentity; if(STAT(FROZEN, this) == 2) { @@ -706,7 +711,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) movelib_brake_simple(this, stpspeed); setanim(this, this.anim_idle, true, false, false); - this.enemy = world; + this.enemy = NULL; this.nextthink = time + this.ticrate; if(this.revive_progress >= 1) @@ -725,7 +730,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) movelib_brake_simple(this, stpspeed); setanim(this, this.anim_idle, true, false, false); - this.enemy = world; + this.enemy = NULL; this.nextthink = time + this.ticrate; if(this.health < 1) @@ -750,7 +755,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) { this.last_trace = time + 0.4; - Damage (this, world, world, 2, DEATH_DROWN.m_id, this.origin, '0 0 0'); + Damage (this, NULL, NULL, 2, DEATH_DROWN.m_id, this.origin, '0 0 0'); this.angles = '90 90 0'; if(random() < 0.5) { @@ -766,23 +771,21 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) } - this.movetype = MOVETYPE_BOUNCE; + set_movetype(this, MOVETYPE_BOUNCE); //this.velocity_z = -200; return; } - else if(this.movetype == MOVETYPE_BOUNCE) + else if(this.move_movetype == MOVETYPE_BOUNCE) { this.angles_x = 0; - this.movetype = MOVETYPE_WALK; + set_movetype(this, MOVETYPE_WALK); } } - targ = this.goalentity; - if (MUTATOR_CALLHOOK(MonsterMove, this, runspeed, walkspeed, targ) || gameover - || this.draggedby != world + || this.draggedby != NULL || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || time < game_starttime || (autocvar_g_campaign && !campaign_bots_may_start) @@ -795,14 +798,14 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) return; } - targ = monster_target; - runspeed = bound(0, monster_speed_run * MONSTER_SKILLMOD(this), runspeed * 2.5); // limit maxspeed to prevent craziness - walkspeed = bound(0, monster_speed_walk * MONSTER_SKILLMOD(this), walkspeed * 2.5); // limit maxspeed to prevent craziness + targ = M_ARGV(3, entity); + runspeed = bound(0, M_ARGV(1, float) * MONSTER_SKILLMOD(this), runspeed * 2.5); // limit maxspeed to prevent craziness + walkspeed = bound(0, M_ARGV(2, float) * MONSTER_SKILLMOD(this), walkspeed * 2.5); // limit maxspeed to prevent craziness if(teamplay) if(autocvar_g_monsters_teams) if(DIFF_TEAM(this.monster_follow, this)) - this.monster_follow = world; + this.monster_follow = NULL; if(time >= this.last_enemycheck) { @@ -866,10 +869,10 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) } else { - entity e = find(world, targetname, this.target2); + entity e = this.goalentity; //find(NULL, targetname, this.target2); if(e.target2) this.target2 = e.target2; - else if(e.target) + else if(e.target) // compatibility this.target2 = e.target; movelib_brake_simple(this, stpspeed); @@ -892,7 +895,8 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed) this.angles_y += turny; } - Monster_Attack_Check(this, this.enemy); + .entity weaponentity = weaponentities[0]; // TODO? + Monster_Attack_Check(this, this.enemy, weaponentity); } void Monster_Remove(entity this) @@ -900,16 +904,20 @@ void Monster_Remove(entity this) if(IS_CLIENT(this)) return; // don't remove it? - .entity weaponentity = weaponentities[0]; if(!this) { return; } if(!MUTATOR_CALLHOOK(MonsterRemove, this)) Send_Effect(EFFECT_ITEM_PICKUP, this.origin, '0 0 0', 1); - if(this.(weaponentity)) { remove(this.(weaponentity)); } - if(this.iceblock) { remove(this.iceblock); } + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(this.(weaponentity)) + delete(this.(weaponentity)); + } + if(this.iceblock) { delete(this.iceblock); } WaypointSprite_Kill(this.sprite); - remove(this); + delete(this); } void Monster_Dead_Think(entity this) @@ -954,8 +962,8 @@ void Monster_Reset(entity this) this.health = this.max_health; this.velocity = '0 0 0'; - this.enemy = world; - this.goalentity = world; + this.enemy = NULL; + this.goalentity = NULL; this.attack_finished_single[0] = 0; this.moveto = this.origin; } @@ -991,7 +999,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); @@ -1012,8 +1020,8 @@ void Monster_Dead(entity this, entity attacker, float gibbed) this.solid = SOLID_CORPSE; this.takedamage = DAMAGE_AIM; this.deadflag = DEAD_DEAD; - this.enemy = world; - this.movetype = MOVETYPE_TOSS; + this.enemy = NULL; + set_movetype(this, MOVETYPE_TOSS); this.moveto = this.origin; settouch(this, Monster_Touch); // reset incase monster was pouncing this.reset = func_null; @@ -1030,7 +1038,10 @@ void Monster_Dead(entity this, entity attacker, float gibbed) mon.mr_death(mon, this); if(this.candrop && this.weapon) - W_ThrowNewWeapon(this, this.weapon, 0, this.origin, randomvec() * 150 + '0 0 325'); + { + .entity weaponentity = weaponentities[0]; // TODO: unhardcode + W_ThrowNewWeapon(this, this.weapon, 0, this.origin, randomvec() * 150 + '0 0 325', weaponentity); + } } void Monster_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) @@ -1047,7 +1058,7 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage if(time < this.spawnshieldtime && deathtype != DEATH_KILL.m_id) return; - if(deathtype == DEATH_FALL.m_id && this.draggedby != world) + if(deathtype == DEATH_FALL.m_id && this.draggedby != NULL) return; vector v; @@ -1057,12 +1068,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 +1109,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 { @@ -1117,7 +1124,7 @@ void Monster_Damage(entity this, entity inflictor, entity attacker, float damage // don't check for enemies, just keep walking in a straight line void Monster_Move_2D(entity this, float mspeed, bool allow_jumpoff) { - if(gameover || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || this.draggedby != world || time < game_starttime || (autocvar_g_campaign && !campaign_bots_may_start) || time < this.spawn_time) + if(gameover || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || this.draggedby != NULL || time < game_starttime || (autocvar_g_campaign && !campaign_bots_may_start) || time < this.spawn_time) { mspeed = 0; if(time >= this.spawn_time) @@ -1270,7 +1277,7 @@ bool Monster_Spawn_Setup(entity this) if(autocvar_g_monsters_healthbars) { - entity wp = WaypointSprite_Spawn(WP_Monster, 0, 1024, this, '0 0 1' * (this.maxs.z + 15), world, this.team, this, sprite, true, RADARICON_DANGER); + entity wp = WaypointSprite_Spawn(WP_Monster, 0, 1024, this, '0 0 1' * (this.maxs.z + 15), NULL, this.team, this, sprite, true, RADARICON_DANGER); wp.wp_extra = this.monsterid; wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 0 0'); if(!(this.spawnflags & MONSTERFLAG_INVINCIBLE)) @@ -1297,6 +1304,9 @@ bool Monster_Spawn(entity this, int mon_id) if(!autocvar_g_monsters) { Monster_Remove(this); return false; } + if(!(this.spawnflags & MONSTERFLAG_RESPAWNED)) + IL_PUSH(g_monsters, this); + if(Monster_Appear_Check(this, mon_id)) { return true; } // return true so the monster isn't removed if(!this.monster_skill) @@ -1319,6 +1329,7 @@ bool Monster_Spawn(entity this, int mon_id) this.classname = "monster"; this.takedamage = DAMAGE_AIM; this.bot_attack = true; + IL_PUSH(g_bot_targets, this); this.iscreature = true; this.teleportable = true; this.damagedbycontents = true; @@ -1327,9 +1338,9 @@ bool Monster_Spawn(entity this, int mon_id) settouch(this, Monster_Touch); this.use = Monster_Use; this.solid = SOLID_BBOX; - this.movetype = MOVETYPE_WALK; + set_movetype(this, MOVETYPE_WALK); this.spawnshieldtime = time + autocvar_g_monsters_spawnshieldtime; - this.enemy = world; + this.enemy = NULL; this.velocity = '0 0 0'; this.moveto = this.origin; this.pos1 = this.origin; @@ -1362,7 +1373,7 @@ bool Monster_Spawn(entity this, int mon_id) if(mon.spawnflags & MONSTER_TYPE_FLY) { this.flags |= FL_FLY; - this.movetype = MOVETYPE_FLY; + set_movetype(this, MOVETYPE_FLY); } if(!(this.spawnflags & MONSTERFLAG_RESPAWNED))