Fake Spectator and weapon select cleanup

This commit is contained in:
Chris Dawalt 2021-08-01 05:12:11 -04:00
parent c3329b3e73
commit de86f7bf49
9 changed files with 254 additions and 311 deletions

View file

@ -94,6 +94,8 @@ ClientGame_ConsoleCommand(void)
//If we're in spectator mode we can do this
// no-screen check, not necessary probably: pSeatLocal->fVGUI_Display == VGUI_SCREEN::NONE &&
printfline("WOO HOO YEA BOY %s", getplayerkeyvalue( player_localnum, "*spec" ));
if(getplayerkeyvalue( player_localnum, "*spec" ) != "0"){
//we can show it!
VGUI_ChangeScreen(VGUI_SCREEN::BUYSIDEMENU);

View file

@ -96,14 +96,6 @@ drawPainArrows(void)
// and now for the screen-wide pain flash.
void
drawPainFlash(void)
@ -144,7 +136,3 @@ ClientGame_DamageDraw(void){
}

View file

@ -55,83 +55,117 @@ void
HUD_Draw(void)
{
player pl = (player)pSeat->m_ePlayer;
if(pl.iState == PLAYER_STATE::SPAWNED){
// A player
g_hud_color = autocvar_con_color * (1 / 255);
g_hud_color = autocvar_con_color * (1 / 255);
/* little point in not drawing these, even if you don't have a suit */
Weapons_DrawCrosshair();
HUD_DrawWeaponSelect();
Obituary_Draw();
Textmenu_Draw();
//TAGGG - NEw
//////////////////////////////////////////////////////////////
//View_HandleZoom();
//printfline("SCOPE LEVEL %.2f", pl.flZoomLevel);
if(pl.flZoomLevel < 0.5){ //is this < 40? yes.
HUD_DrawScope();
}else{
// We'll leave details like extra details for the lasersight and the weight bars at a bare minimum
// (should be drawn at all times, oversight in TS 2.1 that they're missing from melee views
// like with knives, katana, corrected in 3.0 of all things)
HUD_DrawCrosshair();
}
//////////////////////////////////////////////////////////////
GameClient_PlayerInputRaw();
/* little point in not drawing these, even if you don't have a suit */
Weapons_DrawCrosshair();
HUD_DrawWeaponSelect();
Obituary_Draw();
Textmenu_Draw();
//TAGGG - NEw
//////////////////////////////////////////////////////////////
//View_HandleZoom();
//printfline("SCOPE LEVEL %.2f", pl.flZoomLevel);
if(pl.flZoomLevel < 0.5){ //is this < 40? yes.
HUD_DrawScope();
//TAGGG - NEw
//////////////////////////////////////////////////////////////
drawTimer();
drawPlayerStats();
//TAGGG - CRITICAL. Nope, Weapons_DrawCrosshair actually calls a weapon's custom HUD drawing method.
// Odd name, but yes, it's not actually focused on just crosshairs. TS uses the more generic
// "HUD_DrawCrosshair" call above.
//drawPlayerCurrentWeaponStats();
//////////////////////////////////////////////////////////////
// TEST! Just for nuclide, doesn't matter what m_iHUDWeaponSelected is exactly,
// just 0 or non-zero has significance in it.
pSeat->m_iHUDWeaponSelected = (pl.weaponSelectHighlightID != -1);
TS_keyRefTapped = 0; //reset.
HUD_DrawNotify();
// Nuclide provided method, draws the HL pain arrows
// Nope! Replaced with a completely new version that does that and more for more control.
// And not even calling from here, leaving that to PostDraw (draw.qc) instead.
// Might stop the pain flash from affecting the color of HUD draw's.
//Damage_Draw();
//ClientGame_DamageDraw();
}else{
// We'll leave details like extra details for the lasersight and the weight bars at a bare minimum
// (should be drawn at all times, oversight in TS 2.1 that they're missing from melee views
// like with knives, katana, corrected in 3.0 of all things)
HUD_DrawCrosshair();
}
//////////////////////////////////////////////////////////////
GameClient_PlayerInputRaw();
// Fake spectator really.
//printfline("I AM FAKE");
drawfont = FONT_20;
// TAGGG - could have some message from server-to-client on changing from player to spectator
// to call this only then, but I think doing this every frame for spectator is harmless anyway.
// Changing the FOV isn't necessary, that already comes with the spec/player change, some
// things are nicely defaulted for us in FTE.
setsensitivityscaler(1.0f);
//TAGGG - NEw
//////////////////////////////////////////////////////////////
drawTimer();
drawPlayerStats();
//TAGGG - CRITICAL. Nope, Weapons_DrawCrosshair actually calls a weapon's custom HUD drawing method.
// Odd name, but yes, it's not actually focused on just crosshairs. TS uses the more generic
// "HUD_DrawCrosshair" call above.
//drawPlayerCurrentWeaponStats();
//////////////////////////////////////////////////////////////
GameClient_SpectatorInputRaw();
drawTimer();
//TAGGG - Moved over! Is it wise for this to go here?
// Links to drawing the MoTD and buymenu when appropriate
//TAGGG - CRITICAL. "self" is a spectator, not a player!!
// Send over the above "spec" instead too!
CSQC_VGUI_Draw(pl);
}// pl.iState check
// TEST! Just for nuclide, doesn't matter what m_iHUDWeaponSelected is exactly,
// just 0 or non-zero has significance in it.
pSeat->m_iHUDWeaponSelected = (pl.weaponSelectHighlightID != -1);
TS_keyRefTapped = 0; //reset.
HUD_DrawNotify();
// Nuclide provided method, draws the HL pain arrows
// Nope! Replaced with a completely new version that does that and more for more control.
// And not even calling from here, leaving that to PostDraw (draw.qc) instead.
// Might stop the pain flash from affecting the color of HUD draw's.
//Damage_Draw();
//ClientGame_DamageDraw();
}
/*
string g_specmodes[] = {
"Free Camera",
"Third Person",
"First Person"
};
*/
// specatator main entry
// NOTE! This is for the real, Nuclide-provided spectator.
// The fake spectator is a normal player entity with iState set to PLAYER_STATE::NOCLIP.
// HUD_DRAW above is still called in that case. That needs the MoTD and buymenu.
void
HUD_DrawSpectator(void)
{
Textmenu_Draw();
spectator spec = (spectator)pSeat->m_ePlayer;
drawfont = FONT_20;
/*
vector vecPos;
string strText;
// No need to display these.
strText = sprintf("Tracking: %s", getplayerkeyvalue(spec.spec_ent - 1, "name"));
vecPos[0] = g_hudmins[0] + (g_hudres[0] / 2) - (stringwidth(strText, TRUE, [20,20]) / 2);
vecPos[1] = g_hudmins[1] + g_hudres[1] - 60;
@ -141,25 +175,5 @@ HUD_DrawSpectator(void)
vecPos[0] = g_hudmins[0] + (g_hudres[0] / 2) - (stringwidth(strText, TRUE, [20,20]) / 2);
vecPos[1] = g_hudmins[1] + g_hudres[1] - 40;
drawstring(vecPos, strText, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
*/
// TAGGG - could have some message from server-to-client on changing from player to spectator
// to call this only then, but I think doing this every frame for spectator is harmless anyway.
// Changing the FOV isn't necessary, that already comes with the spec/player change, some
// things are nicely defaulted for us in FTE.
setsensitivityscaler(1.0f);
GameClient_SpectatorInputRaw();
drawTimer();
//TAGGG - Moved over! Is it wise for this to go here?
// Links to drawing the MoTD and buymenu when appropriate
//TAGGG - CRITICAL. "self" is a spectator, not a player!!
// Send over the above "spec" instead too!
CSQC_VGUI_Draw( (player)self );
}

View file

@ -1,9 +1,6 @@
//NEW FILE.
//whatever needs to be accessed out of order.
// whatever needs to be accessed out of order.
BOOLEAN HUD_DrawWeaponSelect_CheckClick(void);
BOOLEAN HUD_CloseWeaponSelect(BOOL playOffSound);

View file

@ -14,23 +14,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
vector g_vecHUDNums[6] =
{
[168 / 256, 72 / 128],
[188 / 256, 72 / 128],
[208 / 256, 72 / 128],
[168 / 256, 92 / 128],
[188 / 256, 92 / 128],
[208 / 256, 92 / 128]
};
var float fHUDWeaponLast;
typedef struct {
string sSprite;
vector vOrigin;
@ -61,7 +46,6 @@ HUD_DrawWeaponSelect_PreviousItem(int weaponID_toStartFrom, BOOLEAN freeSlotMove
{
player pl = (player)pSeat->m_ePlayer;
// set to TRUE if we start at an invalid range, so that we may include the first valid of any sort.
BOOLEAN canAcceptSame = FALSE;
@ -81,8 +65,6 @@ HUD_DrawWeaponSelect_PreviousItem(int weaponID_toStartFrom, BOOLEAN freeSlotMove
int currentSlot = -1;
if(weaponID_toStartFrom != -1){
// Get what slot the currently equipped weapon is on.
// If it doesn't match the forcedSlot (if applicable: 1-5 keys forcing one),
@ -93,8 +75,6 @@ HUD_DrawWeaponSelect_PreviousItem(int weaponID_toStartFrom, BOOLEAN freeSlotMove
// to start from.
dynaRef = pl.ary_myWeapons[weaponID_toStartFrom];
if(!freeSlotMovement ){
//That is, if the player was selecting a weapon in akimbo, but the slot is no longer 5..
@ -113,7 +93,6 @@ HUD_DrawWeaponSelect_PreviousItem(int weaponID_toStartFrom, BOOLEAN freeSlotMove
//notice: picking an akimbo weapon choice while a non-akimbo weapon is selected
// will trigger this too, since the forcedSlot will be 5. non-akimbo weapons never have that.
if(currentSlot != forcedSlot){
weaponID_toStartFrom = -1; //hack to start at #0 instead
canAcceptSame = FALSE;
@ -123,9 +102,7 @@ HUD_DrawWeaponSelect_PreviousItem(int weaponID_toStartFrom, BOOLEAN freeSlotMove
pl.weaponSelectHighlightAkimbo = (forcedSlot == 5);
currentSlot = forcedSlot;
}else{
if(!pl.weaponSelectHighlightAkimbo){
//So we have a place to start looking from. Off we go, find the next weapon that belongs to this same slot.
@ -172,7 +149,6 @@ HUD_DrawWeaponSelect_PreviousItem(int weaponID_toStartFrom, BOOLEAN freeSlotMove
weaponID_toStartFromThisSlot -= 1;
}
BOOLEAN scheduleTermination = FALSE;
//int lastWeaponToCheck = 0;
@ -229,9 +205,7 @@ HUD_DrawWeaponSelect_PreviousItem(int weaponID_toStartFrom, BOOLEAN freeSlotMove
}
return i;
}
}
}
//Moving on to check a different slot? Reset weaponID_toStartFromThisSlot then
@ -270,7 +244,6 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
return pl.ary_myWeapons_softMax-1;
}
weapondynamic_t dynaRef;
weapondata_basic_t* weaponBasicP;
@ -278,10 +251,8 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
int currentSlot = -1;
//printfline("HUD_DrawWeaponSelect_NextItem weaponID_toStartFrom:%i", weaponID_toStartFrom);
if(weaponID_toStartFrom != -1){
dynaRef = pl.ary_myWeapons[weaponID_toStartFrom];
@ -309,7 +280,6 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
}
}
if(pl.weaponSelectHighlightAkimbo != (forcedSlot==5) ){
weaponID_toStartFrom = 1; //hack to start at #max instead
canAcceptSame = FALSE;
@ -321,7 +291,6 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
pl.weaponSelectHighlightAkimbo = (forcedSlot == 5);
currentSlot = forcedSlot;
}else{
if(!pl.weaponSelectHighlightAkimbo){
@ -366,8 +335,6 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
currentSlot = forcedSlot;
}
//we only use the toStartFrom offset for finding the next/previous weapon in the same slot.
//After that we start from the beginning/end of the next/previous slot accordingly for searching.
int weaponID_toStartFromThisSlot = weaponID_toStartFrom;
@ -378,7 +345,6 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
BOOLEAN scheduleTermination = FALSE;
//int lastWeaponToCheck = 0;
//printfline("weaponID_toStartFromThisSlot:%i, canAcceptSame:%d", weaponID_toStartFromThisSlot, canAcceptSame);
for(int slotOffset = 0; slotOffset <= 5; slotOffset++){
@ -439,13 +405,9 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
}
return i;
}
}
}
//Moving on to check a different slot? Reset weaponID_toStartFromThisSlot then
// hack to make it start at ary_myWeapons_softMax. That is not having "- 1".
weaponID_toStartFromThisSlot = pl.ary_myWeapons_softMax;
@ -459,7 +421,6 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
}else{
slotOffset -= 1; //keep the slot exactly the same
scheduleTermination = TRUE;
}
}//END OF LOOP THROUGH SLOTS
@ -471,12 +432,13 @@ HUD_DrawWeaponSelect_NextItem(int weaponID_toStartFrom, BOOLEAN freeSlotMovement
}//HUD_DrawWeaponSelect_NextItem
void
HUD_DrawWeaponSelect_Forward(void)
{
player pl = (player)pSeat->m_ePlayer;
if(pl.iState != PLAYER_STATE::SPAWNED){
return;
}
if(pl.weaponSelectHighlightID == -1){
//pick the weapon after then
@ -510,6 +472,9 @@ void
HUD_DrawWeaponSelect_Back(void)
{
player pl = (player)pSeat->m_ePlayer;
if(pl.iState != PLAYER_STATE::SPAWNED){
return;
}
if(pl.weaponSelectHighlightID == -1){
//pick the weapon after then
@ -548,6 +513,11 @@ HUD_DrawWeaponSelect_Back(void)
void
HUD_DrawWeaponSelect_Trigger(void)
{
player pl = (player)pSeat->m_ePlayer;
if(pl.iState != PLAYER_STATE::SPAWNED){
return;
}
//TAGGG - TODO - was commented out in old FreeTS, doing so here too.
// But figure out what it needs to do, this likely wasn't pointless
/*
@ -578,7 +548,7 @@ HUD_DrawWeaponSelect_Trigger(void)
//Cheap way to instantly close the weapon select area
// Cheap way to instantly close the weapon select area
BOOLEAN
HUD_CloseWeaponSelect(BOOL playOffSound)
{
@ -638,59 +608,7 @@ HUD_DrawWeaponSelect(void)
drawPlayerInventory_TopBar(-1, FALSE);
// FreeHL WAY!
/*
player pl = (player)pSeat->m_ePlayer;
if (!pl.inventoryEquippedIndex) {
return;
}
if (pSeat->m_flHUDWeaponSelectTime < time) {
if (pSeat->m_iHUDWeaponSelected) {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudoff.wav", 0.5, ATTN_NONE);
pSeat->m_iHUDWeaponSelected = 0;
}
return;
}
vector vecPos = g_hudmins + [16,16];
int b;
int wantslot = g_weapons[pSeat->m_iHUDWeaponSelected].slot;
int wantpos = g_weapons[pSeat->m_iHUDWeaponSelected].slot_pos;
for (int i = 0; i < 5; i++) {
int slot_selected = 0;
vecPos[1] = g_hudmins[1] + 16;
HUD_DrawWeaponSelect_Num(vecPos, i);
vecPos[1] += 20;
for (int x = 0; x < 32; x++) {
if (i == wantslot) {
slot_selected = TRUE;
if (x == wantpos) {
// Selected Sprite
Weapons_HUDPic(pSeat->m_iHUDWeaponSelected, 1, vecPos, 1.0f);
drawsubpic(vecPos, [170,45], g_hud3_spr,
[0,180/256], [170/256,45/256], g_hud_color, 1, DRAWFLAG_ADDITIVE);
vecPos[1] += 50;
} else if ((b=HUD_InSlotPos(i, x)) != -1) {
// Unselected Sprite
Weapons_HUDPic(b, 0, vecPos, 1.0f);
vecPos[1] += 50;
}
} else if (HUD_InSlotPos(i, x) != -1) {
HUD_DrawWeaponSelect_Num(vecPos, 5);
vecPos[1] += 25;
}
}
if (slot_selected == TRUE) {
vecPos[0] += 175;
} else {
vecPos[0] += 25;
}
}
*/
}//END OF HUD_DrawWeaponSelect
}//HUD_DrawWeaponSelect
@ -700,9 +618,8 @@ HUD_DrawWeaponSelect(void)
BOOLEAN
HUD_DrawWeaponSelect_CheckClick(void)
{
if(getplayerkeyvalue(player_localnum, "*spec") != "0"){
//some form of spectator? NOT ALLOWED.
//printfline("HEY there closing my weapon select 2");
player pl = (player)pSeat->m_ePlayer;
if(pl.iState != PLAYER_STATE::SPAWNED){
HUD_CloseWeaponSelect(FALSE);
return FALSE;
}
@ -745,45 +662,23 @@ HUD_DrawWeaponSelect_Last(void)
*/
}
/*
void
HUD_DrawWeaponSelect_Num(vector vecPos, float fValue)
{
drawsubpic(vecPos, [20,20], g_hud7_spr, g_vecHUDNums[fValue], [20/256, 20/128], g_hud_color, 1, DRAWFLAG_ADDITIVE);
}
*/
/*
int
HUD_InSlotPos(int slot, int pos)
void
HUD_SlotSelect(int slot)
{
player pl = (player)pSeat->m_ePlayer;
for (int i = 1; i < g_weapons.length; i++) {
if (g_weapons[i].slot == slot && g_weapons[i].slot_pos == pos) {
if (pl.g_items & g_weapons[i].id) {
return i;
} else {
return (-1);
}
}
if(pl.iState != PLAYER_STATE::SPAWNED){
return;
}
return (-1);
}
*/
void
TS_SelectSlot(int slotPicked)
{
player pl = (player)pSeat->m_ePlayer;
int slotPicked = slot+1;
// Keep track of the currently open slot. Navigate through it...
// move to another slot if needed...
// move to another slot if needed
//printlinef("HUD_SlotSelect: %i maxweap:%i classname:%s\n", slot, pl.ary_myWeapons_softMax, pl.classname);
//printfline("weapon slot currently highlighted: %i", pl.weaponSelectHighlightID);
if(pl.weaponSelectHighlightID == -1){
@ -810,75 +705,5 @@ TS_SelectSlot(int slotPicked)
}
}
}//TS_SelectSlot
void
HUD_SlotSelect(int slot)
{
player pl = (player)pSeat->m_ePlayer;
//printlinef("HUD_SlotSelect: %i maxweap:%i classname:%s\n", slot, pl.ary_myWeapons_softMax, pl.classname);
if(getplayerkeyvalue(player_localnum, "*spec") != "0"){
// A spectator? Stop.
return;
}
//TAGGG - redirect.
TS_SelectSlot(slot + 1);
/*
player pl = (player)pSeat->m_ePlayer;
int curslot = g_weapons[pSeat->m_iHUDWeaponSelected].slot;
int i;
if (g_textmenu != "") {
Textmenu_Input(slot);
return;
}
// hack to see if we have ANY weapons at all.
if (!pl.inventoryEquippedIndex) {
return;
}
if (pSeat->m_flHUDWeaponSelectTime < time) {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
} else {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
}
// weren't in that slot? select the first one then
if (curslot != slot) {
for (i = 1; i < g_weapons.length; i++) {
if (g_weapons[i].slot == slot && pl.g_items & g_weapons[i].id) {
pSeat->m_iHUDWeaponSelected = i;
pSeat->m_flHUDWeaponSelectTime = time + 3;
break;
}
}
} else {
int first = -1;
for (i = 1; i < g_weapons.length; i++) {
if (g_weapons[i].slot == slot && pl.g_items & g_weapons[i].id) {
if (i < pSeat->m_iHUDWeaponSelected && first == -1) {
first = i;
} else if (i > pSeat->m_iHUDWeaponSelected) {
first = -1;
pSeat->m_iHUDWeaponSelected = i;
pSeat->m_flHUDWeaponSelectTime = time + 3;
break;
}
}
}
if (first > 0) {
pSeat->m_iHUDWeaponSelected = first;
pSeat->m_flHUDWeaponSelectTime = time + 3;
}
}
*/
}

View file

@ -320,9 +320,8 @@ TSMultiplayerRules::PlayerDeath(base_player pp)
TS_resetViewModel(pl);
pl.setInventoryEquippedIndex(-1);
printfline("How many weapons do you have mr player??? %i", pl.ary_myWeapons_softMax);
printfline("How many weapons do you have, dead player? %i", pl.ary_myWeapons_softMax);
for(int i = pl.ary_myWeapons_softMax-1; i >= 0; i--){
printfline("Dropping this weapon my boy", i);
pl.dropWeapon(i, TRUE);
}
@ -583,6 +582,11 @@ TSMultiplayerRules::RestartRound(int iWipe)
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
//self = eFind;
player pl = (player)eFind;
// only affect players ingame!
if(pl.iState != PLAYER_STATE::SPAWNED){
continue;
}
//printfline("PLAYER MONEY 1: %i", pl.money);
@ -592,7 +596,9 @@ TSMultiplayerRules::RestartRound(int iWipe)
// Something about this resets the player money..? Is it changing to Spectator
// right before Player that did it here?
PlayerMakeSpectator(pl);
//PlayerMakeSpectator(pl);
// just let PlayerMakePlayable work.
pl.iState = PLAYER_STATE::NOCLIP;
PlayerMakePlayable(pl);
}
@ -704,6 +710,7 @@ TSMultiplayerRules::CountPlayers(void)
}
}
// These would be authentic spectators, or those that can't even open the buy menu.
for (entity eFind = world; (eFind = find(eFind, ::classname, "spectator"));) {
g_ts_player_spectator++;
}
@ -940,9 +947,6 @@ void TSMultiplayerRules::MakePlayerInvisible(player pl){
pl.SetMovetype(MOVETYPE_NONE);
pl.SetSolid(SOLID_NOT);
pl.takedamage = DAMAGE_NO;
// Don't know what these have to do with being invisible.
pl.armor = pl.activeweapon = pl.g_items = 0;
pl.health = 0;
}
@ -983,8 +987,17 @@ void
TSMultiplayerRules::PlayerMakePlayable(base_player pp)
{
player pl = (player)pp;
if(pl.iState == PLAYER_STATE::SPAWNED){
// no need to do this again.
// Set pl.iState to something else first if this was an intentional re-spawn
// for an ingame player
return;
}
MakePlayable(pp);
pl.iState = PLAYER_STATE::SPAWNED;
printfline("HERE I AM MAKING IT SPAWNED!!!");
// Nope!
//MakePlayable(pp);
forceinfokey(pl, "*team", ftos(pl.team));
PlayerRespawn(pl, pl.team);
@ -1002,14 +1015,43 @@ TSMultiplayerRules::PlayerMakeSpectator(base_player pp)
{
player pl = (player)pp;
if(pl.classname != "spectator" && pl.modelindex != 0){
if(pl.iState == PLAYER_STATE::NOCLIP){
// Already in fake spectator! Stop.
return;
}
//if(pl.classname != "spectator" && pl.modelindex != 0){
if(pl.modelindex != 0){
// assume this is necessary
MakePlayerInvisible(pl);
}
// is that necessary still?
//TS_resetPlayer(pl, TRUE);
MakeSpectator(pl);
// And don't do this! Just change iState
//MakeSpectator(pl);
pl.iState = PLAYER_STATE::NOCLIP;
printfline("WELL??? %d", pl.iState),
// And do the rest of the lines to finish that
// (copied from the Nuclide spectator's constructor)
// Lines already handled by MakePlayerInvisible not here.
pl.flags = FL_CLIENT;
pl.think = NULL;
pl.nextthink = 0.0f;
pl.maxspeed = 250;
//pl.spec_ent = 0;
//pl.spec_mode = 0;
//#ifdef SERVER
forceinfokey(pl, "*spec", "1");
//#endif
pl.armor = pl.activeweapon = pl.g_items = 0;
pl.health = 0;
pl.SetMovetype(MOVETYPE_NOCLIP);
}
@ -1019,6 +1061,15 @@ TSMultiplayerRules::PlayerMakeSpectator(base_player pp)
void
TSMultiplayerRules::PlayerMakeSpectatorDelayed(base_player pp)
{
// Nevermind, this has no significance anymore with the client entity change no longer
// happening. Redirect to the normal version
player pl = (player)pp;
printfline("SO WHAT %d", pl.iState),
PlayerMakeSpectator(pp);
/*
player pl = (player)pp;
if(pl.classname != "spectator" && pl.modelindex != 0){
@ -1039,6 +1090,7 @@ TSMultiplayerRules::PlayerMakeSpectatorDelayed(base_player pp)
// "dead" should already be set.
//forceinfokey(pl, "*dead", "1");
//forceinfokey(pl, "*team", ftos(pl.team));
*/
}
/*
@ -1055,6 +1107,19 @@ TSMultiplayerRules::PlayerSpawn(base_player pp)
{
player pl = (player)pp;
//printfline("PlayerSpawn, what is classname before anything has been done? %s %s", self.classname, pp.classname);
// Apparently the player already arrives as a "player", a Nuclide-implemented event called
// ClientConnect makes the client entity a "player" by using spawnfunc.
// Having the "player" class available that early makes me wonder why "base_player" is used so
// often in implemented methods, but not an issue.
// ClientConnect is called before PutClientInServer (the one that leads to the gamerules
// PlayerSpawn, right here), just for info.
// What this means is, no need for spawnfunc_player here.
// should "Frags" be an infokey to be better preserved through player/spectator changes?
// No clue. And setting these only that way further down by forceinfokey too.
//pl.frags = 0;

View file

@ -3,9 +3,43 @@
class TSWorldGun;
// NOTE-
// even on the "Press Fire To Play!" text, that shows up after the spawn countdown
// finishes (shown on trying to spawn too early), there is actually 1 second left
// until clicking to spawn does anything. Kindof odd, probably an oversight.
// State of the player for whether they're ingame, thirdperson recently on death,
// or in fake-spectator (buy menu).
// Players enter the server in the NOCLIP state.
enum PLAYER_STATE{
// Nothing special. Collision, gravity, equips things.
SPAWNED = 0,
// Like a third-person view of the player's most recent position, unsure
// if it follows the corpse, try dying while moving in TS to see.
// Slowly zooms out to a point.
// Changes to DEAD_NOCLIP (aka "Fake Spectator") on clicking between 1
// and 2.5 seconds, or waiting out the 2.5 seconds (happens anyway)
DEAD_RECENT,
// Starts at the exact point where the dead player was.
// Would probably be better to just leave the camera where it is insead of
// jumping to the player's old point, unnecessary to do that and kinda jarring.
NOCLIP
};
#define PREDICTED_CUSTOM(arg_t, x) arg_t x; arg_t x ##_net
noref int input_sequence;
class player:base_player
{
// On death, the player cannot change the camera to fake-specator until at least 1 second
// has passed.
// On death, set this to 2.5. If it is less than 1.5,
float deathCameraChangeTime;
//TAGGG - I'm not messing around with that memory issue from last time.
// But try again with this removed whenever it turns out ok, see if this is needed anymore.
//virtual void (void)dummyBufferMethod;
@ -24,11 +58,8 @@ class player:base_player
//TAGGG - TODO! Put the PREDICTED_INT/FLOAT/whatever stuff on what needs it.
// Determines if this player should be a fake-spectator with MoTD and buymenu (FALSE)
// or be a physical player that can equip weapons and interact with the world (TRUE).
// Jumping to fake-spectator on death will force this to FALSE too.
// Yet to be implemented.
BOOL spawned;
PREDICTED_CUSTOM(PLAYER_STATE, iState);
#ifdef SSQC

View file

@ -149,6 +149,9 @@ player::ReceiveEntity(float new, float fl)
/////////////////////////////////////////////////////
iState = readfloat();
int inventoryEquippedIndex_temp = readbyte();
// Overflow can do funny things. -1 comes as 255 because thats how bits work
@ -291,7 +294,8 @@ player::PredictPreFrame(void)
SAVE_STATE(ammo_rpg_state);
SAVE_STATE(mode_tempstate);
*/
SAVE_STATE(iState);
SAVE_STATE(inventoryEquippedIndex);
SAVE_STATE(weaponEquippedAkimbo);
SAVE_STATE(w_attack_akimbo_next);
@ -356,6 +360,7 @@ player::PredictPostFrame(void)
ROLL_BACK(mode_tempstate);
*/
ROLL_BACK(iState);
ROLL_BACK(inventoryEquippedIndex);
ROLL_BACK(weaponEquippedAkimbo);
ROLL_BACK(w_attack_akimbo_next);
@ -465,6 +470,7 @@ player::EvaluateEntity(void)
SAVE_STATE(anim_bottom);
SAVE_STATE(anim_bottom_time);
SAVE_STATE(iState);
SAVE_STATE(inventoryEquippedIndex);
SAVE_STATE(weaponEquippedAkimbo);
SAVE_STATE(w_attack_akimbo_next);
@ -574,6 +580,7 @@ player::SendEntity(entity ePEnt, float fChanged)
// OR if a particular weapon states to update its features, perhaps sending itself
// through
WriteFloat(MSG_ENTITY, iState);
WriteByte(MSG_ENTITY, inventoryEquippedIndex );
WriteByte(MSG_ENTITY, weaponEquippedAkimbo );
WriteFloat(MSG_ENTITY, w_attack_akimbo_next );
@ -657,6 +664,8 @@ void player::player(void){
// just in case?
this.classname = "player";
// reasonable default?
iState = PLAYER_STATE::NOCLIP;
#ifdef SSQC
money = 0; //safety?
@ -688,8 +697,11 @@ void player::player(void){
flKarateBlockCooldown = 0;
setInventoryEquippedIndex(-1);
// Should we?
//setInventoryEquippedIndex(-1);
inventoryEquippedIndex_previous = -1;
weaponEquippedAkimbo = FALSE;
//safe default.
@ -754,6 +766,10 @@ player::reset(BOOLEAN resetInventory){
INPUT_TAP_RESET(this)
// should this even make any assumptions about this?
//iState = ?;
#ifdef CSQC
// For safety, doing this.
@ -1399,7 +1415,7 @@ player::dropWeapon(int arg_weaponID, BOOLEAN completeDrop){
// It sees the "drop" command called and so sends an event to the server that got to this "dropWeapon" method
// here in player. okay.
printfline("playerDrop: Anything?");
printfline("playerDrop. weaponID:%i completeDrop:%d", arg_weaponID, completeDrop);
weapondynamic_t dynaRefPRE = ary_myWeapons[arg_weaponID];
weapondata_basic_t* basicP = getInventoryWeaponData(arg_weaponID, TRUE);
@ -1410,9 +1426,11 @@ player::dropWeapon(int arg_weaponID, BOOLEAN completeDrop){
// WARNING! This is still checking the possibly akimbo variant for having a
// worldmodel. The drops are still the singular variant in any case, but verify that.
if((*basicP).sWorldModelPath == ""){
//if the world model path is empty, we can't be dropped.
// Safe assumption.
printfline("...no world model?");
// if the world model path is empty, we can't be dropped.
if(completeDrop){
// But if this is a completeDrop (dead player), delete it anyway.
removeWeaponFromInventory(this, arg_weaponID);
}
return;
}
@ -1426,7 +1444,7 @@ player::dropWeapon(int arg_weaponID, BOOLEAN completeDrop){
}else{
// don't bother with the equip-ideal call that equippedWeaponDeleteCheck does.
deletedCurrentWeapon = inventoryWeaponDeleteCheck(arg_weaponID);
setInventoryEquippedIndex(-1);
//setInventoryEquippedIndex(-1);
}
}else{
// Still, see if this weapon would prefer to disappear rather than
@ -1442,7 +1460,7 @@ player::dropWeapon(int arg_weaponID, BOOLEAN completeDrop){
// No, just use basicPS for below.
//basicP = getEquippedWeaponData_Singular();
printfline("playerDrop: deletedCurrentWeapon? %d", deletedCurrentWeapon);
printfline("-deletedCurrentWeapon? %d", deletedCurrentWeapon);
if(deletedCurrentWeapon){
// STOP. Apparently the player deleted this weapon in the holster call above,

View file

@ -2,6 +2,9 @@
//TAGGG - TODO - some kicks should disarm the player hit, I forget if it's all kicks
// or just crouch-kicks.
// ALSO, weapons that lack world-models will never drop, safe assumption.
// That is why karate never drops.
enum weaponseq_karate{
//nothing = 0