Server Help Forum Index Server Help
Community forums for Subgame, ASSS, and bots
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   StatisticsStatistics   RegisterRegister 
 ProfileProfile   Login to check your private messagesLogin to check your private messages   LoginLogin (SSL) 

Server Help | ASSS Wiki (0) | Shanky.com
WatchDamage module

 
Post new topic   Reply to topic Printable version
 View previous topic  Setting up a Turf zone. Post :: Post ASSS crashing at startup  View next topic  
Author Message
Icebird
Novice


Joined: Sep 01 2008
Posts: 30
Offline

PostPosted: Sun Sep 21, 2008 10:09 am    Post subject: WatchDamage module Reply to topic Reply with quote

Hi.

I need some assistance with the watchdamage module. I do load it in modules.conf and it is attached via arena.conf. Here are the important bits of my own module code:

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;
}


I do register the CB_PLAYERDAMAGE and when a player enters a ship that has shields I setup watches with ModuleWatch and AddWatch. I think I need the AddWatch too because ModuleWatch does not call ToggleWatch, correct?

I see the "Ship change detected" and "You have shields" in ShipChangeCallback but I never see the "SSSC_shields - You took %i damage" message in PlayerDamageCallback when I shoot bombs at nearby walls to damage myself.
Back to top
View users profile Send private message Add User to Ignore List
Dr Brain
Flip-flopping like a wind surfer


Age:39
Gender:Gender:Male
Joined: Dec 01 2002
Posts: 3502
Location: Hyperspace
Offline

PostPosted: Sun Sep 21, 2008 10:24 am    Post subject: Reply to topic Reply with quote

Do /?watchdamage and then try.

Be warned that watching player damage will probably triple your bandwidth usage. If you've got low population, it shouldn't pose an issue.
_________________
Hyperspace Owner

Smong> so long as 99% deaths feel lame it will always be hyperspace to me
Back to top
View users profile Send private message Add User to Ignore List AIM Address Yahoo Messenger MSN Messenger
tcsoccerman
Server Help Squatter


Age:33
Gender:Gender:Male
Joined: Jan 15 2007
Posts: 694
Location: Atlantis
Offline

PostPosted: Sun Sep 21, 2008 11:20 am    Post subject: Reply to topic Reply with quote

Oh you're the one who wanted this module. I started it but never really tested or finished.

I'll attach my work incase it's useful.




Shield.c - 6.37 KB
File downloaded or viewed 27 time(s)
Back to top
View users profile Send private message Add User to Ignore List Send email AIM Address
Icebird
Novice


Joined: Sep 01 2008
Posts: 30
Offline

PostPosted: Sun Sep 21, 2008 5:43 pm    Post subject: Reply to topic Reply with quote

Thank you for your answers. I found the problem after taking a closer look at watchdamage.c.

I always called ModuleWatch and after that AddWatch.

AddWatch has this check at the end:

Code: Show/Hide
if (WATCHCOUNT(wd) == 1)
      ToggleWatch(target, 1);


and WATCHCOUNT is:

Code: Show/Hide
#define WATCHCOUNT(wd) \
   ( LLCount(&wd->watches) + wd->modwatch )


So if i first call ModuleWatch this count is 2 when the check is reached because AddWatch appends a new element to wd->watches just before which makes its LLCount 1 and wd->modwatch is also 1. I wondered if it shouldn't be "if (WATCHCOUNT(wd) >= 1)" but then the package in ToggleWatch would be sent every time a new watch is created for that player which is not necessary.
I think the fix for this would be to append the same check at the end of ModuleWatch so it would look this way:

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);
}
Back to top
View users profile Send private message Add User to Ignore List
Display posts from previous:   
Post new topic   Reply to topic    Server Help Forum Index -> ASSS Questions All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum
View online users | View Statistics | View Ignored List


Software by php BB © php BB Group
Server Load: 41 page(s) served in previous 5 minutes.

phpBB Created this page in 0.839400 seconds : 30 queries executed (92.9%): GZIP compression disabled