void cht_Give (player_t *player, const char *name, int amount) { enum { ALL_NO, ALL_YES, ALL_YESYES } giveall; int i; PClassActor *type; if (player != &players[consoleplayer]) Printf ("%s is a cheater: give %s\n", player->userinfo.GetName(), name); if (player->mo == NULL || player->health <= 0) { return; } giveall = ALL_NO; if (stricmp (name, "all") == 0) { giveall = ALL_YES; } else if (stricmp (name, "everything") == 0) { giveall = ALL_YESYES; } if (stricmp (name, "health") == 0) { if (amount > 0) { player->mo->health += amount; player->health = player->mo->health; } else { player->health = player->mo->health = player->mo->GetMaxHealth(); } } if (giveall || stricmp (name, "backpack") == 0) { // Select the correct type of backpack based on the game type = PClass::FindActor(gameinfo.backpacktype); if (type != NULL) { player->mo->GiveInventory(static_cast<PClassInventory *>(type), 1, true); } if (!giveall) return; } if (giveall || stricmp (name, "ammo") == 0) { // Find every unique type of ammo. Give it to the player if // he doesn't have it already, and set each to its maximum. for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { PClassActor *type = PClassActor::AllActorClasses[i]; if (type->ParentClass == RUNTIME_CLASS(AAmmo)) { PClassAmmo *atype = static_cast<PClassAmmo *>(type); AInventory *ammo = player->mo->FindInventory(atype); if (ammo == NULL) { ammo = static_cast<AInventory *>(Spawn (atype)); ammo->AttachToOwner (player->mo); ammo->Amount = ammo->MaxAmount; } else if (ammo->Amount < ammo->MaxAmount) { ammo->Amount = ammo->MaxAmount; } } } if (!giveall) return; } if (giveall || stricmp (name, "armor") == 0) { if (gameinfo.gametype != GAME_Hexen) { ABasicArmorPickup *armor = Spawn<ABasicArmorPickup> (); armor->SaveAmount = 100*deh.BlueAC; armor->SavePercent = gameinfo.Armor2Percent > 0? gameinfo.Armor2Percent : 0.5; if (!armor->CallTryPickup (player->mo)) { armor->Destroy (); } } else { for (i = 0; i < 4; ++i) { AHexenArmor *armor = Spawn<AHexenArmor> (); armor->health = i; armor->Amount = 0; if (!armor->CallTryPickup (player->mo)) { armor->Destroy (); } } } if (!giveall) return; } if (giveall || stricmp (name, "keys") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { if (PClassActor::AllActorClasses[i]->IsDescendantOf (RUNTIME_CLASS(AKey))) { AKey *key = (AKey *)GetDefaultByType (PClassActor::AllActorClasses[i]); if (key->KeyNumber != 0) { key = static_cast<AKey *>(Spawn(static_cast<PClassActor *>(PClassActor::AllActorClasses[i]))); if (!key->CallTryPickup (player->mo)) { key->Destroy (); } } } } if (!giveall) return; } if (giveall || stricmp (name, "weapons") == 0) { AWeapon *savedpending = player->PendingWeapon; for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { type = PClassActor::AllActorClasses[i]; // Don't give replaced weapons unless the replacement was done by Dehacked. if (type != RUNTIME_CLASS(AWeapon) && type->IsDescendantOf (RUNTIME_CLASS(AWeapon)) && (static_cast<PClassActor *>(type)->GetReplacement() == type || static_cast<PClassActor *>(type)->GetReplacement()->IsDescendantOf(RUNTIME_CLASS(ADehackedPickup)))) { // Give the weapon only if it belongs to the current game or if (player->weapons.LocateWeapon(static_cast<PClassWeapon*>(type), NULL, NULL)) { AWeapon *def = (AWeapon*)GetDefaultByType (type); if (giveall == ALL_YESYES || !(def->WeaponFlags & WIF_CHEATNOTWEAPON)) { player->mo->GiveInventory(static_cast<PClassInventory *>(type), 1, true); } } } } player->PendingWeapon = savedpending; if (!giveall) return; } if (giveall || stricmp (name, "artifacts") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { type = PClassActor::AllActorClasses[i]; if (type->IsDescendantOf (RUNTIME_CLASS(AInventory))) { AInventory *def = (AInventory*)GetDefaultByType (type); if (def->Icon.isValid() && def->MaxAmount > 1 && !type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem)) && !type->IsDescendantOf (RUNTIME_CLASS(APowerup)) && !type->IsDescendantOf (RUNTIME_CLASS(AArmor))) { // Do not give replaced items unless using "give everything" if (giveall == ALL_YESYES || type->GetReplacement() == type) { player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount, true); } } } } if (!giveall) return; } if (giveall || stricmp (name, "puzzlepieces") == 0) { for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { type = PClassActor::AllActorClasses[i]; if (type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem))) { AInventory *def = (AInventory*)GetDefaultByType (type); if (def->Icon.isValid()) { // Do not give replaced items unless using "give everything" if (giveall == ALL_YESYES || type->GetReplacement() == type) { player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount <= 0 ? def->MaxAmount : amount, true); } } } } if (!giveall) return; } if (giveall) return; type = PClass::FindActor(name); if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AInventory))) { if (player == &players[consoleplayer]) Printf ("Unknown item \"%s\"\n", name); } else { player->mo->GiveInventory(static_cast<PClassInventory *>(type), amount, true); } return; }
void cht_Give (player_t *player, const char *name, int amount) { enum { ALL_NO, ALL_YES, ALL_YESYES } giveall; int i; const PClass *type; if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVER_Printf( PRINT_HIGH, "%s is a cheater: give %s\n", player->userinfo.netname, name ); else if (player != &players[consoleplayer]) Printf ("%s is a cheater: give %s\n", player->userinfo.netname, name); if (player->mo == NULL || player->health <= 0) { return; } giveall = ALL_NO; if (stricmp (name, "all") == 0) { giveall = ALL_YES; } else if (stricmp (name, "everything") == 0) { giveall = ALL_YESYES; } if (stricmp (name, "health") == 0) { if (amount > 0) { if (player->mo) { player->mo->health += amount; player->health = player->mo->health; } else { player->health += amount; } } else { if (player->mo != NULL) { player->health = player->mo->health = player->mo->GetMaxHealth(); } else { player->health = deh.GodHealth; } } // [BB]: The server has to inform the clients that this player's health has changed. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { ULONG playerIdx = static_cast<ULONG> ( player - players ); SERVERCOMMANDS_SetPlayerHealth( playerIdx ); } } if (giveall || stricmp (name, "backpack") == 0) { // Select the correct type of backpack based on the game type = PClass::FindClass(gameinfo.backpacktype); if (type != NULL) { GiveSpawner (player, type, 1); } if (!giveall) return; } if (giveall || stricmp (name, "ammo") == 0) { // Find every unique type of ammo. Give it to the player if // he doesn't have it already, and set each to its maximum. for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i) { const PClass *type = PClass::m_Types[i]; if (type->ParentClass == RUNTIME_CLASS(AAmmo)) { AInventory *ammo = player->mo->FindInventory (type); if (ammo == NULL) { ammo = static_cast<AInventory *>(Spawn (type, 0, 0, 0, NO_REPLACE)); ammo->AttachToOwner (player->mo); ammo->Amount = ammo->MaxAmount; } else if (ammo->Amount < ammo->MaxAmount) { ammo->Amount = ammo->MaxAmount; } // [BB] This construction is more or less a hack, but at least the give cheats are now working. SERVER_GiveInventoryToPlayer( player, ammo ); } } if (!giveall) return; } if (giveall || stricmp (name, "armor") == 0) { if (gameinfo.gametype != GAME_Hexen) { ABasicArmorPickup *armor = Spawn<ABasicArmorPickup> (0,0,0, NO_REPLACE); armor->SaveAmount = 100*deh.BlueAC; armor->SavePercent = gameinfo.Armor2Percent > 0? gameinfo.Armor2Percent : FRACUNIT/2; if (!armor->CallTryPickup (player->mo)) { armor->Destroy (); } else { // [BB] This construction is more or less a hack, but at least the give cheats are now working. SERVER_GiveInventoryToPlayer( player, armor ); } } else { for (i = 0; i < 4; ++i) { AHexenArmor *armor = Spawn<AHexenArmor> (0,0,0, NO_REPLACE); armor->health = i; armor->Amount = 0; if (!armor->CallTryPickup (player->mo)) { armor->Destroy (); } else { // [BB] This construction is more or less a hack, but at least the give cheats are now working. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { SERVER_GiveInventoryToPlayer( player, armor ); SERVERCOMMANDS_SyncHexenArmorSlots ( static_cast<ULONG> ( player - players ) ); } } } } if (!giveall) return; } if (giveall || stricmp (name, "keys") == 0) { for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i) { if (PClass::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey))) { AKey *key = (AKey *)GetDefaultByType (PClass::m_Types[i]); if (key->KeyNumber != 0) { key = static_cast<AKey *>(Spawn (PClass::m_Types[i], 0,0,0, NO_REPLACE)); if (!key->CallTryPickup (player->mo)) { key->Destroy (); } else { // [BB] This construction is more or less a hack, but at least the give cheats are now working. SERVER_GiveInventoryToPlayer( player, key ); } } } } if (!giveall) return; } if (giveall || stricmp (name, "weapons") == 0 || stricmp (name, "stdweapons") == 0) { // [BB] Don't give the ST weapons if this it true. Useful if you want // to start a game in the middle of a Doom coop megawad for example. bool stdweapons = (stricmp (name, "stdweapons") == 0); AWeapon *savedpending = player->PendingWeapon; for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i) { type = PClass::m_Types[i]; // Don't give replaced weapons unless the replacement was done by Dehacked. if (type != RUNTIME_CLASS(AWeapon) && type->IsDescendantOf (RUNTIME_CLASS(AWeapon)) && (type->ActorInfo->GetReplacement() == type->ActorInfo || type->ActorInfo->GetReplacement()->Class->IsDescendantOf(RUNTIME_CLASS(ADehackedPickup)))) { // Give the weapon only if it belongs to the current game or // is in a weapon slot. if (type->ActorInfo->GameFilter == GAME_Any || (type->ActorInfo->GameFilter & gameinfo.gametype) || player->weapons.LocateWeapon(type, NULL, NULL)) { if (stdweapons) { const char *WeaponName = type->TypeName.GetChars(); if ( !stricmp (WeaponName, "Railgun") || !stricmp (WeaponName, "Minigun") || !stricmp (WeaponName, "GrenadeLauncher") || !stricmp (WeaponName, "Bfg10K") ) continue; } AWeapon *def = (AWeapon*)GetDefaultByType (type); if (giveall == ALL_YESYES || !(def->WeaponFlags & WIF_CHEATNOTWEAPON)) { GiveSpawner (player, type, 1); } } } } player->PendingWeapon = savedpending; // [BB] If we're the server, also tell the client to restore the original weapon. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { // [BB] We need to make sure that the client has its old weapon up instantly. // Since there is no net command for this and I don't want to add another net command // just for this cheat, we use a workaround here. const bool playerHasInstantWeapSwitch = !!(player->cheats & CF_INSTANTWEAPSWITCH); const ULONG ulPlayer = static_cast<ULONG>( player - players ); if ( playerHasInstantWeapSwitch == false ) { player->cheats |= CF_INSTANTWEAPSWITCH; SERVERCOMMANDS_SetPlayerCheats( ulPlayer ); } SERVERCOMMANDS_WeaponChange( ulPlayer ); if ( playerHasInstantWeapSwitch == false ) { player->cheats &= ~CF_INSTANTWEAPSWITCH; SERVERCOMMANDS_SetPlayerCheats( ulPlayer ); } } if (!giveall) return; } if (giveall || stricmp (name, "artifacts") == 0) { for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i) { type = PClass::m_Types[i]; if (type->IsDescendantOf (RUNTIME_CLASS(AInventory))) { AInventory *def = (AInventory*)GetDefaultByType (type); if (def->Icon.isValid() && def->MaxAmount > 1 && !type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem)) && !type->IsDescendantOf (RUNTIME_CLASS(APowerup)) && !type->IsDescendantOf (RUNTIME_CLASS(AArmor))) { GiveSpawner (player, type, amount <= 0 ? def->MaxAmount : amount); } } } if (!giveall) return; } if (giveall || stricmp (name, "puzzlepieces") == 0) { for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i) { type = PClass::m_Types[i]; if (type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem))) { AInventory *def = (AInventory*)GetDefaultByType (type); if (def->Icon.isValid()) { GiveSpawner (player, type, amount <= 0 ? def->MaxAmount : amount); } } } if (!giveall) return; } if (giveall) return; type = PClass::FindClass (name); if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AInventory))) { if (player == &players[consoleplayer]) Printf ("Unknown item \"%s\"\n", name); } else { GiveSpawner (player, type, amount); } return; }