# HG changeset patch # User Adam Kaminski # Date 1610867483 18000 # Sun Jan 17 02:11:23 2021 -0500 # Node ID 410a312e724f768a00217df03b02a44ee612fc0e # Parent ced2dacfc5d03ae2b70f8aa3445bae7d73498135 Backported geNia's commits from Q-Zandronum which add support for executing ACS scripts by pressing action buttons, as well as predictable variables for action ACS scripts. diff -r ced2dacfc5d0 -r 410a312e724f docs/zandronum-history.txt --- a/docs/zandronum-history.txt Sun Jan 17 01:10:14 2021 -0500 +++ b/docs/zandronum-history.txt Sun Jan 17 02:11:23 2021 -0500 @@ -34,6 +34,7 @@ + - Added ACS functions: SendNetworkString and NamedSendNetworkString, allowing strings to be sent from the server to the client(s) and vice versa, which are passed as the first argument of script to also be executed. Note that sending strings from client to server works just like puking scripts and there's no guarantee they are sent to the server successfully. [Kaminsky] + - Added a new EVENT script type: GAMEEVENT_CHAT that triggers when a non-private chat message is sent. Use this in conjunction with the ACS function: GetChatMessage(int player) to get the last chat message received by the player (or the server if -1 is passed). [Kaminsky] + - Added a new floating icon that shows if a player is in the menu. [DoomJoshuaBoy/geNia] ++ - Added a way to execute ACS scripts by pressing action buttons, as well as predictable variables for action ACS scripts. [geNia] - - Fixed: Bots tries to jump to reach item when sv_nojump is true. [sleep] - - Fixed: ACS function SetSkyScrollSpeed didn't work online. [Edward-san] - - Fixed: color codes in callvote reasons weren't terminated properly. [Dusk] diff -r ced2dacfc5d0 -r 410a312e724f src/cl_pred.cpp --- a/src/cl_pred.cpp Sun Jan 17 01:10:14 2021 -0500 +++ b/src/cl_pred.cpp Sun Jan 17 02:11:23 2021 -0500 @@ -96,6 +96,7 @@ static bool g_bSavedOnMobj[CLIENT_PREDICTION_TICS]; static bool g_bSavedOnGround[CLIENT_PREDICTION_TICS]; static fixed_t g_SavedFloorZ[CLIENT_PREDICTION_TICS]; +static int g_SavedPredictable[CLIENT_PREDICTION_TICS][3]; #ifdef _DEBUG CVAR( Bool, cl_showpredictionsuccess, false, 0 ); @@ -380,6 +381,9 @@ g_SavedTurnTicks[g_ulGameTick % CLIENT_PREDICTION_TICS] = pPlayer->turnticks; g_lSavedReactionTime[g_ulGameTick % CLIENT_PREDICTION_TICS] = pPlayer->mo->reactiontime; g_lSavedWaterLevel[g_ulGameTick % CLIENT_PREDICTION_TICS] = pPlayer->mo->waterlevel; + g_SavedPredictable[g_ulGameTick % CLIENT_PREDICTION_TICS][0] = pPlayer->mo->Predictable1; + g_SavedPredictable[g_ulGameTick % CLIENT_PREDICTION_TICS][1] = pPlayer->mo->Predictable2; + g_SavedPredictable[g_ulGameTick % CLIENT_PREDICTION_TICS][2] = pPlayer->mo->Predictable3; memcpy( &g_SavedTiccmd[g_ulGameTick % CLIENT_PREDICTION_TICS], &pPlayer->cmd, sizeof( ticcmd_t )); } @@ -429,6 +433,9 @@ pPlayer->turnticks = g_SavedTurnTicks[lTick % CLIENT_PREDICTION_TICS]; pPlayer->mo->reactiontime = g_lSavedReactionTime[lTick % CLIENT_PREDICTION_TICS]; pPlayer->mo->waterlevel = g_lSavedWaterLevel[lTick % CLIENT_PREDICTION_TICS]; + pPlayer->mo->Predictable1 = g_SavedPredictable[lTick % CLIENT_PREDICTION_TICS][0]; + pPlayer->mo->Predictable2 = g_SavedPredictable[lTick % CLIENT_PREDICTION_TICS][1]; + pPlayer->mo->Predictable3 = g_SavedPredictable[lTick % CLIENT_PREDICTION_TICS][2]; memcpy( &pPlayer->cmd, &g_SavedTiccmd[lTick % CLIENT_PREDICTION_TICS], sizeof( ticcmd_t )); // Tick the player. @@ -464,5 +471,8 @@ pPlayer->turnticks = g_SavedTurnTicks[g_ulGameTick % CLIENT_PREDICTION_TICS]; pPlayer->mo->reactiontime = g_lSavedReactionTime[g_ulGameTick % CLIENT_PREDICTION_TICS]; pPlayer->mo->waterlevel = g_lSavedWaterLevel[g_ulGameTick % CLIENT_PREDICTION_TICS]; + pPlayer->mo->Predictable1 = g_SavedPredictable[g_ulGameTick % CLIENT_PREDICTION_TICS][0]; + pPlayer->mo->Predictable2 = g_SavedPredictable[g_ulGameTick % CLIENT_PREDICTION_TICS][1]; + pPlayer->mo->Predictable3 = g_SavedPredictable[g_ulGameTick % CLIENT_PREDICTION_TICS][2]; memcpy( &pPlayer->cmd, &g_SavedTiccmd[g_ulGameTick % CLIENT_PREDICTION_TICS], sizeof( ticcmd_t )); } diff -r ced2dacfc5d0 -r 410a312e724f src/d_player.h --- a/src/d_player.h Sun Jan 17 01:10:14 2021 -0500 +++ b/src/d_player.h Sun Jan 17 02:11:23 2021 -0500 @@ -165,6 +165,15 @@ fixed_t AirCapacity; // Multiplier for air supply underwater. const PClass *FlechetteType; + // Scripts to execute when the player presses the action buttons + FNameNoInit + BT_ATTACK_Script, BT_USE_Script, BT_JUMP_Script, BT_CROUCH_Script, + BT_TURN180_Script, BT_ALTATTACK_Script, BT_RELOAD_Script, BT_ZOOM_Script, + BT_SPEED_Script, BT_STRAFE_Script, BT_MOVERIGHT_Script, BT_MOVELEFT_Script, + BT_BACK_Script, BT_FORWARD_Script, BT_RIGHT_Script, BT_LEFT_Script, + BT_LOOKUP_Script, BT_LOOKDOWN_Script, BT_MOVEUP_Script, BT_MOVEDOWN_Script, BT_SHOWSCORES_Script, + BT_USER1_Script, BT_USER2_Script, BT_USER3_Script, BT_USER4_Script; + // [geNia] The server updates player data before sending it to clients, but the player input is still old. // That results in player input being one tic behind position, so we need to remember last position to send it to other clients. fixed_t ClientX, ClientY, ClientZ; @@ -172,6 +181,9 @@ angle_t ClientAngle; fixed_t ClientPitch; + // Values that can be set from ACS and then passed to assigned action scripts + int Predictable1, Predictable2, Predictable3; + // [CW] Fades for when you are being damaged. PalEntry DamageFade; @@ -179,6 +191,10 @@ bool ResetAirSupply (bool playgasp = true); int GetMaxHealth() const; + + int ActionNameToNumber(const char* actionName); + void SetActionScript(int button, const char* scriptName); + void ExecuteActionScript(ticcmd_t *cmd, int button); }; class APlayerChunk : public APlayerPawn diff -r ced2dacfc5d0 -r 410a312e724f src/p_acs.cpp --- a/src/p_acs.cpp Sun Jan 17 01:10:14 2021 -0500 +++ b/src/p_acs.cpp Sun Jan 17 02:11:23 2021 -0500 @@ -5347,6 +5347,9 @@ ACSF_SetPlayerScore, ACSF_GetPlayerScore, ACSF_InDemoMode, + ACSF_SetActionScript, + ACSF_SetPredictableValue, + ACSF_GetPredictableValue, ACSF_ExecuteClientScript, ACSF_NamedExecuteClientScript, ACSF_SendNetworkString, @@ -7590,6 +7593,94 @@ return 0; } + case ACSF_SetActionScript: + if (args[0] == 0) + { + if (activator->IsKindOf(RUNTIME_CLASS(APlayerPawn))) + { + static_cast(&*activator)->SetActionScript(args[1], FBehavior::StaticLookupString(args[2])); + } + } + else + { + AActor *actor; + FActorIterator iterator(args[0]); + + const char* actionName = FBehavior::StaticLookupString(args[2]); + while ((actor = iterator.Next()) != NULL) + { + if (actor->IsKindOf(RUNTIME_CLASS(APlayerPawn))) + { + static_cast(actor)->SetActionScript(args[1], actionName); + } + } + } + return 0; + + case ACSF_SetPredictableValue: + if (args[0] == 0) + { + if (activator->IsKindOf(RUNTIME_CLASS(APlayerPawn))) + { + switch (args[1]) + { + case 1: + static_cast(&*activator)->Predictable1 = args[2]; + break; + case 2: + static_cast(&*activator)->Predictable2 = args[2]; + break; + case 3: + static_cast(&*activator)->Predictable3 = args[2]; + break; + } + } + } + else + { + AActor *actor; + FActorIterator iterator(args[0]); + + const char* actionName = FBehavior::StaticLookupString(args[2]); + while ((actor = iterator.Next()) != NULL) + { + if (actor->IsKindOf(RUNTIME_CLASS(APlayerPawn))) + { + switch (args[1]) + { + case 1: + static_cast(actor)->Predictable1 = args[2]; + break; + case 2: + static_cast(actor)->Predictable2 = args[2]; + break; + case 3: + static_cast(actor)->Predictable3 = args[2]; + break; + } + } + } + } + return 0; + + case ACSF_GetPredictableValue: + { + AActor* actor = SingleActorFromTID(args[0], activator); + if (actor->IsKindOf(RUNTIME_CLASS(APlayerPawn))) + { + switch (args[1]) + { + case 1: + return static_cast(actor)->Predictable1; + case 2: + return static_cast(actor)->Predictable2; + case 3: + return static_cast(actor)->Predictable3; + } + } + } + return 0; + case ACSF_ExecuteClientScript: { return ExecuteClientScript( activator, args[0], args[1], &args[2], argCount - 2 ); diff -r ced2dacfc5d0 -r 410a312e724f src/p_user.cpp --- a/src/p_user.cpp Sun Jan 17 01:10:14 2021 -0500 +++ b/src/p_user.cpp Sun Jan 17 02:11:23 2021 -0500 @@ -1386,6 +1386,144 @@ //=========================================================================== // +// APlayerPawn :: ActionNameToNumber +// +// convert action name to action button number +// +//=========================================================================== + +int strcicmp(char const *a, char const *b) +{ + for (;; a++, b++) { + int d = tolower((unsigned char)*a) - tolower((unsigned char)*b); + if (d != 0 || !*a) + return d; + } +} + +int APlayerPawn::ActionNameToNumber(const char* actionName) +{ + if (!strcicmp(actionName, "attack")) return BT_ATTACK; + else if (!strcicmp(actionName, "use")) return BT_USE; + else if (!strcicmp(actionName, "jump")) return BT_JUMP; + else if (!strcicmp(actionName, "crouch")) return BT_CROUCH; + else if (!strcicmp(actionName, "turn180")) return BT_TURN180; + else if (!strcicmp(actionName, "altattack")) return BT_ALTATTACK; + else if (!strcicmp(actionName, "reload")) return BT_RELOAD; + else if (!strcicmp(actionName, "zoom")) return BT_ZOOM; + else if (!strcicmp(actionName, "speed")) return BT_SPEED; + else if (!strcicmp(actionName, "strafe")) return BT_STRAFE; + else if (!strcicmp(actionName, "moveright")) return BT_MOVERIGHT; + else if (!strcicmp(actionName, "moveleft")) return BT_MOVELEFT; + else if (!strcicmp(actionName, "back")) return BT_BACK; + else if (!strcicmp(actionName, "forward")) return BT_FORWARD; + else if (!strcicmp(actionName, "right")) return BT_RIGHT; + else if (!strcicmp(actionName, "left")) return BT_LEFT; + else if (!strcicmp(actionName, "lookup")) return BT_LOOKUP; + else if (!strcicmp(actionName, "lookdown")) return BT_LOOKDOWN; + else if (!strcicmp(actionName, "moveup")) return BT_MOVEUP; + else if (!strcicmp(actionName, "movedown")) return BT_MOVEDOWN; + else if (!strcicmp(actionName, "showscores")) return BT_SHOWSCORES; + else if (!strcicmp(actionName, "user1")) return BT_USER1; + else if (!strcicmp(actionName, "user2")) return BT_USER2; + else if (!strcicmp(actionName, "user3")) return BT_USER3; + else if (!strcicmp(actionName, "user4")) return BT_USER4; + else return 0; +} + +//=========================================================================== +// +// APlayerPawn :: SetActionScript +// +// assign an ACS script to a specified action +// +//=========================================================================== + +void APlayerPawn::SetActionScript(int button, const char* scriptName) +{ + switch (button) + { + case BT_ATTACK: BT_ATTACK_Script = scriptName; break; + case BT_USE: BT_USE_Script = scriptName; break; + case BT_JUMP: BT_JUMP_Script = scriptName; break; + case BT_CROUCH: BT_CROUCH_Script = scriptName; break; + case BT_TURN180: BT_TURN180_Script = scriptName; break; + case BT_ALTATTACK: BT_ALTATTACK_Script = scriptName; break; + case BT_RELOAD: BT_RELOAD_Script = scriptName; break; + case BT_ZOOM: BT_ZOOM_Script = scriptName; break; + case BT_SPEED: BT_SPEED_Script = scriptName; break; + case BT_STRAFE: BT_STRAFE_Script = scriptName; break; + case BT_MOVERIGHT: BT_MOVERIGHT_Script = scriptName; break; + case BT_MOVELEFT: BT_MOVELEFT_Script = scriptName; break; + case BT_BACK: BT_BACK_Script = scriptName; break; + case BT_FORWARD: BT_FORWARD_Script = scriptName; break; + case BT_RIGHT: BT_RIGHT_Script = scriptName; break; + case BT_LEFT: BT_LEFT_Script = scriptName; break; + case BT_LOOKUP: BT_LOOKUP_Script = scriptName; break; + case BT_LOOKDOWN: BT_LOOKDOWN_Script = scriptName; break; + case BT_MOVEUP: BT_MOVEUP_Script = scriptName; break; + case BT_MOVEDOWN: BT_MOVEDOWN_Script = scriptName; break; + case BT_SHOWSCORES: BT_SHOWSCORES_Script = scriptName; break; + case BT_USER1: BT_USER1_Script = scriptName; break; + case BT_USER2: BT_USER2_Script = scriptName; break; + case BT_USER3: BT_USER3_Script = scriptName; break; + case BT_USER4: BT_USER4_Script = scriptName; break; + } +} + +//========================================================================== +// +// ExecuteUserScript +// +//========================================================================== + +void APlayerPawn::ExecuteActionScript(ticcmd_t *cmd, int button) +{ + int script = 0; + if (cmd->ucmd.buttons & button) + { + switch (button) + { + case BT_ATTACK: script = BT_ATTACK_Script; break; + case BT_USE: script = BT_USE_Script; break; + case BT_JUMP: script = BT_JUMP_Script; break; + case BT_CROUCH: script = BT_CROUCH_Script; break; + case BT_TURN180: script = BT_TURN180_Script; break; + case BT_ALTATTACK: script = BT_ALTATTACK_Script; break; + case BT_RELOAD: script = BT_RELOAD_Script; break; + case BT_ZOOM: script = BT_ZOOM_Script; break; + case BT_SPEED: script = BT_SPEED_Script; break; + case BT_STRAFE: script = BT_STRAFE_Script; break; + case BT_MOVERIGHT: script = BT_MOVERIGHT_Script; break; + case BT_MOVELEFT: script = BT_MOVELEFT_Script; break; + case BT_BACK: script = BT_BACK_Script; break; + case BT_FORWARD: script = BT_FORWARD_Script; break; + case BT_RIGHT: script = BT_RIGHT_Script; break; + case BT_LEFT: script = BT_LEFT_Script; break; + case BT_LOOKUP: script = BT_LOOKUP_Script; break; + case BT_LOOKDOWN: script = BT_LOOKDOWN_Script; break; + case BT_MOVEUP: script = BT_MOVEUP_Script; break; + case BT_MOVEDOWN: script = BT_MOVEDOWN_Script; break; + case BT_SHOWSCORES: script = BT_SHOWSCORES_Script; break; + case BT_USER1: script = BT_USER1_Script; break; + case BT_USER2: script = BT_USER2_Script; break; + case BT_USER3: script = BT_USER3_Script; break; + case BT_USER4: script = BT_USER4_Script; break; + default: script = 0; + } + } + + if (script != 0) + { + int flags = ACS_ALWAYS | ACS_WANTRESULT; + int args[4] = { CLIENT_PREDICT_IsPredicting() ? 1 : 0, Predictable1, Predictable2, Predictable3 }; + + P_StartScript(player->mo, NULL, -script, level.mapname, args, 4, flags); + } +} + +//=========================================================================== +// // APlayerPawn :: UpdateWaterLevel // // Plays surfacing and diving sounds, as appropriate. @@ -2814,6 +2952,33 @@ player->onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (player->cheats & CF_NOCLIP2); + // Execute ACS scripts assigned to action buttons + player->mo->ExecuteActionScript(cmd, BT_ATTACK); + player->mo->ExecuteActionScript(cmd, BT_USE); + player->mo->ExecuteActionScript(cmd, BT_JUMP); + player->mo->ExecuteActionScript(cmd, BT_CROUCH); + player->mo->ExecuteActionScript(cmd, BT_TURN180); + player->mo->ExecuteActionScript(cmd, BT_ALTATTACK); + player->mo->ExecuteActionScript(cmd, BT_RELOAD); + player->mo->ExecuteActionScript(cmd, BT_ZOOM); + player->mo->ExecuteActionScript(cmd, BT_SPEED); + player->mo->ExecuteActionScript(cmd, BT_STRAFE); + player->mo->ExecuteActionScript(cmd, BT_MOVERIGHT); + player->mo->ExecuteActionScript(cmd, BT_MOVELEFT); + player->mo->ExecuteActionScript(cmd, BT_BACK); + player->mo->ExecuteActionScript(cmd, BT_FORWARD); + player->mo->ExecuteActionScript(cmd, BT_RIGHT); + player->mo->ExecuteActionScript(cmd, BT_LEFT); + player->mo->ExecuteActionScript(cmd, BT_LOOKUP); + player->mo->ExecuteActionScript(cmd, BT_LOOKDOWN); + player->mo->ExecuteActionScript(cmd, BT_MOVEUP); + player->mo->ExecuteActionScript(cmd, BT_MOVEDOWN); + player->mo->ExecuteActionScript(cmd, BT_SHOWSCORES); + player->mo->ExecuteActionScript(cmd, BT_USER1); + player->mo->ExecuteActionScript(cmd, BT_USER2); + player->mo->ExecuteActionScript(cmd, BT_USER3); + player->mo->ExecuteActionScript(cmd, BT_USER4); + // killough 10/98: // // We must apply thrust to the player and bobbing separately, to avoid diff -r ced2dacfc5d0 -r 410a312e724f src/thingdef/thingdef_properties.cpp --- a/src/thingdef/thingdef_properties.cpp Sun Jan 17 01:10:14 2021 -0500 +++ b/src/thingdef/thingdef_properties.cpp Sun Jan 17 02:11:23 2021 -0500 @@ -2836,4 +2836,15 @@ info->Class->Meta.SetMetaFixed( APMETA_MaxSkinHeightFactor, heightfactor ); } +//========================================================================== +// [geNia] +//========================================================================== +DEFINE_CLASS_PROPERTY_PREFIX(player, actionscript, S_S, PlayerPawn) +{ + PROP_STRING_PARM(buttonName, 0); + PROP_STRING_PARM(script, 1); + defaults->SetActionScript(defaults->ActionNameToNumber(buttonName), script); +} + +