X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Ftturrets%2Fsystem%2Fsystem_main.qc;h=cc01f29d30c81153e1d59842407ea030755b875f;hb=30cd3220d0370aa10dfb62eeb2ee3145d56b1c68;hp=fb79f5442fffd036ba08b56425209ffc9f57e6e8;hpb=9f4c9acd38081d1bbfa6eec9d22044143abea28f;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/tturrets/system/system_main.qc b/qcsrc/server/tturrets/system/system_main.qc index fb79f5442..cc01f29d3 100644 --- a/qcsrc/server/tturrets/system/system_main.qc +++ b/qcsrc/server/tturrets/system/system_main.qc @@ -1,8 +1,23 @@ #define cvar_base "g_turrets_unit_" +.float clientframe; +void turrets_setframe(float _frame, float client_only) +{ + if((client_only ? self.clientframe : self.frame ) != _frame) + { + self.SendFlags |= TNSF_ANIM; + self.anim_start_time = time; + } + + if(client_only) + self.clientframe = _frame; + else + self.frame = _frame; + +} float turret_send(entity to, float sf) { - dprint("Sending update\n"); + WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET); WriteByte(MSG_ENTITY, sf); if(sf & TNSF_SETUP) @@ -29,10 +44,33 @@ float turret_send(entity to, float sf) WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_y)); } + if(sf & TNSF_MOVE) + { + WriteShort(MSG_ENTITY, rint(self.origin_x)); + WriteShort(MSG_ENTITY, rint(self.origin_y)); + WriteShort(MSG_ENTITY, rint(self.origin_z)); + + WriteShort(MSG_ENTITY, rint(self.velocity_x)); + WriteShort(MSG_ENTITY, rint(self.velocity_y)); + WriteShort(MSG_ENTITY, rint(self.velocity_z)); + + WriteShort(MSG_ENTITY, rint(self.angles_y)); + } + + if(sf & TNSF_ANIM) + { + WriteCoord(MSG_ENTITY, self.anim_start_time); + WriteByte(MSG_ENTITY, self.frame); + } + if(sf & TNSF_STATUS) - { + { WriteByte(MSG_ENTITY, self.team); - WriteByte(MSG_ENTITY, rint((self.health / self.tur_health) * 255)); // Send health as 0-255 insted of real value, where 255 = 100% + + if(self.health <= 0) + WriteByte(MSG_ENTITY, 0); + else + WriteByte(MSG_ENTITY, ceil((self.health / self.tur_health) * 255)); } return TRUE; @@ -103,6 +141,71 @@ void load_unit_settings(entity ent, string unitname, float is_reload) ent.turret_respawnhook(); } +void turret_projectile_explode() +{ + + self.takedamage = DAMAGE_NO; + self.event_damage = SUB_Null; +#ifdef TURRET_DEBUG + float d; + d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); + self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; + self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; +#else + RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); +#endif + remove(self); +} + +void turret_projectile_touch() +{ + PROJECTILE_TOUCH; + turret_projectile_explode(); +} + +void turret_projectile_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) +{ + self.velocity += vforce; + self.health -= damage; + //self.realowner = attacker; // Dont change realowner, it does not make much sense for turrets + if(self.health <= 0) + W_PrepareExplosionByDamage(self.owner, turret_projectile_explode); +} + +entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim) +{ + entity proj; + + sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTN_NORM); + proj = spawn (); + setorigin(proj, self.tur_shotorg); + setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size); + proj.owner = self; + proj.realowner = self; + proj.bot_dodge = TRUE; + proj.bot_dodgerating = self.shot_dmg; + proj.think = turret_projectile_explode; + proj.touch = turret_projectile_touch; + proj.nextthink = time + 9; + proj.movetype = MOVETYPE_FLYMISSILE; + proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed; + proj.flags = FL_PROJECTILE; + proj.enemy = self.enemy; + proj.totalfrags = _death; + PROJECTILE_MAKETRIGGER(proj); + if(_health) + { + proj.health = _health; + proj.takedamage = DAMAGE_YES; + proj.event_damage = turret_projectile_damage; + } + else + proj.flags |= FL_NOTARGET; + + CSQCProjectile(proj, _cli_anim, _proj_type, _cull); + + return proj; +} /** ** updates enemy distances, predicted impact point/time @@ -124,20 +227,20 @@ void turret_do_updates(entity t_turret) self.tur_dist_enemy = vlen(self.tur_shotorg - enemy_pos); self.tur_dist_aimpos = vlen(self.tur_shotorg - self.tur_aimpos); - if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy)) + /*if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy)) { oldpos = self.enemy.origin; - setorigin(self.enemy,self.tur_aimpos); - tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1',self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self); - setorigin(self.enemy,oldpos); + setorigin(self.enemy, self.tur_aimpos); + tracebox(self.tur_shotorg, '-1 -1 -1', '1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self); + setorigin(self.enemy, oldpos); if(trace_ent == self.enemy) self.tur_dist_impact_to_aimpos = 0; else self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos); } - else - tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self); + else*/ + tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self); self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins) * 0.5); self.tur_impactent = trace_ent; @@ -229,7 +332,7 @@ void turret_stdproc_track() if (self.track_flags == TFL_TRACK_NO) return; - if not (self.tur_active) + if not (self.active) target_angle = self.idle_aim - ('1 0 0' * self.aim_maxpitch); else if (self.enemy == world) { @@ -247,8 +350,11 @@ void turret_stdproc_track() self.tur_head.angles_y = anglemods(self.tur_head.angles_y); // Find the diffrence between where we currently aim and where we want to aim - move_angle = target_angle - (self.angles + self.tur_head.angles); - move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles)); + //move_angle = target_angle - (self.angles + self.tur_head.angles); + //move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles)); + + move_angle = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(self.angles), AnglesTransform_FromAngles(target_angle))) - self.tur_head.angles; + move_angle = shortangle_vxy(move_angle, self.tur_head.angles); switch(self.track_type) { @@ -374,7 +480,11 @@ void turret_stdproc_track() float turret_stdproc_firecheck() { // This one just dont care =) - if (self.firecheck_flags & TFL_FIRECHECK_NO) return 1; + if (self.firecheck_flags & TFL_FIRECHECK_NO) + return 1; + + if (self.enemy == world) + return 0; // Ready? if (self.firecheck_flags & TFL_FIRECHECK_REFIRE) @@ -391,11 +501,6 @@ float turret_stdproc_firecheck() if (self.enemy.deadflag != DEAD_NO) return 0; - // Plz stop killing the world! - if (self.firecheck_flags & TFL_FIRECHECK_WORLD) - if (self.enemy == world) - return 0; - // Own ammo? if (self.firecheck_flags & TFL_FIRECHECK_OWM_AMMO) if (self.ammo < self.shot_dmg) @@ -439,9 +544,9 @@ float turret_stdproc_firecheck() if (self.ammo < (self.shot_dmg * self.shot_volly)) return 0; - if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED) + /*if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED) if(self.tur_impactent != self.enemy) - return 0; + return 0;*/ return 1; } @@ -649,12 +754,11 @@ void turret_think() entity e; self.nextthink = time + self.ticrate; - //self.SendFlags = TNSF_UPDATE | TNSF_STATUS | TNSF_ANG | TNSF_AVEL; // ONS uses somewhat backwards linking. if (teamplay) { - if not (g_onslaught) + if (g_onslaught) if (self.target) { e = find(world, targetname,self.target); @@ -682,7 +786,7 @@ void turret_think() // Inactive turrets needs to run the think loop, // So they can handle animation and wake up if need be. - if not (self.tur_active) + if not (self.active) { turret_stdproc_track(); return; @@ -765,9 +869,11 @@ void turret_think() do_target_scan = 1; // Old target (if any) invalid? + if(self.target_validate_time < time) if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0) { self.enemy = world; + self.target_validate_time = time + 0.5; do_target_scan = 1; } @@ -861,9 +967,9 @@ void turret_stdproc_use() self.team = activator.team; if(self.team == 0) - self.tur_active = 0; + self.active = ACTIVE_NOT; else - self.tur_active = 1; + self.active = ACTIVE_ACTIVE; } @@ -922,32 +1028,10 @@ float turret_stdproc_init (string cvar_base_name, string base, string head, floa if not (e) { e = spawn(); - - /* - setorigin(e,'0 0 0'); - setmodel(e,"models/turrets/plasma.md3"); - vector v; - v = gettaginfo(e,gettagindex(e,"tag_fire")); - if(v == '0 0 0') - { - //objerror("^1ERROR: Engine is borken! Turrets will NOT work. force g_turrets to 0 to run maps with turrets anyway."); - //crash(); - } - setmodel(e,""); - */ - e.classname = "turret_manager"; e.think = turrets_manager_think; e.nextthink = time + 2; } - - /* - if(csqc_shared) - { - dprint("WARNING: turret requested csqc_shared but this is not implemented. Expect strange things to happen.\n"); - csqc_shared = 0; - } - */ if not (self.spawnflags & TSF_SUSPENDED) droptofloor_builtin(); @@ -968,6 +1052,8 @@ float turret_stdproc_init (string cvar_base_name, string base, string head, floa self.cvar_basename = cvar_base_name; load_unit_settings(self, self.cvar_basename, 0); + self.effects = EF_NODRAW; + // Handle turret teams. if (autocvar_g_assault != 0) { @@ -995,11 +1081,14 @@ float turret_stdproc_init (string cvar_base_name, string base, string head, floa * if it hits a glitch in my logic :P so try to set as mutch * as possible beforehand. */ - if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT) - self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop - else - self.ticrate = 0.1; // 10 fps for normal turrets - + if not(self.ticrate) + { + if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT) + self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop + else + self.ticrate = 0.1; // 10 fps for normal turrets + } + self.ticrate = bound(sys_frametime, self.ticrate, 60); // keep it sane // General stuff @@ -1054,9 +1143,9 @@ float turret_stdproc_init (string cvar_base_name, string base, string head, floa self.shot_volly_refire = bound(self.shot_refire, self.shot_volly_refire, 60); if not (self.firecheck_flags) - self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | + self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_LOS | TFL_FIRECHECK_AIMDIST | TFL_FIRECHECK_TEAMCECK | - TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_WORLD; + TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE; // Range stuff. if not (self.target_range) @@ -1093,7 +1182,7 @@ float turret_stdproc_init (string cvar_base_name, string base, string head, floa { self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; if(self.turrcaps_flags & TFL_TURRCAPS_RADIUSDMG) - self.aim_flags |= TFL_AIM_GROUND2; + self.aim_flags |= TFL_AIM_GROUNDGROUND; } if not (self.track_type) @@ -1269,7 +1358,7 @@ float turret_stdproc_init (string cvar_base_name, string base, string head, floa self.classname = "turret_main"; - self.tur_active = 1; + self.active = ACTIVE_ACTIVE; // In ONS mode, and linked to a ONS ent. need to call the use to set team. if (g_onslaught && ee) @@ -1278,10 +1367,9 @@ float turret_stdproc_init (string cvar_base_name, string base, string head, floa self.use(); } - turret_stdproc_respawn(); - - if (!turret_tag_fire_update()) - dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n"); + turret_link(); + turret_stdproc_respawn(); + turret_tag_fire_update(); return 1; }