X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fvehicles%2Fsv_vehicles.qc;h=60df770909f67cbb3115461b615cb352a4178d6c;hb=2b18b279a8222a72ba713e6d3b72c2cba888407b;hp=1fbd80210475debd33e63fc5823ca4dd114214bb;hpb=0071121b663dc3d841a2c28d27c1015899f0f402;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index 1fbd80210..bbecb83da 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -1,5 +1,17 @@ #include "sv_vehicles.qh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + bool SendAuxiliaryXhair(entity this, entity to, int sf) { WriteHeader(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR); @@ -9,9 +21,7 @@ bool SendAuxiliaryXhair(entity this, entity to, int sf) if(sf & 2) { - WriteCoord(MSG_ENTITY, this.origin_x); - WriteCoord(MSG_ENTITY, this.origin_y); - WriteCoord(MSG_ENTITY, this.origin_z); + WriteVector(MSG_ENTITY, this.origin); } if(sf & 4) @@ -26,8 +36,8 @@ bool SendAuxiliaryXhair(entity this, entity to, int sf) bool AuxiliaryXhair_customize(entity this, entity client) { - //entity e = WaypointSprite_getviewentity(client); - entity axh = client.(AuxiliaryXhair[this.cnt]); + entity e = WaypointSprite_getviewentity(client); + entity axh = e.(AuxiliaryXhair[this.cnt]); return axh.owner == this.owner; // cheaply check if the client's axh owner is the same as our real owner } @@ -163,53 +173,16 @@ void vehicles_locktarget(entity this, float incr, float decr, float _lock_time) } } -float vehicle_altitude(entity this, float amax) -{ - tracebox(this.origin, this.mins, this.maxs, this.origin - ('0 0 1' * amax), MOVE_WORLDONLY, this); - return vlen(this.origin - trace_endpos); -} - -vector vehicles_force_fromtag_hover(entity this, string tag_name, float spring_length, float max_power) -{ - force_fromtag_origin = gettaginfo(this, gettagindex(this, tag_name)); - v_forward = normalize(v_forward) * -1; - traceline(force_fromtag_origin, force_fromtag_origin - (v_forward * spring_length), MOVE_NORMAL, this); - - force_fromtag_power = (1 - trace_fraction) * max_power; - force_fromtag_normpower = force_fromtag_power / max_power; - - return v_forward * force_fromtag_power; -} - -vector vehicles_force_fromtag_maglev(entity this, string tag_name, float spring_length, float max_power) -{ - force_fromtag_origin = gettaginfo(this, gettagindex(this, tag_name)); - v_forward = normalize(v_forward) * -1; - traceline(force_fromtag_origin, force_fromtag_origin - (v_forward * spring_length), MOVE_NORMAL, this); - - // TODO - this may NOT be compatible with wall/celing movement, unhardcode 0.25 (engine count multiplier) - if(trace_fraction == 1.0) - { - force_fromtag_normpower = -0.25; - return '0 0 -200'; - } - - force_fromtag_power = ((1 - trace_fraction) - trace_fraction) * max_power; - force_fromtag_normpower = force_fromtag_power / max_power; - - return v_forward * force_fromtag_power; -} - // projectile handling -void vehicles_projectile_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) +void vehicles_projectile_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) { // Ignore damage from oterh projectiles from my owner (dont mess up volly's) if(inflictor.owner == this.owner) return; - this.health -= damage; + TakeResource(this, RES_HEALTH, damage); this.velocity += force; - if(this.health < 1) + if(GetResource(this, RES_HEALTH) < 1) { this.takedamage = DAMAGE_NO; this.event_damage = func_null; @@ -232,7 +205,7 @@ void vehicles_projectile_explode(entity this, entity toucher) PROJECTILE_TOUCH(this, toucher); this.event_damage = func_null; - RadiusDamage (this, this.realowner, this.shot_dmg, 0, this.shot_radius, this, NULL, this.shot_force, this.totalfrags, toucher); + RadiusDamage (this, this.realowner, this.shot_dmg, 0, this.shot_radius, this, NULL, this.shot_force, this.projectiledeathtype, DMG_NOWEP, toucher); delete(this); } @@ -247,16 +220,14 @@ void vehicles_projectile_explode_use(entity this, entity actor, entity trigger) vehicles_projectile_explode(this, trigger); } -entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, +entity vehicles_projectile(entity this, entity _mzlfx, Sound _mzlsound, vector _org, vector _vel, float _dmg, float _radi, float _force, float _size, int _deahtype, float _projtype, float _health, bool _cull, bool _clianim, entity _owner) { TC(Sound, _mzlsound); - entity proj; - - proj = spawn(); + entity proj = new(vehicles_projectile); PROJECTILE_MAKETRIGGER(proj); setorigin(proj, _org); @@ -264,7 +235,7 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, proj.shot_dmg = _dmg; proj.shot_radius = _radi; proj.shot_force = _force; - proj.totalfrags = _deahtype; + proj.projectiledeathtype = _deahtype; proj.solid = SOLID_BBOX; set_movetype(proj, MOVETYPE_FLYMISSILE); proj.flags = FL_PROJECTILE; @@ -284,7 +255,7 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, { proj.takedamage = DAMAGE_AIM; proj.event_damage = vehicles_projectile_damage; - proj.health = _health; + SetResourceExplicit(proj, RES_HEALTH, _health); } else proj.flags |= FL_NOTARGET; @@ -292,8 +263,8 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, if(_mzlsound != SND_Null) sound (this, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM); - if(_mzlfx) - Send_Effect_(_mzlfx, proj.origin, proj.velocity, 1); + if(_mzlfx != EFFECT_Null) + Send_Effect(_mzlfx, proj.origin, proj.velocity, 1); setsize (proj, '-1 -1 -1' * _size, '1 1 1' * _size); @@ -326,7 +297,7 @@ void vehicles_gib_think(entity this) entity vehicle_tossgib(entity this, entity _template, vector _vel, string _tag, bool _burn, bool _explode, float _maxtime, vector _rot) { - entity _gib = spawn(); + entity _gib = new(vehicle_gib); _setmodel(_gib, _template.model); vector org = gettaginfo(this, gettagindex(this, _tag)); setorigin(_gib, org); @@ -369,10 +340,10 @@ bool vehicle_addplayerslot( entity _owner, _slot.PlayerPhysplug = _framefunc; _slot.vehicle_exit = _exitfunc; _slot.vehicle_enter = _enterfunc; - _slot.hud = _hud; + STAT(HUD, _slot) = _hud; _slot.vehicle_flags = VHF_PLAYERSLOT; - _slot.vehicle_viewport = spawn(); - _slot.vehicle_hudmodel = spawn(); + _slot.vehicle_viewport = new(vehicle_viewport); + _slot.vehicle_hudmodel = new(vehicle_hudmodel); _slot.vehicle_hudmodel.viewmodelforclient = _slot; _slot.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT); @@ -387,7 +358,7 @@ bool vehicle_addplayerslot( entity _owner, vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname, float _pichlimit_min, float _pichlimit_max, - float _rotlimit_min, float _rotlimit_max, float _aimspeed) + float _rotlimit_min, float _rotlimit_max, float _aimspeed, float dt) { vector vtmp, vtag; float ftmp; @@ -395,7 +366,7 @@ vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string vtmp = vectoangles(normalize(_target - vtag)); vtmp = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(_vehic.angles), AnglesTransform_FromAngles(vtmp))) - _turrret.angles; vtmp = AnglesTransform_Normalize(vtmp, true); - ftmp = _aimspeed * frametime; + ftmp = _aimspeed * dt; vtmp_y = bound(-ftmp, vtmp_y, ftmp); vtmp_x = bound(-ftmp, vtmp_x, ftmp); _turrret.angles_y = bound(_rotlimit_min, _turrret.angles_y + vtmp_y, _rotlimit_max); @@ -452,7 +423,7 @@ void vehicles_reset_colors(entity this, entity player) this.velocity = '0 0 0'; this.effects = eff; - Vehicle info = Vehicles_from(this.vehicleid); + Vehicle info = this.vehicledef; //REGISTRY_GET(Vehicles, this.vehicleid); info.vr_setcolors(info, this); } @@ -522,6 +493,7 @@ void vehicles_showwp(entity this) else rgb = '1 1 1'; entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, ent, '0 0 64', NULL, 0, ent, waypointsprite_attached, true, RADARICON_Vehicle); + wp.wp_extra = ent.wp00.vehicleid; wp.colormod = rgb; if(ent.waypointsprite_attached) { @@ -588,7 +560,7 @@ void vehicles_regen(entity this, float timer, .float regen_field, float field_ma if(timer + rpause < time) { if(_healthscale) - regen = regen * (this.vehicle_health / this.max_health); + regen = regen * (GetResource(this, RES_HEALTH) / this.max_health); this.(regen_field) = min(this.(regen_field) + regen * delta_time, field_max); @@ -597,6 +569,23 @@ void vehicles_regen(entity this, float timer, .float regen_field, float field_ma } } +void vehicles_regen_resource(entity this, float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale, int resource) +{ + float resource_amount = GetResource(this, resource); + + if(resource_amount < field_max) + if(timer + rpause < time) + { + if(_healthscale) + regen = regen * (resource_amount / this.max_health); + + SetResource(this, resource, min(resource_amount + regen * delta_time, field_max)); + + if(this.owner) + this.owner.(regen_field) = (GetResource(this, resource) / field_max) * 100; + } +} + void shieldhit_think(entity this) { this.alpha -= 0.1; @@ -614,7 +603,7 @@ void shieldhit_think(entity this) void vehicles_painframe(entity this) { - int myhealth = ((this.owner) ? this.owner.vehicle_health : ((this.vehicle_health / this.max_health) * 100)); + int myhealth = ((this.owner) ? this.owner.vehicle_health : ((GetResource(this, RES_HEALTH) / this.max_health) * 100)); if(myhealth <= 50) if(this.pain_frame < time) @@ -627,10 +616,12 @@ void vehicles_painframe(entity this) this.velocity += randomvec() * 30; if(this.vehicle_flags & VHF_DMGROLL) + { if(this.vehicle_flags & VHF_DMGHEADROLL) this.tur_head.angles += randomvec(); else this.angles += randomvec(); + } } } @@ -639,7 +630,7 @@ void vehicles_frame(entity this, entity actor) vehicles_painframe(this); } -void vehicles_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) +void vehicles_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) { this.dmg_time = time; @@ -665,7 +656,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag { if (wasfreed(this.vehicle_shieldent) || this.vehicle_shieldent == NULL) { - this.vehicle_shieldent = spawn(); + this.vehicle_shieldent = new(vehicle_shieldent); this.vehicle_shieldent.effects = EF_LOWPRECISION; setmodel(this.vehicle_shieldent, MDL_VEH_SHIELD); @@ -685,7 +676,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag if(this.vehicle_shield < 0) { - this.vehicle_health -= fabs(this.vehicle_shield); + TakeResource(this, RES_HEALTH, fabs(this.vehicle_shield)); this.vehicle_shieldent.colormod = '2 0 0'; this.vehicle_shield = 0; this.vehicle_shieldent.alpha = 0.75; @@ -700,7 +691,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag } else { - this.vehicle_health -= damage; + TakeResource(this, RES_HEALTH, damage); if(sound_allowed(MSG_BROADCAST, attacker)) spamsound (this, CH_PAIN, SND_ONS_HIT2, VOL_BASE, ATTEN_NORM); // FIXME: PLACEHOLDER @@ -711,23 +702,36 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag else this.velocity += force; - if(this.vehicle_health <= 0) + if(GetResource(this, RES_HEALTH) <= 0) { if(this.owner) + { if(this.vehicle_flags & VHF_DEATHEJECT) vehicles_exit(this, VHEF_EJECT); else vehicles_exit(this, VHEF_RELEASE); - + } antilag_clear(this, this); - Vehicle info = Vehicles_from(this.vehicleid); + Vehicle info = this.vehicledef; //REGISTRY_GET(Vehicles, this.vehicleid); info.vr_death(info, this); vehicles_setreturn(this); } } +bool vehicles_heal(entity targ, entity inflictor, float amount, float limit) +{ + float true_limit = ((limit != RES_LIMIT_NONE) ? limit : targ.max_health); + if(GetResource(targ, RES_HEALTH) <= 0 || GetResource(targ, RES_HEALTH) >= true_limit) + return false; + + GiveResourceWithLimit(targ, RES_HEALTH, amount, true_limit); + if(targ.owner) + targ.owner.vehicle_health = (GetResource(targ, RES_HEALTH) / targ.max_health) * 100; + return true; +} + bool vehicles_crushable(entity e) { if(IS_PLAYER(e) && time >= e.vehicle_enter_delay) @@ -746,17 +750,12 @@ void vehicles_impact(entity this, float _minspeed, float _speedfac, float _maxpa if(this.play_time < time) { - float wc = vlen(this.velocity - this.oldvelocity); - //dprint("oldvel: ", vtos(this.oldvelocity), "\n"); - //dprint("vel: ", vtos(this.velocity), "\n"); - if(_minspeed < wc) + if(vdist(this.velocity - this.oldvelocity, >, _minspeed)) { + float wc = vlen(this.velocity - this.oldvelocity); float take = min(_speedfac * wc, _maxpain); - Damage (this, NULL, NULL, take, DEATH_FALL.m_id, this.origin, '0 0 0'); + Damage(this, NULL, NULL, take, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0'); this.play_time = time + 0.25; - - //dprint("wc: ", ftos(wc), "\n"); - //dprint("take: ", ftos(take), "\n"); } } } @@ -798,7 +797,6 @@ void vehicles_exit(entity vehic, bool eject) vehicles_exit_running = true; - // TODO: this was in an IS_CLIENT check, make sure it isn't actually needed! if(vehic.vehicle_flags & VHF_PLAYERSLOT) { vehic.vehicle_exit(vehic, eject); @@ -814,6 +812,7 @@ void vehicles_exit(entity vehic, bool eject) WriteByte (MSG_ONE, SVC_SETVIEWPORT); WriteEntity( MSG_ONE, player); + // NOTE: engine networked WriteByte (MSG_ONE, SVC_SETVIEWANGLES); WriteAngle(MSG_ONE, 0); WriteAngle(MSG_ONE, vehic.angles_y); @@ -826,13 +825,13 @@ void vehicles_exit(entity vehic, bool eject) player.solid = SOLID_SLIDEBOX; set_movetype(player, MOVETYPE_WALK); player.effects &= ~EF_NODRAW; - player.teleportable = TELEPORT_NORMAL; - player.alpha = 1; + player.teleportable = TELEPORT_NORMAL; + player.alpha = default_player_alpha; player.PlayerPhysplug = func_null; player.vehicle = NULL; - player.view_ofs = STAT(PL_VIEW_OFS, player); - player.event_damage = PlayerDamage; - player.hud = HUD_NORMAL; + player.view_ofs = STAT(PL_VIEW_OFS, player); + player.event_damage = PlayerDamage; + STAT(HUD, player) = HUD_NORMAL; for(int slot = 0; slot < MAX_WEAPONSLOTS; ++ slot) { .entity weaponentity = weaponentities[slot]; @@ -894,19 +893,19 @@ void vehicles_touch(entity this, entity toucher) // Vehicle currently in use if(this.owner) { - if(!forbidWeaponUse(this.owner)) if(toucher != NULL) if((this.origin_z + this.maxs_z) > (toucher.origin_z)) if(vehicles_crushable(toucher)) + if(!weaponLocked(this.owner)) { - if(vdist(this.velocity, >=, 30)) - Damage(toucher, this, this.owner, autocvar_g_vehicles_crush_dmg, DEATH_VH_CRUSH.m_id, '0 0 0', normalize(toucher.origin - this.origin) * autocvar_g_vehicles_crush_force); + if(vdist(this.velocity, >=, autocvar_g_vehicles_crush_minspeed)) + Damage(toucher, this, this.owner, autocvar_g_vehicles_crush_dmg, DEATH_VH_CRUSH.m_id, DMG_NOWEP, '0 0 0', normalize(toucher.origin - this.origin) * autocvar_g_vehicles_crush_force); return; // Dont do selfdamage when hitting "soft targets". } if(this.play_time < time) { - Vehicle info = Vehicles_from(this.vehicleid); + Vehicle info = this.vehicledef; //REGISTRY_GET(Vehicles, this.vehicleid); info.vr_impact(info, this); } @@ -939,7 +938,7 @@ bool vehicle_impulse(entity this, int imp) void vehicles_enter(entity pl, entity veh) { - // Remove this when bots know how to use vehicles + // Remove this when bots know how to use vehicles if((IS_BOT_CLIENT(pl) && !autocvar_g_vehicles_allow_bots)) return; @@ -951,7 +950,7 @@ void vehicles_enter(entity pl, entity veh) || (pl.vehicle) ) { return; } - Vehicle info = Vehicles_from(veh.vehicleid); + Vehicle info = veh.vehicledef; //REGISTRY_GET(Vehicles, veh.vehicleid); if(autocvar_g_vehicles_enter) // vehicle's touch function should handle this if entering via use key is disabled (TODO) if(veh.vehicle_flags & VHF_MULTISLOT) @@ -1001,11 +1000,12 @@ void vehicles_enter(entity pl, entity veh) veh.vehicle_hudmodel.viewmodelforclient = pl; - pl.crouch = false; + UNSET_DUCKED(pl); pl.view_ofs = STAT(PL_VIEW_OFS, pl); setsize(pl, STAT(PL_MIN, pl), STAT(PL_MAX, pl)); veh.event_damage = vehicles_damage; + veh.event_heal = vehicles_heal; veh.nextthink = 0; pl.items &= ~IT_USING_JETPACK; pl.angles = veh.angles; @@ -1026,7 +1026,7 @@ void vehicles_enter(entity pl, entity veh) veh.(weaponentity) = new(temp_wepent); veh.(weaponentity).m_switchweapon = pl.(weaponentity).m_switchweapon; } - pl.hud = veh.vehicleid; + STAT(HUD, pl) = veh.vehicleid; pl.PlayerPhysplug = veh.PlayerPhysplug; pl.vehicle_ammo1 = veh.vehicle_ammo1; @@ -1055,6 +1055,7 @@ void vehicles_enter(entity pl, entity veh) WriteByte (MSG_ONE, SVC_SETVIEWPORT); WriteEntity(MSG_ONE, veh.vehicle_viewport); + // NOTE: engine networked WriteByte (MSG_ONE, SVC_SETVIEWANGLES); if(veh.tur_head) { @@ -1087,9 +1088,9 @@ void vehicles_think(entity this) this.nextthink = time + autocvar_g_vehicles_thinkrate; if(this.owner) - this.owner.vehicle_weapon2mode = this.vehicle_weapon2mode; + STAT(VEHICLESTAT_W2MODE, this.owner) = STAT(VEHICLESTAT_W2MODE, this); - Vehicle info = Vehicles_from(this.vehicleid); + Vehicle info = this.vehicledef; //REGISTRY_GET(Vehicles, this.vehicleid); info.vr_think(info, this); vehicles_painframe(this); @@ -1119,6 +1120,7 @@ void vehicles_spawn(entity this) this.owner = NULL; settouch(this, vehicles_touch); this.event_damage = vehicles_damage; + this.event_heal = vehicles_heal; this.reset = vehicles_reset; this.iscreature = true; this.teleportable = false; // no teleporting for vehicles, too buggy @@ -1161,7 +1163,7 @@ void vehicles_spawn(entity this) }); - Vehicle info = Vehicles_from(this.vehicleid); + Vehicle info = this.vehicledef; //REGISTRY_GET(Vehicles, this.vehicleid); info.vr_spawn(info, this); vehicles_reset_colors(this, NULL); @@ -1178,10 +1180,7 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop) return false; if(!this.tur_head) - { info.vr_precache(info); - IL_PUSH(g_vehicles, this); - } if(this.targetname && this.targetname != "") { @@ -1229,8 +1228,10 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop) this.damagedbycontents = true; IL_PUSH(g_damagedbycontents, this); this.vehicleid = info.vehicleid; + this.vehicledef = info; this.PlayerPhysplug = info.PlayerPhysplug; this.event_damage = func_null; + this.event_heal = func_null; settouch(this, vehicles_touch); setthink(this, vehicles_spawn); this.nextthink = time;