From 62199f7814c4dd3b44e1cfbe97c610e66f73b5b6 Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Sun, 28 Apr 2024 22:27:28 -0300 Subject: [PATCH] Implement missing functions --- extras/acs/srb2defs.acs | 57 ++++ extras/acs/srb2special.acs | 17 +- src/acs/call-funcs.cpp | 527 ++++++++++++++++++++++++++++++++++++- src/acs/call-funcs.hpp | 13 + src/acs/environment.cpp | 21 +- 5 files changed, 619 insertions(+), 16 deletions(-) diff --git a/extras/acs/srb2defs.acs b/extras/acs/srb2defs.acs index 321f1beef..b09ac93fd 100644 --- a/extras/acs/srb2defs.acs +++ b/extras/acs/srb2defs.acs @@ -183,12 +183,69 @@ #define SECSPAC_FloorMissile 1024 // when a projectile touches the floor of this sector #define SECSPAC_CeilingMissile 2048 // when a projectile touches the ceiling of this sector +// Player powers + +#define POWER_INVULNERABILITY 0 +#define POWER_SNEAKERS 1 +#define POWER_FLASHING 2 +#define POWER_SHIELD 3 +#define POWER_TAILSFLY 4 +#define POWER_UNDERWATER 5 +#define POWER_SPACETIME 6 +#define POWER_GRAVITYBOOTS 7 +#define POWER_EMERALDS 8 +#define POWER_NIGHTS_SUPERLOOP 9 +#define POWER_NIGHTS_HELPER 10 +#define POWER_NIGHTS_LINKFREEZE 11 +#define POWER_AUTOMATICRING 12 +#define POWER_BOUNCERING 13 +#define POWER_SCATTERRING 14 +#define POWER_GRENADERING 15 +#define POWER_EXPLOSIONRING 16 +#define POWER_RAILRING 17 + +// Player shields + +#define SHIELD_NONE 0 +#define SHIELD_PITY 1 +#define SHIELD_WHIRLWIND 2 +#define SHIELD_ARMAGEDDON 3 +#define SHIELD_PINK 4 + +#define SHIELD_PROTECTFIRE 0x400 +#define SHIELD_PROTECTWATER 0x800 +#define SHIELD_PROTECTELECTRIC 0x1000 +#define SHIELD_PROTECTSPIKE 0x2000 + +#define SHIELD_ATTRACT (SHIELD_PITY | SHIELD_PROTECTELECTRIC) +#define SHIELD_ELEMENTAL (SHIELD_PITY | SHIELD_PROTECTFIRE | SHIELD_PROTECTWATER) +#define SHIELD_FLAMEAURA (SHIELD_PITY | SHIELD_PROTECTFIRE) +#define SHIELD_BUBBLEWRAP (SHIELD_PITY | SHIELD_PROTECTWATER) +#define SHIELD_THUNDERCOIN (SHIELD_WHIRLWIND | SHIELD_PROTECTELECTRIC) + +#define SHIELD_FORCE 0x100 +#define SHIELD_FIREFLOWER 0x200 + +#define SHIELD_STACK SHIELD_FIREFLOWER +#define SHIELD_NOSTACK (~SHIELD_STACK) + +#define SHIELD_FORCEHP 0xFF + // Teams #define NO_TEAM 0 #define TEAM_RED 1 #define TEAM_BLUE 2 +// Weapons + +#define WEAPON_AUTO 0 +#define WEAPON_BOUNCE 1 +#define WEAPON_SCATTER 2 +#define WEAPON_GRENADE 3 +#define WEAPON_EXPLODE 4 +#define WEAPON_RAIL 5 + // Bot types #define BOT_NONE 0 diff --git a/extras/acs/srb2special.acs b/extras/acs/srb2special.acs index 631c736e1..17b64d09a 100644 --- a/extras/acs/srb2special.acs +++ b/extras/acs/srb2special.acs @@ -11,10 +11,13 @@ special -11:SetThingProperty(3), -100:strcmp(2,3), -101:strcasecmp(2,3), + -120:PlayerRings(0), + -122:PlayerScore(0), + -123:PlayerSuper(0), -300:CountEnemies(2), -301:CountPushables(2), - // -302:SkinAvailable(1), - -303:HasUnlockable(1), + -302:HasUnlockable(1), + -303:SkinUnlocked(1), -304:PlayerSkin(0), -305:PlayerEmeralds(0), -306:PlayerBot(0), @@ -34,12 +37,18 @@ special // -324:Thing_Spawn(1), // NOTE: would it be better to implement Spawn? (https://zdoom.org/wiki/Spawn) -325:Thing_TrackAngle(4,6), -326:Thing_StopTrackingAngle(1), - // -327:GiveShield(1,2), - // -328:GivePowerUp(1,2), + -327:CheckPowerUp(1), + -328:GivePowerUp(1,2), + -329:CheckAmmo(1), + -330:GiveAmmo(2), + -331:TakeAmmo(2), + -332:DoSuperTransformation(0,1), + -333:DoSuperDetransformation(0), -500:CameraWait(1), -503:SetLineRenderStyle(3), -504:MapWarp(2), -505:AddBot(1, 4), + -506:RemoveBot(1), -507:ExitLevel(0,1), -508:MusicPlay(1,2), -509:MusicStopAll(0,1), diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index 1e4303b53..132066bd4 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -169,7 +169,7 @@ static bool ACS_GetSpriteFromString(const char *word, spritenum_t *type) for (int i = 0; i < NUMSPRITES; i++) { - if (fastncmp(word, sprnames[i], 4)) + if (strcmp(word, sprnames[i]) == 0) { *type = static_cast(i); return true; @@ -1269,6 +1269,30 @@ bool CallFunc_PlayerScore(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM: return false; } +/*-------------------------------------------------- + bool CallFunc_PlayerScore(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Returns if the activating player is super. +--------------------------------------------------*/ +bool CallFunc_PlayerSuper(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + auto info = &static_cast(thread)->info; + bool super = false; + + (void)argV; + (void)argC; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + super = (info->mo->player->powers[pw_super] != 0); + } + + thread->dataStk.push(super); + return false; +} + /*-------------------------------------------------- bool CallFunc_PlayerNumber(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) @@ -1501,6 +1525,33 @@ bool CallFunc_HasUnlockable(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSV return false; } +/*-------------------------------------------------- + bool CallFunc_SkinUnlocked(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Checks if a certain skin has been unlocked. +--------------------------------------------------*/ +bool CallFunc_SkinUnlocked(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + bool unlocked = false; + auto info = &static_cast(thread)->info; + + (void)argC; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + INT32 skinNum; + if (ACS_GetSkinFromString(thread->scopeMap->getString( argV[0] )->str, &skinNum) == true) + { + unlocked = R_SkinUsable(info->mo->player - players, skinNum); + } + } + + thread->dataStk.push(unlocked); + return false; +} + /*-------------------------------------------------- bool CallFunc_PlayerSkin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) @@ -2074,6 +2125,38 @@ bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word return false; } +/*-------------------------------------------------- + bool CallFunc_RemoveBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Removes a bot. +--------------------------------------------------*/ +bool CallFunc_RemoveBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + (void)argC; + + int playernum = argV[0]; + + if (playernum < 0 || playernum >= MAXPLAYERS) + { + CONS_Alert(CONS_WARNING, "RemoveBot player %d out of range (expected 0 - %d).\n", playernum, MAXPLAYERS-1); + } + else if (playeringame[playernum]) + { + if (players[playernum].bot == BOT_NONE) + { + CONS_Alert(CONS_WARNING, "RemoveBot cannot remove human\n"); + } + else + { + players[playernum].removing = true; + } + } + + thread->dataStk.push(0); + + return false; +} + /*-------------------------------------------------- bool CallFunc_ExitLevel(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) @@ -3157,9 +3240,7 @@ bool CallFunc_GetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A #define PROP_SPR(x, y) \ case x: \ { \ - char crunched[5] = {0}; \ - strncpy(crunched, sprnames[ mobj->y ], 4); \ - value = static_cast( ~env->getString( crunched )->idx ); \ + value = static_cast( ~env->getString( sprnames[ mobj->y ] )->idx ); \ break; \ } @@ -3560,6 +3641,442 @@ bool CallFunc_SetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A return false; } +enum +{ + POWER_INVULNERABILITY, + POWER_SNEAKERS, + POWER_FLASHING, + POWER_SHIELD, + POWER_TAILSFLY, + POWER_UNDERWATER, + POWER_SPACETIME, + POWER_GRAVITYBOOTS, + POWER_EMERALDS, + POWER_NIGHTS_SUPERLOOP, + POWER_NIGHTS_HELPER, + POWER_NIGHTS_LINKFREEZE, + POWER_AUTOMATICRING, + POWER_BOUNCERING, + POWER_SCATTERRING, + POWER_GRENADERING, + POWER_EXPLOSIONRING, + POWER_RAILRING, + POWER__MAX +}; + +/*-------------------------------------------------- + bool CallFunc_CheckPowerUp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Checks the amount of the activator's given power-up. +--------------------------------------------------*/ +bool CallFunc_CheckPowerUp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + (void)argC; + + INT32 value = 0; + + auto info = &static_cast(thread)->info; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + INT32 property = argV[0]; + + player_t *player = info->mo->player; + +#define POWER(x, y) \ + case x: \ + { \ + value = player->powers[y]; \ + break; \ + } + +#define WEAPON(x, y) \ + case x: \ + { \ + value = (player->ringweapons & y) != 0; \ + break; \ + } + + switch (property) + { + POWER(POWER_INVULNERABILITY, pw_invulnerability) + POWER(POWER_SNEAKERS, pw_sneakers) + POWER(POWER_FLASHING, pw_flashing) + POWER(POWER_SHIELD, pw_shield) + POWER(POWER_TAILSFLY, pw_tailsfly) + POWER(POWER_UNDERWATER, pw_underwater) + POWER(POWER_SPACETIME, pw_spacetime) + POWER(POWER_GRAVITYBOOTS, pw_gravityboots) + POWER(POWER_EMERALDS, pw_emeralds) + POWER(POWER_NIGHTS_SUPERLOOP, pw_nights_superloop) + POWER(POWER_NIGHTS_HELPER, pw_nights_helper) + POWER(POWER_NIGHTS_LINKFREEZE, pw_nights_linkfreeze) + WEAPON(POWER_AUTOMATICRING, WEP_AUTO) + WEAPON(POWER_BOUNCERING, WEP_BOUNCE) + WEAPON(POWER_SCATTERRING, WEP_SCATTER) + WEAPON(POWER_GRENADERING, WEP_GRENADE) + WEAPON(POWER_EXPLOSIONRING, WEP_EXPLODE) + WEAPON(POWER_RAILRING, WEP_RAIL) + default: + { + CONS_Alert(CONS_WARNING, "CheckPowerUp type %d out of range (expected 0 - %d).\n", property, POWER__MAX-1); + break; + } + } + +#undef POWER +#undef WEAPON + } + + thread->dataStk.push(value); + + return false; +} + +/*-------------------------------------------------- + static void ACS_SetPowerUp(player_t *player, INT32 property, const ACSVM::Word *argV, ACSVM::Word argC) + + Helper for CallFunc_GivePowerUp. +--------------------------------------------------*/ +static void ACS_SetPowerUp(player_t *player, INT32 property, const ACSVM::Word *argV, ACSVM::Word argC) +{ +#define POWER(x, y, z) \ + case x: \ + { \ + if (argC >= 2) \ + player->powers[y] = argV[1]; \ + else \ + player->powers[y] = z; \ + break; \ + } + +#define WEAPON(x, y) \ + case x: \ + { \ + if (argC >= 2 && (argV[1] > 0)) \ + player->ringweapons |= y; \ + else \ + player->ringweapons &= ~y; \ + break; \ + } + + switch (property) + { + POWER(POWER_INVULNERABILITY, pw_invulnerability, invulntics) + POWER(POWER_SNEAKERS, pw_sneakers, sneakertics) + POWER(POWER_FLASHING, pw_flashing, flashingtics) + POWER(POWER_SHIELD, pw_shield, 0) + POWER(POWER_TAILSFLY, pw_tailsfly, tailsflytics) + POWER(POWER_UNDERWATER, pw_underwater, underwatertics) + POWER(POWER_SPACETIME, pw_spacetime, spacetimetics) + POWER(POWER_GRAVITYBOOTS, pw_gravityboots, 20*TICRATE) + POWER(POWER_EMERALDS, pw_emeralds, 0) + POWER(POWER_NIGHTS_SUPERLOOP, pw_nights_superloop, 0) + POWER(POWER_NIGHTS_HELPER, pw_nights_helper, 0) + POWER(POWER_NIGHTS_LINKFREEZE, pw_nights_linkfreeze, 0) + WEAPON(POWER_AUTOMATICRING, WEP_AUTO) + WEAPON(POWER_BOUNCERING, WEP_BOUNCE) + WEAPON(POWER_SCATTERRING, WEP_SCATTER) + WEAPON(POWER_GRENADERING, WEP_GRENADE) + WEAPON(POWER_EXPLOSIONRING, WEP_EXPLODE) + WEAPON(POWER_RAILRING, WEP_RAIL) + default: + { + CONS_Alert(CONS_WARNING, "GivePowerUp type %d out of range (expected 0 - %d).\n", property, POWER__MAX-1); + break; + } + } + + // Give the player a shield + if (property == POWER_SHIELD && player->powers[pw_shield] != SH_NONE) + { + P_SpawnShieldOrb(player); + } + +#undef POWER +#undef AMMO +} + +/*-------------------------------------------------- + bool CallFunc_GivePowerUp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Awards a power-up to the activator. + Like GiveInventory, if this is called with no activator, this awards the power-up to all players. +--------------------------------------------------*/ +bool CallFunc_GivePowerUp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + auto info = &static_cast(thread)->info; + + INT32 property = argV[0]; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + ACS_SetPowerUp(info->mo->player, property, argV, argC); + } + else + { + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + ACS_SetPowerUp(&players[i], property, argV, argC); + } + } + + thread->dataStk.push(0); + + return false; +} + +enum +{ + WEAPON_AUTO, + WEAPON_BOUNCE, + WEAPON_SCATTER, + WEAPON_GRENADE, + WEAPON_EXPLODE, + WEAPON_RAIL, + WEAPON__MAX +}; + +/*-------------------------------------------------- + bool CallFunc_CheckAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Checks the ammo of the activator's weapon. +--------------------------------------------------*/ +bool CallFunc_CheckAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + (void)argC; + + INT32 value = 0; + + auto info = &static_cast(thread)->info; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + INT32 weapon = argV[0]; + + player_t *player = info->mo->player; + +#define AMMO(x, y) \ + case x: \ + { \ + value = player->powers[y]; \ + break; \ + } + + switch (weapon) + { + AMMO(WEAPON_AUTO, pw_automaticring) + AMMO(WEAPON_BOUNCE, pw_bouncering) + AMMO(WEAPON_SCATTER, pw_scatterring) + AMMO(WEAPON_GRENADE, pw_grenadering) + AMMO(WEAPON_EXPLODE, pw_explosionring) + AMMO(WEAPON_RAIL, pw_railring) + default: + { + CONS_Alert(CONS_WARNING, "GiveAmmo weapon %d out of range (expected 0 - %d).\n", weapon, WEAPON__MAX-1); + break; + } + } + +#undef AMMO + } + + thread->dataStk.push(value); + + return false; +} + +/*-------------------------------------------------- + static void ACS_GiveAmmo(player_t *player, INT32 weapon, INT32 value) + + Helper for CallFunc_GiveAmmo/CallFunc_TakeAmmo. +--------------------------------------------------*/ +static bool ACS_GiveAmmo(player_t *player, INT32 weapon, INT32 value) +{ +#define AMMO(x, y) \ + case x: \ + { \ + player->powers[y] += value; \ + return true; \ + } + + switch (weapon) + { + AMMO(WEAPON_AUTO, pw_automaticring) + AMMO(WEAPON_BOUNCE, pw_bouncering) + AMMO(WEAPON_SCATTER, pw_scatterring) + AMMO(WEAPON_GRENADE, pw_grenadering) + AMMO(WEAPON_EXPLODE, pw_explosionring) + AMMO(WEAPON_RAIL, pw_railring) + } + +#undef AMMO + + return false; +} + +/*-------------------------------------------------- + bool CallFunc_GiveAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Gives ammo to the activator. + Like GiveInventory, if this is called with no activator, this awards ammo to all players. +--------------------------------------------------*/ +bool CallFunc_GiveAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + auto info = &static_cast(thread)->info; + + INT32 weapon = argV[0]; + INT32 value = argC >= 2 ? (argV[1]) : 0; + + bool fail = false; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + fail = !ACS_GiveAmmo(info->mo->player, weapon, value); + } + else + { + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + if (!ACS_GiveAmmo(&players[i], weapon, value)) + { + fail = true; + break; + } + } + } + } + + if (fail) + { + CONS_Alert(CONS_WARNING, "GiveAmmo weapon %d out of range (expected 0 - %d).\n", weapon, WEAPON__MAX-1); + } + + thread->dataStk.push(0); + + return false; +} + +/*-------------------------------------------------- + bool CallFunc_TakeAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Takes ammo from the activator. + Like TakeInventory, if this is called with no activator, this takes ammo from all players. +--------------------------------------------------*/ +bool CallFunc_TakeAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + auto info = &static_cast(thread)->info; + + INT32 weapon = argV[0]; + INT32 value = argC >= 2 ? (argV[1]) : 0; + + bool fail = false; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + fail = !ACS_GiveAmmo(info->mo->player, weapon, -value); + } + else + { + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + { + if (!ACS_GiveAmmo(&players[i], weapon, -value)) + { + fail = true; + break; + } + } + } + } + + if (fail) + { + CONS_Alert(CONS_WARNING, "TakeAmmo weapon %d out of range (expected 0 - %d).\n", weapon, WEAPON__MAX-1); + } + + thread->dataStk.push(0); + + return false; +} + +/*-------------------------------------------------- + bool CallFunc_DoSuperTransformation(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Turns the activator super. +--------------------------------------------------*/ +bool CallFunc_DoSuperTransformation(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + auto info = &static_cast(thread)->info; + + bool giverings = argC >= 2 ? (argV[1] != 0) : false; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + P_DoSuperTransformation(info->mo->player, giverings); + } + else + { + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + P_DoSuperTransformation(&players[i], giverings); + } + } + + thread->dataStk.push(0); + + return false; +} + +/*-------------------------------------------------- + bool CallFunc_DoSuperTransformation(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Detransforms the activator if super. +--------------------------------------------------*/ +bool CallFunc_DoSuperDetransformation(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + (void)argV; + (void)argC; + + auto info = &static_cast(thread)->info; + + if ((info != NULL) + && (info->mo != NULL && P_MobjWasRemoved(info->mo) == false) + && (info->mo->player != NULL)) + { + P_DoSuperDetransformation(info->mo->player); + } + else + { + for (UINT8 i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + P_DoSuperDetransformation(&players[i]); + } + } + + thread->dataStk.push(0); + + return false; +} + /*-------------------------------------------------- static angle_t ACS_GetAngle(int angle) @@ -3742,7 +4259,7 @@ bool CallFunc_OppositeColor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSV if (color < 1 || color >= numskincolors) { - CONS_Alert(CONS_WARNING, "OppositeColor: out of range\n"); + CONS_Alert(CONS_WARNING, "OppositeColor color %d out of range (expected 1 - %d).\n", color, numskincolors-1); } else { diff --git a/src/acs/call-funcs.hpp b/src/acs/call-funcs.hpp index 5d2918257..7fe0269b8 100644 --- a/src/acs/call-funcs.hpp +++ b/src/acs/call-funcs.hpp @@ -63,6 +63,7 @@ bool CallFunc_EndPrintBold(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM bool CallFunc_PlayerTeam(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PlayerRings(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PlayerScore(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_PlayerSuper(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PlayerNumber(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_ActivatorTID(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_EndLog(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); @@ -73,6 +74,7 @@ bool CallFunc_strcasecmp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM:: bool CallFunc_CountEnemies(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_CountPushables(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_HasUnlockable(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_SkinUnlocked(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PlayerSkin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PlayerBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PlayerExiting(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); @@ -96,6 +98,7 @@ bool CallFunc_SetLineRenderStyle(ACSVM::Thread *thread, const ACSVM::Word *argV, bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_RemoveBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_ExitLevel(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_MusicPlay(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_MusicStopAll(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); @@ -111,6 +114,16 @@ bool CallFunc_SetSectorProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, bool CallFunc_GetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_SetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_CheckPowerUp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_GivePowerUp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); + +bool CallFunc_CheckAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_GiveAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_TakeAmmo(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); + +bool CallFunc_DoSuperTransformation(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_DoSuperDetransformation(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); + bool CallFunc_Sin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_Cos(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_Tan(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); diff --git a/src/acs/environment.cpp b/src/acs/environment.cpp index 626ad00c2..f9c850c45 100644 --- a/src/acs/environment.cpp +++ b/src/acs/environment.cpp @@ -96,9 +96,6 @@ Environment::Environment() // Skulltag p-codes begin here addCodeDataACS0(118, {"", 0, addCallFunc(CallFunc_IsNetworkGame)}); addCodeDataACS0(119, {"", 0, addCallFunc(CallFunc_PlayerTeam)}); - addCodeDataACS0(120, {"", 0, addCallFunc(CallFunc_PlayerRings)}); - - addCodeDataACS0(122, {"", 0, addCallFunc(CallFunc_PlayerScore)}); // 136 to 137: Implemented by ACSVM @@ -160,10 +157,14 @@ Environment::Environment() addFuncDataACS0( 100, addCallFunc(CallFunc_strcmp)); addFuncDataACS0( 101, addCallFunc(CallFunc_strcasecmp)); + addFuncDataACS0( 120, addCallFunc(CallFunc_PlayerRings)); + addFuncDataACS0( 122, addCallFunc(CallFunc_PlayerScore)); + addFuncDataACS0( 123, addCallFunc(CallFunc_PlayerSuper)); + addFuncDataACS0( 300, addCallFunc(CallFunc_CountEnemies)); addFuncDataACS0( 301, addCallFunc(CallFunc_CountPushables)); - // addFuncDataACS0( 302, addCallFunc(CallFunc_SkinAvailable)); - addFuncDataACS0( 303, addCallFunc(CallFunc_HasUnlockable)); + addFuncDataACS0( 302, addCallFunc(CallFunc_HasUnlockable)); + addFuncDataACS0( 303, addCallFunc(CallFunc_SkinUnlocked)); addFuncDataACS0( 304, addCallFunc(CallFunc_PlayerSkin)); addFuncDataACS0( 305, addCallFunc(CallFunc_PlayerEmeralds)); addFuncDataACS0( 306, addCallFunc(CallFunc_PlayerBot)); @@ -183,13 +184,19 @@ Environment::Environment() // addFuncDataACS0( 324, addCallFunc(CallFunc_SpawnObject)); addFuncDataACS0( 325, addCallFunc(CallFunc_TrackObjectAngle)); addFuncDataACS0( 326, addCallFunc(CallFunc_StopTrackingObjectAngle)); - // addFuncDataACS0( 327, addCallFunc(CallFunc_GiveShield)); - // addFuncDataACS0( 328, addCallFunc(CallFunc_GivePowerUp)); + addFuncDataACS0( 327, addCallFunc(CallFunc_CheckPowerUp)); + addFuncDataACS0( 328, addCallFunc(CallFunc_GivePowerUp)); + addFuncDataACS0( 329, addCallFunc(CallFunc_CheckAmmo)); + addFuncDataACS0( 330, addCallFunc(CallFunc_GiveAmmo)); + addFuncDataACS0( 331, addCallFunc(CallFunc_TakeAmmo)); + addFuncDataACS0( 332, addCallFunc(CallFunc_DoSuperTransformation)); + addFuncDataACS0( 333, addCallFunc(CallFunc_DoSuperDetransformation)); addFuncDataACS0( 500, addCallFunc(CallFunc_CameraWait)); addFuncDataACS0( 503, addCallFunc(CallFunc_SetLineRenderStyle)); addFuncDataACS0( 504, addCallFunc(CallFunc_MapWarp)); addFuncDataACS0( 505, addCallFunc(CallFunc_AddBot)); + addFuncDataACS0( 506, addCallFunc(CallFunc_RemoveBot)); addFuncDataACS0( 507, addCallFunc(CallFunc_ExitLevel)); addFuncDataACS0( 508, addCallFunc(CallFunc_MusicPlay)); addFuncDataACS0( 509, addCallFunc(CallFunc_MusicStopAll));