Merge branch 'master' into gonesolong
Conflicts: src/CMakeLists.txt src/b_think.cpp src/g_doom/a_doomweaps.cpp src/g_hexen/a_clericstaff.cpp src/g_hexen/a_fighterplayer.cpp src/namedef.h src/p_enemy.cpp src/p_local.h src/p_mobj.cpp src/p_teleport.cpp src/sc_man_tokens.h src/thingdef/thingdef_codeptr.cpp src/thingdef/thingdef_function.cpp src/thingdef/thingdef_parse.cpp wadsrc/static/actors/actor.txt wadsrc/static/actors/constants.txt wadsrc/static/actors/shared/inventory.txt - Added register reuse to VMFunctionBuilder for FxPick's code emitter. - Note to self: Need to reimplement IsPointerEqual and CheckClass, which were added to thingdef_function.cpp over the past year, as this file no longer exists in this branch.
This commit is contained in:
commit
b5e4153c78
182 changed files with 23025 additions and 8730 deletions
278
src/p_user.cpp
278
src/p_user.cpp
|
|
@ -62,8 +62,32 @@ static FRandom pr_skullpop ("SkullPop");
|
|||
|
||||
// Variables for prediction
|
||||
CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR(Bool, cl_predict_specials, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
CUSTOM_CVAR(Float, cl_predict_lerpscale, 0.05f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
P_PredictionLerpReset();
|
||||
}
|
||||
CUSTOM_CVAR(Float, cl_predict_lerpthreshold, 2.00f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
if (self < 0.1f)
|
||||
self = 0.1f;
|
||||
P_PredictionLerpReset();
|
||||
}
|
||||
|
||||
struct PredictPos
|
||||
{
|
||||
int gametic;
|
||||
fixed_t x;
|
||||
fixed_t y;
|
||||
fixed_t z;
|
||||
fixed_t pitch;
|
||||
fixed_t yaw;
|
||||
} static PredictionLerpFrom, PredictionLerpResult, PredictionLast;
|
||||
static int PredictionLerptics;
|
||||
|
||||
static player_t PredictionPlayerBackup;
|
||||
static BYTE PredictionActorBackup[sizeof(AActor)];
|
||||
static BYTE PredictionActorBackup[sizeof(APlayerPawn)];
|
||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||
static TArray<AActor *> PredictionSectorListBackup;
|
||||
static TArray<msecnode_t *> PredictionSector_sprev_Backup;
|
||||
|
|
@ -238,7 +262,6 @@ player_t::player_t()
|
|||
health(0),
|
||||
inventorytics(0),
|
||||
CurrentPlayerClass(0),
|
||||
backpack(0),
|
||||
fragcount(0),
|
||||
lastkilltime(0),
|
||||
multicount(0),
|
||||
|
|
@ -271,28 +294,7 @@ player_t::player_t()
|
|||
respawn_time(0),
|
||||
camera(0),
|
||||
air_finished(0),
|
||||
savedyaw(0),
|
||||
savedpitch(0),
|
||||
angle(0),
|
||||
dest(0),
|
||||
prev(0),
|
||||
enemy(0),
|
||||
missile(0),
|
||||
mate(0),
|
||||
last_mate(0),
|
||||
t_active(0),
|
||||
t_respawn(0),
|
||||
t_strafe(0),
|
||||
t_react(0),
|
||||
t_fight(0),
|
||||
t_roam(0),
|
||||
t_rocket(0),
|
||||
isbot(0),
|
||||
first_shot(0),
|
||||
sleft(0),
|
||||
allround(0),
|
||||
oldx(0),
|
||||
oldy(0),
|
||||
Bot(0),
|
||||
BlendR(0),
|
||||
BlendG(0),
|
||||
BlendB(0),
|
||||
|
|
@ -311,7 +313,6 @@ player_t::player_t()
|
|||
memset (&cmd, 0, sizeof(cmd));
|
||||
memset (frags, 0, sizeof(frags));
|
||||
memset (psprites, 0, sizeof(psprites));
|
||||
memset (&skill, 0, sizeof(skill));
|
||||
}
|
||||
|
||||
player_t &player_t::operator=(const player_t &p)
|
||||
|
|
@ -339,7 +340,6 @@ player_t &player_t::operator=(const player_t &p)
|
|||
health = p.health;
|
||||
inventorytics = p.inventorytics;
|
||||
CurrentPlayerClass = p.CurrentPlayerClass;
|
||||
backpack = p.backpack;
|
||||
memcpy(frags, &p.frags, sizeof(frags));
|
||||
fragcount = p.fragcount;
|
||||
lastkilltime = p.lastkilltime;
|
||||
|
|
@ -380,30 +380,8 @@ player_t &player_t::operator=(const player_t &p)
|
|||
camera = p.camera;
|
||||
air_finished = p.air_finished;
|
||||
LastDamageType = p.LastDamageType;
|
||||
savedyaw = p.savedyaw;
|
||||
savedpitch = p.savedpitch;
|
||||
angle = p.angle;
|
||||
dest = p.dest;
|
||||
prev = p.prev;
|
||||
enemy = p.enemy;
|
||||
missile = p.missile;
|
||||
mate = p.mate;
|
||||
last_mate = p.last_mate;
|
||||
Bot = p.Bot;
|
||||
settings_controller = p.settings_controller;
|
||||
skill = p.skill;
|
||||
t_active = p.t_active;
|
||||
t_respawn = p.t_respawn;
|
||||
t_strafe = p.t_strafe;
|
||||
t_react = p.t_react;
|
||||
t_fight = p.t_fight;
|
||||
t_roam = p.t_roam;
|
||||
t_rocket = p.t_rocket;
|
||||
isbot = p.isbot;
|
||||
first_shot = p.first_shot;
|
||||
sleft = p.sleft;
|
||||
allround = p.allround;
|
||||
oldx = p.oldx;
|
||||
oldy = p.oldy;
|
||||
BlendR = p.BlendR;
|
||||
BlendG = p.BlendG;
|
||||
BlendB = p.BlendB;
|
||||
|
|
@ -445,12 +423,7 @@ size_t player_t::FixPointers (const DObject *old, DObject *rep)
|
|||
if (*&poisoner == old) poisoner = replacement, changed++;
|
||||
if (*&attacker == old) attacker = replacement, changed++;
|
||||
if (*&camera == old) camera = replacement, changed++;
|
||||
if (*&dest == old) dest = replacement, changed++;
|
||||
if (*&prev == old) prev = replacement, changed++;
|
||||
if (*&enemy == old) enemy = replacement, changed++;
|
||||
if (*&missile == old) missile = replacement, changed++;
|
||||
if (*&mate == old) mate = replacement, changed++;
|
||||
if (*&last_mate == old) last_mate = replacement, changed++;
|
||||
if (*&Bot == old) Bot = static_cast<DBot *>(rep), changed++;
|
||||
if (ReadyWeapon == old) ReadyWeapon = static_cast<AWeapon *>(rep), changed++;
|
||||
if (PendingWeapon == old) PendingWeapon = static_cast<AWeapon *>(rep), changed++;
|
||||
if (*&PremorphWeapon == old) PremorphWeapon = static_cast<AWeapon *>(rep), changed++;
|
||||
|
|
@ -465,12 +438,7 @@ size_t player_t::PropagateMark()
|
|||
GC::Mark(poisoner);
|
||||
GC::Mark(attacker);
|
||||
GC::Mark(camera);
|
||||
GC::Mark(dest);
|
||||
GC::Mark(prev);
|
||||
GC::Mark(enemy);
|
||||
GC::Mark(missile);
|
||||
GC::Mark(mate);
|
||||
GC::Mark(last_mate);
|
||||
GC::Mark(Bot);
|
||||
GC::Mark(ReadyWeapon);
|
||||
GC::Mark(ConversationNPC);
|
||||
GC::Mark(ConversationPC);
|
||||
|
|
@ -712,7 +680,16 @@ void APlayerPawn::BeginPlay ()
|
|||
FString crouchspritename = sprites[crouchsprite].name;
|
||||
|
||||
int spritenorm = Wads.CheckNumForName(normspritename + "A1", ns_sprites);
|
||||
if (spritenorm==-1)
|
||||
{
|
||||
spritenorm = Wads.CheckNumForName(normspritename + "A0", ns_sprites);
|
||||
}
|
||||
|
||||
int spritecrouch = Wads.CheckNumForName(crouchspritename + "A1", ns_sprites);
|
||||
if (spritecrouch==-1)
|
||||
{
|
||||
spritecrouch = Wads.CheckNumForName(crouchspritename + "A0", ns_sprites);
|
||||
}
|
||||
|
||||
if (spritenorm==-1 || spritecrouch ==-1)
|
||||
{
|
||||
|
|
@ -794,10 +771,10 @@ void APlayerPawn::SetupWeaponSlots()
|
|||
// If we're the local player, then there's a bit more work to do.
|
||||
// This also applies if we're a bot and this is the net arbitrator.
|
||||
if (player - players == consoleplayer ||
|
||||
(player->isbot && consoleplayer == Net_Arbitrator))
|
||||
(player->Bot != NULL && consoleplayer == Net_Arbitrator))
|
||||
{
|
||||
FWeaponSlots local_slots(player->weapons);
|
||||
if (player->isbot)
|
||||
if (player->Bot != NULL)
|
||||
{ // Bots only need weapons from KEYCONF, not INI modifications.
|
||||
P_PlaybackKeyConfWeapons(&local_slots);
|
||||
}
|
||||
|
|
@ -1311,9 +1288,6 @@ void APlayerPawn::GiveDefaultInventory ()
|
|||
{
|
||||
if (player == NULL) return;
|
||||
|
||||
// [GRB] Give inventory specified in DECORATE
|
||||
player->health = GetDefault ()->health;
|
||||
|
||||
// HexenArmor must always be the first item in the inventory because
|
||||
// it provides player class based protection that should not affect
|
||||
// any other protection item.
|
||||
|
|
@ -2233,7 +2207,7 @@ void P_DeathThink (player_t *player)
|
|||
if ((player->cmd.ucmd.buttons & BT_USE ||
|
||||
((multiplayer || alwaysapplydmflags) && (dmflags & DF_FORCE_RESPAWN))) && !(dmflags2 & DF2_NO_RESPAWN))
|
||||
{
|
||||
if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && !player->isbot))
|
||||
if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && player->Bot == NULL))
|
||||
{
|
||||
player->cls = NULL; // Force a new class if the player is using a random class
|
||||
player->playerstate = (multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN)) ? PST_REBORN : PST_ENTER;
|
||||
|
|
@ -2703,7 +2677,8 @@ void P_PlayerThink (player_t *player)
|
|||
{
|
||||
if (player->mo->waterlevel < 3 ||
|
||||
(player->mo->flags2 & MF2_INVULNERABLE) ||
|
||||
(player->cheats & (CF_GODMODE | CF_NOCLIP2)))
|
||||
(player->cheats & (CF_GODMODE | CF_NOCLIP2)) ||
|
||||
(player->cheats & CF_GODMODE2))
|
||||
{
|
||||
player->mo->ResetAirSupply ();
|
||||
}
|
||||
|
|
@ -2715,6 +2690,29 @@ void P_PlayerThink (player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
void P_PredictionLerpReset()
|
||||
{
|
||||
PredictionLerptics = PredictionLast.gametic = PredictionLerpFrom.gametic = PredictionLerpResult.gametic = 0;
|
||||
}
|
||||
|
||||
bool P_LerpCalculate(PredictPos from, PredictPos to, PredictPos &result, float scale)
|
||||
{
|
||||
FVector3 vecFrom(FIXED2DBL(from.x), FIXED2DBL(from.y), FIXED2DBL(from.z));
|
||||
FVector3 vecTo(FIXED2DBL(to.x), FIXED2DBL(to.y), FIXED2DBL(to.z));
|
||||
FVector3 vecResult;
|
||||
vecResult = vecTo - vecFrom;
|
||||
vecResult *= scale;
|
||||
vecResult = vecResult + vecFrom;
|
||||
FVector3 delta = vecResult - vecTo;
|
||||
|
||||
result.x = FLOAT2FIXED(vecResult.X);
|
||||
result.y = FLOAT2FIXED(vecResult.Y);
|
||||
result.z = FLOAT2FIXED(vecResult.Z);
|
||||
|
||||
// As a fail safe, assume extrapolation is the threshold.
|
||||
return (delta.LengthSquared() > cl_predict_lerpthreshold && scale <= 1.00f);
|
||||
}
|
||||
|
||||
void P_PredictPlayer (player_t *player)
|
||||
{
|
||||
int maxtic;
|
||||
|
|
@ -2742,8 +2740,8 @@ void P_PredictPlayer (player_t *player)
|
|||
// Save original values for restoration later
|
||||
PredictionPlayerBackup = *player;
|
||||
|
||||
AActor *act = player->mo;
|
||||
memcpy (PredictionActorBackup, &act->x, sizeof(AActor)-((BYTE *)&act->x-(BYTE *)act));
|
||||
APlayerPawn *act = player->mo;
|
||||
memcpy(PredictionActorBackup, &act->x, sizeof(APlayerPawn) - ((BYTE *)&act->x - (BYTE *)act));
|
||||
|
||||
act->flags &= ~MF_PICKUP;
|
||||
act->flags2 &= ~MF2_PUSHWALL;
|
||||
|
|
@ -2800,11 +2798,67 @@ void P_PredictPlayer (player_t *player)
|
|||
}
|
||||
act->BlockNode = NULL;
|
||||
|
||||
// Values too small to be usable for lerping can be considered "off".
|
||||
bool CanLerp = (!(cl_predict_lerpscale < 0.01f) && (ticdup == 1)), DoLerp = false, NoInterpolateOld = R_GetViewInterpolationStatus();
|
||||
for (int i = gametic; i < maxtic; ++i)
|
||||
{
|
||||
if (!NoInterpolateOld)
|
||||
R_RebuildViewInterpolation(player);
|
||||
|
||||
player->cmd = localcmds[i % LOCALCMDTICS];
|
||||
P_PlayerThink (player);
|
||||
player->mo->Tick ();
|
||||
|
||||
if (CanLerp && PredictionLast.gametic > 0 && i == PredictionLast.gametic && !NoInterpolateOld)
|
||||
{
|
||||
// Z is not compared as lifts will alter this with no apparent change
|
||||
// Make lerping less picky by only testing whole units
|
||||
DoLerp = ((PredictionLast.x >> 16) != (player->mo->x >> 16) ||
|
||||
(PredictionLast.y >> 16) != (player->mo->y >> 16));
|
||||
|
||||
// Aditional Debug information
|
||||
if (developer && DoLerp)
|
||||
{
|
||||
DPrintf("Lerp! Ltic (%d) && Ptic (%d) | Lx (%d) && Px (%d) | Ly (%d) && Py (%d)\n",
|
||||
PredictionLast.gametic, i,
|
||||
(PredictionLast.x >> 16), (player->mo->x >> 16),
|
||||
(PredictionLast.y >> 16), (player->mo->y >> 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CanLerp)
|
||||
{
|
||||
if (NoInterpolateOld)
|
||||
P_PredictionLerpReset();
|
||||
|
||||
else if (DoLerp)
|
||||
{
|
||||
// If lerping is already in effect, use the previous camera postion so the view doesn't suddenly snap
|
||||
PredictionLerpFrom = (PredictionLerptics == 0) ? PredictionLast : PredictionLerpResult;
|
||||
PredictionLerptics = 1;
|
||||
}
|
||||
|
||||
PredictionLast.gametic = maxtic - 1;
|
||||
PredictionLast.x = player->mo->x;
|
||||
PredictionLast.y = player->mo->y;
|
||||
PredictionLast.z = player->mo->z;
|
||||
|
||||
if (PredictionLerptics > 0)
|
||||
{
|
||||
if (PredictionLerpFrom.gametic > 0 &&
|
||||
P_LerpCalculate(PredictionLerpFrom, PredictionLast, PredictionLerpResult, (float)PredictionLerptics * cl_predict_lerpscale))
|
||||
{
|
||||
PredictionLerptics++;
|
||||
player->mo->x = PredictionLerpResult.x;
|
||||
player->mo->y = PredictionLerpResult.y;
|
||||
player->mo->z = PredictionLerpResult.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
PredictionLerptics = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2817,9 +2871,12 @@ void P_UnPredictPlayer ()
|
|||
if (player->cheats & CF_PREDICTING)
|
||||
{
|
||||
unsigned int i;
|
||||
AActor *act = player->mo;
|
||||
APlayerPawn *act = player->mo;
|
||||
AActor *savedcamera = player->camera;
|
||||
|
||||
TObjPtr<AInventory> InvSel = act->InvSel;
|
||||
int inventorytics = player->inventorytics;
|
||||
|
||||
*player = PredictionPlayerBackup;
|
||||
|
||||
// Restore the camera instead of using the backup's copy, because spynext/prev
|
||||
|
|
@ -2827,7 +2884,7 @@ void P_UnPredictPlayer ()
|
|||
player->camera = savedcamera;
|
||||
|
||||
act->UnlinkFromWorld();
|
||||
memcpy(&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x - (BYTE *)act));
|
||||
memcpy(&act->x, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->x - (BYTE *)act));
|
||||
|
||||
// The blockmap ordering needs to remain unchanged, too.
|
||||
// Restore sector links and refrences.
|
||||
|
|
@ -2932,6 +2989,9 @@ void P_UnPredictPlayer ()
|
|||
}
|
||||
block = block->NextBlock;
|
||||
}
|
||||
|
||||
act->InvSel = InvSel;
|
||||
player->inventorytics = inventorytics;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2962,9 +3022,13 @@ void player_t::Serialize (FArchive &arc)
|
|||
<< vely
|
||||
<< centering
|
||||
<< health
|
||||
<< inventorytics
|
||||
<< backpack
|
||||
<< fragcount
|
||||
<< inventorytics;
|
||||
if (SaveVersion < 4513)
|
||||
{
|
||||
bool backpack;
|
||||
arc << backpack;
|
||||
}
|
||||
arc << fragcount
|
||||
<< spreecount
|
||||
<< multicount
|
||||
<< lastkilltime
|
||||
|
|
@ -2993,9 +3057,17 @@ void player_t::Serialize (FArchive &arc)
|
|||
<< respawn_time
|
||||
<< air_finished
|
||||
<< turnticks
|
||||
<< oldbuttons
|
||||
<< isbot
|
||||
<< BlendR
|
||||
<< oldbuttons;
|
||||
bool IsBot;
|
||||
if (SaveVersion >= 4514)
|
||||
{
|
||||
arc << Bot;
|
||||
}
|
||||
else
|
||||
{
|
||||
arc << IsBot;
|
||||
}
|
||||
arc << BlendR
|
||||
<< BlendG
|
||||
<< BlendB
|
||||
<< BlendA;
|
||||
|
|
@ -3078,33 +3150,37 @@ void player_t::Serialize (FArchive &arc)
|
|||
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (cheats & CF_NOCLIP2);
|
||||
}
|
||||
|
||||
if (isbot)
|
||||
if (SaveVersion < 4514 && IsBot)
|
||||
{
|
||||
arc << angle
|
||||
<< dest
|
||||
<< prev
|
||||
<< enemy
|
||||
<< missile
|
||||
<< mate
|
||||
<< last_mate
|
||||
<< skill
|
||||
<< t_active
|
||||
<< t_respawn
|
||||
<< t_strafe
|
||||
<< t_react
|
||||
<< t_fight
|
||||
<< t_roam
|
||||
<< t_rocket
|
||||
<< first_shot
|
||||
<< sleft
|
||||
<< allround
|
||||
<< oldx
|
||||
<< oldy;
|
||||
Bot = new DBot;
|
||||
|
||||
arc << Bot->angle
|
||||
<< Bot->dest
|
||||
<< Bot->prev
|
||||
<< Bot->enemy
|
||||
<< Bot->missile
|
||||
<< Bot->mate
|
||||
<< Bot->last_mate
|
||||
<< Bot->skill
|
||||
<< Bot->t_active
|
||||
<< Bot->t_respawn
|
||||
<< Bot->t_strafe
|
||||
<< Bot->t_react
|
||||
<< Bot->t_fight
|
||||
<< Bot->t_roam
|
||||
<< Bot->t_rocket
|
||||
<< Bot->first_shot
|
||||
<< Bot->sleft
|
||||
<< Bot->allround
|
||||
<< Bot->oldx
|
||||
<< Bot->oldy;
|
||||
}
|
||||
else
|
||||
|
||||
if (SaveVersion < 4516 && Bot != NULL)
|
||||
{
|
||||
dest = prev = enemy = missile = mate = last_mate = NULL;
|
||||
Bot->player = this;
|
||||
}
|
||||
|
||||
if (arc.IsLoading ())
|
||||
{
|
||||
// If the player reloaded because they pressed +use after dying, we
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue