#include "bzfsAPI.h" #include #include #include BZ_GET_PLUGIN_VERSION using namespace std; class Dodgeball : public bz_EventHandler, public bz_CustomSlashCommandHandler { public: virtual bool handle(int playerID, bzApiString cmd, bzApiString msg, bzAPIStringList*); virtual void process(bz_EventData *eventData); float abs(float x); bool checkWin(void); int intval(const char* str, int returnIfError); int jail[256]; int jailbreak; int score_red; int score_blue; bool sendHelpMsg[256]; int map_size_y; }; Dodgeball dodgeball; BZF_PLUGIN_CALL int bz_Load(const char* params) { srand((unsigned int)time(NULL) + (int)floor(bz_getCurrentTime() * 1000)); dodgeball.jailbreak = ((rand() % 3) + 3) * 60 + (int)time(NULL); dodgeball.map_size_y = dodgeball.intval(params, 400); bz_registerCustomSlashCommand("dodgeball", &dodgeball); bz_registerEvent(bz_eGetPlayerSpawnPosEvent, &dodgeball); bz_registerEvent(bz_ePlayerDieEvent, &dodgeball); bz_registerEvent(bz_ePlayerJoinEvent, &dodgeball); bz_registerEvent(bz_ePlayerSpawnEvent, &dodgeball); bz_registerEvent(bz_eTickEvent, &dodgeball); bz_setMaxWaitTime(0.01f); bz_debugMessage(4, "Dodgeball -> Loaded"); return 0; } BZF_PLUGIN_CALL int bz_Unload(void) { bz_removeCustomSlashCommand("dodgeball"); bz_removeEvent(bz_eGetPlayerSpawnPosEvent, &dodgeball); bz_removeEvent(bz_ePlayerDieEvent, &dodgeball); bz_removeEvent(bz_ePlayerJoinEvent, &dodgeball); bz_removeEvent(bz_ePlayerSpawnEvent, &dodgeball); bz_removeEvent(bz_eTickEvent, &dodgeball); bz_debugMessage(4, "Dodgeball -> Loaded"); return 0; } bool Dodgeball::handle(int playerID, bzApiString cmd, bzApiString msg, bzAPIStringList*) { cmd.tolower(); msg.tolower(); if (cmd != "dodgeball") return false; if (msg == "help off") { dodgeball.sendHelpMsg[playerID] = false; bz_sendTextMessage(BZ_SERVER, playerID, "Help messages have been turned OFF."); } else if (msg == "help on") { dodgeball.sendHelpMsg[playerID] = true; bz_sendTextMessage(BZ_SERVER, playerID, "Help messages have been turned ON."); } return true; } float Dodgeball::abs(float x) { if (x < 0.0f) { return -x; } else { return x; } } void Dodgeball::process(bz_EventData *eventData) { if (eventData == NULL) return; srand((unsigned int)time(NULL) + (int)floor(bz_getCurrentTime() * 1000)); if (eventData->eventType == bz_eGetPlayerSpawnPosEvent) { bz_GetPlayerSpawnPosEventData *spawnData = (bz_GetPlayerSpawnPosEventData*)eventData; if (dodgeball.jail[spawnData->playerID] == 2) { spawnData->handled = true; spawnData->pos[0] = (float)(((spawnData->team == eBlueTeam) ? 1 : -1) * 387.5); spawnData->pos[1] = (float)(dodgeball.map_size_y - (rand() % (dodgeball.map_size_y * 2))); spawnData->pos[2] = 0.1f; spawnData->rot = (float)(rand() % 360); } else { dodgeball.jail[spawnData->playerID] = 0; spawnData->handled = true; spawnData->pos[0] = (float)(((spawnData->team == eRedTeam) ? 1 : -1) * 280); spawnData->pos[1] = 0.0f; spawnData->pos[2] = 7.0f; spawnData->rot = (float)(rand() % 360); } } else if (eventData->eventType == bz_ePlayerDieEvent) { bz_PlayerDieEventData *dieData = (bz_PlayerDieEventData*)eventData; bool msgKiller = false; bool msgPlayer = false; if (dodgeball.jail[dieData->playerID] == 0) { if (dodgeball.jail[dieData->killerID] == 2 && dieData->killerID != dieData->playerID && dieData->killerTeam != dieData->team) { dodgeball.jail[dieData->killerID] = 1; bz_killPlayer(dieData->killerID, true, BZ_SERVER); msgKiller = true; } if (dieData->killerTeam != dieData->team || dieData->killerID == dieData->playerID) { dodgeball.jail[dieData->playerID] = 2; msgPlayer = true; } if (!dodgeball.checkWin()) { if (msgKiller) { if (dodgeball.sendHelpMsg[dieData->killerID]) { bz_sendTextMessage(BZ_SERVER, dieData->killerID, "You are freed from the jail. You will respawn on your base."); } } if (msgPlayer) { if (dodgeball.sendHelpMsg[dieData->playerID]) { bz_sendTextMessage(BZ_SERVER, dieData->playerID, "When you respawn, you will be in jail. You must kill an enemy tank to be freed."); } } } } else if (dodgeball.jail[dieData->playerID] == 1) { dodgeball.jail[dieData->playerID] = 0; } } else if (eventData->eventType == bz_ePlayerJoinEvent) { bz_PlayerJoinPartEventData *joinData = (bz_PlayerJoinPartEventData*)eventData; if (bz_getTeamCount(eRedTeam) + bz_getTeamCount(eBlueTeam) >= 4) { dodgeball.jail[joinData->playerID] = 2; } else { dodgeball.jail[joinData->playerID] = 0; } dodgeball.sendHelpMsg[joinData->playerID] = true; } else if (eventData->eventType == bz_ePlayerSpawnEvent) { dodgeball.checkWin(); } else if (eventData->eventType == bz_eTickEvent) { bzAPIIntList *pList = bz_newIntList(); bz_getPlayerIndexList(pList); for (unsigned int i = 0; i < pList->size(); i++) { bz_PlayerRecord *pRec = bz_getPlayerByIndex(pList->get(i)); if (pRec) { if (pRec->spawned) { if (floor(abs(pRec->pos[0])) > 400 || floor(abs(pRec->pos[1])) > dodgeball.map_size_y) { bz_killPlayer(pList->get(i), false, BZ_SERVER); bz_sendTextMessage(BZ_SERVER, pList->get(i), "No cheating."); bz_debugMessage(0, bz_format("Player %s was caught cheating.", pRec->callsign.c_str())); bz_sendTextMessage(pList->get(i), eAdministrators, "I tried to cheat myself out of the playing arena!"); } else if (((pRec->team == eRedTeam) ? 1 : -1) * ((dodgeball.jail[pList->get(i)] == 2) ? -1 : 1) * pRec->pos[0] < 0) { bz_killPlayer(pList->get(i), false, BZ_SERVER); bz_sendTextMessage(BZ_SERVER, pList->get(i), "No cheating."); bz_debugMessage(0, bz_format("Player %s was caught cheating.", pRec->callsign.c_str())); bz_sendTextMessage(pList->get(i), eAdministrators, "I tried to cheat myself across the center divider!"); } else if (dodgeball.jail[pList->get(i)] != 2) { if (ceil(abs(pRec->pos[0])) > 360 || ceil(abs(pRec->pos[1])) > 160) { bz_killPlayer(pList->get(i), false, BZ_SERVER); if (pRec->pos[2] < 20) { bz_sendTextMessage(BZ_SERVER, pList->get(i), "No cheating."); bz_debugMessage(0, bz_format("Player %s was caught cheating.", pRec->callsign.c_str())); bz_sendTextMessage(pList->get(i), eAdministrators, "I tried to cheat myself out of jail!"); } else { bz_sendTextMessage(BZ_SERVER, pList->get(i), "No cheating."); bz_debugMessage(0, bz_format("Player %s was caught cheating.", pRec->callsign.c_str())); bz_sendTextMessage(pList->get(i), eAdministrators, "I tried to cheat myself onto the top of the jail!"); } } } else { if (floor(abs(pRec->pos[0])) < 360 && floor(abs(pRec->pos[1])) < 160) { bz_killPlayer(pList->get(i), false, BZ_SERVER); bz_sendTextMessage(BZ_SERVER, pList->get(i), "No cheating."); bz_debugMessage(0, bz_format("Player %s was caught cheating.", pRec->callsign.c_str())); bz_sendTextMessage(pList->get(i), eAdministrators, "I tried to cheat myself out of jail!"); } } } } bz_freePlayerRecord(pRec); } if (!dodgeball.checkWin()) { if ((int)time(NULL) >= dodgeball.jailbreak) { int count = 0; for (unsigned int i = 0; i < pList->size(); i++) { if (dodgeball.jail[pList->get(i)] == 2) { bz_PlayerRecord *pRec = bz_getPlayerByIndex(pList->get(i)); if (pRec) { count++; if (pRec->spawned) { dodgeball.jail[pList->get(i)] = 1; bz_killPlayer(pList->get(i), true, BZ_SERVER); } else { dodgeball.jail[pList->get(i)] = 0; } } bz_freePlayerRecord(pRec); } } srand((unsigned int)time(NULL) + (int)floor(bz_getCurrentTime() * 1000)); dodgeball.jailbreak = ((rand() % 3) + 3) * 60 + (int)time(NULL); if (count > 0) { bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, " ___ ___ _____ _ ____________ _____ ___ _ ___ "); bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, " |_ |/ _ \\|_ _| | | ___ \\ ___ \\ ___|/ _ \\ | | / / |"); bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, " | / /_\\ \\ | | | | | |_/ / |_/ / |__ / /_\\ \\| |/ /| |"); bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, " | | _ | | | | | | ___ \\ /| __|| _ || \\| |"); bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "/\\__/ / | | |_| |_| |____| |_/ / |\\ \\| |___| | | || |\\ \\_|"); bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "\\____/\\_| |_/\\___/\\_____/\\____/\\_| \\_\\____/\\_| |_/\\_| \\_(_)"); } } } bz_deleteIntList(pList); } return; } bool Dodgeball::checkWin(void) { bool red_lose = true; bool blue_lose = true; int red_players = 0; int blue_players = 0; bzAPIIntList *pList = bz_newIntList(); bz_getPlayerIndexList(pList); for (unsigned int i = 0; i < pList->size(); i++) { bz_PlayerRecord *pRec = bz_getPlayerByIndex(pList->get(i)); if (pRec) { if (pRec->spawned || dodgeball.jail[pList->get(i)] == 2) { if (pRec->team == eRedTeam) { red_players++; if (dodgeball.jail[pList->get(i)] != 2) { red_lose = false; } } else if (pRec->team == eBlueTeam) { blue_players++; if (dodgeball.jail[pList->get(i)] != 2) { blue_lose = false; } } } } bz_freePlayerRecord(pRec); } if (red_players == 0 || blue_players == 0) { bz_deleteIntList(pList); return false; } else if ((red_lose || blue_lose) && red_lose != blue_lose) { for (unsigned int i = 0; i < pList->size(); i++) { bz_PlayerRecord *pRec = bz_getPlayerByIndex(pList->get(i)); if (pRec) { if (pRec->spawned) { dodgeball.jail[pList->get(i)] = 1; bz_killPlayer(pList->get(i), true, BZ_SERVER); } else { dodgeball.jail[pList->get(i)] = 0; } } bz_freePlayerRecord(pRec); } if (!red_lose) { bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "Red team has won the round!"); dodgeball.score_red++; } else if (!blue_lose) { bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "Blue team has won the round!"); dodgeball.score_blue++; } if (dodgeball.score_red + dodgeball.score_blue >= 50) { bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "Resetting scores."); dodgeball.score_red = 0; dodgeball.score_blue = 0; } bz_setTeamWins(eRedTeam, dodgeball.score_red); bz_setTeamLosses(eRedTeam, dodgeball.score_blue); bz_setTeamWins(eBlueTeam, dodgeball.score_blue); bz_setTeamLosses(eBlueTeam, dodgeball.score_red); bz_deleteIntList(pList); return true; } return false; } int Dodgeball::intval(const char* src_, int returnIfError) { std::string src = std::string(src_); int digit; bool negative = false; int val = 0; for (unsigned int x = 0; x < (int)src.length(); x++) { if (x == 0 && src[x] == '-') { negative = true; } else { if (src[x] < '0' || src[x] > '9') { return returnIfError; } digit = static_cast(src[x] - '0'); val *= 10; val += digit; } } if (negative) val = 0 - val; return val; }