 |
Server Help Community forums for Subgame, ASSS, and bots
|
Author |
Message |
Icebird Novice
Joined: Sep 01 2008 Posts: 30 Offline
|
Posted: Sun Sep 21, 2008 10:09 am Post subject: WatchDamage module |
 |
|
|
|
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:
#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 |
|
 |
Dr Brain Flip-flopping like a wind surfer

Age:39 Gender: Joined: Dec 01 2002 Posts: 3502 Location: Hyperspace Offline
|
Posted: Sun Sep 21, 2008 10:24 am Post subject: |
 |
|
|
|
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 |
|
 |
tcsoccerman Server Help Squatter
Age:33 Gender: Joined: Jan 15 2007 Posts: 694 Location: Atlantis Offline
|
Posted: Sun Sep 21, 2008 11:20 am Post subject: |
 |
|
|
|
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 |
|
 |
Icebird Novice
Joined: Sep 01 2008 Posts: 30 Offline
|
Posted: Sun Sep 21, 2008 5:43 pm Post subject: |
 |
|
|
|
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:
if (WATCHCOUNT(wd) == 1)
ToggleWatch(target, 1); |
and WATCHCOUNT is:
#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:
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 |
|
 |
|
|
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
|
Software by php BB © php BB Group Server Load: 41 page(s) served in previous 5 minutes.
|