From: TimePath Date: Sat, 3 Oct 2015 08:29:19 +0000 (+1000) Subject: Merge branch 'master' into TimePath/unified_weapons X-Git-Tag: xonotic-v0.8.2~1874^2~11 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=a8cc9eb71b0d0e44e9a968a9cf5554f6226cc838;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'master' into TimePath/unified_weapons # Conflicts: # qcsrc/common/turrets/turret/ewheel.qc # qcsrc/common/turrets/turret/hk_weapon.qc # qcsrc/common/turrets/turret/walker.qc # qcsrc/common/turrets/unit/flac.qc # qcsrc/common/turrets/unit/fusionreactor.qc # qcsrc/common/turrets/unit/hellion.qc # qcsrc/common/turrets/unit/machinegun.qc # qcsrc/common/turrets/unit/mlrs.qc # qcsrc/common/turrets/unit/phaser.qc # qcsrc/common/turrets/unit/plasma.qc # qcsrc/common/turrets/unit/plasma_dual.qc # qcsrc/common/turrets/unit/tesla.qc # qcsrc/common/vehicles/vehicle/bumblebee.qc # qcsrc/common/weapons/weapon/hook.qc # qcsrc/common/weapons/weapon/vortex.qc # qcsrc/server/mutators/mutator_overkill.qc --- a8cc9eb71b0d0e44e9a968a9cf5554f6226cc838 diff --cc qcsrc/common/monsters/monster/shambler.qc index 40d0ef6a3,fe6078303..937c83c9e --- a/qcsrc/common/monsters/monster/shambler.qc +++ b/qcsrc/common/monsters/monster/shambler.qc @@@ -222,11 -211,15 +222,11 @@@ float M_Shambler_Attack(float attack_ty return false; } - void spawnfunc_monster_shambler() { Monster_Spawn(MON_SHAMBLER.monsterid); } + spawnfunc(monster_shambler) { Monster_Spawn(MON_SHAMBLER.monsterid); } #endif // SVQC -bool M_Shambler(int req) -{SELFPARAM(); - switch(req) - { #ifdef SVQC - case MR_THINK: + METHOD(Shambler, mr_think, bool(Shambler thismon)) { return true; } diff --cc qcsrc/common/monsters/monster/spider.qc index 8f3bc1178,ba2b12695..e262ca87d --- a/qcsrc/common/monsters/monster/spider.qc +++ b/qcsrc/common/monsters/monster/spider.qc @@@ -171,11 -124,15 +171,11 @@@ bool M_Spider_Attack(int attack_type, e return false; } - void spawnfunc_monster_spider() { Monster_Spawn(MON_SPIDER.monsterid); } + spawnfunc(monster_spider) { Monster_Spawn(MON_SPIDER.monsterid); } #endif // SVQC -bool M_Spider(int req) -{SELFPARAM(); - switch(req) - { #ifdef SVQC - case MR_THINK: + METHOD(Spider, mr_think, bool(Spider thismon)) { return true; } diff --cc qcsrc/common/monsters/monster/wyvern.qc index 2b1c035ed,d65bcf648..c901e3ae3 --- a/qcsrc/common/monsters/monster/wyvern.qc +++ b/qcsrc/common/monsters/monster/wyvern.qc @@@ -136,11 -101,15 +136,11 @@@ float M_Wyvern_Attack(float attack_type return false; } - void spawnfunc_monster_wyvern() { Monster_Spawn(MON_WYVERN.monsterid); } + spawnfunc(monster_wyvern) { Monster_Spawn(MON_WYVERN.monsterid); } #endif // SVQC -bool M_Wyvern(int req) -{SELFPARAM(); - switch(req) - { #ifdef SVQC - case MR_THINK: + METHOD(Wyvern, mr_think, bool(Wyvern thismon)) { return true; } diff --cc qcsrc/common/monsters/monster/zombie.qc index b9619be19,6242a757d..8425a123a --- a/qcsrc/common/monsters/monster/zombie.qc +++ b/qcsrc/common/monsters/monster/zombie.qc @@@ -149,13 -138,16 +149,13 @@@ float M_Zombie_Attack(float attack_type return false; } - void spawnfunc_monster_zombie() { Monster_Spawn(MON_ZOMBIE.monsterid); } + spawnfunc(monster_zombie) { Monster_Spawn(MON_ZOMBIE.monsterid); } #endif // SVQC -bool M_Zombie(int req) -{SELFPARAM(); - switch(req) - { #ifdef SVQC - case MR_THINK: + METHOD(Zombie, mr_think, bool(Zombie thismon)) { + SELFPARAM(); if(time >= self.spawn_time) self.damageforcescale = autocvar_g_monster_zombie_damageforcescale; return true; diff --cc qcsrc/common/turrets/turret/ewheel.qc index 6dab61727,000000000..cdb9a605c mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/ewheel.qc +++ b/qcsrc/common/turrets/turret/ewheel.qc @@@ -1,270 -1,0 +1,270 @@@ +#ifndef TURRET_EWHEEL_H +#define TURRET_EWHEEL_H + +//#define EWHEEL_FANCYPATH + +#include "ewheel_weapon.qc" + +CLASS(EWheel, Turret) +/* spawnflags */ ATTRIB(EWheel, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM); +/* mins */ ATTRIB(EWheel, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(EWheel, maxs, vector, '32 32 48'); +/* modelname */ ATTRIB(EWheel, mdl, string, "ewheel-base2.md3"); +/* model */ ATTRIB(EWheel, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(EWheel, head_model, string, strzone(strcat("models/turrets/", "ewheel-gun1.md3"))); +/* netname */ ATTRIB(EWheel, netname, string, "ewheel"); +/* fullname */ ATTRIB(EWheel, turret_name, string, _("eWheel Turret")); + ATTRIB(EWheel, m_weapon, Weapon, WEP_EWHEEL); +ENDCLASS(EWheel) +REGISTER_TURRET(EWHEEL, NEW(EWheel)); + +#endif + +#ifdef IMPLEMENTATION + +#include "ewheel_weapon.qc" + +#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; + +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)) remove(self); } ++spawnfunc(turret_ewheel) { if(!turret_initialize(TUR_EWHEEL)) remove(self); } + + METHOD(EWheel, tr_think, void(EWheel thistur)) + { + SELFPARAM(); + 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; + } + METHOD(EWheel, tr_death, void(EWheel this, entity it)) + { + it.velocity = '0 0 0'; + +#ifdef EWHEEL_FANCYPATH + if (self.pathcurrent) + pathlib_deletepath(it.pathcurrent.owner); +#endif + it.pathcurrent = NULL; + } + METHOD(EWheel, tr_setup, void(EWheel this, entity it)) + { + entity e; + + if(it.movetype == MOVETYPE_WALK) + { + it.velocity = '0 0 0'; + it.enemy = world; + + setorigin(it, it.pos1); + + if (it.target != "") + { + e = find(world, targetname, it.target); + if (!e) + { + LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n"); + it.target = ""; + } + + if (e.classname != "turret_checkpoint") + LOG_TRACE("Warning: not a turrret path\n"); + else + { + +#ifdef EWHEEL_FANCYPATH + it.pathcurrent = WALKER_PATH(it.origin,e.origin); + it.pathgoal = e; +#else + it.pathcurrent = e; +#endif + } + } + } + + it.iscreature = true; + it.teleportable = TELEPORT_NORMAL; + it.damagedbycontents = true; + it.movetype = MOVETYPE_WALK; + it.solid = SOLID_SLIDEBOX; + it.takedamage = DAMAGE_AIM; + it.idle_aim = '0 0 0'; + it.pos1 = it.origin; + it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; + it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; + it.frame = it.tur_head.frame = 1; + it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE; + + // Convert from dgr / sec to dgr / tic + it.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate); + it.tur_head.aim_speed = it.tur_head.aim_speed / (1 / it.ticrate); + } + +#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); +} + + METHOD(EWheel, tr_setup, void(EWheel this, entity it)) + { + it.gravity = 1; + it.movetype = MOVETYPE_BOUNCE; + it.move_movetype = MOVETYPE_BOUNCE; + it.move_origin = it.origin; + it.move_time = time; + it.draw = ewheel_draw; + } + +#endif // CSQC +#endif diff --cc qcsrc/common/turrets/turret/flac.qc index a2de5cac4,000000000..1c9122f67 mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/flac.qc +++ b/qcsrc/common/turrets/turret/flac.qc @@@ -1,39 -1,0 +1,39 @@@ +#ifndef TURRET_FLAC_H +#define TURRET_FLAC_H + +#include "flac_weapon.qc" + +CLASS(Flac, Turret) +/* spawnflags */ ATTRIB(Flac, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE); +/* mins */ ATTRIB(Flac, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(Flac, maxs, vector, '32 32 64'); +/* modelname */ ATTRIB(Flac, mdl, string, "base.md3"); +/* model */ ATTRIB(Flac, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(Flac, head_model, string, strzone(strcat("models/turrets/", "flac.md3"))); +/* netname */ ATTRIB(Flac, netname, string, "flac"); +/* fullname */ ATTRIB(Flac, turret_name, string, _("FLAC Cannon")); + ATTRIB(Flac, m_weapon, Weapon, WEP_FLAC); +ENDCLASS(Flac) +REGISTER_TURRET(FLAC, NEW(Flac)); + +#endif + +#ifdef IMPLEMENTATION + +#include "flac_weapon.qc" + +#ifdef SVQC + - void spawnfunc_turret_flac() { SELFPARAM(); if (!turret_initialize(TUR_FLAC)) remove(self); } ++spawnfunc(turret_flac) { if (!turret_initialize(TUR_FLAC)) remove(self); } + +METHOD(Flac, tr_setup, void(Flac this, entity it)) +{ + it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE; + it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; + it.damage_flags |= TFL_DMG_HEADSHAKE; + it.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY; +} + +#endif + +#endif diff --cc qcsrc/common/turrets/turret/fusionreactor.qc index fcd611377,000000000..1077d5c63 mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/fusionreactor.qc +++ b/qcsrc/common/turrets/turret/fusionreactor.qc @@@ -1,77 -1,0 +1,77 @@@ +#ifndef TURRET_FUSIONREACTOR_H +#define TURRET_FUSIONREACTOR_H + +CLASS(FusionReactor, Turret) +/* spawnflags */ ATTRIB(FusionReactor, spawnflags, int, TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE); +/* mins */ ATTRIB(FusionReactor, mins, vector, '-34 -34 0'); +/* maxs */ ATTRIB(FusionReactor, maxs, vector, '34 34 90'); +/* modelname */ ATTRIB(FusionReactor, mdl, string, "base.md3"); +/* model */ ATTRIB(FusionReactor, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(FusionReactor, head_model, string, strzone(strcat("models/turrets/", "reactor.md3"))); +/* netname */ ATTRIB(FusionReactor, netname, string, "fusionreactor"); +/* fullname */ ATTRIB(FusionReactor, turret_name, string, _("Fusion Reactor")); +ENDCLASS(FusionReactor) +REGISTER_TURRET(FUSIONREACTOR, NEW(FusionReactor)); + +#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)) remove(self); } ++spawnfunc(turret_fusionreactor) { if (!turret_initialize(TUR_FUSIONREACTOR)) remove(self); } + +METHOD(FusionReactor, tr_attack, void(FusionReactor this)) +{ + self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max); + vector fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax); + te_smallflash(fl_org); +} +METHOD(FusionReactor, tr_think, void(FusionReactor thistur)) +{ + self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max); +} +METHOD(FusionReactor, tr_setup, void(FusionReactor this, entity it)) +{ + it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE; + it.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS; + it.firecheck_flags = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD; + it.shoot_flags = TFL_SHOOT_HITALLVALID; + it.aim_flags = TFL_AIM_NO; + it.track_flags = TFL_TRACK_NO; + + it.tur_head.scale = 0.75; + it.tur_head.avelocity = '0 50 0'; + + it.turret_firecheckfunc = turret_fusionreactor_firecheck; +} + +#endif +#endif diff --cc qcsrc/common/turrets/turret/hellion.qc index f2c6f7fc9,000000000..203be93db mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/hellion.qc +++ b/qcsrc/common/turrets/turret/hellion.qc @@@ -1,46 -1,0 +1,46 @@@ +#ifndef TURRET_HELLION_H +#define TURRET_HELLION_H + +#include "hellion_weapon.qc" + +CLASS(Hellion, Turret) +/* spawnflags */ ATTRIB(Hellion, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE); +/* mins */ ATTRIB(Hellion, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(Hellion, maxs, vector, '32 32 64'); +/* modelname */ ATTRIB(Hellion, mdl, string, "base.md3"); +/* model */ ATTRIB(Hellion, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(Hellion, head_model, string, strzone(strcat("models/turrets/", "hellion.md3"))); +/* netname */ ATTRIB(Hellion, netname, string, "hellion"); +/* fullname */ ATTRIB(Hellion, turret_name, string, _("Hellion Missile Turret")); + ATTRIB(Hellion, m_weapon, Weapon, WEP_HELLION); +ENDCLASS(Hellion) +REGISTER_TURRET(HELLION, NEW(Hellion)); + +#endif + +#ifdef IMPLEMENTATION + +#include "hellion_weapon.qc" + +#ifdef SVQC + - void spawnfunc_turret_hellion() { SELFPARAM(); if (!turret_initialize(TUR_HELLION)) remove(self); } ++spawnfunc(turret_hellion) { if (!turret_initialize(TUR_HELLION)) remove(self); } + +METHOD(Hellion, tr_think, void(Hellion thistur)) +{ + if (self.tur_head.frame != 0) + self.tur_head.frame += 1; + + if (self.tur_head.frame >= 7) + self.tur_head.frame = 0; +} +METHOD(Hellion, tr_setup, void(Hellion this, entity it)) +{ + it.aim_flags = TFL_AIM_SIMPLE; + it.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ; + it.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN; + it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE; +} + +#endif +#endif diff --cc qcsrc/common/turrets/turret/hk.qc index 0d7dc6dd0,000000000..61d8318db mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/hk.qc +++ b/qcsrc/common/turrets/turret/hk.qc @@@ -1,72 -1,0 +1,72 @@@ +#ifndef TURRET_HK_H +#define TURRET_HK_H + +//#define TURRET_DEBUG_HK + +#include "hk_weapon.qc" + +CLASS(HunterKiller, Turret) +/* spawnflags */ ATTRIB(HunterKiller, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS); +/* mins */ ATTRIB(HunterKiller, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(HunterKiller, maxs, vector, '32 32 64'); +/* modelname */ ATTRIB(HunterKiller, mdl, string, "base.md3"); +/* model */ ATTRIB(HunterKiller, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(HunterKiller, head_model, string, strzone(strcat("models/turrets/", "hk.md3"))); +/* netname */ ATTRIB(HunterKiller, netname, string, "hk"); +/* fullname */ ATTRIB(HunterKiller, turret_name, string, _("Hunter-Killer Turret")); + ATTRIB(HunterKiller, m_weapon, Weapon, WEP_HK); +ENDCLASS(HunterKiller) +REGISTER_TURRET(HK, NEW(HunterKiller)); + +#endif + +#ifdef IMPLEMENTATION + +#include "hk_weapon.qc" + +#ifdef SVQC + +#ifdef TURRET_DEBUG_HK +.float atime; +#endif + - void spawnfunc_turret_hk() { SELFPARAM(); if(!turret_initialize(TUR_HK)) remove(self); } ++spawnfunc(turret_hk) { if(!turret_initialize(TUR_HK)) remove(self); } + +METHOD(HunterKiller, tr_think, void(HunterKiller thistur)) +{ + 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; +} + +float turret_hk_addtarget(entity e_target,entity e_sender); +METHOD(HunterKiller, tr_setup, void(HunterKiller this, entity it)) +{ + it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE; + it.aim_flags = TFL_AIM_SIMPLE; + it.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK; + it.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF; + it.shoot_flags = TFL_SHOOT_CLEARTARGET; + it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK; + + it.turret_addtarget = turret_hk_addtarget; +} + +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; +} + +#endif // SVQC +#endif diff --cc qcsrc/common/turrets/turret/machinegun.qc index 8fc1f4251,000000000..9911b97c6 mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/machinegun.qc +++ b/qcsrc/common/turrets/turret/machinegun.qc @@@ -1,39 -1,0 +1,39 @@@ +#ifndef TURRET_MACHINEGUN_H +#define TURRET_MACHINEGUN_H + +#include "machinegun_weapon.qc" + +CLASS(MachineGunTurret, Turret) +/* spawnflags */ ATTRIB(MachineGunTurret, spawnflags, int, TUR_FLAG_PLAYER); +/* mins */ ATTRIB(MachineGunTurret, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(MachineGunTurret, maxs, vector, '32 32 64'); +/* modelname */ ATTRIB(MachineGunTurret, mdl, string, "base.md3"); +/* model */ ATTRIB(MachineGunTurret, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(MachineGunTurret, head_model, string, strzone(strcat("models/turrets/", "machinegun.md3"))); +/* netname */ ATTRIB(MachineGunTurret, netname, string, "machinegun"); +/* fullname */ ATTRIB(MachineGunTurret, turret_name, string, _("Machinegun Turret")); + ATTRIB(MachineGunTurret, m_weapon, Weapon, WEP_TUR_MACHINEGUN); +ENDCLASS(MachineGunTurret) +REGISTER_TURRET(MACHINEGUN, NEW(MachineGunTurret)); + +#endif + +#ifdef IMPLEMENTATION + +#include "machinegun_weapon.qc" + +#ifdef SVQC + - void spawnfunc_turret_machinegun() { SELFPARAM(); if (!turret_initialize(TUR_MACHINEGUN)) remove(self); } ++spawnfunc(turret_machinegun) { if (!turret_initialize(TUR_MACHINEGUN)) remove(self); } + +METHOD(MachineGunTurret, tr_setup, void(MachineGunTurret this, entity it)) +{ + it.damage_flags |= TFL_DMG_HEADSHAKE; + it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK; + it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE; + it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; + it.turret_flags |= TUR_FLAG_HITSCAN; +} + +#endif // SVQC +#endif diff --cc qcsrc/common/turrets/turret/mlrs.qc index 7920c1a02,000000000..ae2d1d47c mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/mlrs.qc +++ b/qcsrc/common/turrets/turret/mlrs.qc @@@ -1,50 -1,0 +1,50 @@@ +#ifndef TURRET_MLRS_H +#define TURRET_MLRS_H + +#include "mlrs_weapon.qc" + +CLASS(MLRSTurret, Turret) +/* spawnflags */ ATTRIB(MLRSTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER); +/* mins */ ATTRIB(MLRSTurret, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(MLRSTurret, maxs, vector, '32 32 64'); +/* modelname */ ATTRIB(MLRSTurret, mdl, string, "base.md3"); +/* model */ ATTRIB(MLRSTurret, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(MLRSTurret, head_model, string, strzone(strcat("models/turrets/", "mlrs.md3"))); +/* netname */ ATTRIB(MLRSTurret, netname, string, "mlrs"); +/* fullname */ ATTRIB(MLRSTurret, turret_name, string, _("MLRS Turret")); + ATTRIB(MLRSTurret, m_weapon, Weapon, WEP_TUR_MLRS); +ENDCLASS(MLRSTurret) +REGISTER_TURRET(MLRS, NEW(MLRSTurret)); + +#endif + +#ifdef IMPLEMENTATION + +#include "mlrs_weapon.qc" + +#ifdef SVQC + - void spawnfunc_turret_mlrs() { SELFPARAM(); if (!turret_initialize(TUR_MLRS)) remove(self); } ++spawnfunc(turret_mlrs) { if (!turret_initialize(TUR_MLRS)) remove(self); } + +METHOD(MLRSTurret, tr_think, void(MLRSTurret thistur)) +{ + // 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"); + } +} +METHOD(MLRSTurret, tr_setup, void(MLRSTurret this, entity it)) +{ + it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE; + it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; + + it.damage_flags |= TFL_DMG_HEADSHAKE; + it.shoot_flags |= TFL_SHOOT_VOLLYALWAYS; + it.volly_counter = it.shot_volly; +} + +#endif // SVQC +#endif diff --cc qcsrc/common/turrets/turret/phaser.qc index 7fcb0131f,000000000..24d4d30c5 mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/phaser.qc +++ b/qcsrc/common/turrets/turret/phaser.qc @@@ -1,67 -1,0 +1,67 @@@ +#ifndef TURRET_PHASER_H +#define TURRET_PHASER_H + +#include "phaser_weapon.qc" + +CLASS(PhaserTurret, Turret) +/* spawnflags */ ATTRIB(PhaserTurret, spawnflags, int, TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER); +/* mins */ ATTRIB(PhaserTurret, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(PhaserTurret, maxs, vector, '32 32 64'); +/* modelname */ ATTRIB(PhaserTurret, mdl, string, "base.md3"); +/* model */ ATTRIB(PhaserTurret, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(PhaserTurret, head_model, string, strzone(strcat("models/turrets/", "phaser.md3"))); +/* netname */ ATTRIB(PhaserTurret, netname, string, "phaser"); +/* fullname */ ATTRIB(PhaserTurret, turret_name, string, _("Phaser Cannon")); + ATTRIB(PhaserTurret, m_weapon, Weapon, WEP_PHASER); +ENDCLASS(PhaserTurret) +REGISTER_TURRET(PHASER, NEW(PhaserTurret)); + +#endif + +#ifdef IMPLEMENTATION + +#include "phaser_weapon.qc" + +#ifdef SVQC + - void spawnfunc_turret_phaser() { SELFPARAM(); if (!turret_initialize(TUR_PHASER)) remove(self); } ++spawnfunc(turret_phaser) { if (!turret_initialize(TUR_PHASER)) remove(self); } + +METHOD(PhaserTurret, tr_think, void(PhaserTurret thistur)) +{ + 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; + } + } + } +} +float turret_phaser_firecheck(); +METHOD(PhaserTurret, tr_setup, void(PhaserTurret this, entity it)) +{ + it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE; + it.aim_flags = TFL_AIM_LEAD; + + it.turret_firecheckfunc = turret_phaser_firecheck; +} +float turret_phaser_firecheck() +{ + SELFPARAM(); + if (self.fireflag != 0) return 0; + return turret_firecheck(); +} + +#endif +#endif diff --cc qcsrc/common/turrets/turret/plasma.qc index 04f81cbc0,000000000..7c40299aa mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/plasma.qc +++ b/qcsrc/common/turrets/turret/plasma.qc @@@ -1,68 -1,0 +1,68 @@@ +#ifndef TURRET_PLASMA_H +#define TURRET_PLASMA_H + +#include "plasma_weapon.qc" + +CLASS(PlasmaTurret, Turret) +/* spawnflags */ ATTRIB(PlasmaTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER); +/* mins */ ATTRIB(PlasmaTurret, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(PlasmaTurret, maxs, vector, '32 32 64'); +/* modelname */ ATTRIB(PlasmaTurret, mdl, string, "base.md3"); +/* model */ ATTRIB(PlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(PlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasma.md3"))); +/* netname */ ATTRIB(PlasmaTurret, netname, string, "plasma"); +/* fullname */ ATTRIB(PlasmaTurret, turret_name, string, _("Plasma Cannon")); + ATTRIB(PlasmaTurret, m_weapon, Weapon, WEP_PLASMA); +ENDCLASS(PlasmaTurret) +REGISTER_TURRET(PLASMA, NEW(PlasmaTurret)); + +#endif + +#ifdef IMPLEMENTATION + +#include "plasma_weapon.qc" + +#ifdef SVQC + - void spawnfunc_turret_plasma() { SELFPARAM(); if (!turret_initialize(TUR_PLASMA)) remove(self); } ++spawnfunc(turret_plasma) { if (!turret_initialize(TUR_PLASMA)) remove(self); } + +METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this)) +{ + if(g_instagib) + { + 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); + } + else + { + super.tr_attack(this); + } + if (self.tur_head.frame == 0) + self.tur_head.frame = 1; +} +METHOD(PlasmaTurret, tr_think, void(PlasmaTurret thistur)) +{ + 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; +} +METHOD(PlasmaTurret, tr_setup, void(PlasmaTurret this, entity it)) +{ + it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE; + it.damage_flags |= TFL_DMG_HEADSHAKE; + it.firecheck_flags |= TFL_FIRECHECK_AFF; + it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH; + + turret_do_updates(it); +} + +#endif +#endif diff --cc qcsrc/common/turrets/turret/plasma_dual.qc index faac00d26,000000000..e1143bc04 mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/plasma_dual.qc +++ b/qcsrc/common/turrets/turret/plasma_dual.qc @@@ -1,58 -1,0 +1,58 @@@ +#ifndef TURRET_PLASMA_DUAL_H +#define TURRET_PLASMA_DUAL_H + +CLASS(PlasmaDualAttack, PlasmaAttack) +/* refname */ ATTRIB(PlasmaDualAttack, netname, string, "turret_plasma_dual"); +/* wepname */ ATTRIB(PlasmaDualAttack, message, string, _("Dual plasma")); +ENDCLASS(PlasmaDualAttack) +REGISTER_WEAPON(PLASMA_DUAL, NEW(PlasmaDualAttack)); + +CLASS(DualPlasmaTurret, PlasmaTurret) +/* spawnflags */ ATTRIB(DualPlasmaTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER); +/* mins */ ATTRIB(DualPlasmaTurret, mins, vector, '-32 -32 0'); +/* maxs */ ATTRIB(DualPlasmaTurret, maxs, vector, '32 32 64'); +/* modelname */ ATTRIB(DualPlasmaTurret, mdl, string, "base.md3"); +/* model */ ATTRIB(DualPlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(DualPlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasmad.md3"))); +/* netname */ ATTRIB(DualPlasmaTurret, netname, string, "plasma_dual"); +/* fullname */ ATTRIB(DualPlasmaTurret, turret_name, string, _("Dual Plasma Cannon")); + ATTRIB(DualPlasmaTurret, m_weapon, Weapon, WEP_PLASMA_DUAL); +ENDCLASS(DualPlasmaTurret) +REGISTER_TURRET(PLASMA_DUAL, NEW(DualPlasmaTurret)); + +#endif + +#ifdef IMPLEMENTATION + +#ifdef SVQC + - void spawnfunc_turret_plasma_dual() { SELFPARAM(); if (!turret_initialize(TUR_PLASMA_DUAL)) remove(self); } ++spawnfunc(turret_plasma_dual) { if (!turret_initialize(TUR_PLASMA_DUAL)) remove(self); } + +METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret this)) +{ + if (g_instagib) { + 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); + } else { + super.vtblbase.tr_attack(this); + } + self.tur_head.frame += 1; +} +METHOD(DualPlasmaTurret, tr_think, void(DualPlasmaTurret thistur)) +{ + 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; +} + +#endif +#endif diff --cc qcsrc/common/turrets/turret/tesla.qc index 65733a8cb,000000000..3ae039c3c mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/tesla.qc +++ b/qcsrc/common/turrets/turret/tesla.qc @@@ -1,111 -1,0 +1,111 @@@ +#ifndef TURRET_TESLA_H +#define TURRET_TESLA_H + +#include "tesla_weapon.qc" + +CLASS(TeslaCoil, Turret) +/* spawnflags */ ATTRIB(TeslaCoil, spawnflags, int, TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE); +/* mins */ ATTRIB(TeslaCoil, mins, vector, '-60 -60 0'); +/* maxs */ ATTRIB(TeslaCoil, maxs, vector, '60 60 128'); +/* modelname */ ATTRIB(TeslaCoil, mdl, string, "tesla_base.md3"); +/* model */ ATTRIB(TeslaCoil, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(TeslaCoil, head_model, string, strzone(strcat("models/turrets/", "tesla_head.md3"))); +/* netname */ ATTRIB(TeslaCoil, netname, string, "tesla"); +/* fullname */ ATTRIB(TeslaCoil, turret_name, string, _("Tesla Coil")); + ATTRIB(TeslaCoil, m_weapon, Weapon, WEP_TESLA); +ENDCLASS(TeslaCoil) +REGISTER_TURRET(TESLA, NEW(TeslaCoil)); + +#endif + +#ifdef IMPLEMENTATION + +#include "tesla_weapon.qc" + +#ifdef SVQC + - void spawnfunc_turret_tesla() { SELFPARAM(); if (!turret_initialize(TUR_TESLA)) remove(self); } ++spawnfunc(turret_tesla) { if (!turret_initialize(TUR_TESLA)) remove(self); } + +METHOD(TeslaCoil, tr_think, void(TeslaCoil thistur)) +{ + if(!self.active) + { + self.tur_head.avelocity = '0 0 0'; + return; + } + + 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; + + 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)); + } +} + +float turret_tesla_firecheck(); +METHOD(TeslaCoil, tr_setup, void(TeslaCoil this, entity it)) +{ + it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | + TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK; + + it.turret_firecheckfunc = turret_tesla_firecheck; + it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | + TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK; + + it.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN; + it.shoot_flags = TFL_SHOOT_CUSTOM; + it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE; + it.aim_flags = TFL_AIM_NO; + it.track_flags = TFL_TRACK_NO; +} + +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; +} + +#endif +#endif diff --cc qcsrc/common/turrets/turret/walker.qc index 49e93c09d,000000000..1feace46a mode 100644,000000..100644 --- a/qcsrc/common/turrets/turret/walker.qc +++ b/qcsrc/common/turrets/turret/walker.qc @@@ -1,667 -1,0 +1,667 @@@ +#ifndef TURRET_WALKER_H +#define TURRET_WALKER_H + +//#define WALKER_FANCYPATHING + +#include "walker_weapon.qc" + +CLASS(WalkerTurret, Turret) +/* spawnflags */ ATTRIB(WalkerTurret, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE); +/* mins */ ATTRIB(WalkerTurret, mins, vector, '-70 -70 0'); +/* maxs */ ATTRIB(WalkerTurret, maxs, vector, '70 70 95'); +/* modelname */ ATTRIB(WalkerTurret, mdl, string, "walker_body.md3"); +/* model */ ATTRIB(WalkerTurret, model, string, strzone(strcat("models/turrets/", this.mdl))); +/* head_model */ ATTRIB(WalkerTurret, head_model, string, strzone(strcat("models/turrets/", "walker_head_minigun.md3"))); +/* netname */ ATTRIB(WalkerTurret, netname, string, "walker"); +/* fullname */ ATTRIB(WalkerTurret, turret_name, string, _("Walker Turret")); + ATTRIB(WalkerTurret, m_weapon, Weapon, WEP_WALKER); +ENDCLASS(WalkerTurret) +REGISTER_TURRET(WALKER, NEW(WalkerTurret)); + +#endif + +#ifdef IMPLEMENTATION + +#include "walker_weapon.qc" + +#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; + +const int ANIM_NO = 0; +const int ANIM_TURN = 1; +const int ANIM_WALK = 2; +const int ANIM_RUN = 3; +const int ANIM_STRAFE_L = 4; +const int ANIM_STRAFE_R = 5; +const int ANIM_JUMP = 6; +const int ANIM_LAND = 7; +const int ANIM_PAIN = 8; +const int ANIM_MELEE = 9; +const int ANIM_SWIM = 10; +const int 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; + } +} + +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)) remove(self); } ++spawnfunc(turret_walker) { if(!turret_initialize(TUR_WALKER)) remove(self); } + + METHOD(WalkerTurret, tr_think, void(WalkerTurret thistur)) + { + 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); + } + METHOD(WalkerTurret, tr_death, void(WalkerTurret this, entity it)) + { +#ifdef WALKER_FANCYPATHING + if (it.pathcurrent) + pathlib_deletepath(it.pathcurrent.owner); +#endif + it.pathcurrent = NULL; + } + METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it)) + { + it.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(it.movetype == MOVETYPE_WALK) + { + if(it.pos1) + setorigin(it, it.pos1); + if(it.pos2) + it.angles = it.pos2; + } + + it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE; + it.aim_flags = TFL_AIM_LEAD; + it.turret_flags |= TUR_FLAG_HITSCAN; + + it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; + it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS; + it.iscreature = true; + it.teleportable = TELEPORT_NORMAL; + it.damagedbycontents = true; + it.solid = SOLID_SLIDEBOX; + it.takedamage = DAMAGE_AIM; + if(it.movetype != MOVETYPE_WALK) + { + setorigin(it, it.origin); + tracebox(it.origin + '0 0 128', it.mins, it.maxs, it.origin - '0 0 10000', MOVE_NORMAL, it); + setorigin(it, trace_endpos + '0 0 4'); + it.pos1 = it.origin; + it.pos2 = it.angles; + } + it.movetype = MOVETYPE_WALK; + it.idle_aim = '0 0 0'; + it.turret_firecheckfunc = walker_firecheck; + + if (it.target != "") + { + e = find(world, targetname, it.target); + if (!e) + { + LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n"); + it.target = ""; + } + + if (e.classname != "turret_checkpoint") + LOG_TRACE("Warning: not a turrret path\n"); + else + { +#ifdef WALKER_FANCYPATHING + it.pathcurrent = WALKER_PATH(it.origin, e.origin); + it.pathgoal = e; +#else + it.pathcurrent = e; +#endif + } + } + } + +#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); +} + + METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it)) + { + it.gravity = 1; + it.movetype = MOVETYPE_BOUNCE; + it.move_movetype = MOVETYPE_BOUNCE; + it.move_origin = it.origin; + it.move_time = time; + it.draw = walker_draw; + } + +#endif // CSQC +#endif diff --cc qcsrc/common/vehicles/vehicle/bumblebee.qc index ee276f2b2,000000000..011fdf165 mode 100644,000000..100644 --- a/qcsrc/common/vehicles/vehicle/bumblebee.qc +++ b/qcsrc/common/vehicles/vehicle/bumblebee.qc @@@ -1,975 -1,0 +1,975 @@@ +#ifndef VEHICLE_BUMBLEBEE +#define VEHICLE_BUMBLEBEE +#include "bumblebee.qh" + +#include "bumblebee_weapons.qc" + +CLASS(Bumblebee, Vehicle) +/* spawnflags */ ATTRIB(Bumblebee, spawnflags, int, VHF_DMGSHAKE); +/* mins */ ATTRIB(Bumblebee, mins, vector, '-245 -130 -130'); +/* maxs */ ATTRIB(Bumblebee, maxs, vector, '230 130 130'); +/* model */ ATTRIB(Bumblebee, mdl, string, "models/vehicles/bumblebee_body.dpm"); +/* model */ ATTRIB(Bumblebee, model, string, "models/vehicles/bumblebee_body.dpm"); +/* head_model */ ATTRIB(Bumblebee, head_model, string, ""); +/* hud_model */ ATTRIB(Bumblebee, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm"); +/* tags */ ATTRIB(Bumblebee, tag_head, string, ""); +/* tags */ ATTRIB(Bumblebee, tag_hud, string, ""); +/* tags */ ATTRIB(Bumblebee, tag_view, string, "tag_viewport"); +/* netname */ ATTRIB(Bumblebee, netname, string, "bumblebee"); +/* fullname */ ATTRIB(Bumblebee, vehicle_name, string, _("Bumblebee")); +/* icon */ ATTRIB(Bumblebee, m_icon, string, "vehicle_bumble"); +ENDCLASS(Bumblebee) +REGISTER_VEHICLE(BUMBLEBEE, NEW(Bumblebee)); + +#endif + +#ifdef IMPLEMENTATION + +const float BRG_SETUP = 2; +const float BRG_START = 4; +const float BRG_END = 8; + +#include "bumblebee_weapons.qc" + +#ifdef SVQC +float autocvar_g_vehicle_bumblebee_speed_forward; +float autocvar_g_vehicle_bumblebee_speed_strafe; +float autocvar_g_vehicle_bumblebee_speed_up; +float autocvar_g_vehicle_bumblebee_speed_down; +float autocvar_g_vehicle_bumblebee_turnspeed; +float autocvar_g_vehicle_bumblebee_pitchspeed; +float autocvar_g_vehicle_bumblebee_pitchlimit; +float autocvar_g_vehicle_bumblebee_friction; + +float autocvar_g_vehicle_bumblebee_energy; +float autocvar_g_vehicle_bumblebee_energy_regen; +float autocvar_g_vehicle_bumblebee_energy_regen_pause; + +float autocvar_g_vehicle_bumblebee_health; +float autocvar_g_vehicle_bumblebee_health_regen; +float autocvar_g_vehicle_bumblebee_health_regen_pause; + +float autocvar_g_vehicle_bumblebee_shield; +float autocvar_g_vehicle_bumblebee_shield_regen; +float autocvar_g_vehicle_bumblebee_shield_regen_pause; + +float autocvar_g_vehicle_bumblebee_cannon_ammo; +float autocvar_g_vehicle_bumblebee_cannon_ammo_regen; +float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause; + +float autocvar_g_vehicle_bumblebee_cannon_lock = 0; + +float autocvar_g_vehicle_bumblebee_cannon_turnspeed; +float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down; +float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up; +float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in; +float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out; + + +float autocvar_g_vehicle_bumblebee_raygun_turnspeed; +float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down; +float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up; +float autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides; + +float autocvar_g_vehicle_bumblebee_raygun_range; +float autocvar_g_vehicle_bumblebee_raygun_dps; +float autocvar_g_vehicle_bumblebee_raygun_aps; +float autocvar_g_vehicle_bumblebee_raygun_fps; + +float autocvar_g_vehicle_bumblebee_raygun; +float autocvar_g_vehicle_bumblebee_healgun_hps; +float autocvar_g_vehicle_bumblebee_healgun_hmax; +float autocvar_g_vehicle_bumblebee_healgun_aps; +float autocvar_g_vehicle_bumblebee_healgun_amax; +float autocvar_g_vehicle_bumblebee_healgun_sps; +float autocvar_g_vehicle_bumblebee_healgun_locktime; + +float autocvar_g_vehicle_bumblebee_respawntime; + +float autocvar_g_vehicle_bumblebee_blowup_radius; +float autocvar_g_vehicle_bumblebee_blowup_coredamage; +float autocvar_g_vehicle_bumblebee_blowup_edgedamage; +float autocvar_g_vehicle_bumblebee_blowup_forceintensity; +vector autocvar_g_vehicle_bumblebee_bouncepain; + +bool autocvar_g_vehicle_bumblebee = 0; + +float bumblebee_gunner_frame() +{SELFPARAM(); + entity vehic = self.vehicle.owner; + entity gun = self.vehicle; + entity gunner = self; + setself(vehic); + + vehic.solid = SOLID_NOT; + //setorigin(gunner, vehic.origin); + gunner.velocity = vehic.velocity; + + float _in, _out; + vehic.angles_x *= -1; + makevectors(vehic.angles); + vehic.angles_x *= -1; + if(gun == vehic.gun1) + { + _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in; + _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out; + setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * 128); + } + else + { + _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out; + _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in; + setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128); + } + + crosshair_trace(gunner); + vector _ct = trace_endpos; + vector ad; + + if(autocvar_g_vehicle_bumblebee_cannon_lock) + { + if(gun.lock_time < time) + gun.enemy = world; + + if(trace_ent) + if(trace_ent.movetype) + if(trace_ent.takedamage) + if(!trace_ent.deadflag) + { + if(DIFF_TEAM(trace_ent, gunner)) + { + gun.enemy = trace_ent; + gun.lock_time = time + 5; + } + } + } + + if(gun.enemy) + { + float distance, impact_time; + + vector vf = real_origin(gun.enemy); + vector _vel = gun.enemy.velocity; + if(gun.enemy.movetype == MOVETYPE_WALK) + _vel.z *= 0.1; + + + ad = vf; + distance = vlen(ad - gunner.origin); + impact_time = distance / autocvar_g_vehicle_bumblebee_cannon_speed; + ad = vf + _vel * impact_time; + trace_endpos = ad; + + + UpdateAuxiliaryXhair(gunner, ad, '1 0 1', 1); + vehicle_aimturret(vehic, trace_endpos, gun, "fire", + autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up, + _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed); + + } + else + vehicle_aimturret(vehic, _ct, gun, "fire", + autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up, + _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed); + + if(!forbidWeaponUse(gunner)) + if(gunner.BUTTON_ATCK) + if(time > gun.attack_finished_single) + if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost) + { + gun.vehicle_energy -= autocvar_g_vehicle_bumblebee_cannon_cost; + bumblebee_fire_cannon(gun, "fire", gunner); + gun.delay = time; + gun.attack_finished_single = time + autocvar_g_vehicle_bumblebee_cannon_refire; + } + + VEHICLE_UPDATE_PLAYER(gunner, health, bumblebee); + + if(vehic.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(gunner, shield, bumblebee); + + ad = gettaginfo(gun, gettagindex(gun, "fire")); + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, gun); + + UpdateAuxiliaryXhair(gunner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), 0); + + if(vehic.owner) + UpdateAuxiliaryXhair(vehic.owner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), ((gunner == vehic.gunner1) ? 1 : 2)); + + vehic.solid = SOLID_BBOX; + gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0; + gunner.vehicle_energy = (gun.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100; + + setself(gunner); + return 1; +} + +vector bumblebee_gunner_findgoodexit(vector prefer_spot, entity gunner, entity player) +{ + //vector exitspot; + float mysize; + + tracebox(gunner.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, player); + if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) + return prefer_spot; + + mysize = 1.5 * vlen(PL_MAX - PL_MIN); // can't use gunner's size, as they don't have a size + float i; + vector v, v2; + v2 = 0.5 * (gunner.absmin + gunner.absmax); + for(i = 0; i < 100; ++i) + { + v = randomvec(); + v_z = 0; + v = v2 + normalize(v) * mysize; + tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, player); + if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) + return v; + } + + return prefer_spot; // this should be considered a fallback?! +} + +void bumblebee_gunner_exit(int _exitflag) +{SELFPARAM(); + entity player = self; + entity gunner = player.vehicle; + entity vehic = gunner.owner; + + if(IS_REAL_CLIENT(player)) + { + msg_entity = player; + WriteByte(MSG_ONE, SVC_SETVIEWPORT); + WriteEntity(MSG_ONE, player); + + WriteByte(MSG_ONE, SVC_SETVIEWANGLES); + WriteAngle(MSG_ONE, 0); + WriteAngle(MSG_ONE, vehic.angles.y); + WriteAngle(MSG_ONE, 0); + } + + CSQCVehicleSetup(player, HUD_NORMAL); + setsize(player, PL_MIN, PL_MAX); + + player.takedamage = DAMAGE_AIM; + player.solid = SOLID_SLIDEBOX; + player.movetype = MOVETYPE_WALK; + player.effects &= ~EF_NODRAW; + player.alpha = 1; + player.PlayerPhysplug = func_null; + player.view_ofs = PL_VIEW_OFS; + player.event_damage = PlayerDamage; + player.hud = HUD_NORMAL; + player.teleportable = TELEPORT_NORMAL; + player.switchweapon = gunner.switchweapon; + player.vehicle_enter_delay = time + 2; + + fixedmakevectors(vehic.angles); + + if(player == vehic.gunner1) { vehic.gunner1 = world; } + if(player == vehic.gunner2) { vehic.gunner2 = world; v_right *= -1; } + + vector spot = real_origin(gunner); + spot = spot + v_up * 128 + v_forward * 300 + v_right * 150; + spot = bumblebee_gunner_findgoodexit(spot, gunner, player); + + // TODO: figure a way to move player out of the gunner + + player.velocity = 0.75 * vehic.velocity + normalize(spot - vehic.origin) * 200; + player.velocity_z += 10; + + gunner.phase = time + 5; + gunner.vehicle_hudmodel.viewmodelforclient = gunner; + + MUTATOR_CALLHOOK(VehicleExit, player, gunner); + + player.vehicle = world; +} + +bool bumblebee_gunner_enter() +{SELFPARAM(); + entity vehic = self; + entity player = other; + entity gunner = world; + + if(!vehic.gunner1 && !vehic.gunner2 && ((time >= vehic.gun1.phase) + (time >= vehic.gun2.phase)) == 2) + { + // we can have some fun + if(vlen(real_origin(vehic.gun2) - player.origin) < vlen(real_origin(vehic.gun1) - player.origin)) + { + gunner = vehic.gun2; + vehic.gunner2 = player; + } + else + { + gunner = vehic.gun1; + vehic.gunner1 = player; + } + } + else if(!vehic.gunner1 && time >= vehic.gun1.phase) { gunner = vehic.gun1; vehic.gunner1 = player; } + else if(!vehic.gunner2 && time >= vehic.gun2.phase) { gunner = vehic.gun2; vehic.gunner2 = player; } + else { LOG_TRACE("Vehicle is full, fail\n"); return false; } + + player.vehicle = gunner; + player.angles = vehic.angles; + player.takedamage = DAMAGE_NO; + player.solid = SOLID_NOT; + player.alpha = -1; + player.movetype = MOVETYPE_NOCLIP; + player.event_damage = func_null; + player.view_ofs = '0 0 0'; + player.hud = gunner.hud; + player.teleportable = false; + player.PlayerPhysplug = gunner.PlayerPhysplug; + player.vehicle_ammo1 = vehic.vehicle_ammo1; + player.vehicle_ammo2 = vehic.vehicle_ammo2; + player.vehicle_reload1 = vehic.vehicle_reload1; + player.vehicle_reload2 = vehic.vehicle_reload2; + player.vehicle_energy = vehic.vehicle_energy; + player.flags &= ~FL_ONGROUND; + + RemoveGrapplingHook(player); + + gunner.switchweapon = player.switchweapon; + gunner.vehicle_exit = bumblebee_gunner_exit; + gunner.vehicle_hudmodel.viewmodelforclient = player; + + if(IS_REAL_CLIENT(player)) + { + msg_entity = player; + WriteByte(MSG_ONE, SVC_SETVIEWPORT); + WriteEntity(MSG_ONE, gunner.vehicle_viewport); + + WriteByte(MSG_ONE, SVC_SETVIEWANGLES); + WriteAngle(MSG_ONE, gunner.angles_x + vehic.angles_x); // tilt + WriteAngle(MSG_ONE, gunner.angles_y + vehic.angles_y); // yaw + WriteAngle(MSG_ONE, 0); // roll + } + + CSQCVehicleSetup(player, player.hud); + + MUTATOR_CALLHOOK(VehicleEnter, player, gunner); + + return true; +} + +bool vehicles_valid_pilot() +{SELFPARAM(); + if(IS_BOT_CLIENT(other) && !autocvar_g_vehicles_allow_bots) + return false; + + if((!IS_PLAYER(other)) + || (other.deadflag != DEAD_NO) + || (other.vehicle) + || (DIFF_TEAM(other, self)) + ) { return false; } + + return true; +} + +void bumblebee_touch() +{SELFPARAM(); + if(autocvar_g_vehicles_enter) { return; } + + if(self.gunner1 != world && self.gunner2 != world) + { + vehicles_touch(); + return; + } + + if(vehicles_valid_pilot()) + { + float phase_time = (time >= self.gun1.phase) + (time >= self.gun2.phase); + + if(time >= other.vehicle_enter_delay && phase_time) + if(bumblebee_gunner_enter()) + return; + } + + vehicles_touch(); +} + +void bumblebee_regen() +{SELFPARAM(); + if(self.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time) + self.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo, + self.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime); + + if(self.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time) + self.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo, + self.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime); + + if(self.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(self.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, true); + + if(self.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(self.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, false); + + if(self.vehicle_flags & VHF_ENERGYREGEN) + vehicles_regen(self.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, false); + +} + +float bumblebee_pilot_frame() +{SELFPARAM(); + entity pilot, vehic; + vector newvel; + + if(intermission_running) + { + self.vehicle.velocity = '0 0 0'; + self.vehicle.avelocity = '0 0 0'; + return 1; + } + + pilot = self; + vehic = self.vehicle; + setself(vehic); + + if(vehic.deadflag != DEAD_NO) + { + setself(pilot); + pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0; + return 1; + } + + bumblebee_regen(); + + crosshair_trace(pilot); + + vector vang; + float ftmp; + + vang = vehic.angles; + newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32')); + vang.x *= -1; + newvel.x *= -1; + if(newvel.x > 180) newvel.x -= 360; + if(newvel.x < -180) newvel.x += 360; + if(newvel.y > 180) newvel.y -= 360; + if(newvel.y < -180) newvel.y += 360; + + ftmp = shortangle_f(pilot.v_angle.y - vang.y, vang.y); + if(ftmp > 180) ftmp -= 360; + if(ftmp < -180) ftmp += 360; + vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity.y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed); + + // Pitch + ftmp = 0; + if(pilot.movement.x > 0 && vang.x < autocvar_g_vehicle_bumblebee_pitchlimit) + ftmp = 4; + else if(pilot.movement.x < 0 && vang.x > -autocvar_g_vehicle_bumblebee_pitchlimit) + ftmp = -8; + + newvel.x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x , autocvar_g_vehicle_bumblebee_pitchlimit); + ftmp = vang.x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit); + vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity.x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed); + + vehic.angles_x = anglemods(vehic.angles.x); + vehic.angles_y = anglemods(vehic.angles.y); + vehic.angles_z = anglemods(vehic.angles.z); + + makevectors('0 1 0' * vehic.angles.y); + newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction; + + if(pilot.movement.x != 0) + { + if(pilot.movement.x > 0) + newvel += v_forward * autocvar_g_vehicle_bumblebee_speed_forward; + else if(pilot.movement.x < 0) + newvel -= v_forward * autocvar_g_vehicle_bumblebee_speed_forward; + } + + if(pilot.movement.y != 0) + { + if(pilot.movement.y < 0) + newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe; + else if(pilot.movement.y > 0) + newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe; + ftmp = newvel * v_right; + ftmp *= frametime * 0.1; + vehic.angles_z = bound(-15, vehic.angles.z + ftmp, 15); + } + else + { + vehic.angles_z *= 0.95; + if(vehic.angles.z >= -1 && vehic.angles.z <= -1) + vehic.angles_z = 0; + } + + if(pilot.BUTTON_CROUCH) + newvel -= v_up * autocvar_g_vehicle_bumblebee_speed_down; + else if(pilot.BUTTON_JUMP) + newvel += v_up * autocvar_g_vehicle_bumblebee_speed_up; + + vehic.velocity += newvel * frametime; + pilot.velocity = pilot.movement = vehic.velocity; + + + if(autocvar_g_vehicle_bumblebee_healgun_locktime) + { + if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag) + vehic.tur_head.enemy = world; + + if(trace_ent) + if(trace_ent.movetype) + if(trace_ent.takedamage) + if(!trace_ent.deadflag) + { + if(teamplay) + { + if(trace_ent.team == pilot.team) + { + vehic.tur_head.enemy = trace_ent; + vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime; + } + } + else + { + vehic.tur_head.enemy = trace_ent; + vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime; + } + } + + if(vehic.tur_head.enemy) + { + trace_endpos = real_origin(vehic.tur_head.enemy); + UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0); + } + } + + vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire", + autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up, + autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1, autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides, autocvar_g_vehicle_bumblebee_raygun_turnspeed); + + if(!forbidWeaponUse(pilot)) + if((pilot.BUTTON_ATCK || pilot.BUTTON_ATCK2) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0)) + { + vehic.gun3.enemy.realowner = pilot; + vehic.gun3.enemy.effects &= ~EF_NODRAW; + + vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire")); + vehic.gun3.enemy.SendFlags |= BRG_START; + + traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic); + + if(trace_ent) + { + if(autocvar_g_vehicle_bumblebee_raygun) + { + Damage(trace_ent, vehic, pilot, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime); + vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime; + } + else + { + if(trace_ent.deadflag == DEAD_NO) + if((teamplay && trace_ent.team == pilot.team) || !teamplay) + { + + if(trace_ent.vehicle_flags & VHF_ISVEHICLE) + { + if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.max_health) + trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * frametime, trace_ent.tur_head.max_health); + + if(autocvar_g_vehicle_bumblebee_healgun_hps) + trace_ent.vehicle_health = min(trace_ent.vehicle_health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health); + } + else if(IS_CLIENT(trace_ent)) + { + if(trace_ent.health <= autocvar_g_vehicle_bumblebee_healgun_hmax && autocvar_g_vehicle_bumblebee_healgun_hps) + trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax); + + if(trace_ent.armorvalue <= autocvar_g_vehicle_bumblebee_healgun_amax && autocvar_g_vehicle_bumblebee_healgun_aps) + trace_ent.armorvalue = min(trace_ent.armorvalue + autocvar_g_vehicle_bumblebee_healgun_aps * frametime, autocvar_g_vehicle_bumblebee_healgun_amax); + + trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax); + } + else if(IS_TURRET(trace_ent)) + { + if(trace_ent.health <= trace_ent.max_health && autocvar_g_vehicle_bumblebee_healgun_hps) + trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health); + //else ..hmmm what? ammo? + + trace_ent.SendFlags |= TNSF_STATUS; + } + } + } + } + + vehic.gun3.enemy.hook_end = trace_endpos; + setorigin(vehic.gun3.enemy, trace_endpos); + vehic.gun3.enemy.SendFlags |= BRG_END; + + vehic.wait = time + 1; + } + else + vehic.gun3.enemy.effects |= EF_NODRAW; + /*{ + if(vehic.gun3.enemy) + remove(vehic.gun3.enemy); + + vehic.gun3.enemy = world; + } + */ + + VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee); + VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee); + + pilot.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100; + pilot.vehicle_ammo2 = (vehic.gun2.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100; + + if(vehic.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee); + + vehic.angles_x *= -1; + makevectors(vehic.angles); + vehic.angles_x *= -1; + setorigin(pilot, vehic.origin + v_up * 48 + v_forward * 160); + + pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0; + setself(pilot); + + return 1; +} + +void bumblebee_land() +{SELFPARAM(); + float hgt; + + hgt = raptor_altitude(512); + self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime); + self.angles_x *= 0.95; + self.angles_z *= 0.95; + + if(hgt < 16) + self.think = vehicles_think; + + self.nextthink = time; + + CSQCMODEL_AUTOUPDATE(self); +} + +void bumblebee_exit(float eject) +{SELFPARAM(); + if(self.owner.vehicleid == VEH_BUMBLEBEE.vehicleid) + { + bumblebee_gunner_exit(eject); + return; + } + + self.touch = vehicles_touch; + + if(self.deadflag == DEAD_NO) + { + self.think = bumblebee_land; + self.nextthink = time; + } + + self.movetype = MOVETYPE_TOSS; + + if(!self.owner) + return; + + fixedmakevectors(self.angles); + vector spot; + if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5) + spot = self.origin + v_up * 128 + v_forward * 300; + else + spot = self.origin + v_up * 128 - v_forward * 300; + + spot = vehicles_findgoodexit(spot); + + // Hide beam + if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) { + self.gun3.enemy.effects |= EF_NODRAW; + } + + self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200; + self.owner.velocity_z += 10; + setorigin(self.owner, spot); + + antilag_clear(self.owner); + self.owner = world; +} + +void bumblebee_blowup() +{SELFPARAM(); + RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage, + autocvar_g_vehicle_bumblebee_blowup_edgedamage, + autocvar_g_vehicle_bumblebee_blowup_radius, self, world, + autocvar_g_vehicle_bumblebee_blowup_forceintensity, + DEATH_VH_BUMB_DEATH, world); + + sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM); + Send_Effect(EFFECT_EXPLOSION_BIG, (self.origin + '0 0 100') + (randomvec() * 80), '0 0 0', 1); + + if(self.owner.deadflag == DEAD_DYING) + self.owner.deadflag = DEAD_DEAD; + + remove(self); +} + +void bumblebee_diethink() +{SELFPARAM(); + if(time >= self.wait) + self.think = bumblebee_blowup; + + if(random() < 0.1) + { + sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM); + Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1); + } + + self.nextthink = time + 0.1; +} + - void spawnfunc_vehicle_bumblebee() - {SELFPARAM(); ++spawnfunc(vehicle_bumblebee) ++{ + if(!autocvar_g_vehicle_bumblebee) { remove(self); return; } + if(!vehicle_initialize(VEH_BUMBLEBEE, false)) { remove(self); return; } +} + + METHOD(Bumblebee, vr_impact, void(Bumblebee thisveh)) + { + if(autocvar_g_vehicle_bumblebee_bouncepain) + vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z); + } + METHOD(Bumblebee, vr_enter, void(Bumblebee thisveh)) + { + SELFPARAM(); + self.touch = bumblebee_touch; + self.nextthink = 0; + self.movetype = MOVETYPE_BOUNCEMISSILE; + } + METHOD(Bumblebee, vr_think, void(Bumblebee thisveh)) + { + SELFPARAM(); + self.angles_z *= 0.8; + self.angles_x *= 0.8; + + self.nextthink = time; + + if(!self.owner) + { + entity oldself = self; + if(self.gunner1) + { + setself(self.gunner1); + oldself.gun1.vehicle_exit(VHEF_EJECT); + entity oldother = other; + other = self; + setself(oldself); + self.phase = 0; + self.touch(); + other = oldother; + return; + } + + if(self.gunner2) + { + setself(self.gunner2); + oldself.gun2.vehicle_exit(VHEF_EJECT); + entity oldother = other; + other = self; + setself(oldself); + self.phase = 0; + self.touch(); + other = oldother; + return; + } + } + } + METHOD(Bumblebee, vr_death, void(Bumblebee thisveh)) + { + SELFPARAM(); + entity oldself = self; + + CSQCModel_UnlinkEntity(); + + // Hide beam + if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) + self.gun3.enemy.effects |= EF_NODRAW; + + if(self.gunner1) + { + setself(self.gunner1); + oldself.gun1.vehicle_exit(VHEF_EJECT); + setself(oldself); + } + + if(self.gunner2) + { + setself(self.gunner2); + oldself.gun2.vehicle_exit(VHEF_EJECT); + setself(oldself); + } + + self.vehicle_exit(VHEF_EJECT); + + fixedmakevectors(self.angles); + vehicle_tossgib(self.gun1, self.velocity + v_right * 300 + v_up * 100 + randomvec() * 200, "cannon_right", rint(random()), rint(random()), 6, randomvec() * 200); + vehicle_tossgib(self.gun2, self.velocity + v_right * -300 + v_up * 100 + randomvec() * 200, "cannon_left", rint(random()), rint(random()), 6, randomvec() * 200); + vehicle_tossgib(self.gun3, self.velocity + v_forward * 300 + v_up * -100 + randomvec() * 200, "raygun", rint(random()), rint(random()), 6, randomvec() * 300); + + entity _body = vehicle_tossgib(self, self.velocity + randomvec() * 200, "", rint(random()), rint(random()), 6, randomvec() * 100); + + if(random() > 0.5) + _body.touch = bumblebee_blowup; + else + _body.touch = func_null; + + _body.think = bumblebee_diethink; + _body.nextthink = time; + _body.wait = time + 2 + (random() * 8); + _body.owner = self; + _body.enemy = self.enemy; + _body.scale = 1.5; + _body.angles = self.angles; + + Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation(self.origin, 16), '0 0 0', 1); + + self.health = 0; + self.event_damage = func_null; + self.solid = SOLID_NOT; + self.takedamage = DAMAGE_NO; + self.deadflag = DEAD_DYING; + self.movetype = MOVETYPE_NONE; + self.effects = EF_NODRAW; + self.colormod = '0 0 0'; + self.avelocity = '0 0 0'; + self.velocity = '0 0 0'; + self.touch = func_null; + self.nextthink = 0; + + setorigin(self, self.pos1); + } + METHOD(Bumblebee, vr_spawn, void(Bumblebee thisveh)) + { + SELFPARAM(); + if(!self.gun1) + { + // for some reason, autosizing of the shield entity refuses to work for this one so set it up in advance. + self.vehicle_shieldent = spawn(); + self.vehicle_shieldent.effects = EF_LOWPRECISION; + setmodel(self.vehicle_shieldent, MDL_VEH_BUMBLEBEE_SHIELD); + setattachment(self.vehicle_shieldent, self, ""); + setorigin(self.vehicle_shieldent, real_origin(self) - self.origin); + self.vehicle_shieldent.scale = 512 / vlen(self.maxs - self.mins); + self.vehicle_shieldent.think = shieldhit_think; + self.vehicle_shieldent.alpha = -1; + self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW; + + self.gun1 = spawn(); + self.gun2 = spawn(); + self.gun3 = spawn(); + + self.vehicle_flags |= VHF_MULTISLOT; + + self.gun1.owner = self; + self.gun2.owner = self; + self.gun3.owner = self; + + self.gun1.classname = self.gun2.classname = "vehicle_playerslot"; + + setmodel(self.gun1, MDL_VEH_BUMBLEBEE_CANNON_RIGHT); + setmodel(self.gun2, MDL_VEH_BUMBLEBEE_CANNON_LEFT); + setmodel(self.gun3, MDL_VEH_BUMBLEBEE_CANNON_CENTER); + + setattachment(self.gun1, self, "cannon_right"); + setattachment(self.gun2, self, "cannon_left"); + + // Angled bones are no fun, messes up gun-aim; so work arround it. + self.gun3.pos1 = self.angles; + self.angles = '0 0 0'; + vector ofs = gettaginfo(self, gettagindex(self, "raygun")); + ofs -= self.origin; + setattachment(self.gun3, self, ""); + setorigin(self.gun3, ofs); + self.angles = self.gun3.pos1; + + vehicle_addplayerslot(self, self.gun1, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter); + vehicle_addplayerslot(self, self.gun2, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter); + + setorigin(self.vehicle_hudmodel, '50 0 -5'); // Move cockpit forward - down. + setorigin(self.vehicle_viewport, '5 0 2'); // Move camera forward up + + //fixme-model-bones + setorigin(self.gun1.vehicle_hudmodel, '90 -27 -23'); + setorigin(self.gun1.vehicle_viewport, '-85 0 50'); + //fixme-model-bones + setorigin(self.gun2.vehicle_hudmodel, '90 27 -23'); + setorigin(self.gun2.vehicle_viewport, '-85 0 50'); + + self.scale = 1.5; + + // Raygun beam + if(self.gun3.enemy == world) + { + self.gun3.enemy = spawn(); + Net_LinkEntity(self.gun3.enemy, true, 0, bumble_raygun_send); + self.gun3.enemy.SendFlags = BRG_SETUP; + self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun; + self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION; + } + } + + self.vehicle_health = autocvar_g_vehicle_bumblebee_health; + self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield; + self.solid = SOLID_BBOX; + self.movetype = MOVETYPE_TOSS; + self.damageforcescale = 0.025; + + self.PlayerPhysplug = bumblebee_pilot_frame; + + setorigin(self, self.origin + '0 0 25'); + } + METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh)) + { + SELFPARAM(); + if(autocvar_g_vehicle_bumblebee_energy) + if(autocvar_g_vehicle_bumblebee_energy_regen) + self.vehicle_flags |= VHF_ENERGYREGEN; + + if(autocvar_g_vehicle_bumblebee_shield) + self.vehicle_flags |= VHF_HASSHIELD; + + if(autocvar_g_vehicle_bumblebee_shield_regen) + self.vehicle_flags |= VHF_SHIELDREGEN; + + if(autocvar_g_vehicle_bumblebee_health_regen) + self.vehicle_flags |= VHF_HEALTHREGEN; + + self.vehicle_exit = bumblebee_exit; + self.respawntime = autocvar_g_vehicle_bumblebee_respawntime; + self.vehicle_health = autocvar_g_vehicle_bumblebee_health; + self.max_health = self.vehicle_health; + self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield; + } + +#endif // SVQC +#ifdef CSQC + +void CSQC_BUMBLE_GUN_HUD() +{ + Vehicles_drawHUD("vehicle_gunner", "vehicle_gunner_weapon1", string_null, + "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, + string_null, '0 0 0', + string_null); +} + + METHOD(Bumblebee, vr_hud, void(Bumblebee thisveh)) + { + Vehicles_drawHUD(VEH_BUMBLEBEE.m_icon, "vehicle_bumble_weapon1", "vehicle_bumble_weapon2", + "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, + "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, + vCROSS_HEAL); + } + METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh)) + { + AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Raygun-locked + AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1 + AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2 + } + +#endif +#endif diff --cc qcsrc/common/vehicles/vehicle/racer.qc index e9211d545,000000000..b5501806c mode 100644,000000..100644 --- a/qcsrc/common/vehicles/vehicle/racer.qc +++ b/qcsrc/common/vehicles/vehicle/racer.qc @@@ -1,693 -1,0 +1,693 @@@ +#ifndef VEHICLE_RACER +#define VEHICLE_RACER + +#include "racer_weapon.qc" + +CLASS(Racer, Vehicle) +/* spawnflags */ ATTRIB(Racer, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL); +/* mins */ ATTRIB(Racer, mins, vector, '-120 -120 -40' * 0.5); +/* maxs */ ATTRIB(Racer, maxs, vector, '120 120 40' * 0.5); +/* model */ ATTRIB(Racer, mdl, string, "models/vehicles/wakizashi.dpm"); +/* model */ ATTRIB(Racer, model, string, "models/vehicles/wakizashi.dpm"); +/* head_model */ ATTRIB(Racer, head_model, string, "null"); +/* hud_model */ ATTRIB(Racer, hud_model, string, "models/vehicles/wakizashi_cockpit.dpm"); +/* tags */ ATTRIB(Racer, tag_head, string, ""); +/* tags */ ATTRIB(Racer, tag_hud, string, ""); +/* tags */ ATTRIB(Racer, tag_view, string, "tag_viewport"); +/* netname */ ATTRIB(Racer, netname, string, "racer"); +/* fullname */ ATTRIB(Racer, vehicle_name, string, _("Racer")); +/* icon */ ATTRIB(Racer, m_icon, string, "vehicle_racer"); +ENDCLASS(Racer) +REGISTER_VEHICLE(RACER, NEW(Racer)); + +#endif + +#ifdef IMPLEMENTATION + +#include "racer_weapon.qc" + +#ifdef SVQC +#include "../../effects/effects.qh" +#include "../../triggers/trigger/impulse.qh" + +bool autocvar_g_vehicle_racer; + +float autocvar_g_vehicle_racer_speed_afterburn; +float autocvar_g_vehicle_racer_afterburn_cost; + +float autocvar_g_vehicle_racer_waterburn_cost; +float autocvar_g_vehicle_racer_waterburn_speed; + +float autocvar_g_vehicle_racer_water_speed_forward; +float autocvar_g_vehicle_racer_water_speed_strafe; + +float autocvar_g_vehicle_racer_pitchlimit = 30; + +float autocvar_g_vehicle_racer_water_downforce = 0.03; +float autocvar_g_vehicle_racer_water_upforcedamper = 15; + +float autocvar_g_vehicle_racer_anglestabilizer; +float autocvar_g_vehicle_racer_downforce; + +float autocvar_g_vehicle_racer_speed_forward; +float autocvar_g_vehicle_racer_speed_strafe; +float autocvar_g_vehicle_racer_springlength; +float autocvar_g_vehicle_racer_upforcedamper; +float autocvar_g_vehicle_racer_friction; + +float autocvar_g_vehicle_racer_water_time = 5; + +float autocvar_g_vehicle_racer_hovertype; +float autocvar_g_vehicle_racer_hoverpower; + +float autocvar_g_vehicle_racer_turnroll; +float autocvar_g_vehicle_racer_turnspeed; +float autocvar_g_vehicle_racer_pitchspeed; + +float autocvar_g_vehicle_racer_energy; +float autocvar_g_vehicle_racer_energy_regen; +float autocvar_g_vehicle_racer_energy_regen_pause; + +float autocvar_g_vehicle_racer_health; +float autocvar_g_vehicle_racer_health_regen; +float autocvar_g_vehicle_racer_health_regen_pause; + +float autocvar_g_vehicle_racer_shield; +float autocvar_g_vehicle_racer_shield_regen; +float autocvar_g_vehicle_racer_shield_regen_pause; + +float autocvar_g_vehicle_racer_rocket_locktarget; +float autocvar_g_vehicle_racer_rocket_locking_time; +float autocvar_g_vehicle_racer_rocket_locking_releasetime; +float autocvar_g_vehicle_racer_rocket_locked_time; + +float autocvar_g_vehicle_racer_respawntime; + +float autocvar_g_vehicle_racer_blowup_radius; +float autocvar_g_vehicle_racer_blowup_coredamage; +float autocvar_g_vehicle_racer_blowup_edgedamage; +float autocvar_g_vehicle_racer_blowup_forceintensity; + +float autocvar_g_vehicle_racer_bouncefactor; +float autocvar_g_vehicle_racer_bouncestop; +vector autocvar_g_vehicle_racer_bouncepain; + +.float racer_watertime; + +var vector racer_force_from_tag(string tag_name, float spring_length, float max_power); + +void racer_align4point(float _delta) +{SELFPARAM(); + vector push_vector; + float fl_push, fr_push, bl_push, br_push; + + push_vector = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower); + fr_push = force_fromtag_normpower; + //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier); + + push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower); + fl_push = force_fromtag_normpower; + //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier); + + push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower); + br_push = force_fromtag_normpower; + //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier); + + push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower); + bl_push = force_fromtag_normpower; + //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier); + + self.velocity += push_vector * _delta; + + float uforce = autocvar_g_vehicle_racer_upforcedamper; + + int cont = pointcontents(self.origin - '0 0 64'); + if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME) + { + uforce = autocvar_g_vehicle_racer_water_upforcedamper; + + if(self.owner.BUTTON_CROUCH && time < self.air_finished) + self.velocity_z += 30; + else + self.velocity_z += 200; + } + + + // Anti ocilation + if(self.velocity_z > 0) + self.velocity_z *= 1 - uforce * _delta; + + push_vector_x = (fl_push - bl_push); + push_vector_x += (fr_push - br_push); + push_vector_x *= 360; + + push_vector_z = (fr_push - fl_push); + push_vector_z += (br_push - bl_push); + push_vector_z *= 360; + + // Apply angle diffrance + self.angles_z += push_vector_z * _delta; + self.angles_x += push_vector_x * _delta; + + // Apply stabilizer + self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta); + self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta); +} + +void racer_fire_rocket_aim(string tagname, entity trg) +{ + SELFPARAM(); + vector v = gettaginfo(self, gettagindex(self, tagname)); + racer_fire_rocket(v, v_forward, trg); +} + +float racer_frame() +{SELFPARAM(); + entity player, racer; + vector df; + float ftmp; + + if(intermission_running) + { + self.vehicle.velocity = '0 0 0'; + self.vehicle.avelocity = '0 0 0'; + return 1; + } + + player = self; + racer = self.vehicle; + setself(racer); + + vehicles_painframe(); + + if(pointcontents(racer.origin) != CONTENT_WATER) + racer.air_finished = time + autocvar_g_vehicle_racer_water_time; + + if(racer.deadflag != DEAD_NO) + { + setself(player); + player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; + return 1; + } + + racer_align4point(PHYS_INPUT_TIMELENGTH); + + player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0; + + crosshair_trace(player); + + racer.angles_x *= -1; + + // Yaw + ftmp = autocvar_g_vehicle_racer_turnspeed * PHYS_INPUT_TIMELENGTH; + ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp); + racer.angles_y = anglemods(racer.angles_y + ftmp); + + // Roll + racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * PHYS_INPUT_TIMELENGTH; + + // Pitch + ftmp = autocvar_g_vehicle_racer_pitchspeed * PHYS_INPUT_TIMELENGTH; + ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp); + racer.angles_x = bound(-autocvar_g_vehicle_racer_pitchlimit, anglemods(racer.angles_x + ftmp), autocvar_g_vehicle_racer_pitchlimit); + + makevectors(racer.angles); + racer.angles_x *= -1; + + //ftmp = racer.velocity_z; + df = racer.velocity * -autocvar_g_vehicle_racer_friction; + //racer.velocity_z = ftmp; + + int cont = pointcontents(racer.origin); + if(vlen(player.movement) != 0) + { + if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME) + { + if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_water_speed_forward : -autocvar_g_vehicle_racer_water_speed_forward); } + if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_water_speed_strafe : -autocvar_g_vehicle_racer_water_speed_strafe); } + } + else + { + if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward); } + if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe); } + } + +#ifdef SVQC + if(self.sound_nexttime < time || self.sounds != 1) + { + self.sounds = 1; + self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav"); + sound (self, CH_TRIGGER_SINGLE, SND_VEH_RACER_MOVE, VOL_VEHICLEENGINE, ATTEN_NORM); + } +#endif + } +#ifdef SVQC + else + { + if(self.sound_nexttime < time || self.sounds != 0) + { + self.sounds = 0; + self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav"); + sound (self, CH_TRIGGER_SINGLE, SND_VEH_RACER_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM); + } + } +#endif + + // Afterburn + if (PHYS_INPUT_BUTTON_JUMP(player) && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH)) + { +#ifdef SVQC + if(time - racer.wait > 0.2) + pointparticles(particleeffectnum(EFFECT_RACER_BOOSTER), self.origin - v_forward * 32, v_forward * vlen(self.velocity), 1); +#endif + + racer.wait = time; + + if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME) + { + racer.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH; + df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed); + } + else + { + racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH; + df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn); + } + +#ifdef SVQC + if(racer.invincible_finished < time) + { + traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self); + if(trace_fraction != 1.0) + pointparticles(particleeffectnum(EFFECT_SMOKE_SMALL), trace_endpos, '0 0 0', 1); + + racer.invincible_finished = time + 0.1 + (random() * 0.1); + } + + if(racer.strength_finished < time) + { + racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav"); + sound (racer.tur_head, CH_TRIGGER_SINGLE, SND_VEH_RACER_BOOST, VOL_VEHICLEENGINE, ATTEN_NORM); + } +#endif + } + else + { + racer.strength_finished = 0; + sound (racer.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM); + } + + if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME) + racer.racer_watertime = time; + + float dforce = autocvar_g_vehicle_racer_downforce; + if(time - racer.racer_watertime <= 3) + dforce = autocvar_g_vehicle_racer_water_downforce; + + df -= v_up * (vlen(racer.velocity) * dforce); + player.movement = racer.velocity += df * PHYS_INPUT_TIMELENGTH; + +#ifdef SVQC + Weapon wep1 = WEP_RACER; + if (!forbidWeaponUse(player)) + if (player.BUTTON_ATCK) + if (wep1.wr_checkammo1(wep1)) + { + string tagname = (racer.cnt) + ? (racer.cnt = 0, "tag_fire1") + : (racer.cnt = 1, "tag_fire2"); + vector org = gettaginfo(self, gettagindex(self, tagname)); + w_shotorg = org; + w_shotdir = v_forward; + // Fix z-aim (for chase mode) + crosshair_trace(player); + w_shotdir.z = normalize(trace_endpos - org).z * 0.5; + wep1.wr_think(wep1, self, true, false); + } + + if(autocvar_g_vehicle_racer_rocket_locktarget) + { + vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime, + (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime, + autocvar_g_vehicle_racer_rocket_locked_time); + + if(self.lock_target) + { + if(racer.lock_strength == 1) + UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0); + else if(self.lock_strength > 0.5) + UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0); + else if(self.lock_strength < 0.5) + UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0); + } + } + + if(!forbidWeaponUse(player)) + if(time > racer.delay) + if(player.BUTTON_ATCK2) + { + racer.misc_bulletcounter += 1; + racer.delay = time + 0.3; + + if(racer.misc_bulletcounter == 1) + { + racer_fire_rocket_aim("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world); + player.vehicle_ammo2 = 50; + } + else if(racer.misc_bulletcounter == 2) + { + racer_fire_rocket_aim("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world); + racer.lock_strength = 0; + racer.lock_target = world; + racer.misc_bulletcounter = 0; + racer.delay = time + autocvar_g_vehicle_racer_rocket_refire; + racer.lip = time; + player.vehicle_ammo2 = 0; + } + } + else if(racer.misc_bulletcounter == 0) + player.vehicle_ammo2 = 100; + + player.vehicle_reload2 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100); + + if(racer.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(racer.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, true); + + if(racer.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(racer.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, false); + + if(racer.vehicle_flags & VHF_ENERGYREGEN) + vehicles_regen(racer.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, false); + + + VEHICLE_UPDATE_PLAYER(player, health, racer); + VEHICLE_UPDATE_PLAYER(player, energy, racer); + + if(racer.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(player, shield, racer); + + player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; +#endif + + setorigin(player,racer.origin + '0 0 32'); + player.velocity = racer.velocity; + + setself(player); + return 1; +} + +void racer_think() +{SELFPARAM(); + self.nextthink = time; + + float pushdeltatime = time - self.lastpushtime; + if (pushdeltatime > 0.15) pushdeltatime = 0; + self.lastpushtime = time; + if(!pushdeltatime) return; + + tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, self); + + vector df = self.velocity * -autocvar_g_vehicle_racer_friction; + df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2); + + float forced = autocvar_g_vehicle_racer_upforcedamper; + + int cont = pointcontents(self.origin - '0 0 64'); + if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME) + { + forced = autocvar_g_vehicle_racer_water_upforcedamper; + self.velocity_z += 200; + } + + self.velocity += df * pushdeltatime; + if(self.velocity_z > 0) + self.velocity_z *= 1 - forced * pushdeltatime; + + self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime); + self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime); + + CSQCMODEL_AUTOUPDATE(self); +} + +void racer_exit(float eject) +{SELFPARAM(); + vector spot; + + self.think = racer_think; + self.nextthink = time; + self.movetype = MOVETYPE_BOUNCE; + sound (self.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM); + + if(!self.owner) + return; + + makevectors(self.angles); + if(eject) + { + spot = self.origin + v_forward * 100 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); + self.owner.velocity = (v_up + v_forward * 0.25) * 750; + self.owner.oldvelocity = self.owner.velocity; + } + else + { + if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed) + { + self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2; + self.owner.velocity_z += 200; + spot = self.origin + v_forward * 32 + '0 0 32'; + spot = vehicles_findgoodexit(spot); + } + else + { + self.owner.velocity = self.velocity * 0.5; + self.owner.velocity_z += 10; + spot = self.origin - v_forward * 200 + '0 0 32'; + spot = vehicles_findgoodexit(spot); + } + self.owner.oldvelocity = self.owner.velocity; + setorigin(self.owner , spot); + } + antilag_clear(self.owner); + self.owner = world; +} + +void racer_blowup() +{SELFPARAM(); + self.deadflag = DEAD_DEAD; + self.vehicle_exit(VHEF_NORMAL); + + RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage, + autocvar_g_vehicle_racer_blowup_edgedamage, + autocvar_g_vehicle_racer_blowup_radius, world, world, + autocvar_g_vehicle_racer_blowup_forceintensity, + DEATH_VH_WAKI_DEATH, world); + + self.nextthink = time + autocvar_g_vehicle_racer_respawntime; + self.think = vehicles_spawn; + self.movetype = MOVETYPE_NONE; + self.effects = EF_NODRAW; + + self.colormod = '0 0 0'; + self.avelocity = '0 0 0'; + self.velocity = '0 0 0'; + + setorigin(self, self.pos1); +} + +void racer_blowup_think() +{SELFPARAM(); + self.nextthink = time; + + if(time >= self.delay) + racer_blowup(); + + CSQCMODEL_AUTOUPDATE(self); +} + +void racer_deadtouch() +{SELFPARAM(); + self.avelocity_x *= 0.7; + self.cnt -= 1; + if(self.cnt <= 0) + racer_blowup(); +} + - void spawnfunc_vehicle_racer() - {SELFPARAM(); ++spawnfunc(vehicle_racer) ++{ + if(!autocvar_g_vehicle_racer) { remove(self); return; } + if(!vehicle_initialize(VEH_RACER, false)) { remove(self); return; } +} + +#endif // SVQC + +#ifdef CSQC +#if 0 +void racer_draw() +{SELFPARAM(); + float pushdeltatime = time - self.lastpushtime; + if (pushdeltatime > 0.15) pushdeltatime = 0; + self.lastpushtime = time; + if(!pushdeltatime) return; + + tracebox(self.move_origin, self.mins, self.maxs, self.move_origin - ('0 0 1' * getstatf(STAT_VEH_RACER_SPRINGLENGTH)), MOVE_NOMONSTERS, self); + + vector df = self.move_velocity * -getstatf(STAT_VEH_RACER_FRICTION); + df_z += (1 - trace_fraction) * getstatf(STAT_VEH_RACER_HOVERPOWER) + sin(time * 2) * (getstatf(STAT_VEH_RACER_SPRINGLENGTH) * 2); + + float forced = getstatf(STAT_VEH_RACER_UPFORCEDAMPER); + + int cont = pointcontents(self.move_origin - '0 0 64'); + if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME) + { + forced = getstatf(STAT_VEH_RACER_WATER_UPFORCEDAMPER); + self.move_velocity_z += 200; + } + + self.move_velocity += df * pushdeltatime; + if(self.move_velocity_z > 0) + self.move_velocity_z *= 1 - forced * pushdeltatime; + + self.move_angles_x *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime); + self.move_angles_z *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime); + + Movetype_Physics_MatchServer(false); +} +#endif +#endif + + METHOD(Racer, vr_impact, void(Racer thisveh)) + { + #ifdef SVQC + if(autocvar_g_vehicle_racer_bouncepain) + vehicles_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z); + #endif + } + + METHOD(Racer, vr_enter, void(Racer thisveh)) + { + #ifdef SVQC + self.movetype = MOVETYPE_BOUNCE; + self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health) * 100; + self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield) * 100; + + if(self.owner.flagcarried) + setorigin(self.owner.flagcarried, '-190 0 96'); + #elif defined(CSQC) + + self.move_movetype = MOVETYPE_BOUNCE; + #endif + } + + METHOD(Racer, vr_spawn, void(Racer thisveh)) + { + #ifdef SVQC + if(self.scale != 0.5) + { + if(autocvar_g_vehicle_racer_hovertype != 0) + racer_force_from_tag = vehicles_force_fromtag_maglev; + else + racer_force_from_tag = vehicles_force_fromtag_hover; + + // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel). + self.scale = 0.5; + setattachment(self.vehicle_hudmodel, self, ""); + setattachment(self.vehicle_viewport, self, "tag_viewport"); + + self.mass = 900; + } + + self.think = racer_think; + self.nextthink = time; + self.vehicle_health = autocvar_g_vehicle_racer_health; + self.vehicle_shield = autocvar_g_vehicle_racer_shield; + + self.movetype = MOVETYPE_TOSS; + self.solid = SOLID_SLIDEBOX; + self.delay = time; + self.scale = 0.5; + + self.PlayerPhysplug = racer_frame; + + self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor; + self.bouncestop = autocvar_g_vehicle_racer_bouncestop; + self.damageforcescale = 0.5; + self.vehicle_health = autocvar_g_vehicle_racer_health; + self.vehicle_shield = autocvar_g_vehicle_racer_shield; + #endif + } + + METHOD(Racer, vr_death, void(Racer thisveh)) + { + #ifdef SVQC + self.SendEntity = func_null; // stop networking this racer (for now) + self.health = 0; + self.event_damage = func_null; + self.solid = SOLID_CORPSE; + self.takedamage = DAMAGE_NO; + self.deadflag = DEAD_DYING; + self.movetype = MOVETYPE_BOUNCE; + self.wait = time; + self.delay = 2 + time + random() * 3; + self.cnt = 1 + random() * 2; + self.touch = racer_deadtouch; + + Send_Effect(EFFECT_EXPLOSION_MEDIUM, self.origin, '0 0 0', 1); + + if(random() < 0.5) + self.avelocity_z = 32; + else + self.avelocity_z = -32; + + self.avelocity_x = -vlen(self.velocity) * 0.2; + self.velocity += '0 0 700'; + self.colormod = '-0.5 -0.5 -0.5'; + + self.think = racer_blowup_think; + self.nextthink = time; + #endif + } + +#ifdef CSQC + METHOD(Racer, vr_hud, void(Racer thisveh)) + { + Vehicles_drawHUD(VEH_RACER.m_icon, "vehicle_racer_weapon1", "vehicle_racer_weapon2", + "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, + "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color, + vCROSS_GUIDE); + } +#endif + METHOD(Racer, vr_setup, void(Racer thisveh)) + { + #ifdef SVQC + self.vehicle_exit = racer_exit; + #endif + + #ifdef SVQC + // we have no need to network energy + if(autocvar_g_vehicle_racer_energy) + if(autocvar_g_vehicle_racer_energy_regen) + self.vehicle_flags |= VHF_ENERGYREGEN; + + if(autocvar_g_vehicle_racer_shield) + self.vehicle_flags |= VHF_HASSHIELD; + + if(autocvar_g_vehicle_racer_shield_regen) + self.vehicle_flags |= VHF_SHIELDREGEN; + + if(autocvar_g_vehicle_racer_health_regen) + self.vehicle_flags |= VHF_HEALTHREGEN; + + self.respawntime = autocvar_g_vehicle_racer_respawntime; + self.vehicle_health = autocvar_g_vehicle_racer_health; + self.vehicle_shield = autocvar_g_vehicle_racer_shield; + self.max_health = self.vehicle_health; + #endif + + #ifdef CSQC + AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Rocket + #endif + } + +#endif diff --cc qcsrc/common/vehicles/vehicle/raptor.qc index db3d88022,000000000..1f623379e mode 100644,000000..100644 --- a/qcsrc/common/vehicles/vehicle/raptor.qc +++ b/qcsrc/common/vehicles/vehicle/raptor.qc @@@ -1,797 -1,0 +1,797 @@@ +#ifndef VEHICLE_RAPTOR +#define VEHICLE_RAPTOR +#include "raptor.qh" + +#include "raptor_weapons.qc" + +CLASS(Raptor, Vehicle) +/* spawnflags */ ATTRIB(Raptor, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL); +/* mins */ ATTRIB(Raptor, mins, vector, '-80 -80 0'); +/* maxs */ ATTRIB(Raptor, maxs, vector, '80 80 70'); +/* model */ ATTRIB(Raptor, mdl, string, "models/vehicles/raptor.dpm"); +/* model */ ATTRIB(Raptor, model, string, "models/vehicles/raptor.dpm"); +/* head_model */ ATTRIB(Raptor, head_model, string, ""); +/* hud_model */ ATTRIB(Raptor, hud_model, string, "models/vehicles/raptor_cockpit.dpm"); +/* tags */ ATTRIB(Raptor, tag_head, string, ""); +/* tags */ ATTRIB(Raptor, tag_hud, string, "tag_hud"); +/* tags */ ATTRIB(Raptor, tag_view, string, "tag_camera"); +/* netname */ ATTRIB(Raptor, netname, string, "raptor"); +/* fullname */ ATTRIB(Raptor, vehicle_name, string, _("Raptor")); +/* icon */ ATTRIB(Raptor, m_icon, string, "vehicle_raptor"); +ENDCLASS(Raptor) +REGISTER_VEHICLE(RAPTOR, NEW(Raptor)); + +#endif + +#ifdef IMPLEMENTATION + +#include "raptor_weapons.qc" + +#ifdef SVQC + +bool autocvar_g_vehicle_raptor; + +float autocvar_g_vehicle_raptor_respawntime; +float autocvar_g_vehicle_raptor_takeofftime; + +float autocvar_g_vehicle_raptor_movestyle; +float autocvar_g_vehicle_raptor_turnspeed; +float autocvar_g_vehicle_raptor_pitchspeed; +float autocvar_g_vehicle_raptor_pitchlimit; + +float autocvar_g_vehicle_raptor_speed_forward; +float autocvar_g_vehicle_raptor_speed_strafe; +float autocvar_g_vehicle_raptor_speed_up; +float autocvar_g_vehicle_raptor_speed_down; +float autocvar_g_vehicle_raptor_friction; + +float autocvar_g_vehicle_raptor_cannon_turnspeed; +float autocvar_g_vehicle_raptor_cannon_turnlimit; +float autocvar_g_vehicle_raptor_cannon_pitchlimit_up; +float autocvar_g_vehicle_raptor_cannon_pitchlimit_down; + +float autocvar_g_vehicle_raptor_cannon_locktarget; +float autocvar_g_vehicle_raptor_cannon_locking_time; +float autocvar_g_vehicle_raptor_cannon_locking_releasetime; +float autocvar_g_vehicle_raptor_cannon_locked_time; +float autocvar_g_vehicle_raptor_cannon_predicttarget; + +float autocvar_g_vehicle_raptor_energy; +float autocvar_g_vehicle_raptor_energy_regen; +float autocvar_g_vehicle_raptor_energy_regen_pause; + +float autocvar_g_vehicle_raptor_health; +float autocvar_g_vehicle_raptor_health_regen; +float autocvar_g_vehicle_raptor_health_regen_pause; + +float autocvar_g_vehicle_raptor_shield; +float autocvar_g_vehicle_raptor_shield_regen; +float autocvar_g_vehicle_raptor_shield_regen_pause; + +float autocvar_g_vehicle_raptor_bouncefactor; +float autocvar_g_vehicle_raptor_bouncestop; +vector autocvar_g_vehicle_raptor_bouncepain; + +.entity bomb1; +.entity bomb2; + +float raptor_altitude(float amax) +{SELFPARAM(); + tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), MOVE_WORLDONLY, self); + return vlen(self.origin - trace_endpos); +} + +void raptor_land() +{SELFPARAM(); + float hgt; + + hgt = raptor_altitude(512); + self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime); + self.angles_x *= 0.95; + self.angles_z *= 0.95; + + if(hgt < 128) + if(hgt > 0) + self.frame = (hgt / 128) * 25; + + self.bomb1.gun1.avelocity_y = 90 + ((self.frame / 25) * 2000); + self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y; + + if(hgt < 16) + { + self.movetype = MOVETYPE_TOSS; + self.think = vehicles_think; + self.frame = 0; + } + + self.nextthink = time; + + CSQCMODEL_AUTOUPDATE(self); +} + +void raptor_exit(float eject) +{SELFPARAM(); + vector spot; + self.tur_head.exteriormodeltoclient = world; + + if(self.deadflag == DEAD_NO) + { + self.think = raptor_land; + self.nextthink = time; + } + + if(!self.owner) + return; + + makevectors(self.angles); + if(eject) + { + spot = self.origin + v_forward * 100 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); + self.owner.velocity = (v_up + v_forward * 0.25) * 750; + self.owner.oldvelocity = self.owner.velocity; + } + else + { + if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed) + { + self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2; + self.owner.velocity_z += 200; + spot = self.origin + v_forward * 32 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + } + else + { + self.owner.velocity = self.velocity * 0.5; + self.owner.velocity_z += 10; + spot = self.origin - v_forward * 200 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + } + self.owner.oldvelocity = self.owner.velocity; + setorigin(self.owner , spot); + } + + antilag_clear(self.owner); + self.owner = world; +} + +float raptor_frame() +{SELFPARAM(); + entity player, raptor; + float ftmp = 0; + vector df; + + if(intermission_running) + { + self.vehicle.velocity = '0 0 0'; + self.vehicle.avelocity = '0 0 0'; + return 1; + } + + player = self; + raptor = self.vehicle; + setself(raptor); + + vehicles_painframe(); + /* + ftmp = vlen(self.velocity); + if(ftmp > autocvar_g_vehicle_raptor_speed_forward) + ftmp = 1; + else + ftmp = ftmp / autocvar_g_vehicle_raptor_speed_forward; + */ + + if(self.sound_nexttime < time) + { + self.sound_nexttime = time + 7.955812; + //sound (self.tur_head, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_FLY, 1 - ftmp, ATTEN_NORM ); + sound (self, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_SPEED, 1, ATTEN_NORM); + self.wait = ftmp; + } + /* + else if(fabs(ftmp - self.wait) > 0.2) + { + sound (self.tur_head, CH_TRIGGER_SINGLE, SND_Null, 1 - ftmp, ATTEN_NORM ); + sound (self, CH_TRIGGER_SINGLE, SND_Null, ftmp, ATTEN_NORM); + self.wait = ftmp; + } + */ + + if(raptor.deadflag != DEAD_NO) + { + setself(player); + player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; + return 1; + } + crosshair_trace(player); + + //if(time - self.lastteleporttime < 1) + //{ + if(raptor.angles_z > 50 || raptor.angles_z < -50) + { + if(player.BUTTON_JUMP) + { + player.BUTTON_CROUCH = true; + player.BUTTON_JUMP = false; + } + } + //} + + vector vang; + vang = raptor.angles; + df = vectoangles(normalize(trace_endpos - self.origin + '0 0 32')); + vang_x *= -1; + df_x *= -1; + if(df_x > 180) df_x -= 360; + if(df_x < -180) df_x += 360; + if(df_y > 180) df_y -= 360; + if(df_y < -180) df_y += 360; + + ftmp = shortangle_f(player.v_angle_y - vang_y, vang_y); + if(ftmp > 180) ftmp -= 360; if(ftmp < -180) ftmp += 360; + raptor.avelocity_y = bound(-autocvar_g_vehicle_raptor_turnspeed, ftmp + raptor.avelocity_y * 0.9, autocvar_g_vehicle_raptor_turnspeed); + + // Pitch + ftmp = 0; + if(player.movement_x > 0 && vang_x < autocvar_g_vehicle_raptor_pitchlimit) ftmp = 5; + else if(player.movement_x < 0 && vang_x > -autocvar_g_vehicle_raptor_pitchlimit) ftmp = -20; + + df_x = bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x , autocvar_g_vehicle_raptor_pitchlimit); + ftmp = vang_x - bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x + ftmp, autocvar_g_vehicle_raptor_pitchlimit); + raptor.avelocity_x = bound(-autocvar_g_vehicle_raptor_pitchspeed, ftmp + raptor.avelocity_x * 0.9, autocvar_g_vehicle_raptor_pitchspeed); + + raptor.angles_x = anglemods(raptor.angles_x); + raptor.angles_y = anglemods(raptor.angles_y); + raptor.angles_z = anglemods(raptor.angles_z); + + if(autocvar_g_vehicle_raptor_movestyle == 1) + makevectors('0 1 0' * raptor.angles_y); + else + makevectors(player.v_angle); + + df = raptor.velocity * -autocvar_g_vehicle_raptor_friction; + + if(player.movement_x != 0) + { + if(player.movement_x > 0) + df += v_forward * autocvar_g_vehicle_raptor_speed_forward; + else if(player.movement_x < 0) + df -= v_forward * autocvar_g_vehicle_raptor_speed_forward; + } + + if(player.movement_y != 0) + { + if(player.movement_y < 0) + df -= v_right * autocvar_g_vehicle_raptor_speed_strafe; + else if(player.movement_y > 0) + df += v_right * autocvar_g_vehicle_raptor_speed_strafe; + + raptor.angles_z = bound(-30,raptor.angles_z + (player.movement_y / autocvar_g_vehicle_raptor_speed_strafe),30); + } + else + { + raptor.angles_z *= 0.95; + if(raptor.angles_z >= -1 && raptor.angles_z <= -1) + raptor.angles_z = 0; + } + + if(player.BUTTON_CROUCH) + df -= v_up * autocvar_g_vehicle_raptor_speed_down; + else if (player.BUTTON_JUMP) + df += v_up * autocvar_g_vehicle_raptor_speed_up; + + raptor.velocity += df * frametime; + player.velocity = player.movement = raptor.velocity; + setorigin(player, raptor.origin + '0 0 32'); + + player.vehicle_weapon2mode = raptor.vehicle_weapon2mode; + + vector vf, ad; + // Target lock & predict + if(autocvar_g_vehicle_raptor_cannon_locktarget == 2) + { + if(raptor.gun1.lock_time < time || raptor.gun1.enemy.deadflag) + raptor.gun1.enemy = world; + + if(trace_ent) + if(trace_ent.movetype) + if(trace_ent.takedamage) + if(!trace_ent.deadflag) + { + if(teamplay) + { + if(trace_ent.team != player.team) + { + raptor.gun1.enemy = trace_ent; + raptor.gun1.lock_time = time + 5; + } + } + else + { + raptor.gun1.enemy = trace_ent; + raptor.gun1.lock_time = time + 0.5; + } + } + + if(raptor.gun1.enemy) + { + float distance, impact_time; + + vf = real_origin(raptor.gun1.enemy); + UpdateAuxiliaryXhair(player, vf, '1 0 0', 1); + vector _vel = raptor.gun1.enemy.velocity; + if(raptor.gun1.enemy.movetype == MOVETYPE_WALK) + _vel_z *= 0.1; + + if(autocvar_g_vehicle_raptor_cannon_predicttarget) + { + ad = vf; + distance = vlen(ad - player.origin); + impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed; + ad = vf + _vel * impact_time; + trace_endpos = ad; + } + else + trace_endpos = vf; + } + } + else if(autocvar_g_vehicle_raptor_cannon_locktarget == 1) + { + + vehicles_locktarget((1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime, + (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * frametime, + autocvar_g_vehicle_raptor_cannon_locked_time); + + if(self.lock_target != world) + if(autocvar_g_vehicle_raptor_cannon_predicttarget) + if(self.lock_strength == 1) + { + float i, distance, impact_time; + + vf = real_origin(raptor.lock_target); + ad = vf; + for(i = 0; i < 4; ++i) + { + distance = vlen(ad - raptor.origin); + impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed; + ad = vf + raptor.lock_target.velocity * impact_time; + } + trace_endpos = ad; + } + + if(self.lock_target) + { + if(raptor.lock_strength == 1) + UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '1 0 0', 1); + else if(self.lock_strength > 0.5) + UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 1 0', 1); + else if(self.lock_strength < 0.5) + UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 0 1', 1); + } + } + + + vehicle_aimturret(raptor, trace_endpos, raptor.gun1, "fire1", + autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1, autocvar_g_vehicle_raptor_cannon_pitchlimit_up, + autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed); + + vehicle_aimturret(raptor, trace_endpos, raptor.gun2, "fire1", + autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1, autocvar_g_vehicle_raptor_cannon_pitchlimit_up, + autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed); + + /* + ad = ad * 0.5; + v_forward = vf * 0.5; + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, raptor); + UpdateAuxiliaryXhair(player, trace_endpos, '0 1 0', 0); + */ + + Weapon wep1 = WEP_RAPTOR; + if(!forbidWeaponUse(player)) + if(player.BUTTON_ATCK) + if (wep1.wr_checkammo1(wep1)) + { + wep1.wr_think(wep1, self, true, false); + } + + if(self.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true); + + if(self.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false); + + if(self.vehicle_flags & VHF_ENERGYREGEN) + vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false); + + Weapon wep2a = WEP_RAPTOR_BOMB; + if(!forbidWeaponUse(player)) + if(raptor.vehicle_weapon2mode == RSM_BOMB) + { + if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire) + if(player.BUTTON_ATCK2) + { + wep2a.wr_think(wep2a, self, false, true); + raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire; + raptor.lip = time; + } + } + else + { + Weapon wep2b = WEP_RAPTOR_FLARE; + if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire) + if(player.BUTTON_ATCK2) + { + wep2b.wr_think(wep2b, self, false, true); + raptor.delay = time + autocvar_g_vehicle_raptor_flare_refire; + raptor.lip = time; + } + } + + raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip); + player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100); + player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0; + + if(self.bomb1.cnt < time) + { + entity _missile = findchainentity(enemy, raptor); + float _incomming = 0; + while(_missile) + { + if(_missile.flags & FL_PROJECTILE) + if(MISSILE_IS_TRACKING(_missile)) + if(vlen(self.origin - _missile.origin) < 2 * autocvar_g_vehicle_raptor_flare_range) + ++_incomming; + + _missile = _missile.chain; + } + + if(_incomming) + sound(self, CH_PAIN_SINGLE, SND_VEH_MISSILE_ALARM, VOL_BASE, ATTEN_NONE); + + self.bomb1.cnt = time + 1; + } + + + VEHICLE_UPDATE_PLAYER(player, health, raptor); + VEHICLE_UPDATE_PLAYER(player, energy, raptor); + if(self.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(player, shield, raptor); + + player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0; + + setself(player); + return 1; +} + +float raptor_takeoff() +{SELFPARAM(); + entity player, raptor; + + player = self; + raptor = self.vehicle; + setself(raptor); + + self.nextthink = time; + CSQCMODEL_AUTOUPDATE(self); + self.nextthink = 0; // will this work? + + if(self.sound_nexttime < time) + { + self.sound_nexttime = time + 7.955812; //soundlength("vehicles/raptor_fly.wav"); + sound (self, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_SPEED, VOL_VEHICLEENGINE, ATTEN_NORM); + } + + // Takeoff sequense + if(raptor.frame < 25) + { + raptor.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / sys_frametime); + raptor.velocity_z = min(raptor.velocity_z * 1.5, 256); + self.bomb1.gun1.avelocity_y = 90 + ((raptor.frame / 25) * 25000); + self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y; + player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0; + + setorigin(player, raptor.origin + '0 0 32'); + } + else + player.PlayerPhysplug = raptor_frame; + + if(self.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true); + + if(self.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false); + + if(self.vehicle_flags & VHF_ENERGYREGEN) + vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false); + + + raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip); + player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100); + player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0; + + VEHICLE_UPDATE_PLAYER(player, health, raptor); + VEHICLE_UPDATE_PLAYER(player, energy, raptor); + if(self.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(player, shield, raptor); + + player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0; + setself(player); + return 1; +} + +void raptor_blowup() +{SELFPARAM(); + self.deadflag = DEAD_DEAD; + self.vehicle_exit(VHEF_NORMAL); + RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_RAPT_DEATH, world); + + self.alpha = -1; + self.movetype = MOVETYPE_NONE; + self.effects = EF_NODRAW; + self.colormod = '0 0 0'; + self.avelocity = '0 0 0'; + self.velocity = '0 0 0'; + + setorigin(self, self.pos1); + self.touch = func_null; + self.nextthink = 0; +} + +void raptor_diethink() +{SELFPARAM(); + if(time >= self.wait) + self.think = raptor_blowup; + + if(random() < 0.05) + { + sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM); + Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1); + } + self.nextthink = time; + + CSQCMODEL_AUTOUPDATE(self); +} + +// If we dont do this ever now and then, the raptors rotors +// stop working, presumably due to angle overflow. cute. +void raptor_rotor_anglefix() +{SELFPARAM(); + self.gun1.angles_y = anglemods(self.gun1.angles_y); + self.gun2.angles_y = anglemods(self.gun2.angles_y); + self.nextthink = time + 15; +} + +float raptor_impulse(float _imp) +{SELFPARAM(); + switch(_imp) + { + case 1: + self.vehicle.vehicle_weapon2mode = RSM_BOMB; + CSQCVehicleSetup(self, 0); + return true; + case 2: + self.vehicle.vehicle_weapon2mode = RSM_FLARE; + CSQCVehicleSetup(self, 0); + return true; + + case 10: + case 15: + case 18: + self.vehicle.vehicle_weapon2mode += 1; + if(self.vehicle.vehicle_weapon2mode > RSM_LAST) + self.vehicle.vehicle_weapon2mode = RSM_FIRST; + + CSQCVehicleSetup(self, 0); + return true; + case 11: + case 12: + case 16: + case 19: + self.vehicle.vehicle_weapon2mode -= 1; + if(self.vehicle.vehicle_weapon2mode < RSM_FIRST) + self.vehicle.vehicle_weapon2mode = RSM_LAST; + + CSQCVehicleSetup(self, 0); + return true; + + /* + case 17: // toss gun, could be used to exit? + break; + case 20: // Manual minigun reload? + break; + */ + } + return false; +} + - void spawnfunc_vehicle_raptor() - {SELFPARAM(); ++spawnfunc(vehicle_raptor) ++{ + if(!autocvar_g_vehicle_raptor) { remove(self); return; } + if(!vehicle_initialize(VEH_RAPTOR, false)) { remove(self); return; } +} + + METHOD(Raptor, vr_impact, void(Raptor thisveh)) + { + if(autocvar_g_vehicle_raptor_bouncepain) + vehicles_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z); + } + METHOD(Raptor, vr_enter, void(Raptor thisveh)) + { + self.vehicle_weapon2mode = RSM_BOMB; + self.owner.PlayerPhysplug = raptor_takeoff; + self.movetype = MOVETYPE_BOUNCEMISSILE; + self.solid = SOLID_SLIDEBOX; + self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_raptor_health) * 100; + self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100; + self.velocity_z = 1; // Nudge upwards to takeoff sequense can work. + self.tur_head.exteriormodeltoclient = self.owner; + + self.delay = time + autocvar_g_vehicle_raptor_bombs_refire; + self.lip = time; + + if(self.owner.flagcarried) + setorigin(self.owner.flagcarried, '-20 0 96'); + + CSQCVehicleSetup(self.owner, 0); + } + METHOD(Raptor, vr_death, void(Raptor thisveh)) + { + self.health = 0; + self.event_damage = func_null; + self.solid = SOLID_CORPSE; + self.takedamage = DAMAGE_NO; + self.deadflag = DEAD_DYING; + self.movetype = MOVETYPE_BOUNCE; + self.think = raptor_diethink; + self.nextthink = time; + self.wait = time + 5 + (random() * 5); + + Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation (self.origin, 16), '0 0 0', 1); + + self.velocity_z += 600; + + self.avelocity = '0 0.5 1' * (random() * 400); + self.avelocity -= '0 0.5 1' * (random() * 400); + + self.colormod = '-0.5 -0.5 -0.5'; + self.touch = raptor_blowup; + } + METHOD(Raptor, vr_spawn, void(Raptor thisveh)) + { + if(!self.gun1) + { + entity spinner; + vector ofs; + + //FIXME: Camera is in a bad place in HUD model. + //setorigin(self.vehicle_viewport, '25 0 5'); + + self.vehicles_impulse = raptor_impulse; + + self.frame = 0; + + self.bomb1 = spawn(); + self.bomb2 = spawn(); + self.gun1 = spawn(); + self.gun2 = spawn(); + + setmodel(self.bomb1, MDL_VEH_RAPTOR_CB_FOLDED); + setmodel(self.bomb2, MDL_VEH_RAPTOR_CB_FOLDED); + setmodel(self.gun1, MDL_VEH_RAPTOR_GUN); + setmodel(self.gun2, MDL_VEH_RAPTOR_GUN); + setmodel(self.tur_head, MDL_VEH_RAPTOR_TAIL); + + setattachment(self.bomb1, self, "bombmount_left"); + setattachment(self.bomb2, self, "bombmount_right"); + setattachment(self.tur_head, self,"root"); + + // FIXMODEL Guns mounts to angled bones + self.bomb1.angles = self.angles; + self.angles = '0 0 0'; + // This messes up gun-aim, so work arround it. + //setattachment(self.gun1, self, "gunmount_left"); + ofs = gettaginfo(self, gettagindex(self, "gunmount_left")); + ofs -= self.origin; + setattachment(self.gun1, self, ""); + setorigin(self.gun1, ofs); + + //setattachment(self.gun2, self, "gunmount_right"); + ofs = gettaginfo(self, gettagindex(self, "gunmount_right")); + ofs -= self.origin; + setattachment(self.gun2, self, ""); + setorigin(self.gun2, ofs); + + self.angles = self.bomb1.angles; + self.bomb1.angles = '0 0 0'; + + spinner = spawn(); + spinner.owner = self; + setmodel(spinner, MDL_VEH_RAPTOR_PROP); + setattachment(spinner, self, "engine_left"); + spinner.movetype = MOVETYPE_NOCLIP; + spinner.avelocity = '0 90 0'; + self.bomb1.gun1 = spinner; + + spinner = spawn(); + spinner.owner = self; + setmodel(spinner, MDL_VEH_RAPTOR_PROP); + setattachment(spinner, self, "engine_right"); + spinner.movetype = MOVETYPE_NOCLIP; + spinner.avelocity = '0 -90 0'; + self.bomb1.gun2 = spinner; + + // Sigh. + self.bomb1.think = raptor_rotor_anglefix; + self.bomb1.nextthink = time; + + self.mass = 1 ; + } + + self.frame = 0; + self.vehicle_health = autocvar_g_vehicle_raptor_health; + self.vehicle_shield = autocvar_g_vehicle_raptor_shield; + self.movetype = MOVETYPE_TOSS; + self.solid = SOLID_SLIDEBOX; + self.vehicle_energy = 1; + + self.PlayerPhysplug = raptor_frame; + + self.bomb1.gun1.avelocity_y = 90; + self.bomb1.gun2.avelocity_y = -90; + + self.delay = time; + + self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor; + self.bouncestop = autocvar_g_vehicle_raptor_bouncestop; + self.damageforcescale = 0.25; + self.vehicle_health = autocvar_g_vehicle_raptor_health; + self.vehicle_shield = autocvar_g_vehicle_raptor_shield; + } + METHOD(Raptor, vr_setup, void(Raptor thisveh)) + { + if(autocvar_g_vehicle_raptor_shield) + self.vehicle_flags |= VHF_HASSHIELD; + + if(autocvar_g_vehicle_raptor_shield_regen) + self.vehicle_flags |= VHF_SHIELDREGEN; + + if(autocvar_g_vehicle_raptor_health_regen) + self.vehicle_flags |= VHF_HEALTHREGEN; + + if(autocvar_g_vehicle_raptor_energy_regen) + self.vehicle_flags |= VHF_ENERGYREGEN; + + self.vehicle_exit = raptor_exit; + self.respawntime = autocvar_g_vehicle_raptor_respawntime; + self.vehicle_health = autocvar_g_vehicle_raptor_health; + self.vehicle_shield = autocvar_g_vehicle_raptor_shield; + self.max_health = self.vehicle_health; + } + +#endif +#ifdef CSQC + + METHOD(Raptor, vr_hud, void(Raptor thisveh)) + { + string crosshair; + + switch(weapon2mode) + { + case RSM_FLARE: crosshair = vCROSS_RAIN; break; + case RSM_BOMB: crosshair = vCROSS_BURST; break; + default: crosshair = vCROSS_BURST; + } + + Vehicles_drawHUD(VEH_RAPTOR.m_icon, "vehicle_raptor_weapon1", "vehicle_raptor_weapon2", + "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, + "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color, + crosshair); + } + METHOD(Raptor, vr_setup, void(Raptor thisveh)) + { + AuxiliaryXhair[1].axh_image = vCROSS_LOCK; + } + +#endif +#endif diff --cc qcsrc/common/vehicles/vehicle/spiderbot.qc index ede09c5c3,000000000..9d524ef0a mode 100644,000000..100644 --- a/qcsrc/common/vehicles/vehicle/spiderbot.qc +++ b/qcsrc/common/vehicles/vehicle/spiderbot.qc @@@ -1,671 -1,0 +1,671 @@@ +#ifndef VEHICLE_SPIDERBOT +#define VEHICLE_SPIDERBOT + +#include "spiderbot_weapons.qc" + +CLASS(Spiderbot, Vehicle) +/* spawnflags */ ATTRIB(Spiderbot, spawnflags, int, VHF_DMGSHAKE); +/* mins */ ATTRIB(Spiderbot, mins, vector, '-75 -75 10'); +/* maxs */ ATTRIB(Spiderbot, maxs, vector, '75 75 125'); +/* model */ ATTRIB(Spiderbot, mdl, string, "models/vehicles/spiderbot.dpm"); +/* model */ ATTRIB(Spiderbot, model, string, "models/vehicles/spiderbot.dpm"); +/* head_model */ ATTRIB(Spiderbot, head_model, string, "models/vehicles/spiderbot_top.dpm"); +/* hud_model */ ATTRIB(Spiderbot, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm"); +/* tags */ ATTRIB(Spiderbot, tag_head, string, "tag_head"); +/* tags */ ATTRIB(Spiderbot, tag_hud, string, "tag_hud"); +/* tags */ ATTRIB(Spiderbot, tag_view, string, ""); +/* netname */ ATTRIB(Spiderbot, netname, string, "spiderbot"); +/* fullname */ ATTRIB(Spiderbot, vehicle_name, string, _("Spiderbot")); +/* icon */ ATTRIB(Spiderbot, m_icon, string, "vehicle_spider"); +ENDCLASS(Spiderbot) + +REGISTER_VEHICLE(SPIDERBOT, NEW(Spiderbot)); + +#endif + +#ifdef IMPLEMENTATION + +const int SBRM_FIRST = 1; +const int SBRM_VOLLY = 1; +const int SBRM_GUIDE = 2; +const int SBRM_ARTILLERY = 3; +const int SBRM_LAST = 3; + +#include "spiderbot_weapons.qc" + +#ifdef SVQC +bool autocvar_g_vehicle_spiderbot; + +float autocvar_g_vehicle_spiderbot_respawntime; + +float autocvar_g_vehicle_spiderbot_speed_stop; +float autocvar_g_vehicle_spiderbot_speed_strafe; +float autocvar_g_vehicle_spiderbot_speed_walk; +float autocvar_g_vehicle_spiderbot_speed_run = 700; +float autocvar_g_vehicle_spiderbot_turnspeed; +float autocvar_g_vehicle_spiderbot_turnspeed_strafe; +float autocvar_g_vehicle_spiderbot_movement_inertia; + +float autocvar_g_vehicle_spiderbot_springlength; +float autocvar_g_vehicle_spiderbot_springup; +float autocvar_g_vehicle_spiderbot_springblend; +float autocvar_g_vehicle_spiderbot_tiltlimit; + +float autocvar_g_vehicle_spiderbot_head_pitchlimit_down; +float autocvar_g_vehicle_spiderbot_head_pitchlimit_up; +float autocvar_g_vehicle_spiderbot_head_turnlimit; +float autocvar_g_vehicle_spiderbot_head_turnspeed; + +int autocvar_g_vehicle_spiderbot_health; +float autocvar_g_vehicle_spiderbot_health_regen; +float autocvar_g_vehicle_spiderbot_health_regen_pause; + +int autocvar_g_vehicle_spiderbot_shield; +float autocvar_g_vehicle_spiderbot_shield_regen; +float autocvar_g_vehicle_spiderbot_shield_regen_pause; + +vector autocvar_g_vehicle_spiderbot_bouncepain; + +.float jump_delay; +float spiderbot_frame() +{SELFPARAM(); + vector ad, vf; + entity player, spider; + float ftmp; + + if(intermission_running) + { + self.vehicle.velocity = '0 0 0'; + self.vehicle.avelocity = '0 0 0'; + return 1; + } + + player = self; + spider = self.vehicle; + setself(spider); + + vehicles_painframe(); + + player.BUTTON_ZOOM = 0; + player.BUTTON_CROUCH = 0; + player.switchweapon = 0; + player.vehicle_weapon2mode = spider.vehicle_weapon2mode; + + +#if 1 // 0 to enable per-gun impact aux crosshairs + // Avarage gun impact point's -> aux cross + ad = gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint01")); + vf = v_forward; + ad += gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint02")); + vf += v_forward; + ad = ad * 0.5; + v_forward = vf * 0.5; + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider); + UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0); +#else + ad = gettaginfo(spider.gun1, gettagindex(spider.gun1, "barrels")); + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider); + UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0); + vf = ad; + ad = gettaginfo(spider.gun2, gettagindex(spider.gun2, "barrels")); + traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider); + UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 1); + ad = 0.5 * (ad + vf); +#endif + + crosshair_trace(player); + ad = vectoangles(normalize(trace_endpos - ad)); + ad = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(spider.angles), AnglesTransform_FromAngles(ad))) - spider.tur_head.angles; + ad = AnglesTransform_Normalize(ad, true); + //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2); + + // Rotate head + ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime; + ad_y = bound(-ftmp, ad_y, ftmp); + spider.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, spider.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit); + + // Pitch head + ad_x = bound(ftmp * -1, ad_x, ftmp); + spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up); + + + //fixedmakevectors(spider.angles); + makevectors(spider.angles + '-2 0 0' * spider.angles_x); + + movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend, autocvar_g_vehicle_spiderbot_tiltlimit); + + if(spider.flags & FL_ONGROUND) + spider.jump_delay = time; // reset now so movement can begin + + //if(spider.flags & FL_ONGROUND) + { + if(spider.flags & FL_ONGROUND) + if(spider.frame == 4 && self.tur_head.wait != 0) + { + sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_LAND, VOL_VEHICLEENGINE, ATTEN_NORM); + spider.frame = 5; + } + + if(!player.BUTTON_JUMP) + spider.BUTTON_JUMP = 0; + + if((spider.flags & FL_ONGROUND) && player.BUTTON_JUMP && !spider.BUTTON_JUMP && self.tur_head.wait < time) + { + sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_JUMP, VOL_VEHICLEENGINE, ATTEN_NORM); + //dprint("spiderbot_jump:", ftos(soundlength("vehicles/spiderbot_jump.wav")), "\n"); + self.delay = 0; + + self.tur_head.wait = time + 2; + spider.jump_delay = time + 2; + spider.BUTTON_JUMP = 1; // set spider's jump + //player.BUTTON_JUMP = 0; + + vector movefix = '0 0 0'; + if(player.movement_x > 0) movefix_x = 1; + if(player.movement_x < 0) movefix_x = -1; + if(player.movement_y > 0) movefix_y = 1; + if(player.movement_y < 0) movefix_y = -1; + + vector rt = movefix_y * v_right; + vector sd = movefix_x * v_forward; + if(movefix_y == 0 && movefix_x == 0) + sd = v_forward; // always do forward + + spider.flags &= ~FL_ONGROUND; + + spider.velocity = sd * 700 + rt * 600 + v_up * 600; + spider.frame = 4; + } + else if(time >= spider.jump_delay) + { + if(vlen(player.movement) == 0) + { + if(spider.flags & FL_ONGROUND) + { + if(self.sound_nexttime < time || self.delay != 3) + { + self.delay = 3; + self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_idle.wav"); + //dprint("spiderbot_idle:", ftos(soundlength("vehicles/spiderbot_idle.wav")), "\n"); + sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM); + } + movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop); + spider.frame = 5; + } + } + else + { + // Turn Body + if(player.movement_x == 0 && player.movement_y != 0) + ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime; + else + ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime; + + ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp); + spider.angles_y = anglemods(spider.angles_y + ftmp); + spider.tur_head.angles_y -= ftmp; + + if(player.movement_x != 0) + { + if(player.movement_x > 0) + { + player.movement_x = 1; + if(spider.flags & FL_ONGROUND) + spider.frame = 0; + } + else if(player.movement_x < 0) + { + player.movement_x = -1; + if(spider.flags & FL_ONGROUND) + spider.frame = 1; + } + player.movement_y = 0; + float oldvelz = spider.velocity_z; + movelib_move_simple(normalize(v_forward * player.movement_x),((player.BUTTON_JUMP) ? autocvar_g_vehicle_spiderbot_speed_run : autocvar_g_vehicle_spiderbot_speed_walk),autocvar_g_vehicle_spiderbot_movement_inertia); + spider.velocity_z = oldvelz; + float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1); + if(spider.velocity_z <= 20) // not while jumping + spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity; + if(spider.flags & FL_ONGROUND) + if(self.sound_nexttime < time || self.delay != 1) + { + self.delay = 1; + self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_walk.wav"); + sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_WALK, VOL_VEHICLEENGINE, ATTEN_NORM); + //dprint("spiderbot_walk:", ftos(soundlength("vehicles/spiderbot_walk.wav")), "\n"); + } + } + else if(player.movement_y != 0) + { + if(player.movement_y < 0) + { + player.movement_y = -1; + if(spider.flags & FL_ONGROUND) + spider.frame = 2; + } + else if(player.movement_y > 0) + { + player.movement_y = 1; + if(spider.flags & FL_ONGROUND) + spider.frame = 3; + } + + float oldvelz = spider.velocity_z; + movelib_move_simple(normalize(v_right * player.movement_y),autocvar_g_vehicle_spiderbot_speed_strafe,autocvar_g_vehicle_spiderbot_movement_inertia); + spider.velocity_z = oldvelz; + float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1); + if(spider.velocity_z <= 20) // not while jumping + spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity; + if(spider.flags & FL_ONGROUND) + if(self.sound_nexttime < time || self.delay != 2) + { + self.delay = 2; + self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_strafe.wav"); + sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_STRAFE, VOL_VEHICLEENGINE, ATTEN_NORM); + //dprint("spiderbot_strafe:", ftos(soundlength("vehicles/spiderbot_strafe.wav")), "\n"); + } + } + } + } + } + + self.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit); + self.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit); + + if(!forbidWeaponUse(player)) + if(player.BUTTON_ATCK) + { + spider.cnt = time; + if(spider.vehicle_ammo1 >= autocvar_g_vehicle_spiderbot_minigun_ammo_cost && spider.tur_head.attack_finished_single <= time) + { + entity gun; + vector v; + spider.misc_bulletcounter += 1; + + setself(player); + + gun = (spider.misc_bulletcounter % 2) ? spider.gun1 : spider.gun2; + + v = gettaginfo(gun, gettagindex(gun, "barrels")); + v_forward = normalize(v_forward); + v += v_forward * 50; + + fireBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration, + autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN, 0); + + sound (gun, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM); + //trailparticles(self, _particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos); + pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_MUZZLEFLASH), v, v_forward * 2500, 1); + + setself(spider); + + spider.vehicle_ammo1 -= autocvar_g_vehicle_spiderbot_minigun_ammo_cost; + spider.tur_head.attack_finished_single = time + autocvar_g_vehicle_spiderbot_minigun_refire; + player.vehicle_ammo1 = (spider.vehicle_ammo1 / autocvar_g_vehicle_spiderbot_minigun_ammo_max) * 100; + spider.gun1.angles_z += 45; + spider.gun2.angles_z -= 45; + if(spider.gun1.angles_z >= 360) + { + spider.gun1.angles_z = 0; + spider.gun2.angles_z = 0; + } + } + } + else + vehicles_regen(spider.cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max, + autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause, + autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime, false); + + + spiderbot_rocket_do(); + + if(self.vehicle_flags & VHF_SHIELDREGEN) + vehicles_regen(spider.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, true); + + if(self.vehicle_flags & VHF_HEALTHREGEN) + vehicles_regen(spider.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, false); + + player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0; + //player.vehicle_ammo2 = spider.tur_head.frame; + player.vehicle_ammo2 = (9 - spider.tur_head.frame) / 8 * 100; // Percentage, like ammo1 + + if(spider.gun2.cnt <= time) + player.vehicle_reload2 = 100; + else + player.vehicle_reload2 = 100 - ((spider.gun2.cnt - time) / spider.attack_finished_single) * 100; + + setorigin(player, spider.origin + '0 0 1' * spider.maxs_z); + player.velocity = spider.velocity; + + VEHICLE_UPDATE_PLAYER(player, health, spiderbot); + + if(self.vehicle_flags & VHF_HASSHIELD) + VEHICLE_UPDATE_PLAYER(player, shield, spiderbot); + + setself(player); + return 1; +} + +void spiderbot_exit(float eject) +{SELFPARAM(); + entity e; + vector spot; + + e = findchain(classname,"spiderbot_rocket"); + while(e) + { + if(e.owner == self.owner) + { + e.realowner = self.owner; + e.owner = world; + } + e = e.chain; + } + + self.think = vehicles_think; + self.nextthink = time; + self.frame = 5; + self.movetype = MOVETYPE_WALK; + + if(!self.owner) + return; + + makevectors(self.angles); + if(eject) + { + spot = self.origin + v_forward * 100 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + setorigin(self.owner , spot); + self.owner.velocity = (v_up + v_forward * 0.25) * 750; + self.owner.oldvelocity = self.owner.velocity; + } + else + { + if(vlen(self.velocity) > autocvar_g_vehicle_spiderbot_speed_strafe) + { + self.owner.velocity = normalize(self.velocity) * vlen(self.velocity); + self.owner.velocity_z += 200; + spot = self.origin + v_forward * 128 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + } + else + { + self.owner.velocity = self.velocity * 0.5; + self.owner.velocity_z += 10; + spot = self.origin + v_forward * 256 + '0 0 64'; + spot = vehicles_findgoodexit(spot); + } + self.owner.oldvelocity = self.owner.velocity; + setorigin(self.owner , spot); + } + + antilag_clear(self.owner); + self.owner = world; +} + +void spiderbot_headfade() +{SELFPARAM(); + self.think = spiderbot_headfade; + self.nextthink = self.fade_time; + self.alpha = 1 - (time - self.fade_time) * self.fade_rate; + + if(self.cnt < time || self.alpha < 0.1) + { + if(self.alpha > 0.1) + { + sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM); + Send_Effect(EFFECT_EXPLOSION_BIG, self.origin + '0 0 100', '0 0 0', 1); + } + remove(self); + } +} + +void spiderbot_blowup() +{SELFPARAM(); + if(self.cnt > time) + { + if(random() < 0.1) + { + sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM); + Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1); + } + self.nextthink = time + 0.1; + return; + } + + entity h, g1, g2, b; + b = spawn(); + h = spawn(); + g1 = spawn(); + g2 = spawn(); + + setmodel(b, MDL_VEH_SPIDERBOT_BODY); + setmodel(h, MDL_VEH_SPIDERBOT_TOP); + setmodel(g1, MDL_VEH_SPIDERBOT_GUN); + setmodel(g2, MDL_VEH_SPIDERBOT_GUN); + + setorigin(b, self.origin); + b.frame = 11; + b.angles = self.angles; + setsize(b, self.mins, self.maxs); + + setorigin(h, gettaginfo(self, gettagindex(self, "tag_head"))); + h.movetype = MOVETYPE_BOUNCE; + h.solid = SOLID_BBOX; + h.velocity = v_up * (500 + random() * 500) + randomvec() * 128; + h.modelflags = MF_ROCKET; + h.effects = EF_FLAME | EF_LOWPRECISION; + h.avelocity = randomvec() * 360; + + h.alpha = 1; + h.cnt = time + (3.5 * random()); + h.fade_rate = 1 / min(self.respawntime, 10); + h.fade_time = time; + h.think = spiderbot_headfade; + h.nextthink = time; + + setorigin(g1, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint01"))); + g1.movetype = MOVETYPE_TOSS; + g1.solid = SOLID_CORPSE; + g1.velocity = v_forward * 700 + (randomvec() * 32); + g1.avelocity = randomvec() * 180; + + setorigin(g2, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint02"))); + g2.movetype = MOVETYPE_TOSS; + g2.solid = SOLID_CORPSE; + g2.velocity = v_forward * 700 + (randomvec() * 32); + g2.avelocity = randomvec() * 180; + + h.colormod = b.colormod = g1.colormod = g2.colormod = '-2 -2 -2'; + + SUB_SetFade(b, time + 5, min(self.respawntime, 1)); + //SUB_SetFade(h, time, min(self.respawntime, 10)); + SUB_SetFade(g1, time, min(self.respawntime, 10)); + SUB_SetFade(g2, time, min(self.respawntime, 10)); + + RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_SPID_DEATH, world); + + self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1; + self.movetype = MOVETYPE_NONE; + self.deadflag = DEAD_DEAD; + self.solid = SOLID_NOT; + self.tur_head.effects &= ~EF_FLAME; + self.vehicle_hudmodel.viewmodelforclient = self; +} + +bool spiderbot_impulse(int _imp) +{SELFPARAM(); + switch(_imp) + { + case 1: + self.vehicle.vehicle_weapon2mode = SBRM_VOLLY; + CSQCVehicleSetup(self, 0); + return true; + case 2: + self.vehicle.vehicle_weapon2mode = SBRM_GUIDE; + CSQCVehicleSetup(self, 0); + return true; + case 3: + self.vehicle.vehicle_weapon2mode = SBRM_ARTILLERY; + CSQCVehicleSetup(self, 0); + return true; + + case 10: + case 15: + case 18: + self.vehicle.vehicle_weapon2mode += 1; + if(self.vehicle.vehicle_weapon2mode > SBRM_LAST) + self.vehicle.vehicle_weapon2mode = SBRM_FIRST; + + //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode))); + CSQCVehicleSetup(self, 0); + return true; + case 11: + case 12: + case 16: + case 19: + self.vehicle.vehicle_weapon2mode -= 1; + if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST) + self.vehicle.vehicle_weapon2mode = SBRM_LAST; + + //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode))); + CSQCVehicleSetup(self, 0); + return true; + + /* + case 17: // toss gun, could be used to exit? + break; + case 20: // Manual minigun reload? + break; + */ + } + return false; +} + - void spawnfunc_vehicle_spiderbot() - {SELFPARAM(); ++spawnfunc(vehicle_spiderbot) ++{ + if(!autocvar_g_vehicle_spiderbot) { remove(self); return; } + if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; } +} + + METHOD(Spiderbot, vr_impact, void(Spiderbot thisveh)) + { + if(autocvar_g_vehicle_spiderbot_bouncepain) + vehicles_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z); + } + METHOD(Spiderbot, vr_enter, void(Spiderbot thisveh)) + { + self.vehicle_weapon2mode = SBRM_GUIDE; + self.movetype = MOVETYPE_WALK; + CSQCVehicleSetup(self.owner, 0); + self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100; + self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100; + + if(self.owner.flagcarried) + { + setattachment(self.owner.flagcarried, self.tur_head, ""); + setorigin(self.owner.flagcarried, '-20 0 120'); + } + } + METHOD(Spiderbot, vr_think, void(Spiderbot thisveh)) + { + if(self.flags & FL_ONGROUND) + movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop); + } + METHOD(Spiderbot, vr_death, void(Spiderbot thisveh)) + { + self.health = 0; + self.event_damage = func_null; + self.takedamage = DAMAGE_NO; + self.touch = func_null; + self.cnt = 3.4 + time + random() * 2; + self.think = spiderbot_blowup; + self.nextthink = time; + self.deadflag = DEAD_DYING; + self.frame = 5; + self.tur_head.effects |= EF_FLAME; + self.colormod = self.tur_head.colormod = '-1 -1 -1'; + self.frame = 10; + self.movetype = MOVETYPE_TOSS; + + CSQCModel_UnlinkEntity(); // networking the death scene would be a nightmare + } + METHOD(Spiderbot, vr_spawn, void(Spiderbot thisveh)) + { + if(!self.gun1) + { + self.vehicles_impulse = spiderbot_impulse; + self.gun1 = spawn(); + self.gun2 = spawn(); + setmodel(self.gun1, MDL_VEH_SPIDERBOT_GUN); + setmodel(self.gun2, MDL_VEH_SPIDERBOT_GUN); + setattachment(self.gun1, self.tur_head, "tag_hardpoint01"); + setattachment(self.gun2, self.tur_head, "tag_hardpoint02"); + self.gravity = 2; + self.mass = 5000; + } + + self.frame = 5; + self.tur_head.frame = 1; + self.movetype = MOVETYPE_WALK; + self.solid = SOLID_SLIDEBOX; + self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1; + self.tur_head.angles = '0 0 0'; + self.vehicle_exit = spiderbot_exit; + + setorigin(self, self.pos1 + '0 0 128'); + self.angles = self.pos2; + self.damageforcescale = 0.03; + self.vehicle_health = autocvar_g_vehicle_spiderbot_health; + self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield; + + self.PlayerPhysplug = spiderbot_frame; + } + METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh)) + { + if(autocvar_g_vehicle_spiderbot_shield) + self.vehicle_flags |= VHF_HASSHIELD; + + if(autocvar_g_vehicle_spiderbot_shield_regen) + self.vehicle_flags |= VHF_SHIELDREGEN; + + if(autocvar_g_vehicle_spiderbot_health_regen) + self.vehicle_flags |= VHF_HEALTHREGEN; + + self.respawntime = autocvar_g_vehicle_spiderbot_respawntime; + self.vehicle_health = autocvar_g_vehicle_spiderbot_health; + self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield; + self.max_health = self.vehicle_health; + self.pushable = true; // spiderbot can use jumppads + } + +#endif // SVQC +#ifdef CSQC +float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6; +float autocvar_cl_vehicle_spiderbot_cross_size = 1; + + METHOD(Spiderbot, vr_hud, void(Spiderbot thisveh)) + { + string crosshair; + + switch(weapon2mode) + { + case SBRM_VOLLY: crosshair = vCROSS_BURST; break; + case SBRM_GUIDE: crosshair = vCROSS_GUIDE; break; + case SBRM_ARTILLERY: crosshair = vCROSS_RAIN; break; + default: crosshair = vCROSS_BURST; + } + + Vehicles_drawHUD(VEH_SPIDERBOT.m_icon, "vehicle_spider_weapon1", "vehicle_spider_weapon2", + "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, + "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color, + crosshair); + } + METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh)) + { + AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1 + AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2 + } + +#endif +#endif diff --cc qcsrc/common/weapons/weapon/hmg.qc index e9ddfb4f7,f4c6a3c75..bcbefbf82 --- a/qcsrc/common/weapons/weapon/hmg.qc +++ b/qcsrc/common/weapons/weapon/hmg.qc @@@ -43,13 -41,13 +43,13 @@@ HMG_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP #ifdef IMPLEMENTATION #ifdef SVQC - void spawnfunc_weapon_hmg() { weapon_defaultspawnfunc(WEP_HMG.m_id); } + spawnfunc(weapon_hmg) { weapon_defaultspawnfunc(WEP_HMG.m_id); } -void W_HeavyMachineGun_Attack_Auto() -{SELFPARAM(); - if (!self.BUTTON_ATCK) +void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, bool fire1, bool fire2) +{ + if (!actor.BUTTON_ATCK) { - w_ready(); + w_ready(thiswep, actor, fire1, fire2); return; } diff --cc qcsrc/common/weapons/weapon/hook.qc index ffee55dd2,6c1f82fdf..9d5eb29ec --- a/qcsrc/common/weapons/weapon/hook.qc +++ b/qcsrc/common/weapons/weapon/hook.qc @@@ -70,7 -59,16 +70,7 @@@ HOOK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PRO #ifdef IMPLEMENTATION #ifdef SVQC - void spawnfunc_weapon_hook() { weapon_defaultspawnfunc(WEP_HOOK.m_id); } -spawnfunc(weapon_hook) -{ - if(g_grappling_hook) // offhand hook - { - startitem_failed = true; - remove(self); - return; - } - weapon_defaultspawnfunc(WEP_HOOK.m_id); -} ++spawnfunc(weapon_hook) { weapon_defaultspawnfunc(WEP_HOOK.m_id); } void W_Hook_ExplodeThink(void) {SELFPARAM(); diff --cc qcsrc/common/weapons/weapon/rifle.qc index d994f0151,c156d84b4..73590a5d5 --- a/qcsrc/common/weapons/weapon/rifle.qc +++ b/qcsrc/common/weapons/weapon/rifle.qc @@@ -49,11 -47,11 +49,11 @@@ RIFLE_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PR #endif #ifdef IMPLEMENTATION #ifdef SVQC - void spawnfunc_weapon_rifle(void) { weapon_defaultspawnfunc(WEP_RIFLE.m_id); } - void spawnfunc_weapon_campingrifle(void) { spawnfunc_weapon_rifle(); } - void spawnfunc_weapon_sniperrifle(void) { spawnfunc_weapon_rifle(); } + spawnfunc(weapon_rifle) { weapon_defaultspawnfunc(WEP_RIFLE.m_id); } + spawnfunc(weapon_campingrifle) { spawnfunc_weapon_rifle(this); } + spawnfunc(weapon_sniperrifle) { spawnfunc_weapon_rifle(this); } -void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound) +void W_Rifle_FireBullet(Weapon thiswep, float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound) {SELFPARAM(); float i; diff --cc qcsrc/common/weapons/weapon/shotgun.qc index 09bdf2107,05f4cf6ab..813fce328 --- a/qcsrc/common/weapons/weapon/shotgun.qc +++ b/qcsrc/common/weapons/weapon/shotgun.qc @@@ -54,9 -52,9 +54,9 @@@ SHOTGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_ #endif #ifdef IMPLEMENTATION #ifdef SVQC - void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); } + spawnfunc(weapon_shotgun) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); } -void W_Shotgun_Attack(float isprimary) +void W_Shotgun_Attack(Weapon thiswep, float isprimary) {SELFPARAM(); float sc; entity flash; diff --cc qcsrc/server/mutators/mutator_overkill.qc index 27eaed042,2114efc92..d2086215f --- a/qcsrc/server/mutators/mutator_overkill.qc +++ b/qcsrc/server/mutators/mutator_overkill.qc @@@ -3,9 -3,9 +3,9 @@@ #include "mutator.qh" -void W_Blaster_Attack(float, float, float, float, float, float, float, float, float, float); +void W_Blaster_Attack(entity, float, float, float, float, float, float, float, float, float, float); - void spawnfunc_weapon_hmg(); - void spawnfunc_weapon_rpc(); + spawnfunc(weapon_hmg); + spawnfunc(weapon_rpc); void ok_DecreaseCharge(entity ent, int wep) {