Code: Show/Hide #include <string.h> #include "asss.h" #include "fake.h" #include "watchdamage.h" #include "defs.h" ... // Interfaces local Imodman *mm; local Iplayerdata *pd; local Imainloop *ml; local Iconfig *conf; local Inet *net; local Iarenaman *aman; local Ifake *fake; local Igame *game; local Ichat *chat; local Iwatchdamage *dmg; // Data ... typedef struct SSSC_Shields_PlayerData { int health; int shields; } SSSC_Shields_PlayerData; ... ... // This function will be called when a player changes ship local void ShipChangeCallback(Player *p, int newship, int newfreq) { const char *shipname = ShipName((i8)newship); SSSC_Shields_PlayerData *dataPlayer = PPDATA(p, playerKey); chat->SendMessage(p, "SSSC_shields - Ship change detected"); // read the health and shield hit points from the config and assign them dataPlayer->health = conf->GetInt(p->arena->cfg, "Health", shipname, 0); dataPlayer->shields = conf->GetInt(p->arena->cfg, "Shields", shipname, 0); // manage watchdamage dmg->ModuleWatch(p, 0); if (0 < dataPlayer->shields) { chat->SendMessage(p, "SSSC_shields - You have shields"); dmg->ModuleWatch(p, 1); dmg->AddWatch(fake->CreateFakePlayer("Damage", p->arena, SHIP_WARBIRD, 9999), p); } } ... ... // This function is called every time a player receives damage local void PlayerDamageCallback(Arena *arena, Player *p, struct S2CWatchDamage *damage, int count) { SSSC_Shields_PlayerData *dataPlayer = PPDATA(p, playerKey); const char *shipname; int maxhealth; int maxshields; int dmg_val; shipname = ShipName(p->pkt.ship); maxhealth = conf->GetInt(arena->cfg, "Health", shipname, 0); maxshields = conf->GetInt(arena->cfg, "Shields", shipname, 0); dmg_val = (int)damage->damage; chat->SendMessage(p, "SSSC_shields - You took %i damage", dmg_val); if (0 < maxshields) // the ship type has shields { if (dataPlayer->shields > 0) // the player still has some shields { if (dataPlayer->shields < dmg_val) // some of the damage gets through the shields { dataPlayer->health -= dmg_val - dataPlayer->shields; dataPlayer->shields = 0; } else // the damage is completely absorbed { dataPlayer->shields -= dmg_val; } } else // no shields left { dataPlayer->health -= dmg_val; } // kill the player if no health is left if (dataPlayer->health < 0) kill(p, "killer", 0, 0); // update the interface UpdateInterface(p); } } // The entry point: EXPORT int MM_sssc_shields(int action, Imodman *mm_, Arena *arena) { int rv = MM_FAIL; // return value if (action == MM_LOAD) { mm = mm_; pd = mm->GetInterface(I_PLAYERDATA, ALLARENAS); ml = mm->GetInterface(I_MAINLOOP, ALLARENAS); conf = mm->GetInterface(I_CONFIG, ALLARENAS); net = mm->GetInterface(I_NET, ALLARENAS); aman = mm->GetInterface(I_ARENAMAN, ALLARENAS); fake = mm->GetInterface(I_FAKE, ALLARENAS); game = mm->GetInterface(I_GAME, ALLARENAS); chat = mm->GetInterface(I_CHAT, ALLARENAS); dmg = mm->GetInterface(I_WATCHDAMAGE, ALLARENAS); if (!pd || !ml || !conf || !net || !aman || !fake || !game || !chat || !dmg) { // release interfaces if loading failed mm->ReleaseInterface(dmg); mm->ReleaseInterface(chat); mm->ReleaseInterface(game); mm->ReleaseInterface(fake); mm->ReleaseInterface(aman); mm->ReleaseInterface(net); mm->ReleaseInterface(conf); mm->ReleaseInterface(ml); mm->ReleaseInterface(pd); rv = MM_FAIL; } else { // allocate data playerKey = pd->AllocatePlayerData(sizeof(SSSC_Shields_PlayerData)); arenaKey = aman->AllocateArenaData(sizeof(ArenaData)); if (playerKey == -1 || arenaKey == -1) // check if we ran out of memory { // release interfaces if loading failed mm->ReleaseInterface(dmg); mm->ReleaseInterface(chat); mm->ReleaseInterface(game); mm->ReleaseInterface(fake); mm->ReleaseInterface(aman); mm->ReleaseInterface(net); mm->ReleaseInterface(conf); mm->ReleaseInterface(ml); mm->ReleaseInterface(pd); if (playerKey != -1) // free data if it was allocated pd->FreePlayerData(playerKey); if (arenaKey != -1) // free data if it was allocated aman->FreeArenaData(arenaKey); rv = MM_FAIL; } else { // callbacks mm->RegCallback(CB_PLAYERACTION, playerActionCallback, ALLARENAS); mm->RegCallback(CB_ARENAACTION, arenaActionCallback, ALLARENAS); mm->RegCallback(CB_SHIPCHANGE, ShipChangeCallback, ALLARENAS); mm->RegCallback(CB_FREQCHANGE, FreqChangeCallback, ALLARENAS); mm->RegCallback(CB_PLAYERDAMAGE, PlayerDamageCallback, ALLARENAS); // timers ml->SetTimer(EverySecond, 100, 100, NULL, NULL); // times are in centiseconds // commands rv = MM_OK; } } } else if (action == MM_UNLOAD) { // clear timers ml->ClearTimer(EverySecond, NULL); ml->ClearTimer(unload_timer, NULL); // unregister callbacks mm->UnregCallback(CB_ARENAACTION, arenaActionCallback, ALLARENAS); mm->UnregCallback(CB_PLAYERACTION, playerActionCallback, ALLARENAS); mm->UnregCallback(CB_SHIPCHANGE, ShipChangeCallback, ALLARENAS); mm->UnregCallback(CB_FREQCHANGE, FreqChangeCallback, ALLARENAS); mm->UnregCallback(CB_PLAYERDAMAGE, PlayerDamageCallback, ALLARENAS); // free allocated data pd->FreePlayerData(playerKey); aman->FreeArenaData(arenaKey); // release interfaces mm->ReleaseInterface(dmg); mm->ReleaseInterface(chat); mm->ReleaseInterface(game); mm->ReleaseInterface(fake); mm->ReleaseInterface(aman); mm->ReleaseInterface(net); mm->ReleaseInterface(conf); mm->ReleaseInterface(ml); mm->ReleaseInterface(pd); rv = MM_OK; } return rv; } |
Code: Show/Hide if (WATCHCOUNT(wd) == 1)
ToggleWatch(target, 1); |
Code: Show/Hide #define WATCHCOUNT(wd) \
( LLCount(&wd->watches) + wd->modwatch ) |
Code: Show/Hide local void ModuleWatch(Player *p, int on)
{ watchdata *wd = PPDATA(p, wdkey); if (on) wd->modwatch++; else wd->modwatch -= wd->modwatch > 0 ? 1 : 0; if (WATCHCOUNT(wd) == 1) ToggleWatch(p, 1); else if (WATCHCOUNT(wd) == 0) ToggleWatch(p, 0); } |