X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Fturrets%2Fsv_turrets.qc;h=37fb5f0d524d78bc7b8180d049213ab407fd72da;hp=83db075b422a7efe3f75dd1bab2a9220102d8060;hb=913b5501b8eaa7793de54875d4992f23c211b6e0;hpb=451e02a2857d8c671f6dcf6a0639ea7c609b3ba9 diff --git a/qcsrc/common/turrets/sv_turrets.qc b/qcsrc/common/turrets/sv_turrets.qc index 83db075b42..37fb5f0d52 100644 --- a/qcsrc/common/turrets/sv_turrets.qc +++ b/qcsrc/common/turrets/sv_turrets.qc @@ -182,9 +182,10 @@ void turret_die(entity this) this.tur_head.solid = this.solid; this.event_damage = func_null; + this.event_heal = func_null; this.takedamage = DAMAGE_NO; - this.health = 0; + SetResourceAmountExplicit(this, RESOURCE_HEALTH, 0); // Go boom //RadiusDamage (this,this, min(this.ammo,50),min(this.ammo,50) * 0.25,250,NULL,min(this.ammo,50)*5,DEATH_TURRET,NULL); @@ -192,6 +193,10 @@ void turret_die(entity this) Turret tur = get_turretinfo(this.m_id); if(this.damage_flags & TFL_DMG_DEATH_NORESPAWN) { + // do a simple explosion effect here, since CSQC can't do it on a to-be-removed entity + sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM); + Send_Effect(EFFECT_ROCKET_EXPLODE, this.origin, '0 0 0', 1); + tur.tr_death(tur, this); delete(this.tur_head); @@ -208,7 +213,7 @@ void turret_die(entity this) } } -void turret_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce) +void turret_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector vforce) { // Enough already! if(this.deadflag == DEAD_DEAD) @@ -226,7 +231,7 @@ void turret_damage(entity this, entity inflictor, entity attacker, float damage, return; } - this.health -= damage; + TakeResource(this, RESOURCE_HEALTH, damage); // thorw head slightly off aim when hit? if (this.damage_flags & TFL_DMG_HEADSHAKE) @@ -240,10 +245,12 @@ void turret_damage(entity this, entity inflictor, entity attacker, float damage, if (this.turret_flags & TUR_FLAG_MOVE) this.velocity = this.velocity + vforce; - if (this.health <= 0) + if (GetResourceAmount(this, RESOURCE_HEALTH) <= 0) { this.event_damage = func_null; this.tur_head.event_damage = func_null; + this.event_heal = func_null; + this.tur_head.event_heal = func_null; this.takedamage = DAMAGE_NO; this.nextthink = time; setthink(this, turret_die); @@ -252,6 +259,17 @@ void turret_damage(entity this, entity inflictor, entity attacker, float damage, this.SendFlags |= TNSF_STATUS; } +bool turret_heal(entity targ, entity inflictor, float amount, float limit) +{ + float true_limit = ((limit != RESOURCE_LIMIT_NONE) ? limit : targ.max_health); + if(GetResourceAmount(targ, RESOURCE_HEALTH) <= 0 || GetResourceAmount(targ, RESOURCE_HEALTH) >= true_limit) + return false; + + GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, true_limit); + targ.SendFlags |= TNSF_STATUS; + return true; +} + void turret_think(entity this); void turret_respawn(entity this) { @@ -264,10 +282,11 @@ void turret_respawn(entity this) this.solid = SOLID_BBOX; this.takedamage = DAMAGE_AIM; this.event_damage = turret_damage; + this.event_heal = turret_heal; this.avelocity = '0 0 0'; this.tur_head.avelocity = this.avelocity; this.tur_head.angles = this.idle_aim; - this.health = this.max_health; + SetResourceAmountExplicit(this, RESOURCE_HEALTH, this.max_health); this.enemy = NULL; this.volly_counter = this.shot_volly; this.ammo = this.ammo_max; @@ -309,9 +328,7 @@ bool turret_send(entity this, entity to, float sf) { WriteByte(MSG_ENTITY, this.m_id); - WriteCoord(MSG_ENTITY, this.origin_x); - WriteCoord(MSG_ENTITY, this.origin_y); - WriteCoord(MSG_ENTITY, this.origin_z); + WriteVector(MSG_ENTITY, this.origin); WriteAngle(MSG_ENTITY, this.angles_x); WriteAngle(MSG_ENTITY, this.angles_y); @@ -331,13 +348,9 @@ bool turret_send(entity this, entity to, float sf) if(sf & TNSF_MOVE) { - WriteShort(MSG_ENTITY, rint(this.origin_x)); - WriteShort(MSG_ENTITY, rint(this.origin_y)); - WriteShort(MSG_ENTITY, rint(this.origin_z)); + WriteVector(MSG_ENTITY, this.origin); - WriteShort(MSG_ENTITY, rint(this.velocity_x)); - WriteShort(MSG_ENTITY, rint(this.velocity_y)); - WriteShort(MSG_ENTITY, rint(this.velocity_z)); + WriteVector(MSG_ENTITY, this.velocity); WriteShort(MSG_ENTITY, rint(this.angles_y)); } @@ -352,10 +365,10 @@ bool turret_send(entity this, entity to, float sf) { WriteByte(MSG_ENTITY, this.team); - if(this.health <= 0) + if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) WriteByte(MSG_ENTITY, 0); else - WriteByte(MSG_ENTITY, ceil((this.health / this.max_health) * 255)); + WriteByte(MSG_ENTITY, ceil((GetResourceAmount(this, RESOURCE_HEALTH) / this.max_health) * 255)); } return true; @@ -386,7 +399,7 @@ void load_unit_settings(entity ent, bool is_reload) ent.tur_head.angles = '0 0 0'; } - ent.health = cvar(strcat(sbase,"_health")) * ent.turret_scale_health; + SetResourceAmountExplicit(ent, RESOURCE_HEALTH, cvar(strcat(sbase,"_health")) * ent.turret_scale_health); ent.respawntime = cvar(strcat(sbase,"_respawntime")) * ent.turret_scale_respawn; ent.shot_dmg = cvar(strcat(sbase,"_shot_dmg")) * ent.turret_scale_damage; @@ -435,11 +448,11 @@ void turret_projectile_explode(entity this) this.event_damage = func_null; #ifdef TURRET_DEBUG float d; - d = RadiusDamage (this, this.owner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, NULL); + d = RadiusDamage (this, this.owner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, DMG_NOWEP, NULL); this.owner.tur_debug_dmg_t_h = this.owner.tur_debug_dmg_t_h + d; this.owner.tur_debug_dmg_t_f = this.owner.tur_debug_dmg_t_f + this.owner.shot_dmg; #else - RadiusDamage (this, this.realowner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, NULL); + RadiusDamage (this, this.realowner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, DMG_NOWEP, NULL); #endif delete(this); } @@ -450,18 +463,18 @@ void turret_projectile_touch(entity this, entity toucher) turret_projectile_explode(this); } -void turret_projectile_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce) +void turret_projectile_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector vforce) { this.velocity += vforce; - this.health -= damage; + TakeResource(this, RESOURCE_HEALTH, damage); //this.realowner = attacker; // Dont change realowner, it does not make much sense for turrets - if(this.health <= 0) + if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0) W_PrepareExplosionByDamage(this, this.owner, turret_projectile_explode); } entity turret_projectile(entity actor, Sound _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim) { - TC(Sound, _snd); + TC(Sound, _snd); entity proj; sound (actor, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM); @@ -485,7 +498,7 @@ entity turret_projectile(entity actor, Sound _snd, float _size, float _health, f PROJECTILE_MAKETRIGGER(proj); if(_health) { - proj.health = _health; + SetResourceAmountExplicit(proj, RESOURCE_HEALTH, _health); proj.takedamage = DAMAGE_YES; proj.event_damage = turret_projectile_damage; } @@ -675,6 +688,7 @@ void turret_track(entity this) + TFL_TARGETSELECT_LOS + TFL_TARGETSELECT_PLAYERS + TFL_TARGETSELECT_MISSILES + + TFL_TARGETSELECT_VEHICLES - TFL_TARGETSELECT_TRIGGERTARGET + TFL_TARGETSELECT_ANGLELIMITS + TFL_TARGETSELECT_RANGELIMITS @@ -703,7 +717,7 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl if(!checkpvs(e_target.origin, e_turret)) return -1; - if(e_target.alpha <= 0.3) + if(e_target.alpha != 0 && e_target.alpha <= 0.3) return -1; if(MUTATOR_CALLHOOK(TurretValidateTarget, e_turret, e_target, validate_flags)) @@ -717,15 +731,17 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl return -5; // Cant touch this + if (GetResourceAmount(e_target, RESOURCE_HEALTH) <= 0) + return -6; + else if (STAT(FROZEN, e_target)) + return -6; + + // vehicle if(IS_VEHICLE(e_target)) { - if (e_target.vehicle_health <= 0) - return -6; + if ((validate_flags & TFL_TARGETSELECT_VEHICLES) && !e_target.owner) + return -7; } - else if (e_target.health <= 0) - return -6; - else if(STAT(FROZEN, e_target) > 0) - return -6; // player if (IS_CLIENT(e_target)) @@ -785,7 +801,7 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl } // Can we even aim this thing? - tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target); + tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target.origin); tvt_tadv = shortangle_vxy(angleofs(e_turret, e_target), e_turret.angles); tvt_thadf = vlen(tvt_thadv); tvt_tadf = vlen(tvt_tadv); @@ -1241,6 +1257,36 @@ void turret_initparams(entity tur) #undef TRY } +bool turret_closetotarget(entity this, vector targ) +{ + vector path_extra_size = '64 64 64'; + return boxesoverlap(targ - path_extra_size, targ + path_extra_size, this.absmin - path_extra_size, this.absmax + path_extra_size); +} + +void turret_findtarget(entity this) +{ + entity e = find(NULL, classname, "turret_manager"); + if(!e) + { + e = new(turret_manager); + setthink(e, turrets_manager_think); + e.nextthink = time + 2; + } + + entity targ = find(NULL, targetname, this.target); + if(targ.classname == "turret_checkpoint") + return; // turrets don't defend checkpoints? + + if (!targ) + { + this.target = ""; + LOG_TRACE("Turret has invalid defendpoint!"); + } + + this.tur_defend = targ; + this.idle_aim = this.tur_head.angles + angleofs(this.tur_head, targ); +} + bool turret_initialize(entity this, Turret tur) { if(!autocvar_g_turrets) @@ -1256,14 +1302,6 @@ bool turret_initialize(entity this, Turret tur) IL_PUSH(g_bot_targets, this); } - entity e = find(NULL, classname, "turret_manager"); - if(!e) - { - e = new(turret_manager); - setthink(e, turrets_manager_think); - e.nextthink = time + 2; - } - if(!(this.spawnflags & TSF_SUSPENDED)) droptofloor(this); @@ -1272,7 +1310,7 @@ bool turret_initialize(entity this, Turret tur) if(!this.team || !teamplay) { this.team = FLOAT_MAX; } if(!this.ticrate) { this.ticrate = ((this.turret_flags & TUR_FLAG_SUPPORT) ? 0.2 : 0.1); } - if(!this.health) { this.health = 1000; } + if(!GetResourceAmount(this, RESOURCE_HEALTH)) { SetResourceAmountExplicit(this, RESOURCE_HEALTH, 1000); } if(!this.shot_refire) { this.shot_refire = 1; } if(!this.tur_shotorg) { this.tur_shotorg = '50 0 50'; } if(!this.turret_flags) { this.turret_flags = TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER; } @@ -1321,7 +1359,7 @@ bool turret_initialize(entity this, Turret tur) ++turret_count; _setmodel(this, tur.model); - setsize(this, tur.mins, tur.maxs); + setsize(this, tur.m_mins, tur.m_maxs); this.m_id = tur.m_id; this.classname = "turret_main"; @@ -1329,7 +1367,7 @@ bool turret_initialize(entity this, Turret tur) this.effects = EF_NODRAW; this.netname = tur.turret_name; this.ticrate = bound(sys_frametime, this.ticrate, 60); - this.max_health = this.health; + this.max_health = GetResourceAmount(this, RESOURCE_HEALTH); this.target_validate_flags = this.target_select_flags; this.ammo = this.ammo_max; this.ammo_recharge *= this.ticrate; @@ -1337,8 +1375,10 @@ bool turret_initialize(entity this, Turret tur) this.takedamage = DAMAGE_AIM; set_movetype(this, MOVETYPE_NOCLIP); this.view_ofs = '0 0 0'; + this.idle_aim = '0 0 0'; this.turret_firecheckfunc = turret_firecheck; this.event_damage = turret_damage; + this.event_heal = turret_heal; this.use = turret_use; this.bot_attack = true; this.nextthink = time + 1; @@ -1357,21 +1397,10 @@ bool turret_initialize(entity this, Turret tur) this.tur_head.solid = SOLID_NOT; set_movetype(this.tur_head, this.move_movetype); - if(!this.tur_defend) - if(this.target != "") - { - this.tur_defend = find(NULL, targetname, this.target); - if (this.tur_defend == NULL) - { - this.target = ""; - LOG_TRACE("Turret has invalid defendpoint!"); - } - } + this.weaponentities[0] = this; // lol - if (this.tur_defend) - this.idle_aim = this.tur_head.angles + angleofs(this.tur_head, this.tur_defend); - else - this.idle_aim = '0 0 0'; + if(!this.tur_defend && this.target != "") + InitializeEntity(this, turret_findtarget, INITPRIO_FINDTARGET); #ifdef TURRET_DEBUG this.tur_debug_start = this.nextthink;