From: TimePath Date: Mon, 28 Sep 2015 06:12:32 +0000 (+1000) Subject: Vehicles: prepare for upgrade X-Git-Tag: xonotic-v0.8.2~1874^2~62 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=807e413f50626007f11b5822a4c60512c22289fc Vehicles: prepare for upgrade --- diff --git a/qcsrc/common/vehicles/all.inc b/qcsrc/common/vehicles/all.inc index eda4e00bb..e4c73a449 100644 --- a/qcsrc/common/vehicles/all.inc +++ b/qcsrc/common/vehicles/all.inc @@ -1,6 +1,6 @@ -#include "unit/spiderbot.qc" -#include "unit/raptor.qc" -#include "unit/racer.qc" +#include "vehicle/spiderbot.qc" +#include "vehicle/raptor.qc" +#include "vehicle/racer.qc" #ifndef VEHICLES_NO_UNSTABLE - #include "unit/bumblebee.qc" + #include "vehicle/bumblebee.qc" #endif diff --git a/qcsrc/common/vehicles/all.qc b/qcsrc/common/vehicles/all.qc index 6e26f1712..b071cf5a7 100644 --- a/qcsrc/common/vehicles/all.qc +++ b/qcsrc/common/vehicles/all.qc @@ -3,16 +3,6 @@ #include "all.qh" -#if defined(SVQC) - #include "sv_vehicles.qc" -#elif defined(CSQC) - #include "cl_vehicles.qc" -#endif - -#define IMPLEMENTATION -#include "all.inc" -#undef IMPLEMENTATION - #ifndef MENUQC STATIC_INIT(vehicles_common_initialize) { @@ -40,4 +30,14 @@ entity get_vehicleinfo(int id) return m ? m : VEH_Null; } +#if defined(SVQC) + #include "sv_vehicles.qc" +#elif defined(CSQC) + #include "cl_vehicles.qc" +#endif + +#define IMPLEMENTATION +#include "all.inc" +#undef IMPLEMENTATION + #endif diff --git a/qcsrc/common/vehicles/all.qh b/qcsrc/common/vehicles/all.qh index a18bfe13e..cf4a034eb 100644 --- a/qcsrc/common/vehicles/all.qh +++ b/qcsrc/common/vehicles/all.qh @@ -1,53 +1,7 @@ #ifndef VEHICLES_ALL_H #define VEHICLES_ALL_H -#if defined(SVQC) - #include "sv_vehicles.qh" -#elif defined(CSQC) - #include "cl_vehicles.qh" -#endif - - -// vehicle requests -const int VR_SETUP = 1; // (BOTH) setup vehicle data -const int VR_THINK = 2; // (SERVER) logic to run every frame -const int VR_DEATH = 3; // (SERVER) called when vehicle dies -const int VR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this vehicle -const int VR_ENTER = 5; // (SERVER) called when a player enters this vehicle -const int VR_SPAWN = 6; // (SERVER) called when the vehicle re-spawns -const int VR_IMPACT = 7; // (SERVER) called when a vehicle hits something -const int VR_HUD = 8; // (CLIENT) logic to run every frame - -// vehicle spawn flags (need them here for common registrations) -const int VHF_ISVEHICLE = 2; /// Indicates vehicle -const int VHF_HASSHIELD = 4; /// Vehicle has shileding -const int VHF_SHIELDREGEN = 8; /// Vehicles shield regenerates -const int VHF_HEALTHREGEN = 16; /// Vehicles health regenerates -const int VHF_ENERGYREGEN = 32; /// Vehicles energy regenerates -const int VHF_DEATHEJECT = 64; /// Vehicle ejects pilot upon fatal damage -const int VHF_MOVE_GROUND = 128; /// Vehicle moves on gound -const int VHF_MOVE_HOVER = 256; /// Vehicle hover close to gound -const int VHF_MOVE_FLY = 512; /// Vehicle is airborn -const int VHF_DMGSHAKE = 1024; /// Add random velocity each frame if health < 50% -const int VHF_DMGROLL = 2048; /// Add random angles each frame if health < 50% -const int VHF_DMGHEADROLL = 4096; /// Add random head angles each frame if health < 50% -const int VHF_MULTISLOT = 8192; /// Vehicle has multiple player slots -const int VHF_PLAYERSLOT = 16384; /// This ent is a player slot on a multi-person vehicle - -// functions: -entity get_vehicleinfo(float id); - -// fields: -.entity tur_head; - - -// other useful macros -#define VEH_ACTION(vehicletype,mrequest) (get_vehicleinfo(vehicletype)).vehicle_func(mrequest) -#define VEH_NAME(vehicletype) (get_vehicleinfo(vehicletype)).vehicle_name - -// ===================== -// Vehicle Registration -// ===================== +#include "vehicle.qh" void RegisterVehicles(); const int VEH_MAXCOUNT = 24; @@ -56,10 +10,9 @@ int VEH_COUNT; const int VEH_FIRST = 1; #define VEH_LAST (VEH_FIRST + VEH_COUNT - 1) /** If you register a new vehicle, make sure to add it to all.inc */ -#define REGISTER_VEHICLE(id, class) REGISTER(RegisterVehicles, VEH, vehicle_info, VEH_COUNT, id, vehicleid, NEW(class)) -#include "vehicle.qh" +#define REGISTER_VEHICLE(id, inst) REGISTER(RegisterVehicles, VEH, vehicle_info, VEH_COUNT, id, vehicleid, inst) #define REGISTER_VEHICLE_SIMPLE(id, vehicleflags, min_s, max_s, modelname, headmodelname, hudmodelname, headtag, hudtag, viewtag, shortname, vname) \ - REGISTER_VEHICLE(id, Vehicle) { \ + REGISTER_VEHICLE(id, NEW(Vehicle)) { \ this.netname = shortname; \ this.vehicle_name = vname; \ this.mdl = modelname; \ @@ -76,7 +29,13 @@ const int VEH_FIRST = 1; REGISTER_INIT(VEH, id) REGISTER_REGISTRY(RegisterVehicles) -REGISTER_VEHICLE(Null, Vehicle); +#if defined(SVQC) + #include "sv_vehicles.qh" +#elif defined(CSQC) + #include "cl_vehicles.qh" +#endif + +REGISTER_VEHICLE(Null, NEW(Vehicle)); #include "all.inc" diff --git a/qcsrc/common/vehicles/unit/bumblebee.qc b/qcsrc/common/vehicles/unit/bumblebee.qc deleted file mode 100644 index 6f8a2bf8f..000000000 --- a/qcsrc/common/vehicles/unit/bumblebee.qc +++ /dev/null @@ -1,1126 +0,0 @@ -#ifndef VEHICLE_BUMBLEBEE -#define VEHICLE_BUMBLEBEE -#include "bumblebee.qh" -#ifndef MENUQC -int v_bumblebee(int); -#endif -REGISTER_VEHICLE_SIMPLE( -/* VEH_##id */ BUMBLEBEE, -/* spawnflags */ VHF_DMGSHAKE, -/* mins,maxs */ '-245 -130 -130', '230 130 130', -/* model */ "models/vehicles/bumblebee_body.dpm", -/* head_model */ "", -/* hud_model */ "models/vehicles/spiderbot_cockpit.dpm", -/* tags */ "", "", "tag_viewport", -/* netname */ "bumblebee", -/* fullname */ _("Bumblebee") -) { - this.m_icon = "vehicle_bumble"; -#ifndef MENUQC - this.vehicle_func = v_bumblebee; -#endif -} -#endif - -#ifdef IMPLEMENTATION - -const float BRG_SETUP = 2; -const float BRG_START = 4; -const float BRG_END = 8; - -#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_cost; -float autocvar_g_vehicle_bumblebee_cannon_damage; -float autocvar_g_vehicle_bumblebee_cannon_radius; -float autocvar_g_vehicle_bumblebee_cannon_refire; -float autocvar_g_vehicle_bumblebee_cannon_speed; -float autocvar_g_vehicle_bumblebee_cannon_spread; -float autocvar_g_vehicle_bumblebee_cannon_force; - -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 bumble_raygun_send(entity to, int sf); - -void bumblebee_fire_cannon(entity _gun, string _tagname, entity _owner) -{ - vector v = gettaginfo(_gun, gettagindex(_gun, _tagname)); - vehicles_projectile(EFFECT_BIGPLASMA_MUZZLEFLASH.eent_eff_name, SND(VEH_BUMBLEBEE_FIRE), - v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed, - autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force, 0, - DEATH_VH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner); -} - -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; -} - -float bumble_raygun_send(entity to, float sf) -{SELFPARAM(); - WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN); - - WriteByte(MSG_ENTITY, sf); - if(sf & BRG_SETUP) - { - WriteByte(MSG_ENTITY, num_for_edict(self.realowner)); - WriteByte(MSG_ENTITY, self.realowner.team); - WriteByte(MSG_ENTITY, self.cnt); - } - - if(sf & BRG_START) - { - WriteCoord(MSG_ENTITY, self.hook_start_x); - WriteCoord(MSG_ENTITY, self.hook_start_y); - WriteCoord(MSG_ENTITY, self.hook_start_z); - } - - if(sf & BRG_END) - { - WriteCoord(MSG_ENTITY, self.hook_end_x); - WriteCoord(MSG_ENTITY, self.hook_end_y); - WriteCoord(MSG_ENTITY, self.hook_end_z); - } - - return true; -} - -void spawnfunc_vehicle_bumblebee() -{SELFPARAM(); - if(!autocvar_g_vehicle_bumblebee) { remove(self); return; } - if(!vehicle_initialize(VEH_BUMBLEBEE, false)) { remove(self); return; } -} - -float v_bumblebee(float req) -{SELFPARAM(); - switch(req) - { - case VR_IMPACT: - { - 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); - - return true; - } - case VR_ENTER: - { - self.touch = bumblebee_touch; - self.nextthink = 0; - self.movetype = MOVETYPE_BOUNCEMISSILE; - return true; - } - case VR_THINK: - { - 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 true; - } - - 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 true; - } - } - - return true; - } - case VR_DEATH: - { - 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); - return true; - } - case VR_SPAWN: - { - 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'); - return true; - } - case VR_SETUP: - { - 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; - - return true; - } - case VR_PRECACHE: - { - return true; - } - } - - return true; -} - -#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); -} - -void bumble_raygun_draw() -{SELFPARAM(); - float _len; - vector _dir; - vector _vtmp1, _vtmp2; - - _len = vlen(self.origin - self.move_origin); - _dir = normalize(self.move_origin - self.origin); - - if(self.total_damages < time) - { - boxparticles(self.traileffect, self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA); - boxparticles(self.lip, self, self.move_origin, self.move_origin + _dir * -64, _dir * -200 , _dir * -200, 1, PARTICLES_USEALPHA); - self.total_damages = time + 0.1; - } - - float i, df, sz, al; - for(i = -0.1; i < 0.2; i += 0.1) - { - df = DRAWFLAG_NORMAL; //((random() < 0.5) ? DRAWFLAG_ADDITIVE : DRAWFLAG_SCREEN); - sz = 5 + random() * 5; - al = 0.25 + random() * 0.5; - _vtmp1 = self.origin + _dir * _len * (0.25 + i); - _vtmp1 += (randomvec() * (_len * 0.2) * (frametime * 2)); //self.raygun_l1; - Draw_CylindricLine(self.origin, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin); - - _vtmp2 = self.origin + _dir * _len * (0.5 + i); - _vtmp2 += (randomvec() * (_len * 0.2) * (frametime * 5)); //self.raygun_l2; - Draw_CylindricLine(_vtmp1, _vtmp2, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin); - - _vtmp1 = self.origin + _dir * _len * (0.75 + i); - _vtmp1 += randomvec() * (_len * 0.2) * (frametime * 10); //self.raygun_l3; - Draw_CylindricLine(_vtmp2, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin); - - Draw_CylindricLine(_vtmp1, self.move_origin + randomvec() * 32, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin); - } -} - -void bumble_raygun_read(bool bIsNew) -{SELFPARAM(); - int sf = ReadByte(); - - if(sf & BRG_SETUP) - { - self.cnt = ReadByte(); - self.team = ReadByte(); - self.cnt = ReadByte(); - - if(self.cnt) - self.colormod = '1 0 0'; - else - self.colormod = '0 1 0'; - - self.traileffect = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_MUZZLEFLASH); - self.lip = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_IMPACT); - - self.draw = bumble_raygun_draw; - } - - - if(sf & BRG_START) - { - self.origin_x = ReadCoord(); - self.origin_y = ReadCoord(); - self.origin_z = ReadCoord(); - setorigin(self, self.origin); - } - - if(sf & BRG_END) - { - self.move_origin_x = ReadCoord(); - self.move_origin_y = ReadCoord(); - self.move_origin_z = ReadCoord(); - } -} - -float v_bumblebee(float req) -{ - switch(req) - { - case VR_HUD: - { - 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); - return true; - } - case VR_SETUP: - { - AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Raygun-locked - AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1 - AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2 - return true; - } - case VR_PRECACHE: - { - return true; - } - } - - return true; -} - -#endif // CSQC -#endif // REGISTER_VEHICLE diff --git a/qcsrc/common/vehicles/unit/bumblebee.qh b/qcsrc/common/vehicles/unit/bumblebee.qh deleted file mode 100644 index 7c387e448..000000000 --- a/qcsrc/common/vehicles/unit/bumblebee.qh +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef BUMBLEBEE_H -#define BUMBLEBEE_H - -#ifdef CSQC -void bumble_raygun_read(bool bIsNew); - -void CSQC_BUMBLE_GUN_HUD(); -#endif - -#endif diff --git a/qcsrc/common/vehicles/unit/racer.qc b/qcsrc/common/vehicles/unit/racer.qc deleted file mode 100644 index 3c0db8854..000000000 --- a/qcsrc/common/vehicles/unit/racer.qc +++ /dev/null @@ -1,890 +0,0 @@ -#ifndef VEHICLE_RACER -#define VEHICLE_RACER - -#ifndef MENUQC -int v_racer(int); -#endif -REGISTER_VEHICLE_SIMPLE( -/* VEH_##id */ RACER, -/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL, -/* mins,maxs */ '-120 -120 -40' * 0.5, '120 120 40' * 0.5, -/* model */ "models/vehicles/wakizashi.dpm", -/* head_model */ "null", -/* hud_model */ "models/vehicles/wakizashi_cockpit.dpm", -/* tags */ "", "", "tag_viewport", -/* netname */ "racer", -/* fullname */ _("Racer") -) { - this.m_icon = "vehicle_racer"; -#ifndef MENUQC - this.vehicle_func = v_racer; -#endif -} - -#include "../../weapons/all.qh" - -CLASS(RacerAttack, PortoLaunch) -/* flags */ ATTRIB(RacerAttack, spawnflags, int, WEP_TYPE_OTHER); -/* impulse */ ATTRIB(RacerAttack, impulse, int, 3); -/* refname */ ATTRIB(RacerAttack, netname, string, "racercannon"); -/* wepname */ ATTRIB(RacerAttack, message, string, _("Racer cannon")); -ENDCLASS(RacerAttack) -REGISTER_WEAPON(RACER, NEW(RacerAttack)); - -#endif - -#ifdef IMPLEMENTATION -#ifdef SVQC -#include "../../effects/effects.qh" -#include "../../triggers/trigger/impulse.qh" - -void racer_fire_cannon(string tagname); -METHOD(RacerAttack, wr_think, bool(entity thiswep)) { - SELFPARAM(); - if (self.BUTTON_ATCK) - if (weapon_prepareattack(0, 0)) { - W_SetupShot_Dir(self, v_forward, false, 0, W_Sound("lasergun_fire"), CH_WEAPON_B, 0); - racer_fire_cannon("tag_fire1"); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), w_ready); - } - return true; -} - -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_cannon_cost; -float autocvar_g_vehicle_racer_cannon_damage; -float autocvar_g_vehicle_racer_cannon_radius; -float autocvar_g_vehicle_racer_cannon_refire; -float autocvar_g_vehicle_racer_cannon_speed; -float autocvar_g_vehicle_racer_cannon_spread; -float autocvar_g_vehicle_racer_cannon_force; - -float autocvar_g_vehicle_racer_rocket_accel; -float autocvar_g_vehicle_racer_rocket_damage; -float autocvar_g_vehicle_racer_rocket_radius; -float autocvar_g_vehicle_racer_rocket_force; -float autocvar_g_vehicle_racer_rocket_refire; -float autocvar_g_vehicle_racer_rocket_speed; -float autocvar_g_vehicle_racer_rocket_turnrate; - -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_rocket_locked_maxangle; -float autocvar_g_vehicle_racer_rocket_climbspeed; - -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_cannon(string tagname) -{SELFPARAM(); - vector v; - entity bolt; - - v = gettaginfo(self, gettagindex(self, tagname)); - bolt = vehicles_projectile(EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE), - v, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed, - autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0, - DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, self.owner); - - // Fix z-aim (for chase mode) - v = normalize(trace_endpos - bolt.origin); - v_forward_z = v_z * 0.5; - bolt.velocity = v_forward * autocvar_g_vehicle_racer_cannon_speed; -} - -void racer_rocket_groundhugger() -{SELFPARAM(); - vector olddir, newdir; - float oldvel, newvel; - - self.nextthink = time; - - if(self.owner.deadflag != DEAD_NO || self.cnt < time) - { - self.use(); - return; - } - - if(!self.realowner.vehicle) - { - UpdateCSQCProjectile(self); - return; - } - - olddir = normalize(self.velocity); - oldvel = vlen(self.velocity); - newvel = oldvel + self.lip; - - tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self); - if(trace_fraction <= 0.5) - { - // Hitting somethign soon, just speed ahead - self.velocity = olddir * newvel; - UpdateCSQCProjectile(self); - return; - } - - traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self); - if(trace_fraction != 1.0) - { - newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate; - self.velocity = normalize(olddir + newdir) * newvel; - } - else - { - self.velocity = olddir * newvel; - self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one - } - - int cont = pointcontents(self.origin - '0 0 32'); - if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME) - self.velocity_z += 200; - - UpdateCSQCProjectile(self); - return; -} - -void racer_rocket_tracker() -{SELFPARAM(); - vector olddir, newdir; - float oldvel, newvel; - - self.nextthink = time; - - if (self.owner.deadflag != DEAD_NO || self.cnt < time) - { - self.use(); - return; - } - - if(!self.realowner.vehicle) - { - UpdateCSQCProjectile(self); - return; - } - - olddir = normalize(self.velocity); - oldvel = vlen(self.velocity); - newvel = oldvel + self.lip; - makevectors(vectoangles(olddir)); - - float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1); - vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact; - - traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self); - newdir = normalize(predicted_origin - self.origin); - - //vector - float height_diff = predicted_origin_z - self.origin_z; - - if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle) - { - //bprint("Target lost!\n"); - //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n"); - self.think = racer_rocket_groundhugger; - return; - } - - if(trace_fraction != 1.0 && trace_ent != self.enemy) - newdir_z += 16 * sys_frametime; - - self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel; - self.velocity_z -= 800 * sys_frametime; - self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ; - - UpdateCSQCProjectile(self); - return; -} - -void racer_fire_rocket(string tagname, entity trg) -{SELFPARAM(); - vector v = gettaginfo(self, gettagindex(self, tagname)); - entity rocket = vehicles_projectile(EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE), - v, v_forward * autocvar_g_vehicle_racer_rocket_speed, - autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3, - DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner); - - rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime; - rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate; - rocket.nextthink = time; - rocket.enemy = trg; - rocket.cnt = time + 15; - - if(trg) - rocket.think = racer_rocket_tracker; - else - rocket.think = racer_rocket_groundhugger; -} - -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 - if(!forbidWeaponUse(player)) - if(player.BUTTON_ATCK) - if(time > racer.attack_finished_single) - if(racer.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost) - { - racer.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost; - racer.wait = time; - - crosshair_trace(player); - if(racer.cnt) - { - racer_fire_cannon("tag_fire1"); - racer.cnt = 0; - } - else - { - racer_fire_cannon("tag_fire2"); - racer.cnt = 1; - } - racer.attack_finished_single = time + autocvar_g_vehicle_racer_cannon_refire; - } - - 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("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("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(); - 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 - -bool v_racer(int req) -{SELFPARAM(); - switch(req) - { - case VR_IMPACT: - { - #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 - return true; - } - - case VR_ENTER: - { - #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 - - return true; - } - - case VR_SPAWN: - { - #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 - return true; - } - - case VR_DEATH: - { - #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 - return true; - } - -#ifdef CSQC - case VR_HUD: - { - 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); - return true; - } -#endif - case VR_SETUP: - { - #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 - return true; - } - - case VR_PRECACHE: - { - return true; - } - } - - return true; -} - -#endif // REGISTER_VEHICLE diff --git a/qcsrc/common/vehicles/unit/raptor.qc b/qcsrc/common/vehicles/unit/raptor.qc deleted file mode 100644 index 742ef7b9b..000000000 --- a/qcsrc/common/vehicles/unit/raptor.qc +++ /dev/null @@ -1,1062 +0,0 @@ -#ifndef VEHICLE_RAPTOR -#define VEHICLE_RAPTOR -#include "raptor.qh" -#ifndef MENUQC -int v_raptor(int); -#endif -REGISTER_VEHICLE_SIMPLE( -/* VEH_##id */ RAPTOR, -/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL, -/* mins,maxs */ '-80 -80 0', '80 80 70', -/* model */ "models/vehicles/raptor.dpm", -/* head_model */ "", -/* hud_model */ "models/vehicles/raptor_cockpit.dpm", -/* tags */ "", "tag_hud", "tag_camera", -/* netname */ "raptor", -/* fullname */ _("Raptor") -) { - this.m_icon = "vehicle_raptor"; -#ifndef MENUQC - this.vehicle_func = v_raptor; -#endif -} -#endif - -#ifdef IMPLEMENTATION - -#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_bomblets; -float autocvar_g_vehicle_raptor_bomblet_alt; -float autocvar_g_vehicle_raptor_bomblet_time; -float autocvar_g_vehicle_raptor_bomblet_damage; -float autocvar_g_vehicle_raptor_bomblet_spread; -float autocvar_g_vehicle_raptor_bomblet_edgedamage; -float autocvar_g_vehicle_raptor_bomblet_radius; -float autocvar_g_vehicle_raptor_bomblet_force; -float autocvar_g_vehicle_raptor_bomblet_explode_delay; -float autocvar_g_vehicle_raptor_bombs_refire; - -float autocvar_g_vehicle_raptor_flare_refire; -float autocvar_g_vehicle_raptor_flare_lifetime; -float autocvar_g_vehicle_raptor_flare_chase; -float autocvar_g_vehicle_raptor_flare_range; - -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_cannon_cost; -float autocvar_g_vehicle_raptor_cannon_damage; -float autocvar_g_vehicle_raptor_cannon_radius; -float autocvar_g_vehicle_raptor_cannon_refire; -float autocvar_g_vehicle_raptor_cannon_speed; -float autocvar_g_vehicle_raptor_cannon_spread; -float autocvar_g_vehicle_raptor_cannon_force; - -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_bomblet_boom() -{SELFPARAM(); - RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage, - autocvar_g_vehicle_raptor_bomblet_edgedamage, - autocvar_g_vehicle_raptor_bomblet_radius, world, world, - autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world); - remove(self); -} - -void raptor_bomblet_touch() -{SELFPARAM(); - if(other == self.owner) - return; - - PROJECTILE_TOUCH; - self.think = raptor_bomblet_boom; - self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay; -} - -void raptor_bomb_burst() -{SELFPARAM(); - if(self.cnt > time) - if(autocvar_g_vehicle_raptor_bomblet_alt) - { - self.nextthink = time; - traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self); - if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius)) - { - UpdateCSQCProjectile(self); - return; - } - } - - entity bomblet; - float i; - - Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self); - - for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i) - { - bomblet = spawn(); - setorigin(bomblet, self.origin); - - bomblet.movetype = MOVETYPE_TOSS; - bomblet.touch = raptor_bomblet_touch; - bomblet.think = raptor_bomblet_boom; - bomblet.nextthink = time + 5; - bomblet.owner = self.owner; - bomblet.realowner = self.realowner; - bomblet.velocity = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity); - - PROJECTILE_MAKETRIGGER(bomblet); - CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true); - } - - remove(self); -} - -void raptor_bombdrop() -{SELFPARAM(); - entity bomb_1, bomb_2; - - bomb_1 = spawn(); - bomb_2 = spawn(); - - setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left"))); - setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right"))); - - bomb_1.movetype = bomb_2.movetype = MOVETYPE_BOUNCE; - bomb_1.velocity = bomb_2.velocity = self.velocity; - bomb_1.touch = bomb_2.touch = raptor_bomb_burst; - bomb_1.think = bomb_2.think = raptor_bomb_burst; - bomb_1.cnt = bomb_2.cnt = time + 10; - - if(autocvar_g_vehicle_raptor_bomblet_alt) - bomb_1.nextthink = bomb_2.nextthink = time; - else - bomb_1.nextthink = bomb_2.nextthink = time + autocvar_g_vehicle_raptor_bomblet_time; - - bomb_1.owner = bomb_2.owner = self; - bomb_1.realowner = bomb_2.realowner = self.owner; - bomb_1.solid = bomb_2.solid = SOLID_BBOX; - bomb_1.gravity = bomb_2.gravity = 1; - - PROJECTILE_MAKETRIGGER(bomb_1); - PROJECTILE_MAKETRIGGER(bomb_2); - - CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true); - CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true); -} - - -void raptor_fire_cannon(entity gun, string tagname) -{SELFPARAM(); - vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE), - gettaginfo(gun, gettagindex(gun, tagname)), normalize(v_forward + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed, - autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force, 0, - DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, true, true, self.owner); -} - -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; -} - -void raptor_flare_touch() -{SELFPARAM(); - remove(self); -} - -void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) -{SELFPARAM(); - self.health -= damage; - if(self.health <= 0) - remove(self); -} - -void raptor_flare_think() -{SELFPARAM(); - self.nextthink = time + 0.1; - entity _missile = findchainentity(enemy, self.owner); - while(_missile) - { - if(_missile.flags & FL_PROJECTILE) - if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range) - if(random() > autocvar_g_vehicle_raptor_flare_chase) - _missile.enemy = self; - _missile = _missile.chain; - } - - if(self.tur_impacttime < time) - remove(self); -} - -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); - */ - - if(!forbidWeaponUse(player)) - if(player.BUTTON_ATCK) - if(raptor.attack_finished_single <= time) - if(raptor.vehicle_energy > autocvar_g_vehicle_raptor_cannon_cost) - { - raptor.misc_bulletcounter += 1; - raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire; - if(raptor.misc_bulletcounter <= 2) - raptor_fire_cannon(self.gun1, "fire1"); - else if(raptor.misc_bulletcounter == 3) - raptor_fire_cannon(self.gun2, "fire1"); - else - { - raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire * 2; - raptor_fire_cannon(self.gun2, "fire1"); - raptor.misc_bulletcounter = 0; - } - raptor.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost; - self.cnt = time; - } - - 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); - - if(!forbidWeaponUse(player)) - if(raptor.vehicle_weapon2mode == RSM_BOMB) - { - if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire) - if(player.BUTTON_ATCK2) - { - raptor_bombdrop(); - raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire; - raptor.lip = time; - } - } - else - { - if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire) - if(player.BUTTON_ATCK2) - { - float i; - entity _flare; - - for(i = 0; i < 3; ++i) - { - _flare = spawn(); - setmodel(_flare, MDL_VEH_RAPTOR_FLARE); - _flare.effects = EF_LOWPRECISION | EF_FLAME; - _flare.scale = 0.5; - setorigin(_flare, self.origin - '0 0 16'); - _flare.movetype = MOVETYPE_TOSS; - _flare.gravity = 0.15; - _flare.velocity = 0.25 * raptor.velocity + (v_forward + randomvec() * 0.25)* -500; - _flare.think = raptor_flare_think; - _flare.nextthink = time; - _flare.owner = raptor; - _flare.solid = SOLID_CORPSE; - _flare.takedamage = DAMAGE_YES; - _flare.event_damage = raptor_flare_damage; - _flare.health = 20; - _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime; - _flare.touch = raptor_flare_touch; - } - 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: - case 230: - self.vehicle.vehicle_weapon2mode = RSM_BOMB; - CSQCVehicleSetup(self, 0); - return true; - case 2: - case 231: - 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(); - if(!autocvar_g_vehicle_raptor) { remove(self); return; } - if(!vehicle_initialize(VEH_RAPTOR, false)) { remove(self); return; } -} - -float v_raptor(float req) -{SELFPARAM(); - switch(req) - { - case VR_IMPACT: - { - 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); - - return true; - } - case VR_ENTER: - { - 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); - return true; - } - case VR_THINK: - { - return true; - } - case VR_DEATH: - { - 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; - return true; - } - case VR_SPAWN: - { - 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; - return true; - } - case VR_SETUP: - { - 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; - - return true; - } - case VR_PRECACHE: - { - return true; - } - } - - return true; -} - -#endif // SVQC -#ifdef CSQC - -void RaptorCBShellfragDraw() -{SELFPARAM(); - if(wasfreed(self)) - return; - - Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy); - self.move_avelocity += randomvec() * 15; - self.renderflags = 0; - - if(self.cnt < time) - self.alpha = bound(0, self.nextthink - time, 1); - - if(self.alpha < ALPHA_MIN_VISIBLE) - remove(self); -} - -void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang) -{SELFPARAM(); - entity sfrag; - - sfrag = spawn(); - setmodel(sfrag, MDL_VEH_RAPTOR_CB_FRAGMENT); - setorigin(sfrag, _org); - - sfrag.move_movetype = MOVETYPE_BOUNCE; - sfrag.gravity = 0.15; - sfrag.solid = SOLID_CORPSE; - - sfrag.draw = RaptorCBShellfragDraw; - - sfrag.move_origin = sfrag.origin = _org; - sfrag.move_velocity = _vel; - sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity); - sfrag.angles = self.move_angles = _ang; - - sfrag.move_time = time; - sfrag.damageforcescale = 4; - - sfrag.nextthink = time + 3; - sfrag.cnt = time + 2; - sfrag.alpha = 1; - sfrag.drawmask = MASK_NORMAL; -} - -float v_raptor(float req) -{ - switch(req) - { - case VR_HUD: - { - 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); - return true; - } - case VR_SETUP: - { - AuxiliaryXhair[1].axh_image = vCROSS_LOCK; - return true; - } - case VR_PRECACHE: - { - return true; - } - } - - return true; -} - -#endif // CSQC -#endif // REGISTER_VEHICLE diff --git a/qcsrc/common/vehicles/unit/raptor.qh b/qcsrc/common/vehicles/unit/raptor.qh deleted file mode 100644 index f24939ba9..000000000 --- a/qcsrc/common/vehicles/unit/raptor.qh +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef RAPTOR_H -#define RAPTOR_H - -const int RSM_FIRST = 1; -const int RSM_BOMB = 1; -const int RSM_FLARE = 2; -const int RSM_LAST = 2; - -#endif diff --git a/qcsrc/common/vehicles/unit/spiderbot.qc b/qcsrc/common/vehicles/unit/spiderbot.qc deleted file mode 100644 index f8efe528d..000000000 --- a/qcsrc/common/vehicles/unit/spiderbot.qc +++ /dev/null @@ -1,979 +0,0 @@ -#ifndef VEHICLE_SPIDERBOT -#define VEHICLE_SPIDERBOT -#ifndef MENUQC -int v_spiderbot(int); -#endif -REGISTER_VEHICLE_SIMPLE( -/* VEH_##id */ SPIDERBOT, -/* spawnflags */ VHF_DMGSHAKE, -/* mins,maxs */ '-75 -75 10', '75 75 125', -/* model */ "models/vehicles/spiderbot.dpm", -/* head_model */ "models/vehicles/spiderbot_top.dpm", -/* hud_model */ "models/vehicles/spiderbot_cockpit.dpm", -/* tags */ "tag_head", "tag_hud", "", -/* netname */ "spiderbot", -/* fullname */ _("Spiderbot") -) { - this.m_icon = "vehicle_spider"; -#ifndef MENUQC - this.vehicle_func = v_spiderbot; -#endif -} -#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; - -#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; - -float autocvar_g_vehicle_spiderbot_minigun_damage; -float autocvar_g_vehicle_spiderbot_minigun_refire; -float autocvar_g_vehicle_spiderbot_minigun_spread; -int autocvar_g_vehicle_spiderbot_minigun_ammo_cost; -int autocvar_g_vehicle_spiderbot_minigun_ammo_max; -int autocvar_g_vehicle_spiderbot_minigun_ammo_regen; -float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause; -float autocvar_g_vehicle_spiderbot_minigun_force; -float autocvar_g_vehicle_spiderbot_minigun_solidpenetration; - -float autocvar_g_vehicle_spiderbot_rocket_damage; -float autocvar_g_vehicle_spiderbot_rocket_force; -float autocvar_g_vehicle_spiderbot_rocket_radius; -float autocvar_g_vehicle_spiderbot_rocket_speed; -float autocvar_g_vehicle_spiderbot_rocket_spread; -float autocvar_g_vehicle_spiderbot_rocket_refire; -float autocvar_g_vehicle_spiderbot_rocket_refire2; -float autocvar_g_vehicle_spiderbot_rocket_reload; -float autocvar_g_vehicle_spiderbot_rocket_health; -float autocvar_g_vehicle_spiderbot_rocket_noise; -float autocvar_g_vehicle_spiderbot_rocket_turnrate; -float autocvar_g_vehicle_spiderbot_rocket_lifetime; - -vector autocvar_g_vehicle_spiderbot_bouncepain; - -void spiderbot_rocket_artillery() -{SELFPARAM(); - self.nextthink = time; - UpdateCSQCProjectile(self); -} - -void spiderbot_rocket_unguided() -{SELFPARAM(); - vector newdir, olddir; - - self.nextthink = time; - - olddir = normalize(self.velocity); - newdir = normalize(self.pos1 - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise; - self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed; - - UpdateCSQCProjectile(self); - - if (self.owner.deadflag != DEAD_NO || self.cnt < time || vlen(self.pos1 - self.origin) < 16) - self.use(); -} - -void spiderbot_rocket_guided() -{SELFPARAM(); - vector newdir, olddir; - - self.nextthink = time; - - if(!self.realowner.vehicle) - self.think = spiderbot_rocket_unguided; - - crosshair_trace(self.realowner); - olddir = normalize(self.velocity); - newdir = normalize(trace_endpos - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise; - self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed; - - UpdateCSQCProjectile(self); - - if (self.owner.deadflag != DEAD_NO || self.cnt < time) - self.use(); -} - -void spiderbot_guide_release() -{SELFPARAM(); - entity rkt; - rkt = findchainentity(realowner, self.owner); - if(!rkt) - return; - - crosshair_trace(self.owner); - while(rkt) - { - if(rkt.think == spiderbot_rocket_guided) - { - rkt.pos1 = trace_endpos; - rkt.think = spiderbot_rocket_unguided; - } - rkt = rkt.chain; - } -} - -float spiberbot_calcartillery_flighttime; -vector spiberbot_calcartillery(vector org, vector tgt, float ht) -{ - float grav, sdist, zdist, vs, vz, jumpheight; - vector sdir; - - grav = autocvar_sv_gravity; - zdist = tgt_z - org_z; - sdist = vlen(tgt - org - zdist * '0 0 1'); - sdir = normalize(tgt - org - zdist * '0 0 1'); - - // how high do we need to go? - jumpheight = fabs(ht); - if(zdist > 0) - jumpheight = jumpheight + zdist; - - // push so high... - vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)! - - // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump! - if(ht < 0) - if(zdist < 0) - vz = -vz; - - vector solution; - solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist" - // ALWAYS solvable because jumpheight >= zdist - if(!solution_z) - solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0) - if(zdist == 0) - solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually) - - if(zdist < 0) - { - // down-jump - if(ht < 0) - { - // almost straight line type - // jump apex is before the jump - // we must take the larger one - spiberbot_calcartillery_flighttime = solution_y; - } - else - { - // regular jump - // jump apex is during the jump - // we must take the larger one too - spiberbot_calcartillery_flighttime = solution_y; - } - } - else - { - // up-jump - if(ht < 0) - { - // almost straight line type - // jump apex is after the jump - // we must take the smaller one - spiberbot_calcartillery_flighttime = solution_x; - } - else - { - // regular jump - // jump apex is during the jump - // we must take the larger one - spiberbot_calcartillery_flighttime = solution_y; - } - } - vs = sdist / spiberbot_calcartillery_flighttime; - - // finally calculate the velocity - return sdir * vs + '0 0 1' * vz; -} - -void spiderbot_rocket_do() -{SELFPARAM(); - vector v; - entity rocket = world; - - if (self.wait != -10) - { - if (self.owner.BUTTON_ATCK2 && self.vehicle_weapon2mode == SBRM_GUIDE) - { - if (self.wait == 1) - if (self.tur_head.frame == 9 || self.tur_head.frame == 1) - { - if(self.gun2.cnt < time && self.tur_head.frame == 9) - self.tur_head.frame = 1; - - return; - } - self.wait = 1; - } - else - { - if(self.wait) - spiderbot_guide_release(); - - self.wait = 0; - } - } - - if(self.gun2.cnt > time) - return; - - if (self.tur_head.frame >= 9) - { - self.tur_head.frame = 1; - self.wait = 0; - } - - if(self.wait != -10) - if(!self.owner.BUTTON_ATCK2) - return; - - if(forbidWeaponUse(self.owner)) - return; - - v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire")); - - switch(self.vehicle_weapon2mode) - { - case SBRM_VOLLY: - rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE), - v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, - autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, - DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner); - crosshair_trace(self.owner); - float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos); - _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ; - rocket.nextthink = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed); - rocket.think = vehicles_projectile_explode; - - if(self.owner.BUTTON_ATCK2 && self.tur_head.frame == 1) - self.wait = -10; - break; - case SBRM_GUIDE: - rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE), - v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, - autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, - DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, self.owner); - crosshair_trace(self.owner); - rocket.pos1 = trace_endpos; - rocket.nextthink = time; - rocket.think = spiderbot_rocket_guided; - - - break; - case SBRM_ARTILLERY: - rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE), - v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, - autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, - DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner); - - crosshair_trace(self.owner); - - rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius); - rocket.pos1_z = trace_endpos_z; - - traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self); - float h1 = 0.75 * vlen(v - trace_endpos); - - //v = trace_endpos; - traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self); - float h2 = 0.75 * vlen(rocket.pos1 - v); - - rocket.velocity = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2)); - rocket.movetype = MOVETYPE_TOSS; - rocket.gravity = 1; - //rocket.think = spiderbot_rocket_artillery; - break; - } - rocket.classname = "spiderbot_rocket"; - - rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime; - - self.tur_head.frame += 1; - if (self.tur_head.frame == 9) - self.attack_finished_single = autocvar_g_vehicle_spiderbot_rocket_reload; - else - self.attack_finished_single = ((self.vehicle_weapon2mode == SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire); - - self.gun2.cnt = time + self.attack_finished_single; -} - -.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: - case 230: - self.vehicle.vehicle_weapon2mode = SBRM_VOLLY; - CSQCVehicleSetup(self, 0); - return true; - case 2: - case 231: - self.vehicle.vehicle_weapon2mode = SBRM_GUIDE; - CSQCVehicleSetup(self, 0); - return true; - case 3: - case 232: - case 251: - 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(); - if(!autocvar_g_vehicle_spiderbot) { remove(self); return; } - if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; } -} - -float v_spiderbot(float req) -{SELFPARAM(); - switch(req) - { - case VR_IMPACT: - { - 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); - - return true; - } - case VR_ENTER: - { - 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'); - } - - return true; - } - case VR_THINK: - { - if(self.flags & FL_ONGROUND) - movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop); - - return true; - } - case VR_DEATH: - { - 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 - - return true; - } - case VR_SPAWN: - { - 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; - - return true; - } - case VR_SETUP: - { - 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 - - return true; - } - case VR_PRECACHE: - { - return true; - } - } - - return true; -} - -#endif // SVQC -#ifdef CSQC -float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6; -float autocvar_cl_vehicle_spiderbot_cross_size = 1; - -float v_spiderbot(float req) -{ - switch(req) - { - case VR_HUD: - { - 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); - return true; - } - case VR_SETUP: - { - AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1 - AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2 - - return true; - } - case VR_PRECACHE: - { - return true; - } - } - - return true; -} - -#endif // CSQC -#endif // REGISTER_VEHICLE diff --git a/qcsrc/common/vehicles/vehicle.qh b/qcsrc/common/vehicles/vehicle.qh index 7df34206f..8de51fd36 100644 --- a/qcsrc/common/vehicles/vehicle.qh +++ b/qcsrc/common/vehicles/vehicle.qh @@ -1,7 +1,53 @@ #ifndef VEHICLE_H #define VEHICLE_H -int v_null(int) { return 0; } +// vehicle requests +const int VR_SETUP = 1; // (BOTH) setup vehicle data +.bool(entity) vr_setup; +const int VR_THINK = 2; // (SERVER) logic to run every frame +.bool(entity) vr_think; +const int VR_DEATH = 3; // (SERVER) called when vehicle dies +.bool(entity) vr_death; +const int VR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this vehicle +.bool(entity) vr_precache; +const int VR_ENTER = 5; // (SERVER) called when a player enters this vehicle +.bool(entity) vr_enter; +const int VR_SPAWN = 6; // (SERVER) called when the vehicle re-spawns +.bool(entity) vr_spawn; +const int VR_IMPACT = 7; // (SERVER) called when a vehicle hits something +.bool(entity) vr_impact; +const int VR_HUD = 8; // (CLIENT) logic to run every frame +.bool(entity) vr_hud; + +// vehicle spawn flags (need them here for common registrations) +const int VHF_ISVEHICLE = 2; /// Indicates vehicle +const int VHF_HASSHIELD = 4; /// Vehicle has shileding +const int VHF_SHIELDREGEN = 8; /// Vehicles shield regenerates +const int VHF_HEALTHREGEN = 16; /// Vehicles health regenerates +const int VHF_ENERGYREGEN = 32; /// Vehicles energy regenerates +const int VHF_DEATHEJECT = 64; /// Vehicle ejects pilot upon fatal damage +const int VHF_MOVE_GROUND = 128; /// Vehicle moves on gound +const int VHF_MOVE_HOVER = 256; /// Vehicle hover close to gound +const int VHF_MOVE_FLY = 512; /// Vehicle is airborn +const int VHF_DMGSHAKE = 1024; /// Add random velocity each frame if health < 50% +const int VHF_DMGROLL = 2048; /// Add random angles each frame if health < 50% +const int VHF_DMGHEADROLL = 4096; /// Add random head angles each frame if health < 50% +const int VHF_MULTISLOT = 8192; /// Vehicle has multiple player slots +const int VHF_PLAYERSLOT = 16384; /// This ent is a player slot on a multi-person vehicle + +// functions: +entity get_vehicleinfo(int id); + +// fields: +.entity tur_head; + +// other useful macros +#define _VEH_ACTION(veh, mrequest) veh.vehicle_func(veh, mrequest) +#define VEH_ACTION(veh, mrequest) _VEH_ACTION(get_vehicleinfo(veh), mrequest) +#define VEH_NAME(veh) (get_vehicleinfo(veh)).vehicle_name + +bool v_null(entity, int) { return false; } +bool v_new(entity, int); CLASS(Vehicle, Object) ATTRIB(Vehicle, vehicleid, int, 0) @@ -12,7 +58,7 @@ CLASS(Vehicle, Object) /** human readable name */ ATTRIB(Vehicle, vehicle_name, string, "Vehicle") /** */ - ATTRIB(Vehicle, vehicle_func, int(int), v_null) + ATTRIB(Vehicle, vehicle_func, bool(Vehicle, int), v_null) /** full name of model */ ATTRIB(Vehicle, model, string, "") /** currently a copy of the model */ @@ -37,4 +83,17 @@ CLASS(Vehicle, Object) ATTRIB(Vehicle, maxs, vector, '0 0 0') ENDCLASS(Vehicle) +bool v_new(Vehicle this, int req) +{ + if (req == VR_SETUP) return this.vr_setup ? this.vr_setup(this) : false; + if (req == VR_THINK) return this.vr_think ? this.vr_think(this) : false; + if (req == VR_DEATH) return this.vr_death ? this.vr_death(this) : false; + if (req == VR_PRECACHE) return this.vr_precache ? this.vr_precache(this) : false; + if (req == VR_ENTER) return this.vr_enter ? this.vr_enter(this) : false; + if (req == VR_SPAWN) return this.vr_spawn ? this.vr_spawn(this) : false; + if (req == VR_IMPACT) return this.vr_impact ? this.vr_impact(this) : false; + if (req == VR_HUD) return this.vr_hud ? this.vr_hud(this) : false; + return false; +} + #endif diff --git a/qcsrc/common/vehicles/vehicle/bumblebee.qc b/qcsrc/common/vehicles/vehicle/bumblebee.qc new file mode 100644 index 000000000..490e165c3 --- /dev/null +++ b/qcsrc/common/vehicles/vehicle/bumblebee.qc @@ -0,0 +1,1126 @@ +#ifndef VEHICLE_BUMBLEBEE +#define VEHICLE_BUMBLEBEE +#include "bumblebee.qh" +#ifndef MENUQC +int v_bumblebee(entity, int); +#endif +REGISTER_VEHICLE_SIMPLE( +/* VEH_##id */ BUMBLEBEE, +/* spawnflags */ VHF_DMGSHAKE, +/* mins,maxs */ '-245 -130 -130', '230 130 130', +/* model */ "models/vehicles/bumblebee_body.dpm", +/* head_model */ "", +/* hud_model */ "models/vehicles/spiderbot_cockpit.dpm", +/* tags */ "", "", "tag_viewport", +/* netname */ "bumblebee", +/* fullname */ _("Bumblebee") +) { + this.m_icon = "vehicle_bumble"; +#ifndef MENUQC + this.vehicle_func = v_bumblebee; +#endif +} +#endif + +#ifdef IMPLEMENTATION + +const float BRG_SETUP = 2; +const float BRG_START = 4; +const float BRG_END = 8; + +#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_cost; +float autocvar_g_vehicle_bumblebee_cannon_damage; +float autocvar_g_vehicle_bumblebee_cannon_radius; +float autocvar_g_vehicle_bumblebee_cannon_refire; +float autocvar_g_vehicle_bumblebee_cannon_speed; +float autocvar_g_vehicle_bumblebee_cannon_spread; +float autocvar_g_vehicle_bumblebee_cannon_force; + +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 bumble_raygun_send(entity to, int sf); + +void bumblebee_fire_cannon(entity _gun, string _tagname, entity _owner) +{ + vector v = gettaginfo(_gun, gettagindex(_gun, _tagname)); + vehicles_projectile(EFFECT_BIGPLASMA_MUZZLEFLASH.eent_eff_name, SND(VEH_BUMBLEBEE_FIRE), + v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed, + autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force, 0, + DEATH_VH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner); +} + +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; +} + +float bumble_raygun_send(entity to, float sf) +{SELFPARAM(); + WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN); + + WriteByte(MSG_ENTITY, sf); + if(sf & BRG_SETUP) + { + WriteByte(MSG_ENTITY, num_for_edict(self.realowner)); + WriteByte(MSG_ENTITY, self.realowner.team); + WriteByte(MSG_ENTITY, self.cnt); + } + + if(sf & BRG_START) + { + WriteCoord(MSG_ENTITY, self.hook_start_x); + WriteCoord(MSG_ENTITY, self.hook_start_y); + WriteCoord(MSG_ENTITY, self.hook_start_z); + } + + if(sf & BRG_END) + { + WriteCoord(MSG_ENTITY, self.hook_end_x); + WriteCoord(MSG_ENTITY, self.hook_end_y); + WriteCoord(MSG_ENTITY, self.hook_end_z); + } + + return true; +} + +void spawnfunc_vehicle_bumblebee() +{SELFPARAM(); + if(!autocvar_g_vehicle_bumblebee) { remove(self); return; } + if(!vehicle_initialize(VEH_BUMBLEBEE, false)) { remove(self); return; } +} + +float v_bumblebee(Vehicle thisveh, float req) +{SELFPARAM(); + switch(req) + { + case VR_IMPACT: + { + 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); + + return true; + } + case VR_ENTER: + { + self.touch = bumblebee_touch; + self.nextthink = 0; + self.movetype = MOVETYPE_BOUNCEMISSILE; + return true; + } + case VR_THINK: + { + 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 true; + } + + 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 true; + } + } + + return true; + } + case VR_DEATH: + { + 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); + return true; + } + case VR_SPAWN: + { + 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'); + return true; + } + case VR_SETUP: + { + 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; + + return true; + } + case VR_PRECACHE: + { + return true; + } + } + + return true; +} + +#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); +} + +void bumble_raygun_draw() +{SELFPARAM(); + float _len; + vector _dir; + vector _vtmp1, _vtmp2; + + _len = vlen(self.origin - self.move_origin); + _dir = normalize(self.move_origin - self.origin); + + if(self.total_damages < time) + { + boxparticles(self.traileffect, self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA); + boxparticles(self.lip, self, self.move_origin, self.move_origin + _dir * -64, _dir * -200 , _dir * -200, 1, PARTICLES_USEALPHA); + self.total_damages = time + 0.1; + } + + float i, df, sz, al; + for(i = -0.1; i < 0.2; i += 0.1) + { + df = DRAWFLAG_NORMAL; //((random() < 0.5) ? DRAWFLAG_ADDITIVE : DRAWFLAG_SCREEN); + sz = 5 + random() * 5; + al = 0.25 + random() * 0.5; + _vtmp1 = self.origin + _dir * _len * (0.25 + i); + _vtmp1 += (randomvec() * (_len * 0.2) * (frametime * 2)); //self.raygun_l1; + Draw_CylindricLine(self.origin, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin); + + _vtmp2 = self.origin + _dir * _len * (0.5 + i); + _vtmp2 += (randomvec() * (_len * 0.2) * (frametime * 5)); //self.raygun_l2; + Draw_CylindricLine(_vtmp1, _vtmp2, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin); + + _vtmp1 = self.origin + _dir * _len * (0.75 + i); + _vtmp1 += randomvec() * (_len * 0.2) * (frametime * 10); //self.raygun_l3; + Draw_CylindricLine(_vtmp2, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin); + + Draw_CylindricLine(_vtmp1, self.move_origin + randomvec() * 32, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin); + } +} + +void bumble_raygun_read(bool bIsNew) +{SELFPARAM(); + int sf = ReadByte(); + + if(sf & BRG_SETUP) + { + self.cnt = ReadByte(); + self.team = ReadByte(); + self.cnt = ReadByte(); + + if(self.cnt) + self.colormod = '1 0 0'; + else + self.colormod = '0 1 0'; + + self.traileffect = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_MUZZLEFLASH); + self.lip = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_IMPACT); + + self.draw = bumble_raygun_draw; + } + + + if(sf & BRG_START) + { + self.origin_x = ReadCoord(); + self.origin_y = ReadCoord(); + self.origin_z = ReadCoord(); + setorigin(self, self.origin); + } + + if(sf & BRG_END) + { + self.move_origin_x = ReadCoord(); + self.move_origin_y = ReadCoord(); + self.move_origin_z = ReadCoord(); + } +} + +float v_bumblebee(Vehicle thisveh, float req) +{ + switch(req) + { + case VR_HUD: + { + 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); + return true; + } + case VR_SETUP: + { + AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Raygun-locked + AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1 + AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2 + return true; + } + case VR_PRECACHE: + { + return true; + } + } + + return true; +} + +#endif // CSQC +#endif // REGISTER_VEHICLE diff --git a/qcsrc/common/vehicles/vehicle/bumblebee.qh b/qcsrc/common/vehicles/vehicle/bumblebee.qh new file mode 100644 index 000000000..7c387e448 --- /dev/null +++ b/qcsrc/common/vehicles/vehicle/bumblebee.qh @@ -0,0 +1,10 @@ +#ifndef BUMBLEBEE_H +#define BUMBLEBEE_H + +#ifdef CSQC +void bumble_raygun_read(bool bIsNew); + +void CSQC_BUMBLE_GUN_HUD(); +#endif + +#endif diff --git a/qcsrc/common/vehicles/vehicle/racer.qc b/qcsrc/common/vehicles/vehicle/racer.qc new file mode 100644 index 000000000..0606e9d38 --- /dev/null +++ b/qcsrc/common/vehicles/vehicle/racer.qc @@ -0,0 +1,890 @@ +#ifndef VEHICLE_RACER +#define VEHICLE_RACER + +#ifndef MENUQC +int v_racer(entity, int); +#endif +REGISTER_VEHICLE_SIMPLE( +/* VEH_##id */ RACER, +/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL, +/* mins,maxs */ '-120 -120 -40' * 0.5, '120 120 40' * 0.5, +/* model */ "models/vehicles/wakizashi.dpm", +/* head_model */ "null", +/* hud_model */ "models/vehicles/wakizashi_cockpit.dpm", +/* tags */ "", "", "tag_viewport", +/* netname */ "racer", +/* fullname */ _("Racer") +) { + this.m_icon = "vehicle_racer"; +#ifndef MENUQC + this.vehicle_func = v_racer; +#endif +} + +#include "../../weapons/all.qh" + +CLASS(RacerAttack, PortoLaunch) +/* flags */ ATTRIB(RacerAttack, spawnflags, int, WEP_TYPE_OTHER); +/* impulse */ ATTRIB(RacerAttack, impulse, int, 3); +/* refname */ ATTRIB(RacerAttack, netname, string, "racercannon"); +/* wepname */ ATTRIB(RacerAttack, message, string, _("Racer cannon")); +ENDCLASS(RacerAttack) +REGISTER_WEAPON(RACER, NEW(RacerAttack)); + +#endif + +#ifdef IMPLEMENTATION +#ifdef SVQC +#include "../../effects/effects.qh" +#include "../../triggers/trigger/impulse.qh" + +void racer_fire_cannon(string tagname); +METHOD(RacerAttack, wr_think, bool(entity thiswep)) { + SELFPARAM(); + if (self.BUTTON_ATCK) + if (weapon_prepareattack(0, 0)) { + W_SetupShot_Dir(self, v_forward, false, 0, W_Sound("lasergun_fire"), CH_WEAPON_B, 0); + racer_fire_cannon("tag_fire1"); + weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), w_ready); + } + return true; +} + +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_cannon_cost; +float autocvar_g_vehicle_racer_cannon_damage; +float autocvar_g_vehicle_racer_cannon_radius; +float autocvar_g_vehicle_racer_cannon_refire; +float autocvar_g_vehicle_racer_cannon_speed; +float autocvar_g_vehicle_racer_cannon_spread; +float autocvar_g_vehicle_racer_cannon_force; + +float autocvar_g_vehicle_racer_rocket_accel; +float autocvar_g_vehicle_racer_rocket_damage; +float autocvar_g_vehicle_racer_rocket_radius; +float autocvar_g_vehicle_racer_rocket_force; +float autocvar_g_vehicle_racer_rocket_refire; +float autocvar_g_vehicle_racer_rocket_speed; +float autocvar_g_vehicle_racer_rocket_turnrate; + +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_rocket_locked_maxangle; +float autocvar_g_vehicle_racer_rocket_climbspeed; + +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_cannon(string tagname) +{SELFPARAM(); + vector v; + entity bolt; + + v = gettaginfo(self, gettagindex(self, tagname)); + bolt = vehicles_projectile(EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE), + v, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed, + autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0, + DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, self.owner); + + // Fix z-aim (for chase mode) + v = normalize(trace_endpos - bolt.origin); + v_forward_z = v_z * 0.5; + bolt.velocity = v_forward * autocvar_g_vehicle_racer_cannon_speed; +} + +void racer_rocket_groundhugger() +{SELFPARAM(); + vector olddir, newdir; + float oldvel, newvel; + + self.nextthink = time; + + if(self.owner.deadflag != DEAD_NO || self.cnt < time) + { + self.use(); + return; + } + + if(!self.realowner.vehicle) + { + UpdateCSQCProjectile(self); + return; + } + + olddir = normalize(self.velocity); + oldvel = vlen(self.velocity); + newvel = oldvel + self.lip; + + tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self); + if(trace_fraction <= 0.5) + { + // Hitting somethign soon, just speed ahead + self.velocity = olddir * newvel; + UpdateCSQCProjectile(self); + return; + } + + traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self); + if(trace_fraction != 1.0) + { + newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate; + self.velocity = normalize(olddir + newdir) * newvel; + } + else + { + self.velocity = olddir * newvel; + self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one + } + + int cont = pointcontents(self.origin - '0 0 32'); + if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME) + self.velocity_z += 200; + + UpdateCSQCProjectile(self); + return; +} + +void racer_rocket_tracker() +{SELFPARAM(); + vector olddir, newdir; + float oldvel, newvel; + + self.nextthink = time; + + if (self.owner.deadflag != DEAD_NO || self.cnt < time) + { + self.use(); + return; + } + + if(!self.realowner.vehicle) + { + UpdateCSQCProjectile(self); + return; + } + + olddir = normalize(self.velocity); + oldvel = vlen(self.velocity); + newvel = oldvel + self.lip; + makevectors(vectoangles(olddir)); + + float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1); + vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact; + + traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self); + newdir = normalize(predicted_origin - self.origin); + + //vector + float height_diff = predicted_origin_z - self.origin_z; + + if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle) + { + //bprint("Target lost!\n"); + //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n"); + self.think = racer_rocket_groundhugger; + return; + } + + if(trace_fraction != 1.0 && trace_ent != self.enemy) + newdir_z += 16 * sys_frametime; + + self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel; + self.velocity_z -= 800 * sys_frametime; + self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ; + + UpdateCSQCProjectile(self); + return; +} + +void racer_fire_rocket(string tagname, entity trg) +{SELFPARAM(); + vector v = gettaginfo(self, gettagindex(self, tagname)); + entity rocket = vehicles_projectile(EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE), + v, v_forward * autocvar_g_vehicle_racer_rocket_speed, + autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3, + DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner); + + rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime; + rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate; + rocket.nextthink = time; + rocket.enemy = trg; + rocket.cnt = time + 15; + + if(trg) + rocket.think = racer_rocket_tracker; + else + rocket.think = racer_rocket_groundhugger; +} + +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 + if(!forbidWeaponUse(player)) + if(player.BUTTON_ATCK) + if(time > racer.attack_finished_single) + if(racer.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost) + { + racer.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost; + racer.wait = time; + + crosshair_trace(player); + if(racer.cnt) + { + racer_fire_cannon("tag_fire1"); + racer.cnt = 0; + } + else + { + racer_fire_cannon("tag_fire2"); + racer.cnt = 1; + } + racer.attack_finished_single = time + autocvar_g_vehicle_racer_cannon_refire; + } + + 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("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("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(); + 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 + +bool v_racer(Vehicle thisveh, int req) +{SELFPARAM(); + switch(req) + { + case VR_IMPACT: + { + #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 + return true; + } + + case VR_ENTER: + { + #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 + + return true; + } + + case VR_SPAWN: + { + #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 + return true; + } + + case VR_DEATH: + { + #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 + return true; + } + +#ifdef CSQC + case VR_HUD: + { + 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); + return true; + } +#endif + case VR_SETUP: + { + #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 + return true; + } + + case VR_PRECACHE: + { + return true; + } + } + + return true; +} + +#endif // REGISTER_VEHICLE diff --git a/qcsrc/common/vehicles/vehicle/raptor.qc b/qcsrc/common/vehicles/vehicle/raptor.qc new file mode 100644 index 000000000..21fe402d4 --- /dev/null +++ b/qcsrc/common/vehicles/vehicle/raptor.qc @@ -0,0 +1,1062 @@ +#ifndef VEHICLE_RAPTOR +#define VEHICLE_RAPTOR +#include "raptor.qh" +#ifndef MENUQC +int v_raptor(entity, int); +#endif +REGISTER_VEHICLE_SIMPLE( +/* VEH_##id */ RAPTOR, +/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL, +/* mins,maxs */ '-80 -80 0', '80 80 70', +/* model */ "models/vehicles/raptor.dpm", +/* head_model */ "", +/* hud_model */ "models/vehicles/raptor_cockpit.dpm", +/* tags */ "", "tag_hud", "tag_camera", +/* netname */ "raptor", +/* fullname */ _("Raptor") +) { + this.m_icon = "vehicle_raptor"; +#ifndef MENUQC + this.vehicle_func = v_raptor; +#endif +} +#endif + +#ifdef IMPLEMENTATION + +#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_bomblets; +float autocvar_g_vehicle_raptor_bomblet_alt; +float autocvar_g_vehicle_raptor_bomblet_time; +float autocvar_g_vehicle_raptor_bomblet_damage; +float autocvar_g_vehicle_raptor_bomblet_spread; +float autocvar_g_vehicle_raptor_bomblet_edgedamage; +float autocvar_g_vehicle_raptor_bomblet_radius; +float autocvar_g_vehicle_raptor_bomblet_force; +float autocvar_g_vehicle_raptor_bomblet_explode_delay; +float autocvar_g_vehicle_raptor_bombs_refire; + +float autocvar_g_vehicle_raptor_flare_refire; +float autocvar_g_vehicle_raptor_flare_lifetime; +float autocvar_g_vehicle_raptor_flare_chase; +float autocvar_g_vehicle_raptor_flare_range; + +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_cannon_cost; +float autocvar_g_vehicle_raptor_cannon_damage; +float autocvar_g_vehicle_raptor_cannon_radius; +float autocvar_g_vehicle_raptor_cannon_refire; +float autocvar_g_vehicle_raptor_cannon_speed; +float autocvar_g_vehicle_raptor_cannon_spread; +float autocvar_g_vehicle_raptor_cannon_force; + +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_bomblet_boom() +{SELFPARAM(); + RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage, + autocvar_g_vehicle_raptor_bomblet_edgedamage, + autocvar_g_vehicle_raptor_bomblet_radius, world, world, + autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world); + remove(self); +} + +void raptor_bomblet_touch() +{SELFPARAM(); + if(other == self.owner) + return; + + PROJECTILE_TOUCH; + self.think = raptor_bomblet_boom; + self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay; +} + +void raptor_bomb_burst() +{SELFPARAM(); + if(self.cnt > time) + if(autocvar_g_vehicle_raptor_bomblet_alt) + { + self.nextthink = time; + traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self); + if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius)) + { + UpdateCSQCProjectile(self); + return; + } + } + + entity bomblet; + float i; + + Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self); + + for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i) + { + bomblet = spawn(); + setorigin(bomblet, self.origin); + + bomblet.movetype = MOVETYPE_TOSS; + bomblet.touch = raptor_bomblet_touch; + bomblet.think = raptor_bomblet_boom; + bomblet.nextthink = time + 5; + bomblet.owner = self.owner; + bomblet.realowner = self.realowner; + bomblet.velocity = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity); + + PROJECTILE_MAKETRIGGER(bomblet); + CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true); + } + + remove(self); +} + +void raptor_bombdrop() +{SELFPARAM(); + entity bomb_1, bomb_2; + + bomb_1 = spawn(); + bomb_2 = spawn(); + + setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left"))); + setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right"))); + + bomb_1.movetype = bomb_2.movetype = MOVETYPE_BOUNCE; + bomb_1.velocity = bomb_2.velocity = self.velocity; + bomb_1.touch = bomb_2.touch = raptor_bomb_burst; + bomb_1.think = bomb_2.think = raptor_bomb_burst; + bomb_1.cnt = bomb_2.cnt = time + 10; + + if(autocvar_g_vehicle_raptor_bomblet_alt) + bomb_1.nextthink = bomb_2.nextthink = time; + else + bomb_1.nextthink = bomb_2.nextthink = time + autocvar_g_vehicle_raptor_bomblet_time; + + bomb_1.owner = bomb_2.owner = self; + bomb_1.realowner = bomb_2.realowner = self.owner; + bomb_1.solid = bomb_2.solid = SOLID_BBOX; + bomb_1.gravity = bomb_2.gravity = 1; + + PROJECTILE_MAKETRIGGER(bomb_1); + PROJECTILE_MAKETRIGGER(bomb_2); + + CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true); + CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true); +} + + +void raptor_fire_cannon(entity gun, string tagname) +{SELFPARAM(); + vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE), + gettaginfo(gun, gettagindex(gun, tagname)), normalize(v_forward + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed, + autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force, 0, + DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, true, true, self.owner); +} + +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; +} + +void raptor_flare_touch() +{SELFPARAM(); + remove(self); +} + +void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) +{SELFPARAM(); + self.health -= damage; + if(self.health <= 0) + remove(self); +} + +void raptor_flare_think() +{SELFPARAM(); + self.nextthink = time + 0.1; + entity _missile = findchainentity(enemy, self.owner); + while(_missile) + { + if(_missile.flags & FL_PROJECTILE) + if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range) + if(random() > autocvar_g_vehicle_raptor_flare_chase) + _missile.enemy = self; + _missile = _missile.chain; + } + + if(self.tur_impacttime < time) + remove(self); +} + +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); + */ + + if(!forbidWeaponUse(player)) + if(player.BUTTON_ATCK) + if(raptor.attack_finished_single <= time) + if(raptor.vehicle_energy > autocvar_g_vehicle_raptor_cannon_cost) + { + raptor.misc_bulletcounter += 1; + raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire; + if(raptor.misc_bulletcounter <= 2) + raptor_fire_cannon(self.gun1, "fire1"); + else if(raptor.misc_bulletcounter == 3) + raptor_fire_cannon(self.gun2, "fire1"); + else + { + raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire * 2; + raptor_fire_cannon(self.gun2, "fire1"); + raptor.misc_bulletcounter = 0; + } + raptor.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost; + self.cnt = time; + } + + 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); + + if(!forbidWeaponUse(player)) + if(raptor.vehicle_weapon2mode == RSM_BOMB) + { + if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire) + if(player.BUTTON_ATCK2) + { + raptor_bombdrop(); + raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire; + raptor.lip = time; + } + } + else + { + if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire) + if(player.BUTTON_ATCK2) + { + float i; + entity _flare; + + for(i = 0; i < 3; ++i) + { + _flare = spawn(); + setmodel(_flare, MDL_VEH_RAPTOR_FLARE); + _flare.effects = EF_LOWPRECISION | EF_FLAME; + _flare.scale = 0.5; + setorigin(_flare, self.origin - '0 0 16'); + _flare.movetype = MOVETYPE_TOSS; + _flare.gravity = 0.15; + _flare.velocity = 0.25 * raptor.velocity + (v_forward + randomvec() * 0.25)* -500; + _flare.think = raptor_flare_think; + _flare.nextthink = time; + _flare.owner = raptor; + _flare.solid = SOLID_CORPSE; + _flare.takedamage = DAMAGE_YES; + _flare.event_damage = raptor_flare_damage; + _flare.health = 20; + _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime; + _flare.touch = raptor_flare_touch; + } + 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: + case 230: + self.vehicle.vehicle_weapon2mode = RSM_BOMB; + CSQCVehicleSetup(self, 0); + return true; + case 2: + case 231: + 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(); + if(!autocvar_g_vehicle_raptor) { remove(self); return; } + if(!vehicle_initialize(VEH_RAPTOR, false)) { remove(self); return; } +} + +float v_raptor(Vehicle thisveh, float req) +{SELFPARAM(); + switch(req) + { + case VR_IMPACT: + { + 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); + + return true; + } + case VR_ENTER: + { + 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); + return true; + } + case VR_THINK: + { + return true; + } + case VR_DEATH: + { + 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; + return true; + } + case VR_SPAWN: + { + 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; + return true; + } + case VR_SETUP: + { + 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; + + return true; + } + case VR_PRECACHE: + { + return true; + } + } + + return true; +} + +#endif // SVQC +#ifdef CSQC + +void RaptorCBShellfragDraw() +{SELFPARAM(); + if(wasfreed(self)) + return; + + Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy); + self.move_avelocity += randomvec() * 15; + self.renderflags = 0; + + if(self.cnt < time) + self.alpha = bound(0, self.nextthink - time, 1); + + if(self.alpha < ALPHA_MIN_VISIBLE) + remove(self); +} + +void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang) +{SELFPARAM(); + entity sfrag; + + sfrag = spawn(); + setmodel(sfrag, MDL_VEH_RAPTOR_CB_FRAGMENT); + setorigin(sfrag, _org); + + sfrag.move_movetype = MOVETYPE_BOUNCE; + sfrag.gravity = 0.15; + sfrag.solid = SOLID_CORPSE; + + sfrag.draw = RaptorCBShellfragDraw; + + sfrag.move_origin = sfrag.origin = _org; + sfrag.move_velocity = _vel; + sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity); + sfrag.angles = self.move_angles = _ang; + + sfrag.move_time = time; + sfrag.damageforcescale = 4; + + sfrag.nextthink = time + 3; + sfrag.cnt = time + 2; + sfrag.alpha = 1; + sfrag.drawmask = MASK_NORMAL; +} + +float v_raptor(Vehicle thisveh, float req) +{ + switch(req) + { + case VR_HUD: + { + 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); + return true; + } + case VR_SETUP: + { + AuxiliaryXhair[1].axh_image = vCROSS_LOCK; + return true; + } + case VR_PRECACHE: + { + return true; + } + } + + return true; +} + +#endif // CSQC +#endif // REGISTER_VEHICLE diff --git a/qcsrc/common/vehicles/vehicle/raptor.qh b/qcsrc/common/vehicles/vehicle/raptor.qh new file mode 100644 index 000000000..f24939ba9 --- /dev/null +++ b/qcsrc/common/vehicles/vehicle/raptor.qh @@ -0,0 +1,9 @@ +#ifndef RAPTOR_H +#define RAPTOR_H + +const int RSM_FIRST = 1; +const int RSM_BOMB = 1; +const int RSM_FLARE = 2; +const int RSM_LAST = 2; + +#endif diff --git a/qcsrc/common/vehicles/vehicle/spiderbot.qc b/qcsrc/common/vehicles/vehicle/spiderbot.qc new file mode 100644 index 000000000..f01206f68 --- /dev/null +++ b/qcsrc/common/vehicles/vehicle/spiderbot.qc @@ -0,0 +1,979 @@ +#ifndef VEHICLE_SPIDERBOT +#define VEHICLE_SPIDERBOT +#ifndef MENUQC +int v_spiderbot(entity, int); +#endif +REGISTER_VEHICLE_SIMPLE( +/* VEH_##id */ SPIDERBOT, +/* spawnflags */ VHF_DMGSHAKE, +/* mins,maxs */ '-75 -75 10', '75 75 125', +/* model */ "models/vehicles/spiderbot.dpm", +/* head_model */ "models/vehicles/spiderbot_top.dpm", +/* hud_model */ "models/vehicles/spiderbot_cockpit.dpm", +/* tags */ "tag_head", "tag_hud", "", +/* netname */ "spiderbot", +/* fullname */ _("Spiderbot") +) { + this.m_icon = "vehicle_spider"; +#ifndef MENUQC + this.vehicle_func = v_spiderbot; +#endif +} +#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; + +#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; + +float autocvar_g_vehicle_spiderbot_minigun_damage; +float autocvar_g_vehicle_spiderbot_minigun_refire; +float autocvar_g_vehicle_spiderbot_minigun_spread; +int autocvar_g_vehicle_spiderbot_minigun_ammo_cost; +int autocvar_g_vehicle_spiderbot_minigun_ammo_max; +int autocvar_g_vehicle_spiderbot_minigun_ammo_regen; +float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause; +float autocvar_g_vehicle_spiderbot_minigun_force; +float autocvar_g_vehicle_spiderbot_minigun_solidpenetration; + +float autocvar_g_vehicle_spiderbot_rocket_damage; +float autocvar_g_vehicle_spiderbot_rocket_force; +float autocvar_g_vehicle_spiderbot_rocket_radius; +float autocvar_g_vehicle_spiderbot_rocket_speed; +float autocvar_g_vehicle_spiderbot_rocket_spread; +float autocvar_g_vehicle_spiderbot_rocket_refire; +float autocvar_g_vehicle_spiderbot_rocket_refire2; +float autocvar_g_vehicle_spiderbot_rocket_reload; +float autocvar_g_vehicle_spiderbot_rocket_health; +float autocvar_g_vehicle_spiderbot_rocket_noise; +float autocvar_g_vehicle_spiderbot_rocket_turnrate; +float autocvar_g_vehicle_spiderbot_rocket_lifetime; + +vector autocvar_g_vehicle_spiderbot_bouncepain; + +void spiderbot_rocket_artillery() +{SELFPARAM(); + self.nextthink = time; + UpdateCSQCProjectile(self); +} + +void spiderbot_rocket_unguided() +{SELFPARAM(); + vector newdir, olddir; + + self.nextthink = time; + + olddir = normalize(self.velocity); + newdir = normalize(self.pos1 - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise; + self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed; + + UpdateCSQCProjectile(self); + + if (self.owner.deadflag != DEAD_NO || self.cnt < time || vlen(self.pos1 - self.origin) < 16) + self.use(); +} + +void spiderbot_rocket_guided() +{SELFPARAM(); + vector newdir, olddir; + + self.nextthink = time; + + if(!self.realowner.vehicle) + self.think = spiderbot_rocket_unguided; + + crosshair_trace(self.realowner); + olddir = normalize(self.velocity); + newdir = normalize(trace_endpos - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise; + self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed; + + UpdateCSQCProjectile(self); + + if (self.owner.deadflag != DEAD_NO || self.cnt < time) + self.use(); +} + +void spiderbot_guide_release() +{SELFPARAM(); + entity rkt; + rkt = findchainentity(realowner, self.owner); + if(!rkt) + return; + + crosshair_trace(self.owner); + while(rkt) + { + if(rkt.think == spiderbot_rocket_guided) + { + rkt.pos1 = trace_endpos; + rkt.think = spiderbot_rocket_unguided; + } + rkt = rkt.chain; + } +} + +float spiberbot_calcartillery_flighttime; +vector spiberbot_calcartillery(vector org, vector tgt, float ht) +{ + float grav, sdist, zdist, vs, vz, jumpheight; + vector sdir; + + grav = autocvar_sv_gravity; + zdist = tgt_z - org_z; + sdist = vlen(tgt - org - zdist * '0 0 1'); + sdir = normalize(tgt - org - zdist * '0 0 1'); + + // how high do we need to go? + jumpheight = fabs(ht); + if(zdist > 0) + jumpheight = jumpheight + zdist; + + // push so high... + vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)! + + // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump! + if(ht < 0) + if(zdist < 0) + vz = -vz; + + vector solution; + solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist" + // ALWAYS solvable because jumpheight >= zdist + if(!solution_z) + solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0) + if(zdist == 0) + solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually) + + if(zdist < 0) + { + // down-jump + if(ht < 0) + { + // almost straight line type + // jump apex is before the jump + // we must take the larger one + spiberbot_calcartillery_flighttime = solution_y; + } + else + { + // regular jump + // jump apex is during the jump + // we must take the larger one too + spiberbot_calcartillery_flighttime = solution_y; + } + } + else + { + // up-jump + if(ht < 0) + { + // almost straight line type + // jump apex is after the jump + // we must take the smaller one + spiberbot_calcartillery_flighttime = solution_x; + } + else + { + // regular jump + // jump apex is during the jump + // we must take the larger one + spiberbot_calcartillery_flighttime = solution_y; + } + } + vs = sdist / spiberbot_calcartillery_flighttime; + + // finally calculate the velocity + return sdir * vs + '0 0 1' * vz; +} + +void spiderbot_rocket_do() +{SELFPARAM(); + vector v; + entity rocket = world; + + if (self.wait != -10) + { + if (self.owner.BUTTON_ATCK2 && self.vehicle_weapon2mode == SBRM_GUIDE) + { + if (self.wait == 1) + if (self.tur_head.frame == 9 || self.tur_head.frame == 1) + { + if(self.gun2.cnt < time && self.tur_head.frame == 9) + self.tur_head.frame = 1; + + return; + } + self.wait = 1; + } + else + { + if(self.wait) + spiderbot_guide_release(); + + self.wait = 0; + } + } + + if(self.gun2.cnt > time) + return; + + if (self.tur_head.frame >= 9) + { + self.tur_head.frame = 1; + self.wait = 0; + } + + if(self.wait != -10) + if(!self.owner.BUTTON_ATCK2) + return; + + if(forbidWeaponUse(self.owner)) + return; + + v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire")); + + switch(self.vehicle_weapon2mode) + { + case SBRM_VOLLY: + rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE), + v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, + autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, + DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner); + crosshair_trace(self.owner); + float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos); + _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ; + rocket.nextthink = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed); + rocket.think = vehicles_projectile_explode; + + if(self.owner.BUTTON_ATCK2 && self.tur_head.frame == 1) + self.wait = -10; + break; + case SBRM_GUIDE: + rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE), + v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, + autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, + DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, self.owner); + crosshair_trace(self.owner); + rocket.pos1 = trace_endpos; + rocket.nextthink = time; + rocket.think = spiderbot_rocket_guided; + + + break; + case SBRM_ARTILLERY: + rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE), + v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed, + autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1, + DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner); + + crosshair_trace(self.owner); + + rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius); + rocket.pos1_z = trace_endpos_z; + + traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self); + float h1 = 0.75 * vlen(v - trace_endpos); + + //v = trace_endpos; + traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self); + float h2 = 0.75 * vlen(rocket.pos1 - v); + + rocket.velocity = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2)); + rocket.movetype = MOVETYPE_TOSS; + rocket.gravity = 1; + //rocket.think = spiderbot_rocket_artillery; + break; + } + rocket.classname = "spiderbot_rocket"; + + rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime; + + self.tur_head.frame += 1; + if (self.tur_head.frame == 9) + self.attack_finished_single = autocvar_g_vehicle_spiderbot_rocket_reload; + else + self.attack_finished_single = ((self.vehicle_weapon2mode == SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire); + + self.gun2.cnt = time + self.attack_finished_single; +} + +.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: + case 230: + self.vehicle.vehicle_weapon2mode = SBRM_VOLLY; + CSQCVehicleSetup(self, 0); + return true; + case 2: + case 231: + self.vehicle.vehicle_weapon2mode = SBRM_GUIDE; + CSQCVehicleSetup(self, 0); + return true; + case 3: + case 232: + case 251: + 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(); + if(!autocvar_g_vehicle_spiderbot) { remove(self); return; } + if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; } +} + +float v_spiderbot(Vehicle thisveh, float req) +{SELFPARAM(); + switch(req) + { + case VR_IMPACT: + { + 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); + + return true; + } + case VR_ENTER: + { + 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'); + } + + return true; + } + case VR_THINK: + { + if(self.flags & FL_ONGROUND) + movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop); + + return true; + } + case VR_DEATH: + { + 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 + + return true; + } + case VR_SPAWN: + { + 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; + + return true; + } + case VR_SETUP: + { + 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 + + return true; + } + case VR_PRECACHE: + { + return true; + } + } + + return true; +} + +#endif // SVQC +#ifdef CSQC +float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6; +float autocvar_cl_vehicle_spiderbot_cross_size = 1; + +float v_spiderbot(Vehicle thisveh, float req) +{ + switch(req) + { + case VR_HUD: + { + 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); + return true; + } + case VR_SETUP: + { + AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1 + AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2 + + return true; + } + case VR_PRECACHE: + { + return true; + } + } + + return true; +} + +#endif // CSQC +#endif // REGISTER_VEHICLE