From db9286e2b079036ce41ad86955197613b35257f0 Mon Sep 17 00:00:00 2001 From: tzork Date: Wed, 11 Feb 2009 21:35:32 +0000 Subject: [PATCH] make TFL_DMG_HEADSHAKE work make TFL_SHOOT_VOLLYALWAYS work improve TFL_FIRECHECK_AFF better prediction (still needs a better way system_aimprocs) git-svn-id: svn://svn.icculus.org/nexuiz/trunk@5841 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/server/tturrets/include/turrets.qh | 1 + .../server/tturrets/include/turrets_early.qh | 43 ++++--- .../server/tturrets/system/system_aimprocs.qc | 77 ++++++++----- .../server/tturrets/system/system_damage.qc | 38 ++----- .../server/tturrets/system/system_main.qc | 106 +++++++++++++----- 5 files changed, 166 insertions(+), 99 deletions(-) diff --git a/data/qcsrc/server/tturrets/include/turrets.qh b/data/qcsrc/server/tturrets/include/turrets.qh index ce99fb8a5..c6ea0e19c 100644 --- a/data/qcsrc/server/tturrets/include/turrets.qh +++ b/data/qcsrc/server/tturrets/include/turrets.qh @@ -25,5 +25,6 @@ #include "../units/unit_tessla.qc" /// Chain lightning capabale turret #include "../units/unit_walker.qc" #include "../units/unit_ewheel.qc" +//#include "../units/unit_hive.qc" #endif // TTURRETS_ENABLED diff --git a/data/qcsrc/server/tturrets/include/turrets_early.qh b/data/qcsrc/server/tturrets/include/turrets_early.qh index 072468661..73076fa5b 100644 --- a/data/qcsrc/server/tturrets/include/turrets_early.qh +++ b/data/qcsrc/server/tturrets/include/turrets_early.qh @@ -3,7 +3,7 @@ #ifdef TTURRETS_ENABLED -#message "with tZork turrets rc2" +#message "with tZork turrets" vector real_origin(entity ent); @@ -39,9 +39,9 @@ vector real_origin(entity ent); #define TFL_AIM_NO 1 /// Go for ground, not direct hit #define TFL_AIM_GROUND 2 -/// Go for ground, not direct hit if target is on ground too +/// Go for ground, not direct hit, but only if target is on ground. #define TFL_AIM_GROUND2 4 -/// Use balistic aim (not implemented) +/// Use balistic aim. FIXME: not implemented #define TFL_AIM_BALISTIC 8 /// Try to predict target movement (does not account for gravity) #define TFL_AIM_LEAD 16 @@ -53,9 +53,9 @@ vector real_origin(entity ent); #define TFL_AIM_BEHIND 128 /// blend real and predicted z positions. (fake bounce prediction) #define TFL_AIM_ZEASE 256 -/// Try to do real prediction of targets z pos at impact. +// Try to do real prediction of targets z pos at impact. //#define TFL_AIM_ZPREDICT 256 -/// Just poitn at target's current location +/// Simply aim at target's current location #define TFL_AIM_SIMPLE 512 /// track (turn and pitch head) flags @@ -73,7 +73,7 @@ vector real_origin(entity ent); #define TFL_TRACKTYPE_STEPMOTOR 1 /// Smoth absolute movement. Looks ok, fair accuracy. #define TFL_TRACKTYPE_FLUIDPRECISE 2 -/// Simulated inertia. "Wobbly mode" Looks kool, can mean terrible accuracy depending on how the feilds below are set +/// Simulated inertia. "Wobbly mode" Looks kool, can mean really bad accuracy depending on how the feilds below are set #define TFL_TRACKTYPE_FLUIDINERTIA 3 /// TFL_TRACKTYPE_FLUIDINERTIA: pitch multiplier .float track_accel_pitch; @@ -191,7 +191,7 @@ vector real_origin(entity ent); #define TFL_DMG_RETALIATEONTEAM 16 /// Loses target when damaged #define TFL_DMG_TARGETLOSS 32 -/// Reciving damage trows off aim +/// Reciving damage trows off aim (pointless atm, aim gets recalculated to fast). not implemented. #define TFL_DMG_AIMSHAKE 64 /// Reciving damage slaps the head arround #define TFL_DMG_HEADSHAKE 128 @@ -212,32 +212,49 @@ vector real_origin(entity ent); */ /// Turrets internal ai speed .float ticrate; -/// Where to point the head when no target + +/// Where to point the when no target .vector idle_aim; + /// Top part of turret .entity tur_head; + /// Start/respawn health .float tur_health; + /// Defend this entity (or ratehr this entitys position) .entity tur_defend; + /// on/off toggle. .float tur_active; + /// Aim from this point, .vector tur_aimorg; + /// and shoot from here. (could be non constant, think MLRS) .vector tur_shotorg; + /// Aim at this spot .vector tur_aimpos; + /// Predicted time the round will impact .float tur_impacttime; + /// Predicted place the round will impact .vector tur_impactpoint; + /// What entity the aimtrace hit, if any. .entity tur_impactent; + /// Distance to enemy .float tur_dist_enemy; + +/// Distance to aimspot +.float tur_dist_aimpos; + /// Distance impact<->aim -.float tur_dist_toaimpos; +.float tur_dist_impact_to_aimpos; + /// Decresment counter form .shot_volly to 0. .float volly_counter; @@ -261,7 +278,7 @@ vector real_origin(entity ent); .float shot_force; /// < 1 = shoot # times at target (if possible) .float shot_volly; -/// Refire after a compleated or borken volly. +/// Refire after a compleated volly. .float shot_volly_refire; /// Consider targets within this range @@ -294,7 +311,7 @@ vector real_origin(entity ent); */ /// Maximum offset between impact and aim spot to fire .float aim_firetolerance_dist; -/// Maximum angular offset between head and aimspot to fire +// Maximum angular offset between head and aimspot to fire //.float aim_firetolerance_angle; /// How fast can i rotate/pitch (per second in stepmotor mode, base force in smooth modes) .float aim_speed; @@ -340,7 +357,7 @@ void turret_fire(); .float() turret_firecheckfunc; // Execure BEFORE main ai loop. return 0 to cancel any following proccessing. //.float() turret_prethink; -/// Execure AFTER main AI loop UNLESS turret_prethink returnd 0 +/// Execure AFTER main AI loop .void() turret_postthink; /// Add a target @@ -373,7 +390,7 @@ void turret_fire(); removed. */ -/// function used to aim, usualy turret_stdproc_aim_generic +// function used to aim, usualy turret_stdproc_aim_generic //.vector() turret_aim; /* diff --git a/data/qcsrc/server/tturrets/system/system_aimprocs.qc b/data/qcsrc/server/tturrets/system/system_aimprocs.qc index 322e549c7..8895d709d 100644 --- a/data/qcsrc/server/tturrets/system/system_aimprocs.qc +++ b/data/qcsrc/server/tturrets/system/system_aimprocs.qc @@ -52,10 +52,11 @@ TFL_AIM_BALISTIC vector turret_stdproc_aim_generic() { vector pre_pos; - // entity mover; + float distance,impact_time,i,mintime; + vector prep; - if (self.aim_flags == TFL_AIM_NO) - return self.idle_aim; + //if (self.aim_flags == TFL_AIM_NO) + // return self.idle_aim; // Baseline pre_pos = real_origin(self.enemy); @@ -63,41 +64,63 @@ vector turret_stdproc_aim_generic() if(self.aim_flags & TFL_AIM_SIMPLE) return pre_pos; + // This is not accurate enougth + //pre_pos = bot_shotlead(pre_pos, self.enemy.velocity, self.shot_speed, 0.01); //self.enemy.velocity; * (self.tur_dist_aimpos / self.shot_speed); + + // Keep track of when we can shoot the next tim and + // try to predict where the target will be then, so we can put our aimpoint there. + // + sys_ticrate becouse projectiles dont move during the first tic of their life. + mintime = max(self.attack_finished_single - time,0) + (sys_ticrate * 2); + + if (self.aim_flags & TFL_AIM_INFRONT) // Aim a bit in front of the target + pre_pos += normalize(normalize(self.enemy.velocity) * 16); + + if (self.aim_flags & TFL_AIM_BEHIND) // Aim a bit behind the target + pre_pos -= normalize(normalize(self.enemy.velocity) * 16); + // Lead? - //pre_pos = pre_pos + bot_shotlead(self.enemy.origin, self.enemy.velocity, self.shot_speed, 0.01); //self.enemy.velocity; * (self.tur_dist_enemy / self.shot_speed); if (self.aim_flags & TFL_AIM_LEAD) - if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime + if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime + { + // FIXME: this cant be the best way to do this.. + prep = pre_pos; + for(i = 0; i < 3; ++i) { - pre_pos = pre_pos + self.enemy.velocity * (self.tur_dist_enemy / self.shot_speed); + distance = vlen(prep - self.tur_shotorg_updated); + impact_time = distance / self.shot_speed; + prep = pre_pos + self.enemy.velocity * (impact_time + mintime); + - // FIXME slow projectiles misspredict (well all do, bit the slow ons miss :P) } - else if (self.turrcaps_flags & TFL_TURRCAPS_HITSCAN) // Hitscan gun, conpensate for frametime and posibly refire offset. - pre_pos = pre_pos + self.enemy.velocity * (frametime + min(max(self.attack_finished_single - time,0),self.ticrate*2)); - else // No lead - pre_pos += self.enemy.velocity; + + /* no worky well :/ + if not(self.enemy.flags & FL_ONGROUND) + { + float z; + z = self.enemy.velocity_z; + z = z - (sv_gravity * impact_time); + prep_z += z; + } + */ + + + pre_pos = prep; + } + else + { + pre_pos = pre_pos + self.enemy.velocity * mintime; + } // Smooth out predict-Z? - /* if (self.aim_flags & TFL_AIM_ZEASE) { vector v; v = real_origin(self.enemy); - pre_pos_z = (pre_pos_z + v_z) * 0.5; + pre_pos_z = (pre_pos_z + v_z) * 0.5; } - */ - - /* - if (self.aim_flags & TFL_AIM_INFRONT) // Aim a bit in front of the target - pre_pos -= normalize(self.tur_aimorg_updated - pre_pos) * 32; - - if (self.aim_flags & TFL_AIM_BEHIND) // Aim a bit behind the target - pre_pos += normalize(self.tur_aimorg_updated - pre_pos) * 32; - */ // This turret should hit the ground neer a target rather the do a direct hit - if ( (self.aim_flags & TFL_AIM_GROUND) || ((self.aim_flags & TFL_AIM_GROUND2) && (self.enemy.flags & FL_ONGROUND)) ) { @@ -105,12 +128,6 @@ vector turret_stdproc_aim_generic() pre_pos = trace_endpos; } - - - - - - return pre_pos; } @@ -130,7 +147,7 @@ vector turret_stdproc_aim_rail() pre_pos = real_origin(self.enemy); - self.tur_dist_toaimpos = vlen(self.enemy.origin - self.tur_aimorg_updated); + self.tur_dist_impact_to_aimpos = vlen(self.enemy.origin - self.tur_aimorg_updated); self.tur_impacttime = time; diff --git a/data/qcsrc/server/tturrets/system/system_damage.qc b/data/qcsrc/server/tturrets/system/system_damage.qc index 5405b61ae..5221b144a 100644 --- a/data/qcsrc/server/tturrets/system/system_damage.qc +++ b/data/qcsrc/server/tturrets/system/system_damage.qc @@ -279,16 +279,11 @@ void turret_stdproc_damage (entity inflictor, entity attacker, float damage, flo { entity baseent; - // Damage func is shared on all parts as standard, we need to know what the master entity of this turret is. - if (self.owner) baseent = self.owner; else baseent = self; - //oldself = self; - //self = baseent; - if (self.health <= 0) return; @@ -299,35 +294,30 @@ void turret_stdproc_damage (entity inflictor, entity attacker, float damage, flo //if(attacker.flags & FL_CLIENT) if(clienttype(attacker) == CLIENTTYPE_REAL) sprint(attacker, "\{1}Turret tells you: I'm on your team!\n"); - //if not(attacker.isbot) - if(cvar("g_friendlyfire")) - { - //self = oldself; - return; - } - else - { damage = damage * cvar("g_friendlyfire"); - } + else + return; } self.health = self.health - damage; // thorw head slightly off aim when hit? if (self.classname == "turret_head") - if (self.damage_flags & TFL_DMG_HEADSHAKE) - self.tur_head.angles = self.tur_head.angles + randomvec() * damage; + if (baseent.damage_flags & TFL_DMG_HEADSHAKE) + { + self.angles_x = self.angles_x + random() * damage; + self.angles_y = self.angles_y + random() * damage; + } - if (self.turrcaps_flags & TFL_TURRCAPS_MOVE) - self.velocity = self.velocity + vforce; + if (baseent.turrcaps_flags & TFL_TURRCAPS_MOVE) + baseent.velocity = baseent.velocity + vforce; + // FIXME: Better damage feedback // Start burning when we have 10% or less health left - if (self.health < (self.tur_health * 0.1)) - self.effects = EF_FLAME; - - // self = oldself; + //if (self.health < (self.tur_health * 0.1)) + // self.effects = EF_FLAME; if (self.health <= 0) { @@ -338,10 +328,6 @@ void turret_stdproc_damage (entity inflictor, entity attacker, float damage, flo baseent.nextthink = time; baseent.think = turret_stdproc_die; } - - - - } diff --git a/data/qcsrc/server/tturrets/system/system_main.qc b/data/qcsrc/server/tturrets/system/system_main.qc index b5c1aa81d..1d67f9ff3 100644 --- a/data/qcsrc/server/tturrets/system/system_main.qc +++ b/data/qcsrc/server/tturrets/system/system_main.qc @@ -99,6 +99,8 @@ void turret_stdproc_nothing() **/ void turret_do_updates(entity e_turret) { + vector enemy_pos; + if (self.turrcaps_flags & TFL_TURRCAPS_LINKED) { e_turret.tur_head.angles_x = e_turret.tur_head.angles_x * -1; @@ -113,22 +115,32 @@ void turret_do_updates(entity e_turret) makevectors(e_turret.tur_head.angles); e_turret.tur_head.angles_x = e_turret.tur_head.angles_x * -1; } - // v_right = (v_right * -1); - e_turret.tur_shotorg_updated = e_turret.origin + v_forward * e_turret.tur_shotorg_x + v_right * e_turret.tur_shotorg_y + v_up * e_turret.tur_shotorg_z; + enemy_pos = real_origin(e_turret.enemy); - e_turret.tur_shotdir_updated = normalize((e_turret.tur_shotorg_updated + v_forward) - e_turret.tur_shotorg_updated); + e_turret.tur_shotorg_updated = e_turret.origin + v_forward * e_turret.tur_shotorg_x + v_right * e_turret.tur_shotorg_y + v_up * e_turret.tur_shotorg_z; e_turret.tur_aimorg_updated = e_turret.origin + v_forward * e_turret.tur_aimorg_x + v_right * e_turret.tur_aimorg_y + v_up * e_turret.tur_aimorg_z; + e_turret.tur_shotdir_updated = v_forward; // normalize((e_turret.tur_shotorg_updated + v_forward) - e_turret.tur_shotorg_updated); + e_turret.tur_dist_enemy = vlen(e_turret.tur_aimorg_updated - enemy_pos); + e_turret.tur_dist_aimpos = vlen(e_turret.tur_aimorg_updated - e_turret.tur_aimpos); - e_turret.tur_dist_enemy = vlen(e_turret.tur_aimorg_updated - real_origin(e_turret.enemy)); + //traceline(e_turret.tur_aimorg_updated,e_turret.tur_aimorg_updated + (e_turret.tur_shotdir_updated * e_turret.tur_dist_aimpos),MOVE_NORMAL,e_turret); + tracebox(e_turret.tur_aimorg_updated, '-1 -1 -1','1 1 1',e_turret.tur_aimorg_updated + (e_turret.tur_shotdir_updated * e_turret.tur_dist_aimpos),MOVE_NORMAL,e_turret); - traceline(e_turret.tur_aimorg_updated,e_turret.tur_aimorg_updated+(e_turret.tur_shotdir_updated * e_turret.tur_dist_enemy),MOVE_NORMAL,e_turret); + //traceline(e_turret.tur_aimorg_updated,e_turret.tur_aimpos,MOVE_NORMAL,e_turret); e_turret.tur_impactpoint = trace_endpos; e_turret.tur_impactent = trace_ent; - //e_turret.tur_impacttime = e_turret.tur_dist_enemy / e_turret.shot_speed; - e_turret.tur_impacttime = e_turret.tur_dist_enemy / e_turret.shot_speed; - e_turret.tur_dist_toaimpos = vlen(trace_endpos - e_turret.tur_aimpos); + e_turret.tur_dist_impact_to_aimpos = vlen(trace_endpos - e_turret.tur_aimpos); + e_turret.tur_impacttime = vlen(e_turret.tur_aimorg_updated - trace_endpos) / e_turret.shot_speed; + + +/* +.float tur_dist_enemy; +.float tur_dist_aimpos; +.float tur_dist_impact_to_aimpos; +*/ + } /** @@ -137,9 +149,9 @@ void turret_do_updates(entity e_turret) **/ void turret_stdproc_track() { - vector wish_angle; // This is where we'd need to be + vector wish_angle; // This is where we want to aim - vector real_angle; // This is where we can go + vector real_angle; // This is where we can aim float f_tmp; @@ -155,7 +167,7 @@ void turret_stdproc_track() if (self.turrcaps_flags & TFL_TURRCAPS_LINKED) wish_angle = self.idle_aim + self.angles; else - if(cvar("g_turrets_aimidle_delay") > (time - self.lip)) + if(time > self.lip) wish_angle = self.idle_aim; else wish_angle = self.tur_head.angles; @@ -249,6 +261,7 @@ void turret_stdproc_track() if (self.track_flags & TFL_TRACK_PITCH) self.tur_head.avelocity_x = real_angle_x; if (self.track_flags & TFL_TRACK_ROT) self.tur_head.avelocity_y = real_angle_y; self.tur_head.avelocity_z = real_angle_z; + setsize(self,self.mins,self.maxs); } // Limit pitch @@ -317,6 +330,13 @@ float turret_stdproc_firecheck() if (self.firecheck_flags & TFL_FIRECHECK_REFIRE) if (self.attack_finished_single >= time) return 0; + // Special case.. + if((self.shoot_flags & TFL_SHOOT_VOLLYALWAYS) && (self.volly_counter != self.shot_volly)) + { + return 1; + } + + // if (self.firecheck_flags & TFL_FIRECHECK_DEAD) if (self.enemy.deadflag != DEAD_NO) return 0; @@ -329,17 +349,17 @@ float turret_stdproc_firecheck() if (self.firecheck_flags & TFL_FIRECHECK_OWM_AMMO) if (self.ammo < self.shot_dmg) return 0; - // Other's ammo? (carefull using this...) + // Other's ammo? (support-supply units) if (self.firecheck_flags & TFL_FIRECHECK_OTHER_AMMO) if (self.enemy.ammo >= self.enemy.ammo_max) return 0; if (self.firecheck_flags & TFL_FIRECHECK_DISTANCES) { // Not close enougth? - if (self.tur_dist_enemy > self.target_range_fire) return 0; + if (self.tur_dist_aimpos > self.target_range_fire) return 0; // To close? - if (self.tur_dist_enemy < self.target_range_min) return 0; + if (self.tur_dist_aimpos < self.target_range_min) return 0; } // Try to avoid FF? @@ -348,7 +368,7 @@ float turret_stdproc_firecheck() // aim<->predicted impact if (self.firecheck_flags & TFL_FIRECHECK_AIMDIST) - if (self.tur_dist_toaimpos > self.aim_firetolerance_dist) return 0; + if (self.tur_dist_impact_to_aimpos > self.aim_firetolerance_dist) return 0; // Volly status if (self.shot_volly > 1) @@ -643,8 +663,31 @@ void turret_think() } else { + // Special case for volly always. if it fired once it must compleate the volly. + if((self.shoot_flags & TFL_SHOOT_VOLLYALWAYS) && (self.volly_counter != self.shot_volly)) + { + // Predict or whatnot + if not((self.aim_flags & TFL_AIM_NO)) + self.tur_aimpos = turret_stdproc_aim_generic(); + + + // Turn & pitch + if (!self.track_flags & TFL_TRACK_NO) + turret_stdproc_track(); + + turret_do_updates(self); + + // Fire! + if (self.turret_firecheckfunc() != 0) + turret_fire(); + + self.turret_postthink(); + + return; + } + // Check if we have a vailid enemy, and try to find one if we dont. - if ((turret_validate_target(self,self.enemy,self.target_validate_flags) <= 0) || (self.cnt < time)) + if ((turret_validate_target(self,self.enemy,self.target_validate_flags) <= 0) && (self.cnt < time)) { self.enemy = turret_select_target(); self.cnt = time + cvar("g_turrets_targetscan_mindelay"); @@ -665,19 +708,19 @@ void turret_think() return; } else - self.lip = time; // Keep track of the last time we had a target. + self.lip = time + cvar("g_turrets_aimidle_delay"); // Keep track of the last time we had a target. - turret_do_updates(self); + //turret_do_updates(self); // Predict or whatnot if not((self.aim_flags & TFL_AIM_NO)) self.tur_aimpos = turret_stdproc_aim_generic(); // Fire? - if (self.turret_firecheckfunc() != 0) - turret_fire(); + //if (self.turret_firecheckfunc() != 0) + // turret_fire(); - turret_do_updates(self); + //turret_do_updates(self); // Turn & pitch if (!self.track_flags & TFL_TRACK_NO) @@ -696,20 +739,23 @@ void turret_think() void turret_fire() { - if (cvar("g_turrets_nofire") != 0) return; - if ((!self.tur_active) || (self.deadflag != DEAD_NO)) return; - - self.turret_firefunc(); + if (cvar("g_turrets_nofire") != 0) + return; - self.attack_finished_single = time + self.shot_refire; - self.ammo = self.ammo - self.shot_dmg; - self.volly_counter = self.volly_counter - 1; + if ((!self.tur_active) || (self.deadflag != DEAD_NO)) + return; + self.turret_firefunc(); + self.attack_finished_single = time + self.shot_refire; + self.ammo = self.ammo - self.shot_dmg; + self.volly_counter = self.volly_counter - 1; if (self.volly_counter <= 0) { self.volly_counter = self.shot_volly; - if (self.shoot_flags & TFL_SHOOT_CLEARTARGET) self.enemy = world; + + if (self.shoot_flags & TFL_SHOOT_CLEARTARGET) + self.enemy = world; if (self.shot_volly > 1) self.attack_finished_single = time + self.shot_volly_refire; @@ -717,7 +763,7 @@ void turret_fire() #ifdef TURRET_DEBUG - if (self.enemy) paint_target3(self.tur_aimpos ,64,self.tur_dbg_rvec,self.tur_impacttime+0.25); + if (self.enemy) paint_target3(self.tur_aimpos, 64, self.tur_dbg_rvec, self.tur_impacttime + 0.25); #endif } -- 2.39.2