// needs to be done so early because of the constants they create
static_init();
- CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
#include "../common/items/all.qc"
#include "../common/monsters/all.qc"
#include "../common/mutators/all.qc"
+#include "../common/turrets/all.qc"
#include "../common/vehicles/all.qc"
#include "../common/weapons/all.qc"
#include "../common/turrets/cl_turrets.qc"
-#include "../common/turrets/all.qc"
#include "../common/triggers/include.qc"
{SELFPARAM();
int sf = ReadByte();
- if(sf & TNSF_SETUP)
+ if(sf & 1)
{
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
-#include "unit/ewheel.qc"
-#include "unit/flac.qc"
-#include "unit/fusionreactor.qc"
-#include "unit/hellion.qc"
-#include "unit/hk.qc"
-#include "unit/machinegun.qc"
-#include "unit/mlrs.qc"
-#include "unit/phaser.qc"
-#include "unit/plasma.qc"
-#include "unit/plasma_dual.qc"
-#include "unit/tesla.qc"
-#include "unit/walker.qc"
+#include "turret/ewheel.qc"
+#include "turret/flac.qc"
+#include "turret/fusionreactor.qc"
+#include "turret/hellion.qc"
+#include "turret/hk.qc"
+#include "turret/machinegun.qc"
+#include "turret/mlrs.qc"
+#include "turret/phaser.qc"
+#include "turret/plasma.qc"
+#include "turret/plasma_dual.qc"
+#include "turret/tesla.qc"
+#include "turret/walker.qc"
#include "all.qh"
+Turret get_turretinfo(int id)
+{
+ if (id < 1 || id > TUR_COUNT - 1)
+ return TUR_Null;
+ Turret m = turret_info[id];
+ if (m) return m;
+ return TUR_Null;
+}
+
+#ifdef SVQC
+#include "sv_turrets.qh"
+#endif
+
+#ifdef CSQC
+#include "cl_turrets.qh"
+#endif
+
#define IMPLEMENTATION
#include "all.inc"
#undef IMPLEMENTATION
-#ifndef TURRETS_H
-#define TURRETS_H
+#ifndef TURRETS_ALL_H
+#define TURRETS_ALL_H
-// turret requests
-#define TR_SETUP 1 // (BOTH) setup turret data
-#define TR_THINK 2 // (SERVER) logic to run every frame
-#define TR_DEATH 3 // (SERVER) called when turret dies
-#define TR_PRECACHE 4 // (BOTH) precaches models/sounds used by this turret
-#define TR_ATTACK 5 // (SERVER) called when turret attacks
-#define TR_CONFIG 6 // (ALL)
+#include "turret.qh"
-// functions:
-entity get_turretinfo(int id);
-
-// fields:
-.entity tur_head;
-
-// target selection flags
-.int target_select_flags;
-.int target_validate_flags;
-const int TFL_TARGETSELECT_NO = 2; // don't automatically find targets
-const int TFL_TARGETSELECT_LOS = 4; // require line of sight to find targets
-const int TFL_TARGETSELECT_PLAYERS = 8; // target players
-const int TFL_TARGETSELECT_MISSILES = 16; // target projectiles
-const int TFL_TARGETSELECT_TRIGGERTARGET = 32; // respond to turret_trigger_target events
-const int TFL_TARGETSELECT_ANGLELIMITS = 64; // apply extra angular limits to target selection
-const int TFL_TARGETSELECT_RANGELIMITS = 128; // limit target selection range
-const int TFL_TARGETSELECT_TEAMCHECK = 256; // don't attack teammates
-const int TFL_TARGETSELECT_NOBUILTIN = 512; // only attack targets when triggered
-const int TFL_TARGETSELECT_OWNTEAM = 1024; // only attack teammates
-const int TFL_TARGETSELECT_NOTURRETS = 2048; // don't attack other turrets
-const int TFL_TARGETSELECT_FOV = 4096; // extra limits to attack range
-const int TFL_TARGETSELECT_MISSILESONLY = 8192; // only attack missiles
-
-// aim flags
-.int aim_flags;
-const int TFL_AIM_NO = 1; // no aiming
-const int TFL_AIM_SPLASH = 2; // aim for ground around the target's feet
-const int TFL_AIM_LEAD = 4; // try to predict target movement
-const int TFL_AIM_SHOTTIMECOMPENSATE = 8; // compensate for shot traveltime when leading
-const int TFL_AIM_ZPREDICT = 16; // predict target's z position at impact
-const int TFL_AIM_SIMPLE = 32; // aim at player's current location
-
-// tracking flags
-.int track_flags;
-const int TFL_TRACK_NO = 2; // don't move head
-const int TFL_TRACK_PITCH = 4; // pitch head
-const int TFL_TRACK_ROTATE = 8; // rotate head
-
-// prefire checks
-.int firecheck_flags;
-const int TFL_FIRECHECK_DEAD = 4; // don't attack dead targets (zombies?)
-const int TFL_FIRECHECK_DISTANCES = 8; // another range check
-const int TFL_FIRECHECK_LOS = 16; // line of sight
-const int TFL_FIRECHECK_AIMDIST = 32; // consider distance impactpoint<->aimspot
-const int TFL_FIRECHECK_REALDIST = 64; // consider enemy origin<->impactpoint
-const int TFL_FIRECHECK_ANGLEDIST = 128; // consider angular diff head<->aimspot
-const int TFL_FIRECHECK_TEAMCHECK = 256; // don't attack teammates
-const int TFL_FIRECHECK_AFF = 512; // try to avoid any friendly fire
-const int TFL_FIRECHECK_AMMO_OWN = 1024; // own ammo needs to be larger than damage dealt
-const int TFL_FIRECHECK_AMMO_OTHER = 2048; // target's ammo needs to be less than max
-const int TFL_FIRECHECK_REFIRE = 4096; // check single attack finished delays
-const int TFL_FIRECHECK_NO = 16384; // no prefire checks
-
-// attack flags
-.int shoot_flags;
-const int TFL_SHOOT_NO = 64; // no attacking
-const int TFL_SHOOT_VOLLY = 2; // fire in vollies
-const int TFL_SHOOT_VOLLYALWAYS = 4; // always do a full volly, even if target is lost
-const int TFL_SHOOT_HITALLVALID = 8; // loop through all valid targets
-const int TFL_SHOOT_CLEARTARGET = 16; // lose target after attack (after volly is done if in volly mode)
-const int TFL_SHOOT_CUSTOM = 32; // custom attacking
-
-// turret capabilities
-.int turret_flags;
-const int TUR_FLAG_NONE = 0; // no abilities
-const int TUR_FLAG_SNIPER = 2; // sniping turret
-const int TUR_FLAG_SPLASH = 4; // can deal splash damage
-const int TUR_FLAG_HITSCAN = 8; // hit scan
-const int TUR_FLAG_MULTIGUN = 16; // multiple guns
-const int TUR_FLAG_GUIDED = 32; // laser guided projectiles
-const int TUR_FLAG_SLOWPROJ = 64; // turret fires slow projectiles
-const int TUR_FLAG_MEDPROJ = 128; // turret fires medium projectiles
-const int TUR_FLAG_FASTPROJ = 256; // turret fires fast projectiles
-const int TUR_FLAG_PLAYER = 512; // can damage players
-const int TUR_FLAG_MISSILE = 1024; // can damage missiles
-const int TUR_FLAG_SUPPORT = 2048; // supports other units
-const int TUR_FLAG_AMMOSOURCE = 4096; // can provide ammunition
-const int TUR_FLAG_RECIEVETARGETS = 8192; // can recieve targets from external sources
-const int TUR_FLAG_MOVE = 16384; // can move
-const int TUR_FLAG_ROAM = 32768; // roams around if not attacking
-const int TUR_FLAG_ISTURRET = 65536; // identifies this unit as a turret
-
-// ammo types
-#define ammo_flags currentammo
-const int TFL_AMMO_NONE = 64; // doesn't use ammo
-const int TFL_AMMO_ENERGY = 2; // uses power
-const int TFL_AMMO_BULLETS = 4; // uses bullets
-const int TFL_AMMO_ROCKETS = 8; // uses explosives
-const int TFL_AMMO_RECHARGE = 16; // regenerates ammo
-const int TFL_AMMO_RECIEVE = 32; // can recieve ammo from support units
-
-// damage flags
-.int damage_flags;
-const int TFL_DMG_NO = 256; // doesn't take damage
-const int TFL_DMG_YES = 2; // can be damaged
-const int TFL_DMG_TEAM = 4; // can be damaged by teammates
-const int TFL_DMG_RETALIATE = 8; // target attackers
-const int TFL_DMG_RETALIATE_TEAM = 16; // target attackers, even if on same team
-const int TFL_DMG_TARGETLOSS = 32; // loses target when damaged
-const int TFL_DMG_AIMSHAKE = 64; // damage throws off aim
-const int TFL_DMG_HEADSHAKE = 128; // damage shakes head
-const int TFL_DMG_DEATH_NORESPAWN = 256; // no re-spawning
-
-// spawn flags
-const int TSF_SUSPENDED = 1;
-const int TSF_TERRAINBASE = 2; // currently unused
-const int TSF_NO_AMMO_REGEN = 4; // disable builtin ammo regeneration
-const int TSF_NO_PATHBREAK = 8; // don't break path to chase enemies, will still fire at them if possible
-const int TSL_NO_RESPAWN = 16; // don't re-spawn
-const int TSL_ROAM = 32; // roam while idle
-
-// send flags
-const int TNSF_UPDATE = 2;
-const int TNSF_STATUS = 4;
-const int TNSF_SETUP = 8;
-const int TNSF_ANG = 16;
-const int TNSF_AVEL = 32;
-const int TNSF_MOVE = 64;
-.float anim_start_time;
-const int TNSF_ANIM = 128;
-
-const int TNSF_FULL_UPDATE = 16777215;
-
-
-// other useful macros
-#define TUR_ACTION(turrettype,mrequest) (get_turretinfo(turrettype)).turret_func(mrequest)
-#define TUR_NAME(turrettype) (get_turretinfo(turrettype)).turret_name
-
-// =====================
-// Turret Registration
-// =====================
-
-float t_null(float dummy);
void register_turret(entity e, float(float) func, float turretflags, vector min_s, vector max_s, string modelname, string headmodelname, string shortname, string mname);
const int TUR_MAXCOUNT = 24;
_REGISTER_TURRET(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname)
#endif
-float t_null(float dummy) { return 0; }
-
-CLASS(Turret, Object)
- ATTRIB(Turret, m_id, int, 0)
-
- ATTRIB(Turret, turretid, int, 0)
- /** short name */
- ATTRIB(Turret, netname, string, string_null)
- /** human readable name */
- ATTRIB(Turret, turret_name, string, string_null)
- /** t_... */
- ATTRIB(Turret, turret_func, float(float), t_null)
- /** currently a copy of the model */
- ATTRIB(Turret, mdl, string, string_null)
- /** full name of model */
- ATTRIB(Turret, model, string, string_null)
- /** full name of tur_head model */
- ATTRIB(Turret, head_model, string, string_null)
- /** TODO: deprecate! */
- ATTRIB(Turret, cvar_basename, string, string_null)
-
- ATTRIB(Turret, spawnflags, int, 0)
- /** turret hitbox size */
- ATTRIB(Turret, mins, vector, '0 0 0')
- /** turret hitbox size */
- ATTRIB(Turret, maxs, vector, '0 0 0')
-
- METHOD(Turret, display, void(entity this, void(string name, string icon) returns)) {
- returns(this.turret_name, string_null);
- }
-
void register_turret(Turret e, float(float) func, float turretflags, vector min_s, vector max_s, string modelname, string headmodelname, string shortname, string mname)
{
e.classname = "turret_info";
e.model = strzone(strcat("models/turrets/", modelname));
e.head_model = strzone(strcat("models/turrets/", headmodelname));
}
-ENDCLASS(Turret)
+entity get_turretinfo(int id);
REGISTER_TURRET(Null,
t_null,
"Turret"
);
-entity get_turretinfo(float id)
-{
- entity m;
- if(id < 1 || id > TUR_COUNT - 1)
- return TUR_Null;
- m = turret_info[id];
- if(m)
- return m;
- return TUR_Null;
-}
-
#include "all.inc"
#endif
-#include "all.qh"
-
void turret_remove()
{SELFPARAM();
remove(self.tur_head);
#ifndef CL_TURRETS_H
#define CL_TURRETS_H
-#include "all.qh"
-
void ent_turret();
#endif
#ifdef SVQC
-#include "all.qh"
#include "../../server/autocvars.qh"
// Generic aiming
#ifndef SV_TURRETS_H
#define SV_TURRETS_H
-#include "all.qh"
+entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim);
+void turret_projectile_explode();
+float turret_validate_target(entity e_turret, entity e_target, float validate_flags);
+float turret_firecheck();
+entity turret_select_target();
// turret fields
.float ticrate; // interal ai think rate
--- /dev/null
+#ifndef TURRET_H
+#define TURRET_H
+
+// turret requests
+const int TR_SETUP = 1; // (BOTH) setup turret data
+const int TR_THINK = 2; // (SERVER) logic to run every frame
+const int TR_DEATH = 3; // (SERVER) called when turret dies
+const int TR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this turret
+const int TR_ATTACK = 5; // (SERVER) called when turret attacks
+const int TR_CONFIG = 6; // (ALL)
+
+// functions:
+entity get_turretinfo(int id);
+
+// fields:
+.entity tur_head;
+
+// target selection flags
+.int target_select_flags;
+.int target_validate_flags;
+const int TFL_TARGETSELECT_NO = 2; // don't automatically find targets
+const int TFL_TARGETSELECT_LOS = 4; // require line of sight to find targets
+const int TFL_TARGETSELECT_PLAYERS = 8; // target players
+const int TFL_TARGETSELECT_MISSILES = 16; // target projectiles
+const int TFL_TARGETSELECT_TRIGGERTARGET = 32; // respond to turret_trigger_target events
+const int TFL_TARGETSELECT_ANGLELIMITS = 64; // apply extra angular limits to target selection
+const int TFL_TARGETSELECT_RANGELIMITS = 128; // limit target selection range
+const int TFL_TARGETSELECT_TEAMCHECK = 256; // don't attack teammates
+const int TFL_TARGETSELECT_NOBUILTIN = 512; // only attack targets when triggered
+const int TFL_TARGETSELECT_OWNTEAM = 1024; // only attack teammates
+const int TFL_TARGETSELECT_NOTURRETS = 2048; // don't attack other turrets
+const int TFL_TARGETSELECT_FOV = 4096; // extra limits to attack range
+const int TFL_TARGETSELECT_MISSILESONLY = 8192; // only attack missiles
+
+// aim flags
+.int aim_flags;
+const int TFL_AIM_NO = 1; // no aiming
+const int TFL_AIM_SPLASH = 2; // aim for ground around the target's feet
+const int TFL_AIM_LEAD = 4; // try to predict target movement
+const int TFL_AIM_SHOTTIMECOMPENSATE = 8; // compensate for shot traveltime when leading
+const int TFL_AIM_ZPREDICT = 16; // predict target's z position at impact
+const int TFL_AIM_SIMPLE = 32; // aim at player's current location
+
+// tracking flags
+.int track_flags;
+const int TFL_TRACK_NO = 2; // don't move head
+const int TFL_TRACK_PITCH = 4; // pitch head
+const int TFL_TRACK_ROTATE = 8; // rotate head
+
+// prefire checks
+.int firecheck_flags;
+const int TFL_FIRECHECK_DEAD = 4; // don't attack dead targets (zombies?)
+const int TFL_FIRECHECK_DISTANCES = 8; // another range check
+const int TFL_FIRECHECK_LOS = 16; // line of sight
+const int TFL_FIRECHECK_AIMDIST = 32; // consider distance impactpoint<->aimspot
+const int TFL_FIRECHECK_REALDIST = 64; // consider enemy origin<->impactpoint
+const int TFL_FIRECHECK_ANGLEDIST = 128; // consider angular diff head<->aimspot
+const int TFL_FIRECHECK_TEAMCHECK = 256; // don't attack teammates
+const int TFL_FIRECHECK_AFF = 512; // try to avoid any friendly fire
+const int TFL_FIRECHECK_AMMO_OWN = 1024; // own ammo needs to be larger than damage dealt
+const int TFL_FIRECHECK_AMMO_OTHER = 2048; // target's ammo needs to be less than max
+const int TFL_FIRECHECK_REFIRE = 4096; // check single attack finished delays
+const int TFL_FIRECHECK_NO = 16384; // no prefire checks
+
+// attack flags
+.int shoot_flags;
+const int TFL_SHOOT_NO = 64; // no attacking
+const int TFL_SHOOT_VOLLY = 2; // fire in vollies
+const int TFL_SHOOT_VOLLYALWAYS = 4; // always do a full volly, even if target is lost
+const int TFL_SHOOT_HITALLVALID = 8; // loop through all valid targets
+const int TFL_SHOOT_CLEARTARGET = 16; // lose target after attack (after volly is done if in volly mode)
+const int TFL_SHOOT_CUSTOM = 32; // custom attacking
+
+// turret capabilities
+.int turret_flags;
+const int TUR_FLAG_NONE = 0; // no abilities
+const int TUR_FLAG_SNIPER = 2; // sniping turret
+const int TUR_FLAG_SPLASH = 4; // can deal splash damage
+const int TUR_FLAG_HITSCAN = 8; // hit scan
+const int TUR_FLAG_MULTIGUN = 16; // multiple guns
+const int TUR_FLAG_GUIDED = 32; // laser guided projectiles
+const int TUR_FLAG_SLOWPROJ = 64; // turret fires slow projectiles
+const int TUR_FLAG_MEDPROJ = 128; // turret fires medium projectiles
+const int TUR_FLAG_FASTPROJ = 256; // turret fires fast projectiles
+const int TUR_FLAG_PLAYER = 512; // can damage players
+const int TUR_FLAG_MISSILE = 1024; // can damage missiles
+const int TUR_FLAG_SUPPORT = 2048; // supports other units
+const int TUR_FLAG_AMMOSOURCE = 4096; // can provide ammunition
+const int TUR_FLAG_RECIEVETARGETS = 8192; // can recieve targets from external sources
+const int TUR_FLAG_MOVE = 16384; // can move
+const int TUR_FLAG_ROAM = 32768; // roams around if not attacking
+const int TUR_FLAG_ISTURRET = 65536; // identifies this unit as a turret
+
+// ammo types
+#define ammo_flags currentammo
+const int TFL_AMMO_NONE = 64; // doesn't use ammo
+const int TFL_AMMO_ENERGY = 2; // uses power
+const int TFL_AMMO_BULLETS = 4; // uses bullets
+const int TFL_AMMO_ROCKETS = 8; // uses explosives
+const int TFL_AMMO_RECHARGE = 16; // regenerates ammo
+const int TFL_AMMO_RECIEVE = 32; // can recieve ammo from support units
+
+// damage flags
+.int damage_flags;
+const int TFL_DMG_NO = 256; // doesn't take damage
+const int TFL_DMG_YES = 2; // can be damaged
+const int TFL_DMG_TEAM = 4; // can be damaged by teammates
+const int TFL_DMG_RETALIATE = 8; // target attackers
+const int TFL_DMG_RETALIATE_TEAM = 16; // target attackers, even if on same team
+const int TFL_DMG_TARGETLOSS = 32; // loses target when damaged
+const int TFL_DMG_AIMSHAKE = 64; // damage throws off aim
+const int TFL_DMG_HEADSHAKE = 128; // damage shakes head
+const int TFL_DMG_DEATH_NORESPAWN = 256; // no re-spawning
+
+// spawn flags
+const int TSF_SUSPENDED = 1;
+const int TSF_TERRAINBASE = 2; // currently unused
+const int TSF_NO_AMMO_REGEN = 4; // disable builtin ammo regeneration
+const int TSF_NO_PATHBREAK = 8; // don't break path to chase enemies, will still fire at them if possible
+const int TSL_NO_RESPAWN = 16; // don't re-spawn
+const int TSL_ROAM = 32; // roam while idle
+
+// send flags
+const int TNSF_UPDATE = 2;
+const int TNSF_STATUS = 4;
+const int TNSF_SETUP = 8;
+const int TNSF_ANG = 16;
+const int TNSF_AVEL = 32;
+const int TNSF_MOVE = 64;
+.float anim_start_time;
+const int TNSF_ANIM = 128;
+
+const int TNSF_FULL_UPDATE = 16777215;
+
+
+// other useful macros
+#define TUR_ACTION(turrettype,mrequest) (get_turretinfo(turrettype)).turret_func(mrequest)
+#define TUR_NAME(turrettype) (get_turretinfo(turrettype)).turret_name
+
+float t_null(float dummy) { return 0; }
+
+CLASS(Turret, Object)
+ ATTRIB(Turret, m_id, int, 0)
+
+ ATTRIB(Turret, turretid, int, 0)
+ /** short name */
+ ATTRIB(Turret, netname, string, string_null)
+ /** human readable name */
+ ATTRIB(Turret, turret_name, string, string_null)
+ /** t_... */
+ ATTRIB(Turret, turret_func, float(float), t_null)
+ /** currently a copy of the model */
+ ATTRIB(Turret, mdl, string, string_null)
+ /** full name of model */
+ ATTRIB(Turret, model, string, string_null)
+ /** full name of tur_head model */
+ ATTRIB(Turret, head_model, string, string_null)
+ /** TODO: deprecate! */
+ ATTRIB(Turret, cvar_basename, string, string_null)
+
+ ATTRIB(Turret, spawnflags, int, 0)
+ /** turret hitbox size */
+ ATTRIB(Turret, mins, vector, '-0 -0 -0')
+ /** turret hitbox size */
+ ATTRIB(Turret, maxs, vector, '0 0 0')
+
+ METHOD(Turret, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.turret_name, string_null);
+ }
+
+ENDCLASS(Turret)
+
+#endif
--- /dev/null
+#ifndef TUR_EWHEEL_H
+#define TUR_EWHEEL_H
+REGISTER_TURRET(
+/* TUR_##id */ EWHEEL,
+/* function */ t_ewheel,
+/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM,
+/* mins,maxs */ '-32 -32 0', '32 32 48',
+/* model */ "ewheel-base2.md3",
+/* head_model */ "ewheel-gun1.md3",
+/* netname */ "ewheel",
+/* fullname */ _("eWheel Turret")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+float autocvar_g_turrets_unit_ewheel_speed_fast;
+float autocvar_g_turrets_unit_ewheel_speed_slow;
+float autocvar_g_turrets_unit_ewheel_speed_slower;
+float autocvar_g_turrets_unit_ewheel_speed_stop;
+float autocvar_g_turrets_unit_ewheel_turnrate;
+
+const float ewheel_anim_stop = 0;
+const float ewheel_anim_fwd_slow = 1;
+const float ewheel_anim_fwd_fast = 2;
+const float ewheel_anim_bck_slow = 3;
+const float ewheel_anim_bck_fast = 4;
+
+//#define EWHEEL_FANCYPATH
+void ewheel_move_path()
+{SELFPARAM();
+#ifdef EWHEEL_FANCYPATH
+ // Are we close enougth to a path node to switch to the next?
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ if (self.pathcurrent.path_next == world)
+ {
+ // Path endpoint reached
+ pathlib_deletepath(self.pathcurrent.owner);
+ self.pathcurrent = world;
+
+ if (self.pathgoal)
+ {
+ if (self.pathgoal.use)
+ self.pathgoal.use();
+
+ if (self.pathgoal.enemy)
+ {
+ self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
+ self.pathgoal = self.pathgoal.enemy;
+ }
+ }
+ else
+ self.pathgoal = world;
+ }
+ else
+ self.pathcurrent = self.pathcurrent.path_next;
+
+#else
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ self.pathcurrent = self.pathcurrent.enemy;
+#endif
+
+ if (self.pathcurrent)
+ {
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+ }
+}
+
+void ewheel_move_enemy()
+{SELFPARAM();
+ float newframe;
+
+ self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
+
+ self.moveto = self.origin + self.steerto * 128;
+
+ if (self.tur_dist_enemy > self.target_range_optimal)
+ {
+ if ( self.tur_head.spawnshieldtime < 1 )
+ {
+ newframe = ewheel_anim_fwd_fast;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+ }
+ else if (self.tur_head.spawnshieldtime < 2)
+ {
+
+ newframe = ewheel_anim_fwd_slow;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+ }
+ else
+ {
+ newframe = ewheel_anim_fwd_slow;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
+ }
+ }
+ else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
+ {
+ newframe = ewheel_anim_bck_slow;
+ movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+ }
+ else
+ {
+ newframe = ewheel_anim_stop;
+ movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+ }
+
+ turrets_setframe(newframe, false);
+}
+
+void ewheel_move_idle()
+{SELFPARAM();
+ if(self.frame != 0)
+ {
+ self.SendFlags |= TNSF_ANIM;
+ self.anim_start_time = time;
+ }
+
+ self.frame = 0;
+ if (vlen(self.velocity))
+ movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+}
+
+void spawnfunc_turret_ewheel() { SELFPARAM(); if(!turret_initialize(TUR_EWHEEL.m_id)) remove(self); }
+
+float t_ewheel(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ float i;
+ entity _mis;
+
+ for (i = 0; i < 1; ++i)
+ {
+ turret_do_updates(self);
+
+ _mis = turret_projectile(SND(LASERGUN_FIRE), 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, TRUE, TRUE);
+ _mis.missile_flags = MIF_SPLASH;
+
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ self.tur_head.frame += 2;
+
+ if (self.tur_head.frame > 3)
+ self.tur_head.frame = 0;
+ }
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ float vz;
+ vector wish_angle, real_angle;
+
+ vz = self.velocity_z;
+
+ self.angles_x = anglemods(self.angles_x);
+ self.angles_y = anglemods(self.angles_y);
+
+ fixedmakevectors(self.angles);
+
+ wish_angle = normalize(self.steerto);
+ wish_angle = vectoangles(wish_angle);
+ real_angle = wish_angle - self.angles;
+ real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
+
+ self.tur_head.spawnshieldtime = fabs(real_angle_y);
+ real_angle_y = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
+ self.angles_y = (self.angles_y + real_angle_y);
+
+ if(self.enemy)
+ ewheel_move_enemy();
+ else if(self.pathcurrent)
+ ewheel_move_path();
+ else
+ ewheel_move_idle();
+
+ self.velocity_z = vz;
+
+ if(vlen(self.velocity))
+ self.SendFlags |= TNSF_MOVE;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ self.velocity = '0 0 0';
+
+#ifdef EWHEEL_FANCYPATH
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+#endif
+ self.pathcurrent = world;
+
+ return true;
+ }
+ case TR_SETUP:
+ {
+ entity e;
+
+ if(self.movetype == MOVETYPE_WALK)
+ {
+ self.velocity = '0 0 0';
+ self.enemy = world;
+
+ setorigin(self, self.pos1);
+
+ if (self.target != "")
+ {
+ e = find(world, targetname, self.target);
+ if (!e)
+ {
+ LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
+ self.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ LOG_TRACE("Warning: not a turrret path\n");
+ else
+ {
+
+#ifdef EWHEEL_FANCYPATH
+ self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ self.pathgoal = e;
+#else
+ self.pathcurrent = e;
+#endif
+ }
+ }
+ }
+
+ self.iscreature = true;
+ self.teleportable = TELEPORT_NORMAL;
+ self.damagedbycontents = true;
+ self.movetype = MOVETYPE_WALK;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.idle_aim = '0 0 0';
+ self.pos1 = self.origin;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.frame = self.tur_head.frame = 1;
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+
+ // Convert from dgr / sec to dgr / tic
+ self.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
+ self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+
+void ewheel_draw()
+{SELFPARAM();
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ fixedmakevectors(self.angles);
+ setorigin(self, self.origin + self.velocity * dt);
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+ self.angles_y = self.move_angles_y;
+
+ if (self.health < 127)
+ if(random() < 0.05)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+float t_ewheel(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ self.gravity = 1;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.move_movetype = MOVETYPE_BOUNCE;
+ self.move_origin = self.origin;
+ self.move_time = time;
+ self.draw = ewheel_draw;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_FLAC_H
+#define TUR_FLAC_H
+REGISTER_TURRET(
+/* TUR_##id */ FLAC,
+/* function */ t_flac,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "flac.md3",
+/* netname */ "flac",
+/* fullname */ _("FLAC Cannon")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+void turret_flac_projectile_think_explode()
+{SELFPARAM();
+ if(self.enemy != world)
+ if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
+ setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
+
+#ifdef TURRET_DEBUG
+ float d;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, 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, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+#endif
+ remove(self);
+}
+
+void spawnfunc_turret_flac() { SELFPARAM(); if(!turret_initialize(TUR_FLAC.m_id)) remove(self); }
+
+float t_flac(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity proj;
+
+ turret_tag_fire_update();
+
+ proj = turret_projectile(SND(HAGAR_FIRE), 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, TRUE, TRUE);
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ proj.think = turret_flac_projectile_think_explode;
+ proj.nextthink = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01);
+ proj.missile_flags = MIF_SPLASH | MIF_PROXY;
+
+ self.tur_head.frame = self.tur_head.frame + 1;
+ if (self.tur_head.frame >= 4)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_flac(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_FUSIONREACTOR_H
+#define TUR_FUSIONREACTOR_H
+REGISTER_TURRET(
+/* TUR_##id */ FUSIONREACTOR,
+/* function */ t_fusionreactor,
+/* spawnflags */ TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE,
+/* mins,maxs */ '-34 -34 0', '34 34 90',
+/* model */ "base.md3",
+/* head_model */ "reactor.md3",
+/* netname */ "fusionreactor",
+/* fullname */ _("Fusion Reactor")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+bool turret_fusionreactor_firecheck()
+{SELFPARAM();
+ if (self.attack_finished_single > time)
+ return false;
+
+ if (self.enemy.deadflag != DEAD_NO)
+ return false;
+
+ if (self.enemy == world)
+ return false;
+
+ if (self.ammo < self.shot_dmg)
+ return false;
+
+ if (self.enemy.ammo >= self.enemy.ammo_max)
+ return false;
+
+ if (vlen(self.enemy.origin - self.origin) > self.target_range)
+ return false;
+
+ if(self.team != self.enemy.team)
+ return false;
+
+ if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
+ return false;
+
+ return true;
+}
+
+void spawnfunc_turret_fusionreactor() { SELFPARAM(); if(!turret_initialize(TUR_FUSIONREACTOR.m_id)) remove(self); }
+
+float t_fusionreactor(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ vector fl_org;
+
+ self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
+ fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
+ te_smallflash(fl_org);
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
+ self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
+ self.firecheck_flags = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
+ self.shoot_flags = TFL_SHOOT_HITALLVALID;
+ self.aim_flags = TFL_AIM_NO;
+ self.track_flags = TFL_TRACK_NO;
+
+ self.tur_head.scale = 0.75;
+ self.tur_head.avelocity = '0 50 0';
+
+ self.turret_firecheckfunc = turret_fusionreactor_firecheck;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_fusionreactor(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_HELLION_H
+#define TUR_HELLION_H
+REGISTER_TURRET(
+/* TUR_##id */ HELLION,
+/* function */ t_hellion,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "hellion.md3",
+/* netname */ "hellion",
+/* fullname */ _("Hellion Missile Turret")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+float autocvar_g_turrets_unit_hellion_shot_speed_gain;
+float autocvar_g_turrets_unit_hellion_shot_speed_max;
+
+void turret_hellion_missile_think()
+{SELFPARAM();
+ vector olddir,newdir;
+ vector pre_pos;
+ float itime;
+
+ self.nextthink = time + 0.05;
+
+ olddir = normalize(self.velocity);
+
+ if(self.max_health < time)
+ turret_projectile_explode();
+
+ // Enemy dead? just keep on the current heading then.
+ if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
+ {
+
+ // Make sure we dont return to tracking a respawned player
+ self.enemy = world;
+
+ // Turn model
+ self.angles = vectoangles(self.velocity);
+
+ if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
+ turret_projectile_explode();
+
+ // Accelerate
+ self.velocity = olddir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+ UpdateCSQCProjectile(self);
+
+ return;
+ }
+
+ // Enemy in range?
+ if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
+ turret_projectile_explode();
+
+ // Predict enemy position
+ itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
+ pre_pos = self.enemy.origin + self.enemy.velocity * itime;
+
+ pre_pos = (pre_pos + self.enemy.origin) * 0.5;
+
+ // Find out the direction to that place
+ newdir = normalize(pre_pos - self.origin);
+
+ // Turn
+ newdir = normalize(olddir + newdir * 0.35);
+
+ // Turn model
+ self.angles = vectoangles(self.velocity);
+
+ // Accelerate
+ self.velocity = newdir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+ if (itime < 0.05)
+ self.think = turret_projectile_explode;
+
+ UpdateCSQCProjectile(self);
+}
+
+void spawnfunc_turret_hellion() { SELFPARAM(); if(!turret_initialize(TUR_HELLION.m_id)) remove(self); }
+
+float t_hellion(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ if(self.tur_head.frame != 0)
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
+ else
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
+
+ missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+ missile.think = turret_hellion_missile_think;
+ missile.nextthink = time;
+ missile.flags = FL_PROJECTILE;
+ missile.max_health = time + 9;
+ missile.tur_aimpos = randomvec() * 128;
+ missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+ self.tur_head.frame += 1;
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame += 1;
+
+ if (self.tur_head.frame >= 7)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.aim_flags = TFL_AIM_SIMPLE;
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_hellion(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_HK_H
+#define TUR_HK_H
+REGISTER_TURRET(
+/* TUR_##id */ HK,
+/* function */ t_hk,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "hk.md3",
+/* netname */ "hk",
+/* fullname */ _("Hunter-Killer Turret")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+float autocvar_g_turrets_unit_hk_shot_speed;
+float autocvar_g_turrets_unit_hk_shot_speed_accel;
+float autocvar_g_turrets_unit_hk_shot_speed_accel2;
+float autocvar_g_turrets_unit_hk_shot_speed_decel;
+float autocvar_g_turrets_unit_hk_shot_speed_max;
+float autocvar_g_turrets_unit_hk_shot_speed_turnrate;
+
+//#define TURRET_DEBUG_HK
+
+#ifdef TURRET_DEBUG_HK
+.float atime;
+#endif
+
+float hk_is_valid_target(entity e_target)
+{SELFPARAM();
+ if (e_target == world)
+ return 0;
+
+ // If only this was used more..
+ if (e_target.flags & FL_NOTARGET)
+ return 0;
+
+ // Cant touch this
+ if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
+ return 0;
+
+ // player
+ if (IS_CLIENT(e_target))
+ {
+ if (self.owner.target_select_playerbias < 0)
+ return 0;
+
+ if (e_target.deadflag != DEAD_NO)
+ return 0;
+ }
+
+ // Missile
+ if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
+ return 0;
+
+ // Team check
+ if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
+ return 0;
+
+ return 1;
+}
+
+void turret_hk_missile_think()
+{SELFPARAM();
+ vector vu, vd, vf, vl, vr, ve; // Vector (direction)
+ float fu, fd, ff, fl, fr, fe; // Fraction to solid
+ vector olddir,wishdir,newdir; // Final direction
+ float lt_for; // Length of Trace FORwrad
+ float lt_seek; // Length of Trace SEEK (left, right, up down)
+ float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
+ vector pre_pos;
+ float myspeed;
+ entity e;
+ float ad,edist;
+
+ self.nextthink = time + self.ticrate;
+
+ //if (self.cnt < time)
+ // turret_hk_missile_explode();
+
+ if (self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ // Pick the closest valid target.
+ if (!self.enemy)
+ {
+ e = findradius(self.origin, 5000);
+ while (e)
+ {
+ if (hk_is_valid_target(e))
+ {
+ if (!self.enemy)
+ self.enemy = e;
+ else
+ if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
+ self.enemy = e;
+ }
+ e = e.chain;
+ }
+ }
+
+ self.angles = vectoangles(self.velocity);
+ self.angles_x = self.angles_x * -1;
+ makevectors(self.angles);
+ self.angles_x = self.angles_x * -1;
+
+ if (self.enemy)
+ {
+ edist = vlen(self.origin - self.enemy.origin);
+ // Close enougth to do decent damage?
+ if ( edist <= (self.owner.shot_radius * 0.25) )
+ {
+ turret_projectile_explode();
+ return;
+ }
+
+ // Get data on enemy position
+ pre_pos = self.enemy.origin +
+ self.enemy.velocity *
+ min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
+
+ traceline(self.origin, pre_pos,true,self.enemy);
+ ve = normalize(pre_pos - self.origin);
+ fe = trace_fraction;
+
+ }
+ else
+ {
+ edist = 0;
+ ve = '0 0 0';
+ fe = 0;
+ }
+
+ if ((fe != 1) || (self.enemy == world) || (edist > 1000))
+ {
+ myspeed = vlen(self.velocity);
+
+ lt_for = myspeed * 3;
+ lt_seek = myspeed * 2.95;
+
+ // Trace forward
+ traceline(self.origin, self.origin + v_forward * lt_for,false,self);
+ vf = trace_endpos;
+ ff = trace_fraction;
+
+ // Find angular offset
+ ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
+
+ // To close to something, Slow down!
+ if ( ((ff < 0.7) || (ad > 4)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
+ myspeed = max(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_decel), (autocvar_g_turrets_unit_hk_shot_speed));
+
+ // Failry clear, accelerate.
+ if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel), (autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ // Setup trace pitch
+ pt_seek = 1 - ff;
+ pt_seek = bound(0.15,pt_seek,0.8);
+ if (ff < 0.5) pt_seek = 1;
+
+ // Trace left
+ traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,self);
+ vl = trace_endpos;
+ fl = trace_fraction;
+
+ // Trace right
+ traceline(self.origin, self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vr = trace_endpos;
+ fr = trace_fraction;
+
+ // Trace up
+ traceline(self.origin, self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vu = trace_endpos;
+ fu = trace_fraction;
+
+ // Trace down
+ traceline(self.origin, self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vd = trace_endpos;
+ fd = trace_fraction;
+
+ vl = normalize(vl - self.origin);
+ vr = normalize(vr - self.origin);
+ vu = normalize(vu - self.origin);
+ vd = normalize(vd - self.origin);
+
+ // Panic tresh passed, find a single direction and turn as hard as we can
+ if (pt_seek == 1)
+ {
+ wishdir = v_right;
+ if (fl > fr) wishdir = -1 * v_right;
+ if (fu > fl) wishdir = v_up;
+ if (fd > fu) wishdir = -1 * v_up;
+ }
+ else
+ {
+ // Normalize our trace vectors to make a smooth path
+ wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
+ }
+
+ if (self.enemy)
+ {
+ if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
+ wishdir = (wishdir * (1 - fe)) + (ve * fe);
+ }
+ }
+ else
+ {
+ // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
+ myspeed = vlen(self.velocity);
+ if (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max))
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ wishdir = ve;
+ }
+
+ if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (self.cnt > time))
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ // Ranoutagazfish?
+ if (self.cnt < time)
+ {
+ self.cnt = time + 0.25;
+ self.nextthink = 0;
+ self.movetype = MOVETYPE_BOUNCE;
+ return;
+ }
+
+ // Calculate new heading
+ olddir = normalize(self.velocity);
+ newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
+
+ // Set heading & speed
+ self.velocity = newdir * myspeed;
+
+ // Align model with new heading
+ self.angles = vectoangles(self.velocity);
+
+
+#ifdef TURRET_DEBUG_HK
+ //if(self.atime < time) {
+ if ((fe <= 0.99)||(edist > 1000))
+ {
+ te_lightning2(world,self.origin, self.origin + vr * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vl * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vu * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vd * lt_seek);
+ te_lightning2(world,self.origin, vf);
+ }
+ else
+ {
+ te_lightning2(world,self.origin, self.enemy.origin);
+ }
+ bprint("Speed: ", ftos(rint(myspeed)), "\n");
+ bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
+ bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
+ self.atime = time + 0.2;
+ //}
+#endif
+
+ UpdateCSQCProjectile(self);
+}
+
+float turret_hk_addtarget(entity e_target,entity e_sender)
+{SELFPARAM();
+ if (e_target)
+ {
+ if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
+ {
+ self.enemy = e_target;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void spawnfunc_turret_hk() { SELFPARAM(); if(!turret_initialize(TUR_HK.m_id)) remove(self); }
+
+float t_hk(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+
+ missile.think = turret_hk_missile_think;
+ missile.nextthink = time + 0.25;
+ missile.movetype = MOVETYPE_BOUNCEMISSILE;
+ missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75);
+ missile.angles = vectoangles(missile.velocity);
+ missile.cnt = time + 30;
+ missile.ticrate = max(autocvar_sys_ticrate, 0.05);
+ missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 5)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_SIMPLE;
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
+ self.shoot_flags = TFL_SHOOT_CLEARTARGET;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.turret_addtarget = turret_hk_addtarget;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_hk(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_MACHINEGUN_H
+#define TUR_MACHINEGUN_H
+REGISTER_TURRET(
+/* TUR_##id */ MACHINEGUN,
+/* function */ t_machinegun,
+/* spawnflags */ TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "machinegun.md3",
+/* netname */ "machinegun",
+/* fullname */ _("Machinegun Turret")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+void spawnfunc_turret_machinegun() { SELFPARAM(); if(!turret_initialize(TUR_MACHINEGUN.m_id)) remove(self); }
+
+void W_MachineGun_MuzzleFlash(void);
+
+float t_machinegun(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0);
+
+ W_MachineGun_MuzzleFlash();
+ setattachment(self.muzzle_flash, self.tur_head, "tag_fire");
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+ self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+ self.turret_flags |= TUR_FLAG_HITSCAN;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_machinegun(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_MLRS_H
+#define TUR_MLRS_H
+REGISTER_TURRET(
+/* TUR_##id */ MLRS,
+/* function */ t_mlrs,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "mlrs.md3",
+/* netname */ "mlrs",
+/* fullname */ _("MLRS Turret")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+void spawnfunc_turret_mlrs() { SELFPARAM(); if(!turret_initialize(TUR_MLRS.m_id)) remove(self); }
+
+float t_mlrs(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ turret_tag_fire_update();
+ missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
+ missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
+ missile.missile_flags = MIF_SPLASH;
+ te_explosion (missile.origin);
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ // 0 = full, 6 = empty
+ self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
+ if(self.tur_head.frame < 0)
+ {
+ LOG_TRACE("ammo:",ftos(self.ammo),"\n");
+ LOG_TRACE("shot_dmg:",ftos(self.shot_dmg),"\n");
+ }
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
+ self.volly_counter = self.shot_volly;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_mlrs(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_PHASER_H
+#define TUR_PHASER_H
+REGISTER_TURRET(
+/* TUR_##id */ PHASER,
+/* function */ t_phaser,
+/* spawnflags */ TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "phaser.md3",
+/* netname */ "phaser",
+/* fullname */ _("Phaser Cannon")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+.float fireflag;
+
+float turret_phaser_firecheck()
+{SELFPARAM();
+ if (self.fireflag != 0) return 0;
+ return turret_firecheck();
+}
+
+void beam_think()
+{SELFPARAM();
+ if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
+ {
+ self.owner.attack_finished_single = time + self.owner.shot_refire;
+ self.owner.fireflag = 2;
+ self.owner.tur_head.frame = 10;
+ sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
+ remove(self);
+ return;
+ }
+
+ turret_do_updates(self.owner);
+
+ if (time - self.shot_spread > 0)
+ {
+ self.shot_spread = time + 2;
+ sound (self, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
+ }
+
+
+ self.nextthink = time + self.ticrate;
+
+ self.owner.attack_finished_single = time + frametime;
+ setself(self.owner);
+ FireImoBeam ( self.tur_shotorg,
+ self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
+ '-1 -1 -1' * self.shot_radius,
+ '1 1 1' * self.shot_radius,
+ self.shot_force,
+ this.shot_dmg,
+ 0.75,
+ DEATH_TURRET_PHASER);
+ setself(this);
+ self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
+
+}
+
+void spawnfunc_turret_phaser() { SELFPARAM(); if(!turret_initialize(TUR_PHASER.m_id)) remove(self); }
+
+float t_phaser(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity beam;
+
+ beam = spawn();
+ beam.ticrate = 0.1; //autocvar_sys_ticrate;
+ setmodel(beam, MDL_TUR_PHASER_BEAM);
+ beam.effects = EF_LOWPRECISION;
+ beam.solid = SOLID_NOT;
+ beam.think = beam_think;
+ beam.cnt = time + self.shot_speed;
+ beam.shot_spread = time + 2;
+ beam.nextthink = time;
+ beam.owner = self;
+ beam.shot_dmg = self.shot_dmg / (self.shot_speed / beam.ticrate);
+ beam.scale = self.target_range / 256;
+ beam.movetype = MOVETYPE_NONE;
+ beam.enemy = self.enemy;
+ beam.bot_dodge = true;
+ beam.bot_dodgerating = beam.shot_dmg;
+ sound (beam, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
+ self.fireflag = 1;
+
+ beam.attack_finished_single = self.attack_finished_single;
+ self.attack_finished_single = time; // + autocvar_sys_ticrate;
+
+ setattachment(beam,self.tur_head,"tag_fire");
+
+ soundat (self, trace_endpos, CH_SHOTS, SND(NEXIMPACT), VOL_BASE, ATTEN_NORM);
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ {
+ if (self.fireflag == 1)
+ {
+ if (self.tur_head.frame == 10)
+ self.tur_head.frame = 1;
+ else
+ self.tur_head.frame = self.tur_head.frame +1;
+ }
+ else if (self.fireflag == 2 )
+ {
+ self.tur_head.frame = self.tur_head.frame +1;
+ if (self.tur_head.frame == 15)
+ {
+ self.tur_head.frame = 0;
+ self.fireflag = 0;
+ }
+ }
+ }
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD;
+
+ self.turret_firecheckfunc = turret_phaser_firecheck;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_phaser(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_PLASMA_H
+#define TUR_PLASMA_H
+REGISTER_TURRET(
+/* TUR_##id */ PLASMA,
+/* function */ t_plasma,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "plasma.md3",
+/* netname */ "plasma",
+/* fullname */ _("Plasma Cannon")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+void spawnfunc_turret_plasma() { SELFPARAM(); if(!turret_initialize(TUR_PLASMA.m_id)) remove(self); }
+
+float t_plasma(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ if(g_instagib)
+ {
+ float flying;
+ flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+ FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+ 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+ Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ // teamcolor / hit beam effect
+ vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+ }
+ else
+ {
+ entity missile = turret_projectile(SND(HAGAR_FIRE), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
+ missile.missile_flags = MIF_SPLASH;
+
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+ }
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 5)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.firecheck_flags |= TFL_FIRECHECK_AFF;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
+
+ turret_do_updates(self);
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_plasma(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_PLASMA_DUAL_H
+#define TUR_PLASMA_DUAL_H
+REGISTER_TURRET(
+/* TUR_##id */ PLASMA_DUAL,
+/* function */ t_plasma_dual,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "plasmad.md3",
+/* netname */ "plasma_dual",
+/* fullname */ _("Dual Plasma Cannon")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "../../weapons/all.qh"
+
+CLASS(PlasmaDualAttack, PortoLaunch)
+/* flags */ ATTRIB(PlasmaDualAttack, spawnflags, int, WEP_TYPE_OTHER);
+/* impulse */ ATTRIB(PlasmaDualAttack, impulse, int, 5);
+/* refname */ ATTRIB(PlasmaDualAttack, netname, string, "plasmadual");
+/* wepname */ ATTRIB(PlasmaDualAttack, message, string, _("Dual plasma"));
+ENDCLASS(PlasmaDualAttack)
+REGISTER_WEAPON(PLASMA_DUAL, NEW(PlasmaDualAttack));
+
+#ifdef SVQC
+
+float t_plasma_dual(float req);
+METHOD(PlasmaDualAttack, wr_think, bool(entity thiswep)) {
+ SELFPARAM();
+ if (self.BUTTON_ATCK)
+ if (weapon_prepareattack(0, WEP_CVAR_PRI(electro, refire))) {
+ W_SetupShot_Dir(self, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ self.tur_shotdir_updated = w_shotdir;
+ self.tur_shotorg = w_shotorg;
+ self.tur_head = self;
+ self.shot_speed = max(1, ((!self.shot_speed) ? 2500 : self.shot_speed));
+ self.shot_spread = bound(0.0001, ((!self.shot_spread) ? 0.0125 : self.shot_spread), 500);
+ t_plasma_dual(TR_ATTACK);
+ weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+ return true;
+}
+
+void spawnfunc_turret_plasma_dual() { SELFPARAM(); if(!turret_initialize(TUR_PLASMA_DUAL.m_id)) remove(self); }
+
+float t_plasma_dual(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ if(g_instagib)
+ {
+ float flying;
+ flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+ FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+ 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+
+ Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ // teamcolor / hit beam effect
+ vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
+ self.tur_head.frame += 1;
+ }
+ else
+ {
+ entity missile = turret_projectile(SND(HAGAR_FIRE), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
+ missile.missile_flags = MIF_SPLASH;
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ self.tur_head.frame += 1;
+ }
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 6)
+ self.tur_head.frame = 0;
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.firecheck_flags |= TFL_FIRECHECK_AFF;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
+
+ turret_do_updates(self);
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_plasma_dual(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_TESLA_H
+#define TUR_TESLA_H
+REGISTER_TURRET(
+/* TUR_##id */ TESLA,
+/* function */ t_tesla,
+/* spawnflags */ TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-60 -60 0', '60 60 128',
+/* model */ "tesla_base.md3",
+/* head_model */ "tesla_head.md3",
+/* netname */ "tesla",
+/* fullname */ _("Tesla Coil")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+entity toast(entity from, float range, float damage)
+{SELFPARAM();
+ entity e;
+ entity etarget = world;
+ float d,dd;
+ float r;
+
+ dd = range + 1;
+
+ e = findradius(from.origin,range);
+ while (e)
+ {
+ if ((e.railgunhit != 1) && (e != from))
+ {
+ r = turret_validate_target(self,e,self.target_validate_flags);
+ if (r > 0)
+ {
+ traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
+ if (trace_fraction == 1.0)
+ {
+ d = vlen(e.origin - from.origin);
+ if (d < dd)
+ {
+ dd = d;
+ etarget = e;
+ }
+ }
+ }
+ }
+ e = e.chain;
+ }
+
+ if (etarget)
+ {
+ te_csqc_lightningarc(from.origin,etarget.origin);
+ Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
+ etarget.railgunhit = 1;
+ }
+
+ return etarget;
+}
+
+float turret_tesla_firecheck()
+{SELFPARAM();
+ // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
+ float do_target_scan = 0;
+
+ if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
+ 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;
+ }
+
+ // But never more often then g_turrets_targetscan_mindelay!
+ if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
+ do_target_scan = 0;
+
+ if(do_target_scan)
+ {
+ self.enemy = turret_select_target();
+ self.target_select_time = time;
+ }
+
+ if(!turret_firecheck())
+ return 0;
+
+ if(self.enemy)
+ return 1;
+
+ return 0;
+}
+
+void spawnfunc_turret_tesla() { SELFPARAM(); if(!turret_initialize(TUR_TESLA.m_id)) remove(self); }
+
+float t_tesla(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity e, t;
+ float d, r, i;
+
+ d = self.shot_dmg;
+ r = self.target_range;
+ e = spawn();
+ setorigin(e,self.tur_shotorg);
+
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ t = toast(e,r,d);
+ remove(e);
+
+ if (t == world) return true;
+
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.attack_finished_single = time + self.shot_refire;
+ for (i = 0; i < 10; ++i)
+ {
+ d *= 0.75;
+ r *= 0.85;
+ t = toast(t, r, d);
+ if (t == world) break;
+
+ }
+
+ e = findchainfloat(railgunhit, 1);
+ while (e)
+ {
+ e.railgunhit = 0;
+ e = e.chain;
+ }
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ if(!self.active)
+ {
+ self.tur_head.avelocity = '0 0 0';
+ return true;
+ }
+
+ if(self.ammo < self.shot_dmg)
+ {
+ self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
+ }
+ else
+ {
+ self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
+
+ if(self.attack_finished_single > time)
+ return true;
+
+ float f;
+ f = (self.ammo / self.ammo_max);
+ f = f * f;
+ if(f > random())
+ if(random() < 0.1)
+ te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
+ }
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.turret_firecheckfunc = turret_tesla_firecheck;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
+ self.shoot_flags = TFL_SHOOT_CUSTOM;
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_NO;
+ self.track_flags = TFL_TRACK_NO;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_tesla(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
+#ifndef TUR_WALKER_H
+#define TUR_WALKER_H
+REGISTER_TURRET(
+/* TUR_##id */ WALKER,
+/* function */ t_walker,
+/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE,
+/* mins,maxs */ '-70 -70 0', '70 70 95',
+/* model */ "walker_body.md3",
+/* head_model */ "walker_head_minigun.md3",
+/* netname */ "walker",
+/* fullname */ _("Walker Turret")
+);
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+float autocvar_g_turrets_unit_walker_melee_damage;
+float autocvar_g_turrets_unit_walker_melee_force;
+float autocvar_g_turrets_unit_walker_melee_range;
+float autocvar_g_turrets_unit_walker_rocket_damage;
+float autocvar_g_turrets_unit_walker_rocket_radius;
+float autocvar_g_turrets_unit_walker_rocket_force;
+float autocvar_g_turrets_unit_walker_rocket_speed;
+float autocvar_g_turrets_unit_walker_rocket_range;
+float autocvar_g_turrets_unit_walker_rocket_range_min;
+float autocvar_g_turrets_unit_walker_rocket_refire;
+float autocvar_g_turrets_unit_walker_rocket_turnrate;
+float autocvar_g_turrets_unit_walker_speed_stop;
+float autocvar_g_turrets_unit_walker_speed_walk;
+float autocvar_g_turrets_unit_walker_speed_run;
+float autocvar_g_turrets_unit_walker_speed_jump;
+float autocvar_g_turrets_unit_walker_speed_swim;
+float autocvar_g_turrets_unit_walker_speed_roam;
+float autocvar_g_turrets_unit_walker_turn;
+float autocvar_g_turrets_unit_walker_turn_walk;
+float autocvar_g_turrets_unit_walker_turn_strafe;
+float autocvar_g_turrets_unit_walker_turn_swim;
+float autocvar_g_turrets_unit_walker_turn_run;
+
+#define ANIM_NO 0
+#define ANIM_TURN 1
+#define ANIM_WALK 2
+#define ANIM_RUN 3
+#define ANIM_STRAFE_L 4
+#define ANIM_STRAFE_R 5
+#define ANIM_JUMP 6
+#define ANIM_LAND 7
+#define ANIM_PAIN 8
+#define ANIM_MELEE 9
+#define ANIM_SWIM 10
+#define ANIM_ROAM 11
+
+.float animflag;
+.float idletime;
+
+#define WALKER_PATH(s,e) pathlib_astar(s,e)
+
+float walker_firecheck()
+{SELFPARAM();
+ if (self.animflag == ANIM_MELEE)
+ return 0;
+
+ return turret_firecheck();
+}
+
+void walker_melee_do_dmg()
+{SELFPARAM();
+ vector where;
+ entity e;
+
+ makevectors(self.angles);
+ where = self.origin + v_forward * 128;
+
+ e = findradius(where,32);
+ while (e)
+ {
+ if (turret_validate_target(self, e, self.target_validate_flags))
+ if (e != self && e.owner != self)
+ Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
+
+ e = e.chain;
+ }
+}
+
+void walker_setnoanim()
+{SELFPARAM();
+ turrets_setframe(ANIM_NO, false);
+ self.animflag = self.frame;
+}
+void walker_rocket_explode()
+{SELFPARAM();
+ RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
+ remove (self);
+}
+
+void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{SELFPARAM();
+ self.health = self.health - damage;
+ self.velocity = self.velocity + vforce;
+
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
+}
+
+#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
+void walker_rocket_loop();
+void walker_rocket_think()
+{SELFPARAM();
+ vector newdir;
+ float edist;
+ float itime;
+ float m_speed;
+
+ self.nextthink = time;
+
+ edist = vlen(self.enemy.origin - self.origin);
+
+ // Simulate crude guidance
+ if (self.cnt < time)
+ {
+ if (edist < 1000)
+ self.tur_shotorg = randomvec() * min(edist, 64);
+ else
+ self.tur_shotorg = randomvec() * min(edist, 256);
+
+ self.cnt = time + 0.5;
+ }
+
+ if (edist < 128)
+ self.tur_shotorg = '0 0 0';
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ self.nextthink = time;
+ return;
+ }
+
+ if (self.shot_dmg != 1337 && random() < 0.01)
+ {
+ walker_rocket_loop();
+ return;
+ }
+
+ m_speed = vlen(self.velocity);
+
+ // Enemy dead? just keep on the current heading then.
+ if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ if (self.enemy)
+ {
+ itime = max(edist / m_speed, 1);
+ newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
+ }
+ else
+ newdir = normalize(self.velocity);
+
+ WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop3()
+{SELFPARAM();
+ vector newdir;
+ self.nextthink = time;
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 100 )
+ {
+ self.think = walker_rocket_think;
+ return;
+ }
+
+ newdir = steerlib_pull(self.tur_shotorg);
+ WALKER_ROCKET_MOVE;
+
+ self.angles = vectoangles(self.velocity);
+}
+
+void walker_rocket_loop2()
+{SELFPARAM();
+ vector newdir;
+
+ self.nextthink = time;
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 100 )
+ {
+ self.tur_shotorg = self.origin - '0 0 200';
+ self.think = walker_rocket_loop3;
+ return;
+ }
+
+ newdir = steerlib_pull(self.tur_shotorg);
+ WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop()
+{SELFPARAM();
+ self.nextthink = time;
+ self.tur_shotorg = self.origin + '0 0 300';
+ self.think = walker_rocket_loop2;
+ self.shot_dmg = 1337;
+}
+
+void walker_fire_rocket(vector org)
+{SELFPARAM();
+ entity rocket;
+
+ fixedmakevectors(self.angles);
+
+ te_explosion (org);
+
+ rocket = spawn ();
+ setorigin(rocket, org);
+
+ sound (self, CH_WEAPON_A, SND_HAGAR_FIRE, VOL_BASE, ATTEN_NORM);
+ setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+
+ rocket.classname = "walker_rocket";
+ rocket.owner = self;
+ rocket.bot_dodge = true;
+ rocket.bot_dodgerating = 50;
+ rocket.takedamage = DAMAGE_YES;
+ rocket.damageforcescale = 2;
+ rocket.health = 25;
+ rocket.tur_shotorg = randomvec() * 512;
+ rocket.cnt = time + 1;
+ rocket.enemy = self.enemy;
+
+ if (random() < 0.01)
+ rocket.think = walker_rocket_loop;
+ else
+ rocket.think = walker_rocket_think;
+
+ rocket.event_damage = walker_rocket_damage;
+
+ rocket.nextthink = time;
+ rocket.movetype = MOVETYPE_FLY;
+ rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
+ rocket.angles = vectoangles(rocket.velocity);
+ rocket.touch = walker_rocket_explode;
+ rocket.flags = FL_PROJECTILE;
+ rocket.solid = SOLID_BBOX;
+ rocket.max_health = time + 9;
+ rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+
+ CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
+}
+
+.vector enemy_last_loc;
+.float enemy_last_time;
+void walker_move_to(vector _target, float _dist)
+{SELFPARAM();
+ switch (self.waterlevel)
+ {
+ case WATERLEVEL_NONE:
+ if (_dist > 500)
+ self.animflag = ANIM_RUN;
+ else
+ self.animflag = ANIM_WALK;
+ case WATERLEVEL_WETFEET:
+ case WATERLEVEL_SWIMMING:
+ if (self.animflag != ANIM_SWIM)
+ self.animflag = ANIM_WALK;
+ else
+ self.animflag = ANIM_SWIM;
+ break;
+ case WATERLEVEL_SUBMERGED:
+ self.animflag = ANIM_SWIM;
+ }
+
+ self.moveto = _target;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+ if(self.enemy)
+ {
+ self.enemy_last_loc = _target;
+ self.enemy_last_time = time;
+ }
+}
+
+//#define WALKER_FANCYPATHING
+
+void walker_move_path()
+{SELFPARAM();
+#ifdef WALKER_FANCYPATHING
+ // Are we close enougth to a path node to switch to the next?
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ if (self.pathcurrent.path_next == world)
+ {
+ // Path endpoint reached
+ pathlib_deletepath(self.pathcurrent.owner);
+ self.pathcurrent = world;
+
+ if (self.pathgoal)
+ {
+ if (self.pathgoal.use)
+ self.pathgoal.use();
+
+ if (self.pathgoal.enemy)
+ {
+ self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
+ self.pathgoal = self.pathgoal.enemy;
+ }
+ }
+ else
+ self.pathgoal = world;
+ }
+ else
+ self.pathcurrent = self.pathcurrent.path_next;
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+ walker_move_to(self.moveto, 0);
+
+#else
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ self.pathcurrent = self.pathcurrent.enemy;
+
+ if(!self.pathcurrent)
+ return;
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+ walker_move_to(self.moveto, 0);
+#endif
+}
+
+void spawnfunc_turret_walker() { SELFPARAM(); if(!turret_initialize(TUR_WALKER.m_id)) remove(self); }
+
+float t_walker(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ sound (self, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
+ fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0);
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ return true;
+ }
+ case TR_THINK:
+ {
+ fixedmakevectors(self.angles);
+
+ if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
+ walker_move_path();
+ else if (self.enemy == world)
+ {
+ if(self.pathcurrent)
+ walker_move_path();
+ else
+ {
+ if(self.enemy_last_time != 0)
+ {
+ if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
+ self.enemy_last_time = 0;
+ else
+ walker_move_to(self.enemy_last_loc, 0);
+ }
+ else
+ {
+ if(self.animflag != ANIM_NO)
+ {
+ traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
+
+ if(trace_fraction != 1.0)
+ self.tur_head.idletime = -1337;
+ else
+ {
+ traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
+ if(trace_fraction == 1.0)
+ self.tur_head.idletime = -1337;
+ }
+
+ if(self.tur_head.idletime == -1337)
+ {
+ self.moveto = self.origin + randomvec() * 256;
+ self.tur_head.idletime = 0;
+ }
+
+ self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
+ self.moveto_z = self.origin_z + 64;
+ walker_move_to(self.moveto, 0);
+ }
+
+ if(self.idletime < time)
+ {
+ if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
+ {
+ self.idletime = time + 1 + random() * 5;
+ self.moveto = self.origin;
+ self.animflag = ANIM_NO;
+ }
+ else
+ {
+ self.animflag = ANIM_WALK;
+ self.idletime = time + 4 + random() * 2;
+ self.moveto = self.origin + randomvec() * 256;
+ self.tur_head.moveto = self.moveto;
+ self.tur_head.idletime = 0;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
+ {
+ vector wish_angle;
+
+ wish_angle = angleofs(self, self.enemy);
+ if (self.animflag != ANIM_SWIM)
+ if (fabs(wish_angle_y) < 15)
+ {
+ self.moveto = self.enemy.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+ self.animflag = ANIM_MELEE;
+ }
+ }
+ else if (self.tur_head.attack_finished_single < time)
+ {
+ if(self.tur_head.shot_volly)
+ {
+ self.animflag = ANIM_NO;
+
+ self.tur_head.shot_volly = self.tur_head.shot_volly -1;
+ if(self.tur_head.shot_volly == 0)
+ self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
+ else
+ self.tur_head.attack_finished_single = time + 0.2;
+
+ if(self.tur_head.shot_volly > 1)
+ walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
+ else
+ walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
+ }
+ else
+ {
+ if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
+ if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
+ self.tur_head.shot_volly = 4;
+ }
+ }
+ else
+ {
+ if (self.animflag != ANIM_MELEE)
+ walker_move_to(self.enemy.origin, self.tur_dist_enemy);
+ }
+ }
+
+ {
+ vector real_angle;
+ float turny = 0, turnx = 0;
+ float vz;
+
+ real_angle = vectoangles(self.steerto) - self.angles;
+ vz = self.velocity_z;
+
+ switch (self.animflag)
+ {
+ case ANIM_NO:
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_TURN:
+ turny = (autocvar_g_turrets_unit_walker_turn);
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_WALK:
+ turny = (autocvar_g_turrets_unit_walker_turn_walk);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
+ break;
+
+ case ANIM_RUN:
+ turny = (autocvar_g_turrets_unit_walker_turn_run);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
+ break;
+
+ case ANIM_STRAFE_L:
+ turny = (autocvar_g_turrets_unit_walker_turn_strafe);
+ movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+ break;
+
+ case ANIM_STRAFE_R:
+ turny = (autocvar_g_turrets_unit_walker_turn_strafe);
+ movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+ break;
+
+ case ANIM_JUMP:
+ self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
+ break;
+
+ case ANIM_LAND:
+ break;
+
+ case ANIM_PAIN:
+ if(self.frame != ANIM_PAIN)
+ defer(0.25, walker_setnoanim);
+
+ break;
+
+ case ANIM_MELEE:
+ if(self.frame != ANIM_MELEE)
+ {
+ defer(0.41, walker_setnoanim);
+ defer(0.21, walker_melee_do_dmg);
+ }
+
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_SWIM:
+ turny = (autocvar_g_turrets_unit_walker_turn_swim);
+ turnx = (autocvar_g_turrets_unit_walker_turn_swim);
+
+ self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
+ vz = self.velocity_z + sin(time * 4) * 8;
+ break;
+
+ case ANIM_ROAM:
+ turny = (autocvar_g_turrets_unit_walker_turn_walk);
+ movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
+ break;
+ }
+
+ if(turny)
+ {
+ turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
+ self.angles_y += turny;
+ }
+
+ if(turnx)
+ {
+ turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
+ self.angles_x += turnx;
+ }
+
+ self.velocity_z = vz;
+ }
+
+
+ if(self.origin != self.oldorigin)
+ self.SendFlags |= TNSF_MOVE;
+
+ self.oldorigin = self.origin;
+ turrets_setframe(self.animflag, false);
+
+ return true;
+ }
+ case TR_DEATH:
+ {
+#ifdef WALKER_FANCYPATHING
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+#endif
+ self.pathcurrent = world;
+
+ return true;
+ }
+ case TR_SETUP:
+ {
+ self.ticrate = 0.05;
+
+ entity e;
+
+ // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
+ if(self.movetype == MOVETYPE_WALK)
+ {
+ if(self.pos1)
+ setorigin(self, self.pos1);
+ if(self.pos2)
+ self.angles = self.pos2;
+ }
+
+ self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD;
+ self.turret_flags |= TUR_FLAG_HITSCAN;
+
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.iscreature = true;
+ self.teleportable = TELEPORT_NORMAL;
+ self.damagedbycontents = true;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+ if(self.movetype != MOVETYPE_WALK)
+ {
+ setorigin(self, self.origin);
+ tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
+ setorigin(self, trace_endpos + '0 0 4');
+ self.pos1 = self.origin;
+ self.pos2 = self.angles;
+ }
+ self.movetype = MOVETYPE_WALK;
+ self.idle_aim = '0 0 0';
+ self.turret_firecheckfunc = walker_firecheck;
+
+ if (self.target != "")
+ {
+ e = find(world, targetname, self.target);
+ if (!e)
+ {
+ LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
+ self.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ LOG_TRACE("Warning: not a turrret path\n");
+ else
+ {
+#ifdef WALKER_FANCYPATHING
+ self.pathcurrent = WALKER_PATH(self.origin, e.origin);
+ self.pathgoal = e;
+#else
+ self.pathcurrent = e;
+#endif
+ }
+ }
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // SVQC
+#ifdef CSQC
+
+#include "../../../client/movelib.qh"
+
+void walker_draw()
+{SELFPARAM();
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ fixedmakevectors(self.angles);
+ movelib_groundalign4point(300, 100, 0.25, 45);
+ setorigin(self, self.origin + self.velocity * dt);
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+ self.angles_y = self.move_angles_y;
+
+ if (self.health < 127)
+ if(random() < 0.15)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+float t_walker(float req)
+{SELFPARAM();
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ self.gravity = 1;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.move_movetype = MOVETYPE_BOUNCE;
+ self.move_origin = self.origin;
+ self.move_time = time;
+ self.draw = walker_draw;
+
+ return true;
+ }
+ case TR_PRECACHE:
+ {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ EWHEEL,
-/* function */ t_ewheel,
-/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM,
-/* mins,maxs */ '-32 -32 0', '32 32 48',
-/* model */ "ewheel-base2.md3",
-/* head_model */ "ewheel-gun1.md3",
-/* netname */ "ewheel",
-/* fullname */ _("eWheel Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_ewheel_speed_fast;
-float autocvar_g_turrets_unit_ewheel_speed_slow;
-float autocvar_g_turrets_unit_ewheel_speed_slower;
-float autocvar_g_turrets_unit_ewheel_speed_stop;
-float autocvar_g_turrets_unit_ewheel_turnrate;
-
-const float ewheel_anim_stop = 0;
-const float ewheel_anim_fwd_slow = 1;
-const float ewheel_anim_fwd_fast = 2;
-const float ewheel_anim_bck_slow = 3;
-const float ewheel_anim_bck_fast = 4;
-
-//#define EWHEEL_FANCYPATH
-void ewheel_move_path()
-{SELFPARAM();
-#ifdef EWHEEL_FANCYPATH
- // Are we close enougth to a path node to switch to the next?
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- if (self.pathcurrent.path_next == world)
- {
- // Path endpoint reached
- pathlib_deletepath(self.pathcurrent.owner);
- self.pathcurrent = world;
-
- if (self.pathgoal)
- {
- if (self.pathgoal.use)
- self.pathgoal.use();
-
- if (self.pathgoal.enemy)
- {
- self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
- self.pathgoal = self.pathgoal.enemy;
- }
- }
- else
- self.pathgoal = world;
- }
- else
- self.pathcurrent = self.pathcurrent.path_next;
-
-#else
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- self.pathcurrent = self.pathcurrent.enemy;
-#endif
-
- if (self.pathcurrent)
- {
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
- }
-}
-
-void ewheel_move_enemy()
-{SELFPARAM();
- float newframe;
-
- self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
-
- self.moveto = self.origin + self.steerto * 128;
-
- if (self.tur_dist_enemy > self.target_range_optimal)
- {
- if ( self.tur_head.spawnshieldtime < 1 )
- {
- newframe = ewheel_anim_fwd_fast;
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
- }
- else if (self.tur_head.spawnshieldtime < 2)
- {
-
- newframe = ewheel_anim_fwd_slow;
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
- }
- else
- {
- newframe = ewheel_anim_fwd_slow;
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
- }
- }
- else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
- {
- newframe = ewheel_anim_bck_slow;
- movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
- }
- else
- {
- newframe = ewheel_anim_stop;
- movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
- }
-
- turrets_setframe(newframe, false);
-}
-
-void ewheel_move_idle()
-{SELFPARAM();
- if(self.frame != 0)
- {
- self.SendFlags |= TNSF_ANIM;
- self.anim_start_time = time;
- }
-
- self.frame = 0;
- if (vlen(self.velocity))
- movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
-}
-
-void spawnfunc_turret_ewheel() { SELFPARAM(); if(!turret_initialize(TUR_EWHEEL.m_id)) remove(self); }
-
-float t_ewheel(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- float i;
- entity _mis;
-
- for (i = 0; i < 1; ++i)
- {
- turret_do_updates(self);
-
- _mis = turret_projectile(SND(LASERGUN_FIRE), 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, TRUE, TRUE);
- _mis.missile_flags = MIF_SPLASH;
-
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- self.tur_head.frame += 2;
-
- if (self.tur_head.frame > 3)
- self.tur_head.frame = 0;
- }
-
- return true;
- }
- case TR_THINK:
- {
- float vz;
- vector wish_angle, real_angle;
-
- vz = self.velocity_z;
-
- self.angles_x = anglemods(self.angles_x);
- self.angles_y = anglemods(self.angles_y);
-
- fixedmakevectors(self.angles);
-
- wish_angle = normalize(self.steerto);
- wish_angle = vectoangles(wish_angle);
- real_angle = wish_angle - self.angles;
- real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
-
- self.tur_head.spawnshieldtime = fabs(real_angle_y);
- real_angle_y = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
- self.angles_y = (self.angles_y + real_angle_y);
-
- if(self.enemy)
- ewheel_move_enemy();
- else if(self.pathcurrent)
- ewheel_move_path();
- else
- ewheel_move_idle();
-
- self.velocity_z = vz;
-
- if(vlen(self.velocity))
- self.SendFlags |= TNSF_MOVE;
-
- return true;
- }
- case TR_DEATH:
- {
- self.velocity = '0 0 0';
-
-#ifdef EWHEEL_FANCYPATH
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-#endif
- self.pathcurrent = world;
-
- return true;
- }
- case TR_SETUP:
- {
- entity e;
-
- if(self.movetype == MOVETYPE_WALK)
- {
- self.velocity = '0 0 0';
- self.enemy = world;
-
- setorigin(self, self.pos1);
-
- if (self.target != "")
- {
- e = find(world, targetname, self.target);
- if (!e)
- {
- LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- LOG_TRACE("Warning: not a turrret path\n");
- else
- {
-
-#ifdef EWHEEL_FANCYPATH
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
- self.pathgoal = e;
-#else
- self.pathcurrent = e;
-#endif
- }
- }
- }
-
- self.iscreature = true;
- self.teleportable = TELEPORT_NORMAL;
- self.damagedbycontents = true;
- self.movetype = MOVETYPE_WALK;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
- self.idle_aim = '0 0 0';
- self.pos1 = self.origin;
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.frame = self.tur_head.frame = 1;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-
- // Convert from dgr / sec to dgr / tic
- self.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
- self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-void ewheel_draw()
-{SELFPARAM();
- float dt;
-
- dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- fixedmakevectors(self.angles);
- setorigin(self, self.origin + self.velocity * dt);
- self.tur_head.angles += dt * self.tur_head.move_avelocity;
- self.angles_y = self.move_angles_y;
-
- if (self.health < 127)
- if(random() < 0.05)
- te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-}
-
-float t_ewheel(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_SETUP:
- {
- self.gravity = 1;
- self.movetype = MOVETYPE_BOUNCE;
- self.move_movetype = MOVETYPE_BOUNCE;
- self.move_origin = self.origin;
- self.move_time = time;
- self.draw = ewheel_draw;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ FLAC,
-/* function */ t_flac,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "flac.md3",
-/* netname */ "flac",
-/* fullname */ _("FLAC Cannon")
-);
-#else
-#ifdef SVQC
-void turret_flac_projectile_think_explode()
-{SELFPARAM();
- if(self.enemy != world)
- if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
- setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
-
-#ifdef TURRET_DEBUG
- float d;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, 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, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
-#endif
- remove(self);
-}
-
-void spawnfunc_turret_flac() { SELFPARAM(); if(!turret_initialize(TUR_FLAC.m_id)) remove(self); }
-
-float t_flac(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- entity proj;
-
- turret_tag_fire_update();
-
- proj = turret_projectile(SND(HAGAR_FIRE), 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, TRUE, TRUE);
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- proj.think = turret_flac_projectile_think_explode;
- proj.nextthink = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01);
- proj.missile_flags = MIF_SPLASH | MIF_PROXY;
-
- self.tur_head.frame = self.tur_head.frame + 1;
- if (self.tur_head.frame >= 4)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_THINK:
- {
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_flac(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ FUSIONREACTOR,
-/* function */ t_fusionreactor,
-/* spawnflags */ TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE,
-/* mins,maxs */ '-34 -34 0', '34 34 90',
-/* model */ "base.md3",
-/* head_model */ "reactor.md3",
-/* netname */ "fusionreactor",
-/* fullname */ _("Fusion Reactor")
-);
-#else
-#ifdef SVQC
-bool turret_fusionreactor_firecheck()
-{SELFPARAM();
- if (self.attack_finished_single > time)
- return false;
-
- if (self.enemy.deadflag != DEAD_NO)
- return false;
-
- if (self.enemy == world)
- return false;
-
- if (self.ammo < self.shot_dmg)
- return false;
-
- if (self.enemy.ammo >= self.enemy.ammo_max)
- return false;
-
- if (vlen(self.enemy.origin - self.origin) > self.target_range)
- return false;
-
- if(self.team != self.enemy.team)
- return false;
-
- if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
- return false;
-
- return true;
-}
-
-void spawnfunc_turret_fusionreactor() { SELFPARAM(); if(!turret_initialize(TUR_FUSIONREACTOR.m_id)) remove(self); }
-
-float t_fusionreactor(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- vector fl_org;
-
- self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
- fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
- te_smallflash(fl_org);
-
- return true;
- }
- case TR_THINK:
- {
- self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
- self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
- self.firecheck_flags = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
- self.shoot_flags = TFL_SHOOT_HITALLVALID;
- self.aim_flags = TFL_AIM_NO;
- self.track_flags = TFL_TRACK_NO;
-
- self.tur_head.scale = 0.75;
- self.tur_head.avelocity = '0 50 0';
-
- self.turret_firecheckfunc = turret_fusionreactor_firecheck;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_fusionreactor(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ HELLION,
-/* function */ t_hellion,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "hellion.md3",
-/* netname */ "hellion",
-/* fullname */ _("Hellion Missile Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_hellion_shot_speed_gain;
-float autocvar_g_turrets_unit_hellion_shot_speed_max;
-
-void turret_hellion_missile_think()
-{SELFPARAM();
- vector olddir,newdir;
- vector pre_pos;
- float itime;
-
- self.nextthink = time + 0.05;
-
- olddir = normalize(self.velocity);
-
- if(self.max_health < time)
- turret_projectile_explode();
-
- // Enemy dead? just keep on the current heading then.
- if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
- {
-
- // Make sure we dont return to tracking a respawned player
- self.enemy = world;
-
- // Turn model
- self.angles = vectoangles(self.velocity);
-
- if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
- turret_projectile_explode();
-
- // Accelerate
- self.velocity = olddir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
-
- UpdateCSQCProjectile(self);
-
- return;
- }
-
- // Enemy in range?
- if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
- turret_projectile_explode();
-
- // Predict enemy position
- itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
- pre_pos = self.enemy.origin + self.enemy.velocity * itime;
-
- pre_pos = (pre_pos + self.enemy.origin) * 0.5;
-
- // Find out the direction to that place
- newdir = normalize(pre_pos - self.origin);
-
- // Turn
- newdir = normalize(olddir + newdir * 0.35);
-
- // Turn model
- self.angles = vectoangles(self.velocity);
-
- // Accelerate
- self.velocity = newdir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
-
- if (itime < 0.05)
- self.think = turret_projectile_explode;
-
- UpdateCSQCProjectile(self);
-}
-
-void spawnfunc_turret_hellion() { SELFPARAM(); if(!turret_initialize(TUR_HELLION.m_id)) remove(self); }
-
-float t_hellion(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- entity missile;
-
- if(self.tur_head.frame != 0)
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
- else
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
-
- missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
- te_explosion (missile.origin);
- missile.think = turret_hellion_missile_think;
- missile.nextthink = time;
- missile.flags = FL_PROJECTILE;
- missile.max_health = time + 9;
- missile.tur_aimpos = randomvec() * 128;
- missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
- self.tur_head.frame += 1;
-
- return true;
- }
- case TR_THINK:
- {
- if (self.tur_head.frame != 0)
- self.tur_head.frame += 1;
-
- if (self.tur_head.frame >= 7)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.aim_flags = TFL_AIM_SIMPLE;
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
- self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_hellion(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ HK,
-/* function */ t_hk,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "hk.md3",
-/* netname */ "hk",
-/* fullname */ _("Hunter-Killer Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_hk_shot_speed;
-float autocvar_g_turrets_unit_hk_shot_speed_accel;
-float autocvar_g_turrets_unit_hk_shot_speed_accel2;
-float autocvar_g_turrets_unit_hk_shot_speed_decel;
-float autocvar_g_turrets_unit_hk_shot_speed_max;
-float autocvar_g_turrets_unit_hk_shot_speed_turnrate;
-
-//#define TURRET_DEBUG_HK
-
-#ifdef TURRET_DEBUG_HK
-.float atime;
-#endif
-
-float hk_is_valid_target(entity e_target)
-{SELFPARAM();
- if (e_target == world)
- return 0;
-
- // If only this was used more..
- if (e_target.flags & FL_NOTARGET)
- return 0;
-
- // Cant touch this
- if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
- return 0;
-
- // player
- if (IS_CLIENT(e_target))
- {
- if (self.owner.target_select_playerbias < 0)
- return 0;
-
- if (e_target.deadflag != DEAD_NO)
- return 0;
- }
-
- // Missile
- if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
- return 0;
-
- // Team check
- if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
- return 0;
-
- return 1;
-}
-
-void turret_hk_missile_think()
-{SELFPARAM();
- vector vu, vd, vf, vl, vr, ve; // Vector (direction)
- float fu, fd, ff, fl, fr, fe; // Fraction to solid
- vector olddir,wishdir,newdir; // Final direction
- float lt_for; // Length of Trace FORwrad
- float lt_seek; // Length of Trace SEEK (left, right, up down)
- float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
- vector pre_pos;
- float myspeed;
- entity e;
- float ad,edist;
-
- self.nextthink = time + self.ticrate;
-
- //if (self.cnt < time)
- // turret_hk_missile_explode();
-
- if (self.enemy.deadflag != DEAD_NO)
- self.enemy = world;
-
- // Pick the closest valid target.
- if (!self.enemy)
- {
- e = findradius(self.origin, 5000);
- while (e)
- {
- if (hk_is_valid_target(e))
- {
- if (!self.enemy)
- self.enemy = e;
- else
- if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
- self.enemy = e;
- }
- e = e.chain;
- }
- }
-
- self.angles = vectoangles(self.velocity);
- self.angles_x = self.angles_x * -1;
- makevectors(self.angles);
- self.angles_x = self.angles_x * -1;
-
- if (self.enemy)
- {
- edist = vlen(self.origin - self.enemy.origin);
- // Close enougth to do decent damage?
- if ( edist <= (self.owner.shot_radius * 0.25) )
- {
- turret_projectile_explode();
- return;
- }
-
- // Get data on enemy position
- pre_pos = self.enemy.origin +
- self.enemy.velocity *
- min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
-
- traceline(self.origin, pre_pos,true,self.enemy);
- ve = normalize(pre_pos - self.origin);
- fe = trace_fraction;
-
- }
- else
- {
- edist = 0;
- ve = '0 0 0';
- fe = 0;
- }
-
- if ((fe != 1) || (self.enemy == world) || (edist > 1000))
- {
- myspeed = vlen(self.velocity);
-
- lt_for = myspeed * 3;
- lt_seek = myspeed * 2.95;
-
- // Trace forward
- traceline(self.origin, self.origin + v_forward * lt_for,false,self);
- vf = trace_endpos;
- ff = trace_fraction;
-
- // Find angular offset
- ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
-
- // To close to something, Slow down!
- if ( ((ff < 0.7) || (ad > 4)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
- myspeed = max(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_decel), (autocvar_g_turrets_unit_hk_shot_speed));
-
- // Failry clear, accelerate.
- if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
- myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel), (autocvar_g_turrets_unit_hk_shot_speed_max));
-
- // Setup trace pitch
- pt_seek = 1 - ff;
- pt_seek = bound(0.15,pt_seek,0.8);
- if (ff < 0.5) pt_seek = 1;
-
- // Trace left
- traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,self);
- vl = trace_endpos;
- fl = trace_fraction;
-
- // Trace right
- traceline(self.origin, self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vr = trace_endpos;
- fr = trace_fraction;
-
- // Trace up
- traceline(self.origin, self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vu = trace_endpos;
- fu = trace_fraction;
-
- // Trace down
- traceline(self.origin, self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vd = trace_endpos;
- fd = trace_fraction;
-
- vl = normalize(vl - self.origin);
- vr = normalize(vr - self.origin);
- vu = normalize(vu - self.origin);
- vd = normalize(vd - self.origin);
-
- // Panic tresh passed, find a single direction and turn as hard as we can
- if (pt_seek == 1)
- {
- wishdir = v_right;
- if (fl > fr) wishdir = -1 * v_right;
- if (fu > fl) wishdir = v_up;
- if (fd > fu) wishdir = -1 * v_up;
- }
- else
- {
- // Normalize our trace vectors to make a smooth path
- wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
- }
-
- if (self.enemy)
- {
- if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
- wishdir = (wishdir * (1 - fe)) + (ve * fe);
- }
- }
- else
- {
- // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
- myspeed = vlen(self.velocity);
- if (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max))
- myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
-
- wishdir = ve;
- }
-
- if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (self.cnt > time))
- myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
-
- // Ranoutagazfish?
- if (self.cnt < time)
- {
- self.cnt = time + 0.25;
- self.nextthink = 0;
- self.movetype = MOVETYPE_BOUNCE;
- return;
- }
-
- // Calculate new heading
- olddir = normalize(self.velocity);
- newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
-
- // Set heading & speed
- self.velocity = newdir * myspeed;
-
- // Align model with new heading
- self.angles = vectoangles(self.velocity);
-
-
-#ifdef TURRET_DEBUG_HK
- //if(self.atime < time) {
- if ((fe <= 0.99)||(edist > 1000))
- {
- te_lightning2(world,self.origin, self.origin + vr * lt_seek);
- te_lightning2(world,self.origin, self.origin + vl * lt_seek);
- te_lightning2(world,self.origin, self.origin + vu * lt_seek);
- te_lightning2(world,self.origin, self.origin + vd * lt_seek);
- te_lightning2(world,self.origin, vf);
- }
- else
- {
- te_lightning2(world,self.origin, self.enemy.origin);
- }
- bprint("Speed: ", ftos(rint(myspeed)), "\n");
- bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
- bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
- self.atime = time + 0.2;
- //}
-#endif
-
- UpdateCSQCProjectile(self);
-}
-
-float turret_hk_addtarget(entity e_target,entity e_sender)
-{SELFPARAM();
- if (e_target)
- {
- if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
- {
- self.enemy = e_target;
- return 1;
- }
- }
-
- return 0;
-}
-
-void spawnfunc_turret_hk() { SELFPARAM(); if(!turret_initialize(TUR_HK.m_id)) remove(self); }
-
-float t_hk(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- entity missile;
-
- missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
- te_explosion (missile.origin);
-
- missile.think = turret_hk_missile_think;
- missile.nextthink = time + 0.25;
- missile.movetype = MOVETYPE_BOUNCEMISSILE;
- missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75);
- missile.angles = vectoangles(missile.velocity);
- missile.cnt = time + 30;
- missile.ticrate = max(autocvar_sys_ticrate, 0.05);
- missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- return true;
- }
- case TR_THINK:
- {
- if (self.tur_head.frame != 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 5)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_SIMPLE;
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
- self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
- self.shoot_flags = TFL_SHOOT_CLEARTARGET;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.turret_addtarget = turret_hk_addtarget;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_hk(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ MACHINEGUN,
-/* function */ t_machinegun,
-/* spawnflags */ TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "machinegun.md3",
-/* netname */ "machinegun",
-/* fullname */ _("Machinegun Turret")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_machinegun() { SELFPARAM(); if(!turret_initialize(TUR_MACHINEGUN.m_id)) remove(self); }
-
-void W_MachineGun_MuzzleFlash(void);
-
-float t_machinegun(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0);
-
- W_MachineGun_MuzzleFlash();
- setattachment(self.muzzle_flash, self.tur_head, "tag_fire");
-
- return true;
- }
- case TR_THINK:
- {
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
- self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
- self.turret_flags |= TUR_FLAG_HITSCAN;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_machinegun(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ MLRS,
-/* function */ t_mlrs,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "mlrs.md3",
-/* netname */ "mlrs",
-/* fullname */ _("MLRS Turret")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_mlrs() { SELFPARAM(); if(!turret_initialize(TUR_MLRS.m_id)) remove(self); }
-
-float t_mlrs(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- entity missile;
-
- turret_tag_fire_update();
- missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
- missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
- missile.missile_flags = MIF_SPLASH;
- te_explosion (missile.origin);
-
- return true;
- }
- case TR_THINK:
- {
- // 0 = full, 6 = empty
- self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
- if(self.tur_head.frame < 0)
- {
- LOG_TRACE("ammo:",ftos(self.ammo),"\n");
- LOG_TRACE("shot_dmg:",ftos(self.shot_dmg),"\n");
- }
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
- self.volly_counter = self.shot_volly;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_mlrs(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ PHASER,
-/* function */ t_phaser,
-/* spawnflags */ TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "phaser.md3",
-/* netname */ "phaser",
-/* fullname */ _("Phaser Cannon")
-);
-#else
-#ifdef SVQC
-.float fireflag;
-
-float turret_phaser_firecheck()
-{SELFPARAM();
- if (self.fireflag != 0) return 0;
- return turret_firecheck();
-}
-
-void beam_think()
-{SELFPARAM();
- if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
- {
- self.owner.attack_finished_single = time + self.owner.shot_refire;
- self.owner.fireflag = 2;
- self.owner.tur_head.frame = 10;
- sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
- remove(self);
- return;
- }
-
- turret_do_updates(self.owner);
-
- if (time - self.shot_spread > 0)
- {
- self.shot_spread = time + 2;
- sound (self, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
- }
-
-
- self.nextthink = time + self.ticrate;
-
- self.owner.attack_finished_single = time + frametime;
- setself(self.owner);
- FireImoBeam ( self.tur_shotorg,
- self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
- '-1 -1 -1' * self.shot_radius,
- '1 1 1' * self.shot_radius,
- self.shot_force,
- this.shot_dmg,
- 0.75,
- DEATH_TURRET_PHASER);
- setself(this);
- self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
-
-}
-
-void spawnfunc_turret_phaser() { SELFPARAM(); if(!turret_initialize(TUR_PHASER.m_id)) remove(self); }
-
-float t_phaser(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- entity beam;
-
- beam = spawn();
- beam.ticrate = 0.1; //autocvar_sys_ticrate;
- setmodel(beam, MDL_TUR_PHASER_BEAM);
- beam.effects = EF_LOWPRECISION;
- beam.solid = SOLID_NOT;
- beam.think = beam_think;
- beam.cnt = time + self.shot_speed;
- beam.shot_spread = time + 2;
- beam.nextthink = time;
- beam.owner = self;
- beam.shot_dmg = self.shot_dmg / (self.shot_speed / beam.ticrate);
- beam.scale = self.target_range / 256;
- beam.movetype = MOVETYPE_NONE;
- beam.enemy = self.enemy;
- beam.bot_dodge = true;
- beam.bot_dodgerating = beam.shot_dmg;
- sound (beam, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
- self.fireflag = 1;
-
- beam.attack_finished_single = self.attack_finished_single;
- self.attack_finished_single = time; // + autocvar_sys_ticrate;
-
- setattachment(beam,self.tur_head,"tag_fire");
-
- soundat (self, trace_endpos, CH_SHOTS, SND(NEXIMPACT), VOL_BASE, ATTEN_NORM);
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
-
- return true;
- }
- case TR_THINK:
- {
- if (self.tur_head.frame != 0)
- {
- if (self.fireflag == 1)
- {
- if (self.tur_head.frame == 10)
- self.tur_head.frame = 1;
- else
- self.tur_head.frame = self.tur_head.frame +1;
- }
- else if (self.fireflag == 2 )
- {
- self.tur_head.frame = self.tur_head.frame +1;
- if (self.tur_head.frame == 15)
- {
- self.tur_head.frame = 0;
- self.fireflag = 0;
- }
- }
- }
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.aim_flags = TFL_AIM_LEAD;
-
- self.turret_firecheckfunc = turret_phaser_firecheck;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_phaser(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ PLASMA,
-/* function */ t_plasma,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "plasma.md3",
-/* netname */ "plasma",
-/* fullname */ _("Plasma Cannon")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_plasma() { SELFPARAM(); if(!turret_initialize(TUR_PLASMA.m_id)) remove(self); }
-
-float t_plasma(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- if(g_instagib)
- {
- float flying;
- flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
- FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
- 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
-
- Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- // teamcolor / hit beam effect
- vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
- }
- else
- {
- entity missile = turret_projectile(SND(HAGAR_FIRE), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
- missile.missile_flags = MIF_SPLASH;
-
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
- }
-
- return true;
- }
- case TR_THINK:
- {
- if (self.tur_head.frame != 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 5)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.firecheck_flags |= TFL_FIRECHECK_AFF;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
-
- turret_do_updates(self);
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_plasma(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ PLASMA_DUAL,
-/* function */ t_plasma_dual,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "plasmad.md3",
-/* netname */ "plasma_dual",
-/* fullname */ _("Dual Plasma Cannon")
-);
-#else
-
-#include "../../weapons/all.qh"
-
-CLASS(PlasmaDualAttack, PortoLaunch)
-/* flags */ ATTRIB(PlasmaDualAttack, spawnflags, int, WEP_TYPE_OTHER);
-/* impulse */ ATTRIB(PlasmaDualAttack, impulse, int, 5);
-/* refname */ ATTRIB(PlasmaDualAttack, netname, string, "plasmadual");
-/* wepname */ ATTRIB(PlasmaDualAttack, message, string, _("Dual plasma"));
-ENDCLASS(PlasmaDualAttack)
-REGISTER_WEAPON(PLASMA_DUAL, NEW(PlasmaDualAttack));
-
-#ifdef SVQC
-
-float t_plasma_dual(float req);
-METHOD(PlasmaDualAttack, wr_think, bool(entity thiswep)) {
- SELFPARAM();
- if (self.BUTTON_ATCK)
- if (weapon_prepareattack(0, WEP_CVAR_PRI(electro, refire))) {
- W_SetupShot_Dir(self, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
- self.tur_shotdir_updated = w_shotdir;
- self.tur_shotorg = w_shotorg;
- self.tur_head = self;
- self.shot_speed = max(1, ((!self.shot_speed) ? 2500 : self.shot_speed));
- self.shot_spread = bound(0.0001, ((!self.shot_spread) ? 0.0125 : self.shot_spread), 500);
- t_plasma_dual(TR_ATTACK);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
- }
- return true;
-}
-
-void spawnfunc_turret_plasma_dual() { SELFPARAM(); if(!turret_initialize(TUR_PLASMA_DUAL.m_id)) remove(self); }
-
-float t_plasma_dual(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- if(g_instagib)
- {
- float flying;
- flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
- FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
- 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
-
-
- Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- // teamcolor / hit beam effect
- vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
- self.tur_head.frame += 1;
- }
- else
- {
- entity missile = turret_projectile(SND(HAGAR_FIRE), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
- missile.missile_flags = MIF_SPLASH;
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- self.tur_head.frame += 1;
- }
-
- return true;
- }
- case TR_THINK:
- {
- if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 6)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.firecheck_flags |= TFL_FIRECHECK_AFF;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
-
- turret_do_updates(self);
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_plasma_dual(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ TESLA,
-/* function */ t_tesla,
-/* spawnflags */ TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
-/* mins,maxs */ '-60 -60 0', '60 60 128',
-/* model */ "tesla_base.md3",
-/* head_model */ "tesla_head.md3",
-/* netname */ "tesla",
-/* fullname */ _("Tesla Coil")
-);
-#else
-#ifdef SVQC
-entity toast(entity from, float range, float damage)
-{SELFPARAM();
- entity e;
- entity etarget = world;
- float d,dd;
- float r;
-
- dd = range + 1;
-
- e = findradius(from.origin,range);
- while (e)
- {
- if ((e.railgunhit != 1) && (e != from))
- {
- r = turret_validate_target(self,e,self.target_validate_flags);
- if (r > 0)
- {
- traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
- if (trace_fraction == 1.0)
- {
- d = vlen(e.origin - from.origin);
- if (d < dd)
- {
- dd = d;
- etarget = e;
- }
- }
- }
- }
- e = e.chain;
- }
-
- if (etarget)
- {
- te_csqc_lightningarc(from.origin,etarget.origin);
- Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
- etarget.railgunhit = 1;
- }
-
- return etarget;
-}
-
-float turret_tesla_firecheck()
-{SELFPARAM();
- // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
- float do_target_scan = 0;
-
- if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
- 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;
- }
-
- // But never more often then g_turrets_targetscan_mindelay!
- if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
- do_target_scan = 0;
-
- if(do_target_scan)
- {
- self.enemy = turret_select_target();
- self.target_select_time = time;
- }
-
- if(!turret_firecheck())
- return 0;
-
- if(self.enemy)
- return 1;
-
- return 0;
-}
-
-void spawnfunc_turret_tesla() { SELFPARAM(); if(!turret_initialize(TUR_TESLA.m_id)) remove(self); }
-
-float t_tesla(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- entity e, t;
- float d, r, i;
-
- d = self.shot_dmg;
- r = self.target_range;
- e = spawn();
- setorigin(e,self.tur_shotorg);
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
- t = toast(e,r,d);
- remove(e);
-
- if (t == world) return true;
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
-
- self.attack_finished_single = time + self.shot_refire;
- for (i = 0; i < 10; ++i)
- {
- d *= 0.75;
- r *= 0.85;
- t = toast(t, r, d);
- if (t == world) break;
-
- }
-
- e = findchainfloat(railgunhit, 1);
- while (e)
- {
- e.railgunhit = 0;
- e = e.chain;
- }
-
- return true;
- }
- case TR_THINK:
- {
- if(!self.active)
- {
- self.tur_head.avelocity = '0 0 0';
- return true;
- }
-
- if(self.ammo < self.shot_dmg)
- {
- self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
- }
- else
- {
- self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
-
- if(self.attack_finished_single > time)
- return true;
-
- float f;
- f = (self.ammo / self.ammo_max);
- f = f * f;
- if(f > random())
- if(random() < 0.1)
- te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
- }
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.turret_firecheckfunc = turret_tesla_firecheck;
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
- self.shoot_flags = TFL_SHOOT_CUSTOM;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.aim_flags = TFL_AIM_NO;
- self.track_flags = TFL_TRACK_NO;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_tesla(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifndef IMPLEMENTATION
-REGISTER_TURRET(
-/* TUR_##id */ WALKER,
-/* function */ t_walker,
-/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE,
-/* mins,maxs */ '-70 -70 0', '70 70 95',
-/* model */ "walker_body.md3",
-/* head_model */ "walker_head_minigun.md3",
-/* netname */ "walker",
-/* fullname */ _("Walker Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_walker_melee_damage;
-float autocvar_g_turrets_unit_walker_melee_force;
-float autocvar_g_turrets_unit_walker_melee_range;
-float autocvar_g_turrets_unit_walker_rocket_damage;
-float autocvar_g_turrets_unit_walker_rocket_radius;
-float autocvar_g_turrets_unit_walker_rocket_force;
-float autocvar_g_turrets_unit_walker_rocket_speed;
-float autocvar_g_turrets_unit_walker_rocket_range;
-float autocvar_g_turrets_unit_walker_rocket_range_min;
-float autocvar_g_turrets_unit_walker_rocket_refire;
-float autocvar_g_turrets_unit_walker_rocket_turnrate;
-float autocvar_g_turrets_unit_walker_speed_stop;
-float autocvar_g_turrets_unit_walker_speed_walk;
-float autocvar_g_turrets_unit_walker_speed_run;
-float autocvar_g_turrets_unit_walker_speed_jump;
-float autocvar_g_turrets_unit_walker_speed_swim;
-float autocvar_g_turrets_unit_walker_speed_roam;
-float autocvar_g_turrets_unit_walker_turn;
-float autocvar_g_turrets_unit_walker_turn_walk;
-float autocvar_g_turrets_unit_walker_turn_strafe;
-float autocvar_g_turrets_unit_walker_turn_swim;
-float autocvar_g_turrets_unit_walker_turn_run;
-
-#define ANIM_NO 0
-#define ANIM_TURN 1
-#define ANIM_WALK 2
-#define ANIM_RUN 3
-#define ANIM_STRAFE_L 4
-#define ANIM_STRAFE_R 5
-#define ANIM_JUMP 6
-#define ANIM_LAND 7
-#define ANIM_PAIN 8
-#define ANIM_MELEE 9
-#define ANIM_SWIM 10
-#define ANIM_ROAM 11
-
-.float animflag;
-.float idletime;
-
-#define WALKER_PATH(s,e) pathlib_astar(s,e)
-
-float walker_firecheck()
-{SELFPARAM();
- if (self.animflag == ANIM_MELEE)
- return 0;
-
- return turret_firecheck();
-}
-
-void walker_melee_do_dmg()
-{SELFPARAM();
- vector where;
- entity e;
-
- makevectors(self.angles);
- where = self.origin + v_forward * 128;
-
- e = findradius(where,32);
- while (e)
- {
- if (turret_validate_target(self, e, self.target_validate_flags))
- if (e != self && e.owner != self)
- Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
-
- e = e.chain;
- }
-}
-
-void walker_setnoanim()
-{SELFPARAM();
- turrets_setframe(ANIM_NO, false);
- self.animflag = self.frame;
-}
-void walker_rocket_explode()
-{SELFPARAM();
- RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
- remove (self);
-}
-
-void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
-{SELFPARAM();
- self.health = self.health - damage;
- self.velocity = self.velocity + vforce;
-
- if (self.health <= 0)
- W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
-}
-
-#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
-void walker_rocket_loop();
-void walker_rocket_think()
-{SELFPARAM();
- vector newdir;
- float edist;
- float itime;
- float m_speed;
-
- self.nextthink = time;
-
- edist = vlen(self.enemy.origin - self.origin);
-
- // Simulate crude guidance
- if (self.cnt < time)
- {
- if (edist < 1000)
- self.tur_shotorg = randomvec() * min(edist, 64);
- else
- self.tur_shotorg = randomvec() * min(edist, 256);
-
- self.cnt = time + 0.5;
- }
-
- if (edist < 128)
- self.tur_shotorg = '0 0 0';
-
- if (self.max_health < time)
- {
- self.think = walker_rocket_explode;
- self.nextthink = time;
- return;
- }
-
- if (self.shot_dmg != 1337 && random() < 0.01)
- {
- walker_rocket_loop();
- return;
- }
-
- m_speed = vlen(self.velocity);
-
- // Enemy dead? just keep on the current heading then.
- if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
- self.enemy = world;
-
- if (self.enemy)
- {
- itime = max(edist / m_speed, 1);
- newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
- }
- else
- newdir = normalize(self.velocity);
-
- WALKER_ROCKET_MOVE;
-}
-
-void walker_rocket_loop3()
-{SELFPARAM();
- vector newdir;
- self.nextthink = time;
-
- if (self.max_health < time)
- {
- self.think = walker_rocket_explode;
- return;
- }
-
- if (vlen(self.origin - self.tur_shotorg) < 100 )
- {
- self.think = walker_rocket_think;
- return;
- }
-
- newdir = steerlib_pull(self.tur_shotorg);
- WALKER_ROCKET_MOVE;
-
- self.angles = vectoangles(self.velocity);
-}
-
-void walker_rocket_loop2()
-{SELFPARAM();
- vector newdir;
-
- self.nextthink = time;
-
- if (self.max_health < time)
- {
- self.think = walker_rocket_explode;
- return;
- }
-
- if (vlen(self.origin - self.tur_shotorg) < 100 )
- {
- self.tur_shotorg = self.origin - '0 0 200';
- self.think = walker_rocket_loop3;
- return;
- }
-
- newdir = steerlib_pull(self.tur_shotorg);
- WALKER_ROCKET_MOVE;
-}
-
-void walker_rocket_loop()
-{SELFPARAM();
- self.nextthink = time;
- self.tur_shotorg = self.origin + '0 0 300';
- self.think = walker_rocket_loop2;
- self.shot_dmg = 1337;
-}
-
-void walker_fire_rocket(vector org)
-{SELFPARAM();
- entity rocket;
-
- fixedmakevectors(self.angles);
-
- te_explosion (org);
-
- rocket = spawn ();
- setorigin(rocket, org);
-
- sound (self, CH_WEAPON_A, SND_HAGAR_FIRE, VOL_BASE, ATTEN_NORM);
- setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
-
- rocket.classname = "walker_rocket";
- rocket.owner = self;
- rocket.bot_dodge = true;
- rocket.bot_dodgerating = 50;
- rocket.takedamage = DAMAGE_YES;
- rocket.damageforcescale = 2;
- rocket.health = 25;
- rocket.tur_shotorg = randomvec() * 512;
- rocket.cnt = time + 1;
- rocket.enemy = self.enemy;
-
- if (random() < 0.01)
- rocket.think = walker_rocket_loop;
- else
- rocket.think = walker_rocket_think;
-
- rocket.event_damage = walker_rocket_damage;
-
- rocket.nextthink = time;
- rocket.movetype = MOVETYPE_FLY;
- rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
- rocket.angles = vectoangles(rocket.velocity);
- rocket.touch = walker_rocket_explode;
- rocket.flags = FL_PROJECTILE;
- rocket.solid = SOLID_BBOX;
- rocket.max_health = time + 9;
- rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
-
- CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
-}
-
-.vector enemy_last_loc;
-.float enemy_last_time;
-void walker_move_to(vector _target, float _dist)
-{SELFPARAM();
- switch (self.waterlevel)
- {
- case WATERLEVEL_NONE:
- if (_dist > 500)
- self.animflag = ANIM_RUN;
- else
- self.animflag = ANIM_WALK;
- case WATERLEVEL_WETFEET:
- case WATERLEVEL_SWIMMING:
- if (self.animflag != ANIM_SWIM)
- self.animflag = ANIM_WALK;
- else
- self.animflag = ANIM_SWIM;
- break;
- case WATERLEVEL_SUBMERGED:
- self.animflag = ANIM_SWIM;
- }
-
- self.moveto = _target;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-
- if(self.enemy)
- {
- self.enemy_last_loc = _target;
- self.enemy_last_time = time;
- }
-}
-
-//#define WALKER_FANCYPATHING
-
-void walker_move_path()
-{SELFPARAM();
-#ifdef WALKER_FANCYPATHING
- // Are we close enougth to a path node to switch to the next?
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- if (self.pathcurrent.path_next == world)
- {
- // Path endpoint reached
- pathlib_deletepath(self.pathcurrent.owner);
- self.pathcurrent = world;
-
- if (self.pathgoal)
- {
- if (self.pathgoal.use)
- self.pathgoal.use();
-
- if (self.pathgoal.enemy)
- {
- self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
- self.pathgoal = self.pathgoal.enemy;
- }
- }
- else
- self.pathgoal = world;
- }
- else
- self.pathcurrent = self.pathcurrent.path_next;
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
- walker_move_to(self.moveto, 0);
-
-#else
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- self.pathcurrent = self.pathcurrent.enemy;
-
- if(!self.pathcurrent)
- return;
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
- walker_move_to(self.moveto, 0);
-#endif
-}
-
-void spawnfunc_turret_walker() { SELFPARAM(); if(!turret_initialize(TUR_WALKER.m_id)) remove(self); }
-
-float t_walker(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_ATTACK:
- {
- sound (self, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
- fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0);
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- return true;
- }
- case TR_THINK:
- {
- fixedmakevectors(self.angles);
-
- if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
- walker_move_path();
- else if (self.enemy == world)
- {
- if(self.pathcurrent)
- walker_move_path();
- else
- {
- if(self.enemy_last_time != 0)
- {
- if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
- self.enemy_last_time = 0;
- else
- walker_move_to(self.enemy_last_loc, 0);
- }
- else
- {
- if(self.animflag != ANIM_NO)
- {
- traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
-
- if(trace_fraction != 1.0)
- self.tur_head.idletime = -1337;
- else
- {
- traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
- if(trace_fraction == 1.0)
- self.tur_head.idletime = -1337;
- }
-
- if(self.tur_head.idletime == -1337)
- {
- self.moveto = self.origin + randomvec() * 256;
- self.tur_head.idletime = 0;
- }
-
- self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
- self.moveto_z = self.origin_z + 64;
- walker_move_to(self.moveto, 0);
- }
-
- if(self.idletime < time)
- {
- if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
- {
- self.idletime = time + 1 + random() * 5;
- self.moveto = self.origin;
- self.animflag = ANIM_NO;
- }
- else
- {
- self.animflag = ANIM_WALK;
- self.idletime = time + 4 + random() * 2;
- self.moveto = self.origin + randomvec() * 256;
- self.tur_head.moveto = self.moveto;
- self.tur_head.idletime = 0;
- }
- }
- }
- }
- }
- else
- {
- if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
- {
- vector wish_angle;
-
- wish_angle = angleofs(self, self.enemy);
- if (self.animflag != ANIM_SWIM)
- if (fabs(wish_angle_y) < 15)
- {
- self.moveto = self.enemy.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
- self.animflag = ANIM_MELEE;
- }
- }
- else if (self.tur_head.attack_finished_single < time)
- {
- if(self.tur_head.shot_volly)
- {
- self.animflag = ANIM_NO;
-
- self.tur_head.shot_volly = self.tur_head.shot_volly -1;
- if(self.tur_head.shot_volly == 0)
- self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
- else
- self.tur_head.attack_finished_single = time + 0.2;
-
- if(self.tur_head.shot_volly > 1)
- walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
- else
- walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
- }
- else
- {
- if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
- if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
- self.tur_head.shot_volly = 4;
- }
- }
- else
- {
- if (self.animflag != ANIM_MELEE)
- walker_move_to(self.enemy.origin, self.tur_dist_enemy);
- }
- }
-
- {
- vector real_angle;
- float turny = 0, turnx = 0;
- float vz;
-
- real_angle = vectoangles(self.steerto) - self.angles;
- vz = self.velocity_z;
-
- switch (self.animflag)
- {
- case ANIM_NO:
- movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
- break;
-
- case ANIM_TURN:
- turny = (autocvar_g_turrets_unit_walker_turn);
- movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
- break;
-
- case ANIM_WALK:
- turny = (autocvar_g_turrets_unit_walker_turn_walk);
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
- break;
-
- case ANIM_RUN:
- turny = (autocvar_g_turrets_unit_walker_turn_run);
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
- break;
-
- case ANIM_STRAFE_L:
- turny = (autocvar_g_turrets_unit_walker_turn_strafe);
- movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
- break;
-
- case ANIM_STRAFE_R:
- turny = (autocvar_g_turrets_unit_walker_turn_strafe);
- movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
- break;
-
- case ANIM_JUMP:
- self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
- break;
-
- case ANIM_LAND:
- break;
-
- case ANIM_PAIN:
- if(self.frame != ANIM_PAIN)
- defer(0.25, walker_setnoanim);
-
- break;
-
- case ANIM_MELEE:
- if(self.frame != ANIM_MELEE)
- {
- defer(0.41, walker_setnoanim);
- defer(0.21, walker_melee_do_dmg);
- }
-
- movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
- break;
-
- case ANIM_SWIM:
- turny = (autocvar_g_turrets_unit_walker_turn_swim);
- turnx = (autocvar_g_turrets_unit_walker_turn_swim);
-
- self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
- vz = self.velocity_z + sin(time * 4) * 8;
- break;
-
- case ANIM_ROAM:
- turny = (autocvar_g_turrets_unit_walker_turn_walk);
- movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
- break;
- }
-
- if(turny)
- {
- turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
- self.angles_y += turny;
- }
-
- if(turnx)
- {
- turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
- self.angles_x += turnx;
- }
-
- self.velocity_z = vz;
- }
-
-
- if(self.origin != self.oldorigin)
- self.SendFlags |= TNSF_MOVE;
-
- self.oldorigin = self.origin;
- turrets_setframe(self.animflag, false);
-
- return true;
- }
- case TR_DEATH:
- {
-#ifdef WALKER_FANCYPATHING
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-#endif
- self.pathcurrent = world;
-
- return true;
- }
- case TR_SETUP:
- {
- self.ticrate = 0.05;
-
- entity e;
-
- // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
- if(self.movetype == MOVETYPE_WALK)
- {
- if(self.pos1)
- setorigin(self, self.pos1);
- if(self.pos2)
- self.angles = self.pos2;
- }
-
- self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.aim_flags = TFL_AIM_LEAD;
- self.turret_flags |= TUR_FLAG_HITSCAN;
-
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.iscreature = true;
- self.teleportable = TELEPORT_NORMAL;
- self.damagedbycontents = true;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
- if(self.movetype != MOVETYPE_WALK)
- {
- setorigin(self, self.origin);
- tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
- setorigin(self, trace_endpos + '0 0 4');
- self.pos1 = self.origin;
- self.pos2 = self.angles;
- }
- self.movetype = MOVETYPE_WALK;
- self.idle_aim = '0 0 0';
- self.turret_firecheckfunc = walker_firecheck;
-
- if (self.target != "")
- {
- e = find(world, targetname, self.target);
- if (!e)
- {
- LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- LOG_TRACE("Warning: not a turrret path\n");
- else
- {
-#ifdef WALKER_FANCYPATHING
- self.pathcurrent = WALKER_PATH(self.origin, e.origin);
- self.pathgoal = e;
-#else
- self.pathcurrent = e;
-#endif
- }
- }
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-#include "../../../client/movelib.qh"
-
-void walker_draw()
-{SELFPARAM();
- float dt;
-
- dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- fixedmakevectors(self.angles);
- movelib_groundalign4point(300, 100, 0.25, 45);
- setorigin(self, self.origin + self.velocity * dt);
- self.tur_head.angles += dt * self.tur_head.move_avelocity;
- self.angles_y = self.move_angles_y;
-
- if (self.health < 127)
- if(random() < 0.15)
- te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-}
-
-float t_walker(float req)
-{SELFPARAM();
- switch(req)
- {
- case TR_SETUP:
- {
- self.gravity = 1;
- self.movetype = MOVETYPE_BOUNCE;
- self.move_movetype = MOVETYPE_BOUNCE;
- self.move_origin = self.origin;
- self.move_time = time;
- self.draw = walker_draw;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
// needs to be done so early because of the constants they create
static_init();
- CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
// needs to be done so early because of the constants they create
static_init();
- CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
#include "../common/items/all.qc"
#include "../common/monsters/all.qc"
#include "../common/mutators/all.qc"
+#include "../common/turrets/all.qc"
#include "../common/vehicles/all.qc"
-#include "../common/weapons/all.qc" // TODO
+#include "../common/weapons/all.qc"
#include "../common/turrets/sv_turrets.qc"
#include "../common/turrets/config.qc"
#include "../common/turrets/util.qc"
-#include "../common/turrets/all.qc"
#include "../common/turrets/checkpoint.qc"
#include "../common/turrets/targettrigger.qc"
#include "../common/weapons/config.qc"