X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Fvehicles%2Fsv_vehicles.qc;h=491962b67a5f74d14f193375de0cc4c49c7022e9;hp=2709054b9ae11725df4700f7c07716a166b9900d;hb=87bec07409c336c956a798556064c6819ad40a4d;hpb=da8bf18830fc6ce2af0787e6d326606985b3ad2b diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index 2709054b9..491962b67 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -1,83 +1,62 @@ #include "sv_vehicles.qh" -#if 0 -bool vehicle_send(entity to, int sf) +bool SendAuxiliaryXhair(entity this, entity to, int sf) { - WriteByte(MSG_ENTITY, ENT_CLIENT_VEHICLE); + WriteHeader(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR); WriteByte(MSG_ENTITY, sf); - if(sf & VSF_SPAWN) - { - WriteByte(MSG_ENTITY, this.vehicleid); - } - - if(sf & VSF_SETUP) - { - // send stuff? - } - - if(sf & VSF_ENTER) - { - // player handles the .vehicle stuff, we need only set ourselves up for driving - - // send stuff? - } + WriteByte(MSG_ENTITY, this.cnt); - if(sf & VSF_EXIT) + if(sf & 2) { - // senf stuff? + WriteCoord(MSG_ENTITY, this.origin_x); + WriteCoord(MSG_ENTITY, this.origin_y); + WriteCoord(MSG_ENTITY, this.origin_z); } - if(sf & VSF_PRECACHE) + if(sf & 4) { - // send stuff?! + WriteByte(MSG_ENTITY, rint(this.colormod_x * 255)); + WriteByte(MSG_ENTITY, rint(this.colormod_y * 255)); + WriteByte(MSG_ENTITY, rint(this.colormod_z * 255)); } return true; } -#endif -bool SendAuxiliaryXhair(entity this, entity to, int sf) -{ - - WriteHeader(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR); - - WriteByte(MSG_ENTITY, this.cnt); - - WriteCoord(MSG_ENTITY, this.origin_x); - WriteCoord(MSG_ENTITY, this.origin_y); - WriteCoord(MSG_ENTITY, this.origin_z); - - WriteByte(MSG_ENTITY, rint(this.colormod_x * 255)); - WriteByte(MSG_ENTITY, rint(this.colormod_y * 255)); - WriteByte(MSG_ENTITY, rint(this.colormod_z * 255)); - - return true; -} +.vector axh_prevorigin; +.vector axh_prevcolors; void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, int axh_id) { if(!IS_REAL_CLIENT(own)) return; - entity axh; - axh_id = bound(0, axh_id, MAX_AXH); - axh = own.(AuxiliaryXhair[axh_id]); + entity axh = own.(AuxiliaryXhair[axh_id]); - if(axh == world || wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?) + if(axh == NULL || wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist? Mario: because of sloppy code like this) { - axh = spawn(); - axh.cnt = axh_id; - axh.drawonlytoclient = own; - axh.owner = own; + axh = new(auxiliary_xhair); + axh.cnt = axh_id; + axh.drawonlytoclient = own; + axh.owner = own; Net_LinkEntity(axh, false, 0, SendAuxiliaryXhair); } - setorigin(axh, loc); - axh.colormod = clr; - axh.SendFlags = 0x01; - own.(AuxiliaryXhair[axh_id]) = axh; + if(loc != axh.axh_prevorigin) + { + setorigin(axh, loc); + axh.SendFlags |= 2; + } + + if(clr != axh.axh_prevcolors) + { + axh.colormod = clr; + axh.SendFlags |= 4; + } + + own.(AuxiliaryXhair[axh_id]) = axh; // set it anyway...? } void CSQCVehicleSetup(entity own, int vehicle_id) @@ -95,7 +74,7 @@ void vehicles_locktarget(entity this, float incr, float decr, float _lock_time) { if(this.lock_target && IS_DEAD(this.lock_target)) { - this.lock_target = world; + this.lock_target = NULL; this.lock_strength = 0; this.lock_time = 0; } @@ -112,22 +91,22 @@ void vehicles_locktarget(entity this, float incr, float decr, float _lock_time) return; } - if(trace_ent != world) + if(trace_ent != NULL) { if(SAME_TEAM(trace_ent, this)) - trace_ent = world; + trace_ent = NULL; if(IS_DEAD(trace_ent)) - trace_ent = world; + trace_ent = NULL; if(!(IS_VEHICLE(trace_ent) || IS_TURRET(trace_ent))) - trace_ent = world; + trace_ent = NULL; if(trace_ent.alpha <= 0.5 && trace_ent.alpha != 0) - trace_ent = world; // invisible + trace_ent = NULL; // invisible } - if(this.lock_target == world && trace_ent != world) + if(this.lock_target == NULL && trace_ent != NULL) this.lock_target = trace_ent; if(this.lock_target && trace_ent == this.lock_target) @@ -146,7 +125,7 @@ void vehicles_locktarget(entity this, float incr, float decr, float _lock_time) // Have a locking target // Trace hit current target - if(trace_ent == this.lock_target && trace_ent != world) + if(trace_ent == this.lock_target && trace_ent != NULL) { this.lock_strength = min(this.lock_strength + incr, 1); if(this.lock_strength == 1) @@ -160,10 +139,16 @@ void vehicles_locktarget(entity this, float incr, float decr, float _lock_time) this.lock_strength = max(this.lock_strength - decr, 0); if(this.lock_strength == 0) - this.lock_target = world; + this.lock_target = NULL; } } +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)); @@ -213,28 +198,33 @@ void vehicles_projectile_damage(entity this, entity inflictor, entity attacker, } } -void vehicles_projectile_explode(entity this) +void vehicles_projectile_explode(entity this, entity toucher) { - if(this.owner && other != world) + if(this.owner && toucher != NULL) { - if(other == this.owner.vehicle) + if(toucher == this.owner.vehicle) return; - if(other == this.owner.vehicle.tur_head) + if(toucher == this.owner.vehicle.tur_head) return; } - PROJECTILE_TOUCH(this); + PROJECTILE_TOUCH(this, toucher); this.event_damage = func_null; - RadiusDamage (this, this.realowner, this.shot_dmg, 0, this.shot_radius, this, world, this.shot_force, this.totalfrags, other); + RadiusDamage (this, this.realowner, this.shot_dmg, 0, this.shot_radius, this, NULL, this.shot_force, this.totalfrags, toucher); - remove (this); + delete (this); +} + +void vehicles_projectile_explode_think(entity this) +{ + vehicles_projectile_explode(this, NULL); } void vehicles_projectile_explode_use(entity this, entity actor, entity trigger) { - vehicles_projectile_explode(this); + vehicles_projectile_explode(this, trigger); } entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, @@ -256,8 +246,10 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, proj.shot_force = _force; proj.totalfrags = _deahtype; proj.solid = SOLID_BBOX; - proj.movetype = MOVETYPE_FLYMISSILE; - proj.flags = FL_PROJECTILE; + set_movetype(proj, MOVETYPE_FLYMISSILE); + proj.flags = FL_PROJECTILE; + IL_PUSH(g_projectiles, proj); + IL_PUSH(g_bot_dodge, proj); proj.bot_dodge = true; proj.bot_dodgerating = _dmg; proj.velocity = _vel; @@ -275,7 +267,7 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, proj.health = _health; } else - proj.flags = FL_PROJECTILE | FL_NOTARGET; + proj.flags |= FL_NOTARGET; if(_mzlsound != SND_Null) sound (this, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM); @@ -295,14 +287,19 @@ void vehicles_gib_explode(entity this) sound (this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM); Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (this.origin + '0 0 100'), '0 0 0', 1); Send_Effect(EFFECT_EXPLOSION_SMALL, this.wp00.origin + '0 0 64', '0 0 0', 1); - remove(this); + delete(this); +} + +void vehicles_gib_touch(entity this, entity toucher) +{ + vehicles_gib_explode(this); } void vehicles_gib_think(entity this) { this.alpha -= 0.1; if(this.cnt >= time) - remove(this); + delete(this); else this.nextthink = time + 0.1; } @@ -314,7 +311,7 @@ entity vehicle_tossgib(entity this, entity _template, vector _vel, string _tag, vector org = gettaginfo(this, gettagindex(this, _tag)); setorigin(_gib, org); _gib.velocity = _vel; - _gib.movetype = MOVETYPE_TOSS; + set_movetype(_gib, MOVETYPE_TOSS); _gib.solid = SOLID_CORPSE; _gib.colormod = '-0.5 -0.5 -0.5'; _gib.effects = EF_LOWPRECISION; @@ -327,7 +324,7 @@ entity vehicle_tossgib(entity this, entity _template, vector _vel, string _tag, { setthink(_gib, vehicles_gib_explode); _gib.nextthink = time + random() * _explode; - settouch(_gib, vehicles_gib_explode); + settouch(_gib, vehicles_gib_touch); } else { @@ -343,7 +340,7 @@ bool vehicle_addplayerslot( entity _owner, entity _slot, int _hud, Model _hud_model, - bool(entity) _framefunc, + bool(entity,float) _framefunc, void(entity,bool) _exitfunc, float(entity, entity) _enterfunc) { if(!(_owner.vehicle_flags & VHF_MULTISLOT)) @@ -436,21 +433,17 @@ void vehicles_reset_colors(entity this) void vehicles_clearreturn(entity veh) { - // Remove "return helper", if any. - for (entity ret = findchain(classname, "vehicle_return"); ret; ret = ret.chain) + // Remove "return helper" entities, if any. + IL_EACH(g_vehicle_returners, it.wp00 == veh, { - if(ret.wp00 == veh) - { - ret.classname = ""; - setthink(ret, SUB_Remove); - ret.nextthink = time + 0.1; - - if(ret.waypointsprite_attached) - WaypointSprite_Kill(ret.waypointsprite_attached); + it.classname = ""; + setthink(it, SUB_Remove); + it.nextthink = time + 0.1; + IL_REMOVE(g_vehicle_returners, it); - return; - } - } + if(it.waypointsprite_attached) + WaypointSprite_Kill(it.waypointsprite_attached); + }); } void vehicles_spawn(entity this); @@ -464,7 +457,7 @@ void vehicles_return(entity this) if(this.waypointsprite_attached) WaypointSprite_Kill(this.waypointsprite_attached); - remove(this); + delete(this); } void vehicles_showwp_goaway(entity this) @@ -472,14 +465,11 @@ void vehicles_showwp_goaway(entity this) if(this.waypointsprite_attached) WaypointSprite_Kill(this.waypointsprite_attached); - remove(this); - + delete(this); } void vehicles_showwp(entity this) { - vector rgb; - entity ent = this; if(ent.cnt) @@ -493,7 +483,6 @@ void vehicles_showwp(entity this) ent.nextthink = time + 1; ent = spawn(); - setmodel(ent, MDL_Null); ent.team = this.wp00.team; ent.wp00 = this.wp00; setorigin(ent, this.wp00.pos1); @@ -502,11 +491,12 @@ void vehicles_showwp(entity this) setthink(ent, vehicles_showwp_goaway); } + vector rgb; if(teamplay && ent.team) rgb = Team_ColorRGB(ent.team); else rgb = '1 1 1'; - entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, ent, '0 0 64', world, 0, ent, waypointsprite_attached, true, RADARICON_Vehicle); + entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, ent, '0 0 64', NULL, 0, ent, waypointsprite_attached, true, RADARICON_Vehicle); wp.colormod = rgb; if(ent.waypointsprite_attached) { @@ -519,11 +509,10 @@ void vehicles_showwp(entity this) void vehicles_setreturn(entity veh) { - entity ret; - vehicles_clearreturn(veh); - ret = new(vehicle_return); + entity ret = new(vehicle_return); + IL_PUSH(g_vehicle_returners, ret); ret.wp00 = veh; ret.team = veh.team; setthink(ret, vehicles_showwp); @@ -538,14 +527,12 @@ void vehicles_setreturn(entity veh) ret.nextthink = min(time + veh.respawntime, time + veh.respawntime - 1); } - setmodel(ret, MDL_Null); setorigin(ret, veh.pos1 + '0 0 96'); - } void vehicle_use(entity this, entity actor, entity trigger) { - LOG_TRACE("vehicle ",this.netname, " used by ", actor.classname, "\n"); + LOG_DEBUG("vehicle ", this.netname, " used by ", actor.classname); this.tur_head.team = actor.team; @@ -556,7 +543,7 @@ void vehicle_use(entity this, entity actor, entity trigger) if(this.active == ACTIVE_ACTIVE && !IS_DEAD(this) && !gameover) { - LOG_TRACE("Respawning vehicle: ", this.netname, "\n"); + LOG_DEBUG("Respawning vehicle: ", this.netname); if(this.effects & EF_NODRAW) { setthink(this, vehicles_spawn); @@ -634,20 +621,15 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag // WEAPONTODO if(DEATH_ISWEAPON(deathtype, WEP_VORTEX)) damage *= autocvar_g_vehicles_vortex_damagerate; - - if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN)) + else if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN)) damage *= autocvar_g_vehicles_machinegun_damagerate; - - if(DEATH_ISWEAPON(deathtype, WEP_RIFLE)) + else if(DEATH_ISWEAPON(deathtype, WEP_RIFLE)) damage *= autocvar_g_vehicles_rifle_damagerate; - - if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER)) + else if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER)) damage *= autocvar_g_vehicles_vaporizer_damagerate; - - if(DEATH_ISWEAPON(deathtype, WEP_SEEKER)) + else if(DEATH_ISWEAPON(deathtype, WEP_SEEKER)) damage *= autocvar_g_vehicles_tag_damagerate; - - if(DEATH_WEAPONOF(deathtype) != WEP_Null) + else if(DEATH_WEAPONOF(deathtype) != WEP_Null) damage *= autocvar_g_vehicles_weapon_damagerate; this.enemy = attacker; @@ -656,7 +638,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag if((this.vehicle_flags & VHF_HASSHIELD) && (this.vehicle_shield > 0)) { - if (wasfreed(this.vehicle_shieldent) || this.vehicle_shieldent == world) + if (wasfreed(this.vehicle_shieldent) || this.vehicle_shieldent == NULL) { this.vehicle_shieldent = spawn(); this.vehicle_shieldent.effects = EF_LOWPRECISION; @@ -721,7 +703,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag } } -float vehicles_crushable(entity e) +bool vehicles_crushable(entity e) { if(IS_PLAYER(e) && time >= e.vehicle_enter_delay) return true; @@ -745,7 +727,7 @@ void vehicles_impact(entity this, float _minspeed, float _speedfac, float _maxpa if(_minspeed < wc) { float take = min(_speedfac * wc, _maxpain); - Damage (this, world, world, take, DEATH_FALL.m_id, this.origin, '0 0 0'); + Damage (this, NULL, NULL, take, DEATH_FALL.m_id, this.origin, '0 0 0'); this.play_time = time + 0.25; //dprint("wc: ", ftos(wc), "\n"); @@ -757,18 +739,14 @@ void vehicles_impact(entity this, float _minspeed, float _speedfac, float _maxpa // vehicle enter/exit handling vector vehicles_findgoodexit(entity this, vector prefer_spot) { - //vector exitspot; - float mysize; - tracebox(this.origin + '0 0 32', STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), prefer_spot, MOVE_NORMAL, this.owner); if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) return prefer_spot; - mysize = 1.5 * vlen(this.maxs - this.mins); - float i; - vector v, v2; - v2 = 0.5 * (this.absmin + this.absmax); - for(i = 0; i < 100; ++i) + float mysize = 1.5 * vlen(this.maxs - this.mins); + vector v; + vector v2 = 0.5 * (this.absmin + this.absmax); + for(int i = 0; i < autocvar_g_vehicles_exit_attempts; ++i) { v = randomvec(); v_z = 0; @@ -778,28 +756,6 @@ vector vehicles_findgoodexit(entity this, vector prefer_spot) return v; } - /* - exitspot = (this.origin + '0 0 48') + v_forward * mysize; - tracebox(this.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, this.owner); - if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) - return exitspot; - - exitspot = (this.origin + '0 0 48') - v_forward * mysize; - tracebox(this.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, this.owner); - if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) - return exitspot; - - exitspot = (this.origin + '0 0 48') + v_right * mysize; - tracebox(this.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, this.owner); - if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) - return exitspot; - - exitspot = (this.origin + '0 0 48') - v_right * mysize; - tracebox(this.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, this.owner); - if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid) - return exitspot; - */ - return this.origin; } @@ -809,7 +765,7 @@ void vehicles_exit(entity vehic, bool eject) if(vehicles_exit_running) { - LOG_TRACE("^1vehicles_exit already running! this is not good...\n"); + LOG_TRACE("^1vehicles_exit already running! this is not good..."); return; } @@ -841,16 +797,21 @@ void vehicles_exit(entity vehic, bool eject) player.takedamage = DAMAGE_AIM; player.solid = SOLID_SLIDEBOX; - player.movetype = MOVETYPE_WALK; + set_movetype(player, MOVETYPE_WALK); player.effects &= ~EF_NODRAW; player.teleportable = TELEPORT_NORMAL; player.alpha = 1; player.PlayerPhysplug = func_null; - player.vehicle = world; + player.vehicle = NULL; player.view_ofs = STAT(PL_VIEW_OFS, NULL); player.event_damage = PlayerDamage; player.hud = HUD_NORMAL; - PS(player).m_switchweapon = vehic.m_switchweapon; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++ slot) + { + .entity weaponentity = weaponentities[slot]; + player.(weaponentity).m_switchweapon = vehic.(weaponentity).m_switchweapon; + delete(vehic.(weaponentity)); // no longer needed + } player.last_vehiclecheck = time + 3; player.vehicle_enter_delay = time + 2; @@ -865,7 +826,7 @@ void vehicles_exit(entity vehic, bool eject) if(!IS_DEAD(vehic)) vehic.avelocity = '0 0 0'; - vehic.tur_head.nodrawtoclient = world; + vehic.tur_head.nodrawtoclient = NULL; if(!teamplay) vehic.team = 0; @@ -884,28 +845,28 @@ void vehicles_exit(entity vehic, bool eject) vehicles_setreturn(vehic); vehicles_reset_colors(vehic); - vehic.owner = world; + vehic.owner = NULL; CSQCMODEL_AUTOINIT(vehic); vehicles_exit_running = false; } -void vehicles_touch(entity this) +void vehicles_touch(entity this, entity toucher) { - if(MUTATOR_CALLHOOK(VehicleTouch, this, other)) + if(MUTATOR_CALLHOOK(VehicleTouch, this, toucher)) return; // Vehicle currently in use if(this.owner) { if(!forbidWeaponUse(this.owner)) - if(other != world) - if((this.origin_z + this.maxs_z) > (other.origin_z)) - if(vehicles_crushable(other)) + if(toucher != NULL) + if((this.origin_z + this.maxs_z) > (toucher.origin_z)) + if(vehicles_crushable(toucher)) { if(vdist(this.velocity, >=, 30)) - Damage(other, this, this.owner, autocvar_g_vehicles_crush_dmg, DEATH_VH_CRUSH.m_id, '0 0 0', normalize(other.origin - this.origin) * autocvar_g_vehicles_crush_force); + 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); return; // Dont do selfdamage when hitting "soft targets". } @@ -921,7 +882,7 @@ void vehicles_touch(entity this) if(autocvar_g_vehicles_enter) return; - vehicles_enter(other, this); + vehicles_enter(toucher, this); } bool vehicle_impulse(entity this, int imp) @@ -956,23 +917,20 @@ void vehicles_enter(entity pl, entity veh) || (pl.vehicle) ) { return; } + Vehicle info = Vehicles_from(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) - if(veh.owner) + if(veh.owner && SAME_TEAM(pl, veh)) { - if(!veh.gunner1) - if(time >= veh.gun1.phase) - if(veh.gun1.vehicle_enter) - if(veh.gun1.vehicle_enter(veh, pl)) - return; - - if(!veh.gunner2) - if(time >= veh.gun2.phase) - if(veh.gun2.vehicle_enter) - if(veh.gun2.vehicle_enter(veh, pl)) - return; + // we don't need a return value or anything here + // if successful the owner check below will prevent anything weird + info.vr_gunner_enter(info, veh, pl); } + if(veh.owner) + return; // got here and didn't enter the gunner, return + if(teamplay) if(veh.team) if(DIFF_TEAM(pl, veh)) @@ -983,13 +941,13 @@ void vehicles_enter(entity pl, entity veh) Send_Notification(NOTIF_ONE, pl, MSG_CENTER, CENTER_VEHICLE_STEAL_SELF); if (autocvar_g_vehicles_steal_show_waypoint) { - entity wp = WaypointSprite_Spawn(WP_VehicleIntruder, 0, 0, pl, '0 0 68', world, veh.team, veh, wps_intruder, true, RADARICON_DANGER); + entity wp = WaypointSprite_Spawn(WP_VehicleIntruder, 0, 0, pl, '0 0 68', NULL, veh.team, veh, wps_intruder, true, RADARICON_DANGER); wp.colormod = Team_ColorRGB(pl.team); } } else return; - RemoveGrapplingHook(pl); + RemoveGrapplingHooks(pl); veh.vehicle_ammo1 = 0; veh.vehicle_ammo2 = 0; @@ -1005,7 +963,6 @@ void vehicles_enter(entity pl, entity veh) veh.vehicle_hudmodel.viewmodelforclient = pl; - tracebox(pl.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), pl.origin, false, pl); pl.crouch = false; pl.view_ofs = STAT(PL_VIEW_OFS, NULL); setsize (pl, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL)); @@ -1015,7 +972,8 @@ void vehicles_enter(entity pl, entity veh) pl.angles = veh.angles; pl.takedamage = DAMAGE_NO; pl.solid = SOLID_NOT; - pl.movetype = MOVETYPE_NOCLIP; + pl.disableclientprediction = 1; // physics is no longer run, so this won't be reset + set_movetype(pl, MOVETYPE_NOCLIP); pl.teleportable = false; pl.alpha = -1; pl.event_damage = func_null; @@ -1023,7 +981,12 @@ void vehicles_enter(entity pl, entity veh) veh.colormap = pl.colormap; if(veh.tur_head) veh.tur_head.colormap = pl.colormap; - veh.m_switchweapon = PS(pl).m_switchweapon; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + veh.(weaponentity) = new(temp_wepent); + veh.(weaponentity).m_switchweapon = pl.(weaponentity).m_switchweapon; + } pl.hud = veh.vehicleid; pl.PlayerPhysplug = veh.PlayerPhysplug; @@ -1073,15 +1036,14 @@ void vehicles_enter(entity pl, entity veh) MUTATOR_CALLHOOK(VehicleEnter, pl, veh); CSQCModel_UnlinkEntity(veh); - Vehicle info = Vehicles_from(veh.vehicleid); - WITHSELF(veh, info.vr_enter(info, veh)); + info.vr_enter(info, veh); antilag_clear(pl, CS(pl)); } void vehicles_think(entity this) { - this.nextthink = time; + this.nextthink = time + autocvar_g_vehicles_thinkrate; if(this.owner) this.owner.vehicle_weapon2mode = this.vehicle_weapon2mode; @@ -1094,24 +1056,38 @@ void vehicles_think(entity this) CSQCMODEL_AUTOUPDATE(this); } +void vehicles_reset(entity this) +{ + if(this.owner) + vehicles_exit(this, VHEF_RELEASE); + + vehicles_clearreturn(this); + + if(this.active != ACTIVE_NOT) + vehicles_spawn(this); +} + // initialization void vehicles_spawn(entity this) { - LOG_TRACE("Spawning vehicle: ", this.classname, "\n"); + LOG_DEBUG("Spawning vehicle: ", this.classname); // disown & reset this.vehicle_hudmodel.viewmodelforclient = this; - this.owner = world; + this.owner = NULL; settouch(this, vehicles_touch); this.event_damage = vehicles_damage; + this.reset = vehicles_reset; this.iscreature = true; this.teleportable = false; // no teleporting for vehicles, too buggy this.damagedbycontents = true; - this.movetype = MOVETYPE_WALK; + set_movetype(this, MOVETYPE_WALK); this.solid = SOLID_SLIDEBOX; this.takedamage = DAMAGE_AIM; this.deadflag = DEAD_NO; + if(!this.bot_attack) + IL_PUSH(g_bot_targets, this); this.bot_attack = true; this.flags = FL_NOTARGET; this.avelocity = '0 0 0'; @@ -1121,7 +1097,7 @@ void vehicles_spawn(entity this) // Reset locking this.lock_strength = 0; - this.lock_target = world; + this.lock_target = NULL; this.misc_bulletcounter = 0; // Return to spawn @@ -1133,7 +1109,15 @@ void vehicles_spawn(entity this) if(this.vehicle_controller) this.team = this.vehicle_controller.team; - FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == this, RemoveGrapplingHook(it)); + FOREACH_CLIENT(IS_PLAYER(it), + { + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(it.(weaponentity).hook.aiment == this) + RemoveHook(it.(weaponentity).hook); + } + }); vehicles_reset_colors(this); @@ -1152,14 +1136,17 @@ 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 != "") { - this.vehicle_controller = find(world, target, this.targetname); + this.vehicle_controller = find(NULL, target, this.targetname); if(!this.vehicle_controller) { - bprint("^1WARNING: ^7Vehicle with invalid .targetname\n"); + LOG_DEBUG("^1WARNING: ^7Vehicle with invalid .targetname"); this.active = ACTIVE_ACTIVE; } else @@ -1194,9 +1181,11 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop) this.tur_head.owner = this; this.takedamage = DAMAGE_NO; this.bot_attack = true; + IL_PUSH(g_bot_targets, this); this.iscreature = true; this.teleportable = false; // no teleporting for vehicles, too buggy this.damagedbycontents = true; + IL_PUSH(g_damagedbycontents, this); this.vehicleid = info.vehicleid; this.PlayerPhysplug = info.PlayerPhysplug; this.event_damage = func_null; @@ -1234,6 +1223,8 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop) setsize(this, info.mins, info.maxs); + info.vr_setup(info, this); + if(!nodrop) { setorigin(this, this.origin); @@ -1245,8 +1236,6 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop) this.pos2 = this.angles; this.tur_head.team = this.team; - info.vr_setup(info, this); - if(this.active == ACTIVE_NOT) this.nextthink = 0; // wait until activated else if(autocvar_g_vehicles_delayspawn) @@ -1254,7 +1243,7 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop) else this.nextthink = time + game_starttime; - if(MUTATOR_CALLHOOK(VehicleSpawn, this)) + if(MUTATOR_CALLHOOK(VehicleInit, this)) return false; return true;