Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "asss.h"
- #include "clientset.h"
- #include "statcodes.h"
- #include "stats.h"
- #include "persist.h"
- #include "lvzhud.h"
- #include "colors.h"
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #define N_TEAMS 2
- #define N_BALLS 1
- #define TILE_WIDTH 16
- #define TILE_HEIGHT 16
- #define DELAY_BALLSPAWN 400
- //Time before a ball becomes neutral after being fired
- #define DELAY_BALLNEUT 500
- #define DEFAULT_WARP_X 512
- #define DEFAULT_WARP_Y 490
- #define INFRACTION_DEF_CR "illegal goaltending"
- #define INFRACTION_OFF_CR "creasing"
- #define INFRACTION_GOALIE_KILL "goalie interference"
- ////////////////////////////////////
- //
- //INTERFACES
- //
- ////////////////////////////////////
- local Imodman *mm;
- local Ilogman *lm;
- local Icmdman *cmd;
- local Ichat *chat;
- local Iballs *balls;
- local Icolor *color;
- local Iplayerdata *pd;
- local Imainloop *ml;
- local Igame *game;
- local Iobjects *objs;
- local Imapdata *mapdata;
- local Iclientset *cs;
- local Istats *stats;
- local Ipersist *persist;
- local Iarenaman *aman;
- local Iconfig *cfg;
- local Ilvzhud *hud;
- ////////////////////////////////////
- //
- //TYPEDEFS
- //
- ////////////////////////////////////
- typedef enum
- {
- SOCKEY_WAITING,
- SOCKEY_STARTING,
- SOCKEY_PLAYING,
- SOCKEY_TIMEOUT,
- } SockeyState;
- typedef struct
- {
- int dummy;
- } ped_sockey_t;
- typedef struct
- {
- int gametime;
- int maxgoals;
- int winby;
- int penalty_offcrease;
- int penalty_defcrease;
- int penalty_goalieinterference;
- } sockey_config_t;
- ////////////////////////////////////
- //
- //GLOBAL DATA
- //
- ////////////////////////////////////
- local override_key_t ok_Doormode;
- //PlayerExtraData keys
- local int ped_sockey;
- //ArenaData keys
- local int adkey;
- //
- local SockeyState state;
- local ticks_t gamestarttime;
- local ticks_t gametime;
- local ticks_t pausedcumultime; //total time during which the game was paused
- local ticks_t pausetime; //time at which the game was paused (timeout)
- local int gameistimed;
- local Player* carrier[N_BALLS];
- local Player* lastcarrier[N_BALLS];
- local ticks_t lastthrowtime[N_BALLS];
- local int invalidshot;
- local int score[N_TEAMS];
- // ll_indefcrease[i] is a list of all the players of freq <i> who are in their own crease
- // The first of this list should be goalie, and all the others are considered to be creasing.
- LinkedList ll_indefcrease[N_TEAMS];
- // ll_inoffcrease[i][j] is a list of all the players of freq <i> who are in freq <j>'s crease.
- LinkedList ll_inoffcrease[N_TEAMS][N_TEAMS];
- LinkedList ll_penalties;
- ////////////////////////////////////
- //
- //FUNCTIONS
- //
- ////////////////////////////////////
- local void SetDoors(Arena* arena, int doormode)
- {
- Player *g;
- Link *link;
- cs->ArenaOverride(arena, ok_Doormode, doormode);
- pd->Lock();
- FOR_EACH_PLAYER(g)
- {
- if (g->arena == arena)
- cs->SendClientSettings(g);
- }
- pd->Unlock();
- }
- local void getscorestr(char* str, int maxlen)
- {
- if (N_TEAMS > 2)
- {
- StringBuffer sb;
- int i;
- SBInit(&sb);
- for (i = 0; i < N_TEAMS; i++)
- SBPrintf(&sb, " %3i", score[i]);
- snprintf(str, maxlen, "%s", sb.start);
- SBDestroy(&sb);
- }
- else if (N_TEAMS == 2)
- {
- snprintf(str, maxlen, " %3i - %i", score[0], score[1]);
- //chat->SendArenaMessage(arena, "Score: %i - %i", score[0], score[1]);
- }
- }
- local void showscore(Arena * arena, int inchat)
- {
- char buf[256];
- Target t;
- t.type = T_ARENA;
- t.u.arena = arena;
- if (inchat)
- {
- getscorestr(buf, sizeof(buf));
- //chat->SendArenaMessage(arena, sb.start);
- color->ColorA(COLOR_PINK, arena, "Score: %s", buf);
- }
- hud->SetValueNum(arena, "score0", &t, score[0]);
- hud->SetValueNum(arena, "score1", &t, score[1]);
- }
- local char* addindex(char * str, int index)
- {
- char buf[8];
- snprintf(buf, sizeof(buf), "%i", index);
- strcat(str, buf);
- return str;
- }
- local int playerisinregion(Player* p, const char* regnname)
- {
- if (!p)
- return FALSE;
- Region * rgn = mapdata->FindRegionByName(p->arena, regnname);
- if (rgn)
- return mapdata->Contains(rgn, p->position.x / TILE_WIDTH, p->position.y / TILE_HEIGHT);
- return FALSE;
- }
- local int warpinregion(Arena* arena, Target* target, const char* regnname)
- {
- int x,y;
- Region * rgn = mapdata->FindRegionByName(arena, regnname);
- if (rgn)
- {
- mapdata->FindRandomPoint(rgn, &x, &y);
- if (x >= 0 && y >= 0)
- {
- game->WarpTo(target, x, y);
- return TRUE;
- }
- }
- return FALSE;
- }
- local void endpenalty_cleanup(void *param)
- {
- Player * p = (Player*)param;
- if (p)
- LLRemove(&ll_penalties, p);
- Target t;
- t.type = T_PLAYER;
- t.u.p = p;
- char regnname[32] = "PenaltyExit";
- addindex(regnname, p->p_freq);
- if (warpinregion(p->arena, &t, regnname))
- {
- //Warp successful
- }
- else
- game->WarpTo(&t, DEFAULT_WARP_X, DEFAULT_WARP_Y);
- }
- local int updatetime(void *param)
- {
- static int lastvalue = -1;
- ticks_t curtime;
- Target t;
- t.type = T_ARENA;
- t.u.arena = (Arena*)param;
- int value = 0;
- if (state == SOCKEY_PLAYING)
- {
- if (gameistimed)
- //Show remaining time
- curtime = TICK_DIFF(gametime, TICK_DIFF(TICK_DIFF(current_ticks(), gamestarttime), pausedcumultime));
- else
- //Show elapsed time
- curtime = TICK_DIFF(TICK_DIFF(current_ticks(), gamestarttime), pausedcumultime);
- value = (curtime / 100)%60 + 100*(curtime / 6000);
- }
- else if (state == SOCKEY_TIMEOUT)
- {
- if (gameistimed)
- //Show remaining time
- curtime = TICK_DIFF(gametime, TICK_DIFF(pausetime, gamestarttime));
- else
- //Show elapsed time
- curtime = TICK_DIFF(pausetime, gamestarttime);
- curtime = TICK_DIFF(curtime, pausedcumultime);
- value = (curtime / 100)%60 + 100*(curtime / 6000);
- }
- else if (state == SOCKEY_STARTING)
- {
- if (gameistimed)
- value = (gametime / 100)%60 + 100*(gametime / 6000);
- else
- value = 0;
- }
- if (value != lastvalue)
- {
- hud->SetValueNum((Arena*)param, "time", &t, value);
- lastvalue = value;
- }
- return 1;
- }
- local int endpenalty(void *param)
- {
- endpenalty_cleanup(param);
- return FALSE;
- }
- local void warptopenalty(Player *p)
- {
- Target t;
- t.type = T_PLAYER;
- t.u.p = p;
- char regnname[32] = "Penalty";
- addindex(regnname, p->p_freq);
- if (warpinregion(p->arena, &t, regnname))
- {
- //Warp successful
- }
- }
- local void givepenalty(Player *p, const char* infraction)
- {
- int time = 0;
- sockey_config_t *ad = P_ARENA_DATA(p->arena, adkey);
- if (!strcmp(infraction, INFRACTION_DEF_CR))
- time = ad->penalty_defcrease;
- else if (!strcmp(infraction, INFRACTION_OFF_CR))
- time = ad->penalty_offcrease;
- else if (!strcmp(infraction, INFRACTION_GOALIE_KILL))
- time = ad->penalty_goalieinterference;
- else
- lm->LogA(L_ERROR, "sockey", p->arena, "Invalid penalty '%s' given to %s", infraction, p->name);
- if (time > 0)
- {
- LLAdd(&ll_penalties, p);
- ml->SetTimer(endpenalty, time*100, 0, p, p);
- stats->IncrementStat(p, STAT_PENALTY_TIME, time);
- warptopenalty(p);
- color->ColorASound(COLOR_PINK, p->arena, SOUND_SCREAM, "%i seconds penalty given to %s for %s", time, p->name, infraction);
- }
- }
- local int endgame(void* param);
- local int startgame(void *param);
- local void resetgame(Arena* arena, int warpplayers, int spawnballs);
- local void updatesettings(Arena *arena)
- {
- sockey_config_t *ad = P_ARENA_DATA(arena, adkey);
- ConfigHandle ch = arena->cfg;
- /* cfghelp: Sockey:GameTime, arena, int, def: 600
- * The duration of a game (in seconds). No time limit if 0 or negative. */
- ad->gametime = cfg->GetInt(ch, "Sockey", "GameTime", 600);
- /* cfghelp: Sockey:GoalsToWin, arena, int, def: -1
- * Goals needed to win the game. Game ends at time limit only if 0 or negative. */
- ad->maxgoals = cfg->GetInt(ch, "Sockey", "GoalsToWin", -1);
- /* cfghelp: Sockey:WinBy, arena, int, def: 0
- * Minimum goal difference needed to win. */
- ad->winby = cfg->GetInt(ch, "Sockey", "WinBy", 0);
- /* cfghelp: Sockey:PenaltyOffCrease, arena, int, def: 10
- * Penalty time for shooting from the offensive crease (in seconds). */
- ad->penalty_offcrease = cfg->GetInt(ch, "Sockey", "PenaltyOffCrease", 10);
- /* cfghelp: Sockey:PenaltyDefCrease, arena, int, def: 10
- * Penalty time for defensive creasing (in seconds). */
- ad->penalty_defcrease = cfg->GetInt(ch, "Sockey", "PenaltyDefCrease", 10);
- /* cfghelp: Sockey:PenaltyGoalieKill, arena, int, def: 10
- * Penalty time for goalie interference (in seconds). */
- ad->penalty_goalieinterference = cfg->GetInt(ch, "Sockey", "PenaltyGoalieKill", 10);
- }
- local void cancelgame(Arena* a)
- {
- lm->LogA(L_INFO, "sockey", a, "Game cancelled");
- ml->ClearTimer(startgame, a);
- ml->ClearTimer(endgame, a);
- ml->ClearTimer(updatetime, a);
- state = SOCKEY_WAITING;
- balls->EndGame(a);
- SetDoors(a, 0);
- chat->SendArenaSoundMessage(a, SOUND_DING, "Game cancelled");
- }
- local void showstats(Arena* arena)
- {
- Link *link;
- Player *p;
- int i;
- stats->SendUpdates(NULL);
- for (i = 0; i < N_TEAMS; i++)
- {
- chat->SendArenaMessage(arena," ________");
- chat->SendArenaMessage(arena,"| Team %d |", i);
- chat->SendArenaMessage(arena,"|------------------------------------------------------------------------------|");
- chat->SendArenaMessage(arena,"| Player G A Sh Sa TO St K D GT Pen |");
- chat->SendArenaMessage(arena,"|------------------------------------------------------------------------------|");
- pd->Lock();
- FOR_EACH_PLAYER(p)
- {
- stats->StopTimer(p, STAT_GOALIE_TIME);
- /* Only list players who've played. */
- if (p->p_freq == i && p->p_ship != SHIP_SPEC && p->arena == arena)
- {
- chat->SendArenaMessage(arena,"| %-24s %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %02d:%02d %02d:%02d |",
- p->name,
- stats->GetStat(p, STAT_BALL_GOALS, INTERVAL_GAME),
- stats->GetStat(p, STAT_BALL_ASSISTS, INTERVAL_GAME),
- stats->GetStat(p, STAT_BALL_SHOTS, INTERVAL_GAME),
- stats->GetStat(p, STAT_BALL_SAVES, INTERVAL_GAME),
- stats->GetStat(p, STAT_BALL_TURNOVERS, INTERVAL_GAME),
- stats->GetStat(p, STAT_BALL_STEALS, INTERVAL_GAME),
- stats->GetStat(p, STAT_KILLS, INTERVAL_GAME),
- stats->GetStat(p, STAT_DEATHS, INTERVAL_GAME),
- stats->GetStat(p, STAT_GOALIE_TIME, INTERVAL_GAME) / 60,
- stats->GetStat(p, STAT_GOALIE_TIME, INTERVAL_GAME) % 60,
- stats->GetStat(p, STAT_PENALTY_TIME, INTERVAL_GAME) / 60,
- stats->GetStat(p, STAT_PENALTY_TIME, INTERVAL_GAME) % 60);
- }
- }
- pd->Unlock();
- chat->SendArenaMessage(arena,"|------------------------------------------------------------------------------|");
- }
- }
- local int endgame(void* param)
- {
- Arena* arena = (Arena*)param;
- int winfreq = 0;
- int i;
- lm->LogA(L_INFO, "sockey", arena, "Game ending");
- if (!arena || state == SOCKEY_WAITING)
- return FALSE;
- if (state == SOCKEY_STARTING)
- {
- cancelgame(arena);
- return FALSE;
- }
- //Find winning freq
- if (N_TEAMS == 2)
- {
- if (score[0] == score[1])
- {
- //Tie!
- winfreq = -1;
- }
- else
- winfreq = (score[0] > score[1] ? 0:1 );
- }
- else
- {
- int highestscore = -1;
- for (i = 0; i < N_TEAMS; i++)
- if (score[i] > highestscore)
- {
- winfreq = i;
- highestscore = score[i];
- }
- else if (score[i] == highestscore)
- {
- //Multi-team tie?!
- winfreq = -1;
- }
- }
- Link *link;
- Player *p;
- pd->Lock();
- FOR_EACH_PLAYER(p)
- if (p->status == S_PLAYING &&
- p->arena == arena &&
- p->p_ship != SHIP_SPEC)
- {
- if (p->p_freq == winfreq)
- stats->IncrementStat(p, STAT_BALL_GAMES_WON, 1);
- else
- stats->IncrementStat(p, STAT_BALL_GAMES_LOST, 1);
- }
- pd->Unlock();
- char buf[256];
- getscorestr(buf, sizeof(buf));
- if (winfreq >= 0)
- color->ColorASound(COLOR_GREEN, arena, SOUND_HALLELLULA, "Game over! Team %i won Final score: %s", winfreq, buf);
- else
- color->ColorASound(COLOR_GREEN, arena, SOUND_GAMESUCKS, "Game over! It's a TIE!!! Final score: %s", buf);
- state = SOCKEY_WAITING;
- persist->EndInterval("", arena, INTERVAL_GAME);
- showstats(arena);
- balls->EndGame(arena);
- resetgame(arena, FALSE, FALSE);
- return FALSE;
- }
- local int startgame(void *param)
- {
- Arena* arena = (Arena*)param;
- int i;
- Link * link;
- Player * p;
- Target t;
- t.type = T_ARENA;
- t.u.arena = arena;
- lm->LogA(L_INFO, "sockey", arena, "Starting new game");
- gamestarttime = current_ticks();
- pausedcumultime = 0;
- state = SOCKEY_PLAYING;
- SetDoors(arena, 0);
- chat->SendArenaSoundMessage(arena, SOUND_GOAL, "Go!");
- for (i = 0; i < N_BALLS; i++)
- balls->SpawnBall(arena, i);
- pd->Lock();
- FOR_EACH_PLAYER_IN_ARENA(p,arena)
- stats->ScoreReset(p, INTERVAL_GAME);
- pd->Unlock();
- if (gameistimed)
- ml->SetTimer(endgame, gametime, 0, arena, arena);
- ml->SetTimer(updatetime, 0, 5, arena, arena);
- objs->Toggle(&t, 10, 1);
- showscore(arena, FALSE);
- return FALSE;
- }
- local void newgame(Arena *a, int delaysecs)
- {
- lm->LogA(L_INFO, "sockey", a, "New game starting in %i seconds", delaysecs);
- chat->SendArenaSoundMessage(a, SOUND_PHONE, "GET READY! Game starting in %i seconds...", delaysecs);
- Target t;
- t.type = T_ARENA;
- t.u.arena = a;
- SetDoors(a, 255);
- game->GivePrize(&t, PRIZE_WARP, 1);
- state = SOCKEY_STARTING;
- ml->SetTimer(startgame, delaysecs*100, 0, a, a);
- updatesettings(a);
- sockey_config_t *ad = P_ARENA_DATA(a, adkey);
- gameistimed = (ad->gametime > 0);
- gametime = ad->gametime * 100;
- objs->Toggle(&t, 10, 0);
- updatetime((void*)a);
- showscore(a, FALSE);
- }
- local void resetgame(Arena* arena, int warpplayers, int spawnballs)
- {
- Target t;
- t.type = T_ARENA;
- t.u.arena = arena;
- objs->Toggle(&t, 10, 0);
- lm->LogA(L_INFO, "sockey", arena, "Reseting game");
- ml->CleanupTimer(endpenalty, NULL, endpenalty_cleanup);
- int i,j;
- lm->LogA(L_DRIVEL, "sockey", arena, "Emptying lists");
- for (i = 0; i < N_TEAMS; i++)
- {
- score[i] = 0;
- LLEmpty(&ll_indefcrease[i]);
- for (j = 0; j < N_TEAMS; j++)
- {
- LLEmpty(&ll_inoffcrease[i][j]);
- }
- }
- LLEmpty(&ll_penalties);
- lm->LogA(L_DRIVEL, "sockey", arena, "Initializing balls");
- for (i = 0; i < N_BALLS; i++)
- {
- carrier[i] = NULL;
- lastcarrier[i] = NULL;
- lastthrowtime[i] = current_ticks();
- if (spawnballs)
- {
- lm->LogA(L_DRIVEL, "sockey", arena, "Spawning ball %i", i);
- balls->SpawnBall(arena, i);
- }
- }
- //chat->SendArenaMessage(arena, "Sockey game reset");
- updatesettings(arena);
- sockey_config_t *ad = P_ARENA_DATA(arena, adkey);
- gametime = ad->gametime *100; //100 ticks/s
- if (state == SOCKEY_PLAYING || state == SOCKEY_STARTING || state == SOCKEY_TIMEOUT)
- cancelgame(arena);
- ml->ClearTimer(updatetime, arena);
- updatetime((void*)arena);
- }
- /*
- * Checks if the (x,y) coordinate (in pixels) is in <creaseteam>'s crease
- */
- local int coordincrease(Arena* a, int x, int y, int creaseteam)
- {
- Region * rgn;
- char regionname[32];
- snprintf(regionname, sizeof(regionname), "crease%i", creaseteam);
- rgn = mapdata->FindRegionByName(a, regionname);
- if (!rgn)
- return FALSE;
- return mapdata->Contains(rgn, x / TILE_WIDTH, y / TILE_HEIGHT);
- }
- /*
- * Checks if player <p> is in <creaseteam>'s crease
- * Updates the corresponding linked list
- */
- local int checkcrease(Player* p, int creaseteam)
- {
- int playerteam = p->p_freq;
- int isinregion;
- LinkedList * listtocheck = NULL;
- if ((playerteam >= N_TEAMS) || (p->p_ship == SHIP_SPEC))
- return FALSE;
- isinregion = coordincrease(p->arena, p->position.x, p->position.y, creaseteam);
- if (creaseteam == playerteam)
- //Checking defensive crease
- listtocheck = &ll_indefcrease[creaseteam];
- else
- //Checking offensive crease
- listtocheck = &ll_inoffcrease[playerteam][creaseteam];
- if (isinregion)
- {
- if (creaseteam == playerteam)
- {
- //Manage goaltending time stat
- if (LLCount(listtocheck) == 0)
- stats->StartTimer(p, STAT_GOALIE_TIME);
- }
- //Add the player to the list if he is not in it already
- if (!LLMember(listtocheck, p))
- LLAdd(listtocheck, p);
- }
- else
- {
- if (creaseteam == playerteam)
- stats->StopTimer(p, STAT_GOALIE_TIME);
- //Remove the player from the list if he is in it
- LLRemove(listtocheck, p);
- }
- return isinregion;
- }
- /*
- *
- */
- local void clearplayerrefs(Player *p)
- {
- int i,j;
- pd->Lock();
- for (i = 0; i < N_TEAMS; i++)
- {
- LLRemove(&ll_indefcrease[i], p);
- for (j = 0; j < N_TEAMS; j++)
- LLRemove(&ll_inoffcrease[i][j], p);
- }
- for (i = 0; i < N_BALLS; i++)
- {
- if (carrier[i] == p)
- carrier[i] = NULL;
- if (lastcarrier[i] == p)
- lastcarrier[i] = NULL;
- }
- LLRemove(&ll_penalties, p);
- pd->Unlock();
- ml->ClearTimer(endpenalty, p);
- }
- /*
- * Update the status of player <p> for all creases
- */
- local void checkallcreases(Player *p)
- {
- int i;
- if ((p->p_freq >= N_TEAMS) || (p->p_ship == SHIP_SPEC))
- {
- lm->LogA(L_WARN, "sockey", p->arena, "Called checkallcreases for invalid player (ship %i, freq %i)", p->p_ship, p->p_freq);
- clearplayerrefs(p);
- }
- else
- for (i = 0; i < N_TEAMS; i++)
- checkcrease(p, i);
- }
- local Player* getgoalie(int team)
- {
- if (team >= 0 && team < N_TEAMS)
- if (LLCount(&ll_indefcrease[team]) > 0)
- return ((Player*)LLGetHead(&ll_indefcrease[team])->data);
- return NULL;
- }
- local void showgoal(Player* scorer, Player* assist, int incorner)
- {
- char sound = (incorner ? SOUND_INCONCEIVABLE : SOUND_GOAL);
- if (assist)
- color->ColorASound(COLOR_GREY, scorer->arena, sound, "%sGoal by %s! Assisted by %s", incorner?"Top corner!!! ":"", scorer->name, assist->name);
- else
- color->ColorASound(COLOR_GREY, scorer->arena, sound, "%sGoal by %s!", incorner?"Top corner!!! ":"", scorer->name);
- }
- local void warpaftergoal(Arena* arena, int scoredteam, int scoringteam, int bid)
- {
- int i;
- char regnname[32];
- Link * link;
- Player * p;
- Target t;
- t.type = T_PLAYER;
- for (i = 0; i< N_TEAMS; i++)
- {
- pd->Lock();
- FOR_EACH_PLAYER_IN_ARENA(p, arena)
- {
- if (p->p_freq >= 0 && p->p_freq < N_TEAMS)
- {
- if (!LLMember(&ll_penalties, p))
- {
- snprintf(regnname, sizeof(regnname), "Zone%i", p->p_freq);
- if (!playerisinregion(p, regnname))
- {
- t.u.p = p;
- snprintf(regnname, sizeof(regnname), "Faceoff%i", p->p_freq);
- warpinregion(arena, &t, regnname);
- }
- }
- }
- }
- pd->Unlock();
- }
- //Give ball to scored team
- snprintf(regnname, sizeof(regnname), "CenterCrease%i", scoredteam);
- lm->LogA(L_DRIVEL, "sockey", arena, "Giving ball to freq %i", scoredteam);
- Region *rgn = mapdata->FindRegionByName(arena, regnname);
- if (rgn)
- {
- int x,y;
- mapdata->FindRandomPoint(rgn, &x, &y);
- if (x >= 0 && y >= 0)
- {
- struct BallData newbd;
- newbd.x = x * TILE_WIDTH + TILE_WIDTH / 2;
- newbd.y = y * TILE_HEIGHT + TILE_HEIGHT / 2;
- newbd.carrier = NULL;
- newbd.freq = scoredteam;
- newbd.last_update = current_ticks();
- newbd.time = current_ticks();
- newbd.xspeed = 0;
- newbd.yspeed = 0;
- newbd.state = BALL_ONMAP;
- lm->LogA(L_DRIVEL, "sockey", arena, "Placing ball at %i %i", newbd.x, newbd.y);
- balls->PlaceBall(arena, bid, &newbd);
- }
- }
- }
- ////////////////////////////////////
- //
- //ADVISORS
- //
- ////////////////////////////////////
- /* called on a pickup request.
- * returning FALSE disallows the ballpickup entirely.
- * returning TRUE changes the ball state to the data pointed to by newbd.
- * by default newbd is the usual state of the player carrying the ball, but other advisers might change this.
- */
- int AllowBallPickup(Arena *a, Player *p, int bid, struct BallData *newbd)
- {
- int i;
- Link *link;
- Player *pp;
- if (state == SOCKEY_TIMEOUT)
- return FALSE;
- if (state != SOCKEY_PLAYING)
- return TRUE;
- int playerteam = p->p_freq;
- //Do not allow players outside the game to touch the ball
- if (playerteam < 0 || playerteam >= N_TEAMS)
- return FALSE;
- //Do not allow players in penalty to pick up the ball
- if (LLMember(&ll_penalties, p))
- return FALSE;
- //Do not allow player to pick up ball from enemy crease if there is at least one enemy in it
- //Unless it's a pass; otherwise the player could intentionaly make a teammate's shot phase
- //and get in the goal
- if (!carrier[bid] || (carrier[bid] && carrier[bid]->p_freq != p->p_freq))
- {
- for (i = 0; i < N_TEAMS; i++)
- if (i != playerteam)
- //if (checkcrease(p, i) || coordincrease(a, curballx, curbally, i))
- //Apparently the current ball position is always the same as the player's position... We can't check
- //for a player grabbing the ball in the crease, while the player is just outside of it
- if (checkcrease(p, i))
- {
- if (getgoalie(i))
- {
- //chat->SendArenaMessage(a, "%s attempted to pick up ball in team %i crease", p->name, i);
- return FALSE;
- }
- }
- }
- //Do not allow non-goalie player in defensive crease to pick up ball
- //Ball belonged to someone else before...
- if (checkcrease(p, p->p_freq))
- {
- //Check if he's alone in his crease (check crease status of his entire team)
- pd->Lock();
- FOR_EACH_PLAYER_IN_ARENA(pp, a)
- {
- if (pp->p_freq == playerteam && pp != p && checkcrease(pp, pp->p_freq))
- {
- //Don't bother if the other team is not in control
- if (carrier[bid] && carrier[bid]->p_freq != playerteam)
- {
- //We have a defensive creasing
- Player *penalized, *designatedgoalie;
- if (p == getgoalie(p->p_freq))
- {
- penalized = pp;
- designatedgoalie = p;
- }
- else
- {
- penalized = p;
- designatedgoalie = pp;
- }
- givepenalty(penalized, INFRACTION_DEF_CR);
- color->ColorFSound(COLOR_RED, a, p->p_freq, SOUND_LISTEN, "Only ONE goalie at a time is allowed in your own crease!");
- lm->LogA(L_DRIVEL, "sockey", a, "Defensive crease for team %i: <%s> and %s", p->p_freq, penalized->name, designatedgoalie->name);
- //chat->SendArenaMessage(a, "Defensive creasing! %s and %s", p->name, pp->name);
- /*
- currentballs = balls->GetBallData(a);
- currentballs->balls[bid].carrier = NULL;
- currentballs->balls[bid].xspeed = 0;
- currentballs->balls[bid].yspeed = 0;
- balls->ReleaseBallData(a);
- */
- //Let the ball go through!!!
- return FALSE;
- }
- }
- }
- pd->Unlock();
- }
- //Catch / Pick-up is allowed
- if (carrier[bid])
- {
- //Ball belonged to someone else before...
- if (carrier[bid]->p_freq != playerteam)
- {
- if (current_ticks() - lastthrowtime[bid] < DELAY_BALLNEUT)
- {
- //If p is goalie, it's a save
- if (getgoalie(playerteam) == p)
- {
- //Save
- color->ColorASound(COLOR_GREY, a, SOUND_GEE, "Saved by %s!", p->name);
- //chat->SendArenaMessage(a, "Saved by %s", p->name);
- stats->IncrementStat(p, STAT_BALL_SAVES, 1);
- //Shot on goal for carrier[bid]
- stats->IncrementStat(p, STAT_BALL_SHOTS, 1);
- }
- else
- {
- //Turnover
- //snprintf(msg, sizeof(msg), "Turnover! %s -> %s", carrier[bid]->name, p->name);
- //chat->SendArenaMessage(a, msg);
- stats->IncrementStat(p, STAT_BALL_STEALS, 1);
- stats->IncrementStat(carrier[bid], STAT_BALL_TURNOVERS, 1);
- }
- }
- lastcarrier[bid] = NULL;
- }
- else
- {
- if (carrier[bid] != p)
- {
- //Pass
- //snprintf(msg, sizeof(msg), "Pass %s -> %s", carrier[bid]->name, p->name);
- //chat->SendArenaMessage(a, msg);
- lastcarrier[bid] = carrier[bid];
- }
- else
- {
- //Player passed to himself, cancel assist for previous guy
- lastcarrier[bid] = NULL;
- }
- }
- }
- carrier[bid] = p;
- //Already handled
- //stats->IncrementStat(p, STAT_BALL_CARRIES, 1);
- //stats->StartTimer(p, STAT_BALL_CARRY_TIME);
- return TRUE;
- }
- /* called when a player tries to fire a ball.
- * returning FALSE diallows the ball fire, causing the ball to be restuck to the player.
- * note that there will be no ball timer using this behavior.
- * returning TRUE changes the ball state to the data pointed to by newbd.
- * by default newbd is the state of the ball as if no advisers interfered (traveling on the map)
- * isForced specifies whether the client is firing the ball or the module is forcing a ball fire.
- */
- int AllowBallFire(Arena *a, Player *p, int bid, int isForced, struct BallData *newbd)
- {
- int i;
- invalidshot = FALSE;
- if (state == SOCKEY_TIMEOUT)
- {
- //Leave ball there
- newbd->xspeed = 0;
- newbd->yspeed = 0;
- carrier[bid] = NULL;
- lastcarrier[bid] = NULL;
- return TRUE;
- }
- if (state != SOCKEY_PLAYING)
- return TRUE;
- //Do not allow player to fire ball from enemy crease
- for (i = 0; i < N_TEAMS; i++)
- if (i != p->p_freq)
- if (coordincrease(a, newbd->x, newbd->y, i))
- {
- //This shot cannot result in a goal
- invalidshot = TRUE;
- if (newbd->xspeed == 0 && newbd->yspeed == 0)
- {
- //chat->SendArenaMessage(a, "%s died with the ball in team %i crease", p->name, i);
- }
- else
- {
- //Penalize player
- givepenalty(p, INFRACTION_OFF_CR);
- //chat->SendArenaMessage(a, "%s attempted to fire ball in team %i crease", p->name, i);
- }
- //Leave ball there
- newbd->xspeed = 0;
- newbd->yspeed = 0;
- //Don't leave it in the goal!
- if (mapdata->GetTile(a, newbd->x / TILE_WIDTH, newbd->y / TILE_HEIGHT) == TILE_GOAL)
- {
- char regnname[32] = "CenterCrease";
- addindex(regnname, i);
- Region *rgn = mapdata->FindRegionByName(a, regnname);
- if (rgn)
- {
- int x,y;
- mapdata->FindRandomPoint(rgn, &x, &y);
- if (x >= 0 && y >= 0)
- {
- newbd->x = x * TILE_WIDTH + TILE_WIDTH / 2;
- newbd->y = y * TILE_HEIGHT + TILE_HEIGHT / 2;
- }
- }
- }
- carrier[bid] = NULL;
- lastcarrier[bid] = NULL;
- return TRUE;
- }
- carrier[bid] = p;
- lastthrowtime[bid] = current_ticks();
- return TRUE;
- }
- /* called when a client attempts to score a goal.
- * returning TRUE disallows the ball goal. note that continuum will continue sending goal packets
- * several times in this case. the ball state may be changed by modifying newbd.
- * returning FALSE allows the ball to be scored.
- */
- int BlockBallGoal(Arena *a, Player *p, int bid, int x, int y, struct BallData *newbd)
- {
- if (state != SOCKEY_PLAYING || invalidshot == TRUE)
- return TRUE;
- if (!p || p->p_freq < 0 || p->p_freq >= N_TEAMS)
- return TRUE;
- //Do not allow a penalized player to score
- if (LLMember(&ll_penalties, p))
- return TRUE;
- //Block own goals...
- //Find team who got scored on
- char regnname[32] = "Crease";
- addindex(regnname, p->p_freq);
- Region * rgn = mapdata->FindRegionByName(a, regnname);
- if (rgn)
- if (mapdata->Contains(rgn, x, y))
- return TRUE;
- //Check if someone from the scoring team is in the crease
- return FALSE;
- }
- local Aballs adv_balls =
- {
- ADVISER_HEAD_INIT(A_BALLS)
- AllowBallPickup, AllowBallFire, BlockBallGoal
- };
- ////////////////////////////////////
- //
- //CALLBACKS
- //
- ////////////////////////////////////
- local void spawn(Player *p, int reason)
- {
- //char message[256];
- //snprintf(message,sizeof(message),"%s spawned for reason %i", p->name, reason);
- //chat->SendArenaMessage(p->arena, message);
- checkallcreases(p);
- switch(reason)
- {
- case SPAWN_AFTERDEATH:
- break;
- case SPAWN_SHIPRESET:
- break;
- case SPAWN_FLAGVICTORY:
- break;
- case SPAWN_SHIPCHANGE:
- break;
- case SPAWN_INITIAL:
- break;
- default:
- break;
- }
- }
- local void playeraction(Player *p, int action, Arena *arena)
- {
- switch(action)
- {
- case PA_ENTERARENA:
- break;
- case PA_LEAVEARENA:
- clearplayerrefs(p);
- break;
- default:
- break;
- }
- }
- //Player entered or left a region
- local void region(Player *p, Region *rgn, int x, int y, int entering)
- {
- int i;
- char regnname[32];
- char creasename[32];
- LinkedList * listtocheck;
- if (p->p_freq >= N_TEAMS ||
- p->p_ship == SHIP_SPEC ||
- state != SOCKEY_PLAYING)
- return;
- astrncpy(regnname, mapdata->RegionName(rgn), sizeof(regnname));
- //If a penalized player leaves PenaltyArea, warp him back
- if (!entering && !strcmp(regnname, "PenaltyArea"))
- if (LLMember(&ll_penalties, p))
- {
- color->ColorPSound(COLOR_RED, p, SOUND_GAMESUCKS, "You have to stay in the penalty box until your penalty is over!");
- //chat->SendSoundMessage(p, SOUND_GAMESUCKS, "You have to stay in the penalty box until your penalty is over!");
- warptopenalty(p);
- return;
- }
- /*
- snprintf(zonename, sizeof(zonename), "Zone%i", p->p_freq);
- if (!entering && !ballinplay[0] && !strcmp(regnname, zonename))
- {
- //Player is exiting his zone while ball is not in play
- t.type = T_PLAYER;
- t.u.p = p;
- chat->SendSoundMessage(p, SOUND_PHONE, "You have to stay in your zone for the faceoff until the ball respawns!");
- if (warpinregion(p->arena, &t, zonename))
- return;
- }
- */
- for (i = 0; i < N_TEAMS; i++)
- {
- snprintf(creasename, sizeof(creasename), "Crease%i", i);
- if (!strcmp(regnname, creasename))
- {
- if (i == p->p_freq)
- //Checking defensive crease
- listtocheck = &ll_indefcrease[i];
- else
- //Checking offensive crease
- listtocheck = &ll_inoffcrease[p->p_freq][i];
- if (entering)
- {
- if (i == p->p_freq)
- {
- //Manage goaltending time stat
- if (LLCount(listtocheck) == 0)
- stats->StartTimer(p, STAT_GOALIE_TIME);
- }
- //Add the player to the list if he is not in it already
- if (!LLMember(listtocheck, p))
- LLAdd(listtocheck, p);
- }
- else
- {
- if (i == p->p_freq)
- stats->StopTimer(p, STAT_GOALIE_TIME);
- //Remove the player from the list if he is in it
- LLRemove(listtocheck, p);
- }
- }
- }
- }
- /* called when a player picks up a ball */
- local void ballpickup(Arena *arena, Player *p, int bid)
- {
- /*
- char message[256];
- snprintf(message,sizeof(message),"%s picked up ball %i", p->name, bid);
- chat->SendArenaMessage(arena, message);
- */
- }
- /* called when a player fires a ball */
- local void ballfire(Arena *arena, Player *p, int bid)
- {
- }
- /* called when a player scores a goal */
- local void goal(Arena *arena, Player *p, int bid, int x, int y)
- {
- if (state != SOCKEY_PLAYING)
- return;
- int i;
- int scoredfreq = -1;
- int scoringfreq = p->p_freq;
- //If goal is allowed...
- int incorner;
- if (scoringfreq >= 0 && scoringfreq < N_TEAMS)
- score[scoringfreq]++;
- //Perfect corner shots
- Region * rgn = mapdata->FindRegionByName(arena, "GoalCorner");
- incorner = rgn && (mapdata->Contains(rgn, x, y));
- //Find team who got scored on
- char regnname[32];
- for (i = 0; i < N_TEAMS; i++)
- {
- snprintf(regnname, sizeof(regnname), "Crease%i", i);
- Region * rgn = mapdata->FindRegionByName(arena, regnname);
- if (rgn)
- {
- if (mapdata->Contains(rgn, x, y))
- {
- scoredfreq = i;
- break;
- }
- }
- else
- lm->LogA(L_ERROR, "sockey", arena, "Region Crease%i not found", i);
- }
- //Goal stat handled by default
- //stats->IncrementStat(p, STAT_BALL_GOALS, 1);
- if (lastcarrier[bid])
- stats->IncrementStat(lastcarrier[bid], STAT_BALL_ASSISTS, 1);
- showgoal(p, lastcarrier[bid], incorner);
- showscore(arena, TRUE);
- lastcarrier[bid] = NULL;
- carrier[bid] = NULL;
- warpaftergoal(arena, scoredfreq, scoringfreq, bid);
- //Check victory conditions
- sockey_config_t *ad = P_ARENA_DATA(arena, adkey);
- if (ad->maxgoals > 0)
- {
- if (score[scoringfreq] >= ad->maxgoals)
- {
- if (ad->winby > 0)
- {
- for (i = 0; i < N_TEAMS; i++)
- if (i != scoringfreq && score[scoringfreq] < score[i]+ad->winby)
- return; //cannot win yet
- endgame(arena); //Win!
- }
- else
- endgame(arena); //Win!
- }
- }
- //delayedballspawn(arena, bid, DELAY_BALLSPAWN);
- }
- void kill(Arena *arena, Player *killer, Player *killed, int bounty, int flags, int *pts, int *green)
- {
- if (state != SOCKEY_PLAYING)
- return;
- Link *link;
- Player*p;
- if (!killed || !killer)
- return;
- int killedteam = killed->p_freq;
- //Update all killed's team crease status
- pd->Lock();
- FOR_EACH_PLAYER_IN_ARENA(p, arena)
- {
- if (p->p_freq == killedteam)
- checkcrease(p, killedteam);
- }
- pd->Unlock();
- if (killed == getgoalie(killedteam))
- {
- Target t;
- t.type = T_PLAYER;
- t.u.p = killed;
- //killer just murdered a goalie... not good.
- game->ShipReset(&t);
- givepenalty(killer, INFRACTION_GOALIE_KILL);
- }
- /*
- for (i = 0; i < N_BALLS; i++)
- if (killed == carrier[i])
- {
- for (j = 0; j < N_TEAMS; j++)
- if (j != killed->p_freq)
- if (checkcrease(killed, j))
- {
- //The player was killed in the enemy crease while carrying the ball
- chat->SendArenaMessage(arena, "%s killed in crease with ball", killed->name);
- char regnname[32] = "Spawn";
- Target t;
- t.type = T_PLAYER;
- t.u.p = killed;
- addindex(regnname, killed->p_freq);
- warpinregion(arena, &t, regnname);
- }
- }
- */
- }
- void shipfreqchange(Player *p, int newship, int oldship, int newfreq, int oldfreq)
- {
- /*
- if (state != SOCKEY_PLAYING)
- return;
- */
- if (newship == SHIP_SPEC || newfreq != oldfreq)
- clearplayerrefs(p);
- if (newship != SHIP_SPEC)
- checkallcreases(p);
- }
- void playermove(Player *p, const struct C2SPosition *pos)
- {
- }
- local void arenaaction(Arena *arena, int action)
- {
- if (action == AA_CREATE || action == AA_CONFCHANGED)
- {
- lm->LogA(L_INFO, "sockey", arena, "Reloading settings");
- updatesettings(arena);
- }
- }
- local void timeout(Player* p, Arena* arena)
- {
- if (state == SOCKEY_PLAYING)
- {
- chat->SendArenaSoundMessage(arena, SOUND_DING, "Timeout called by %s", p->name);
- pausetime = current_ticks();
- state = SOCKEY_TIMEOUT;
- chat->SendCmdMessage(p, "Game paused. Type '?sockey timeout' again to resume the game.");
- }
- else if (state == SOCKEY_TIMEOUT)
- {
- pausedcumultime += TICK_DIFF(current_ticks(), pausetime);
- state = SOCKEY_PLAYING;
- chat->SendArenaSoundMessage(arena, SOUND_GOAL, "Game resumed!");
- showscore(arena, TRUE);
- }
- else
- chat->SendCmdMessage(p, "You cannot call a timeout at this time.");
- }
- ////////////////////////////////////
- //
- //COMMANDS
- //
- ////////////////////////////////////
- local helptext_t cmd_setscore=
- "Targets: none\n"
- "Args: <score0> <score1>\n"
- "Sets the score of the current game. Example: ?setscore 3 2\n";
- local void cSetscore(const char *command, const char *params, Player *p, const Target *target)
- {
- char split[64];
- const char *tmp = NULL;
- int i = 0;
- while (i < N_TEAMS && strsplit(params, " ,:-;", split, sizeof(split), &tmp))
- {
- score[i] = atoi(split);
- i++;
- }
- showscore(p->arena, TRUE);
- }
- local helptext_t cmd_sockey=
- "Targets: none\n"
- "Args: start | new, end | cancel, timeout\n"
- "Changes the state of the game.\n";
- local void cSockey(const char *command, const char *params, Player *p, const Target *target)
- {
- if (!stricmp(params, "reset"))
- resetgame(p->arena, TRUE, TRUE);
- else if (!stricmp(params, "start") || !stricmp(params, "new"))
- newgame(p->arena, 5);
- else if (!stricmp(params, "end") || !stricmp(params, "cancel"))
- endgame(p->arena);
- else if (!stricmp(params, "timeout") || !stricmp(params, "pause"))
- timeout(p, p->arena);
- else if (!stricmp(params, "resume") && state == SOCKEY_TIMEOUT)
- timeout(p, p->arena);
- }
- ////////////////////////////////////
- //
- //MODULE INIT
- //
- ////////////////////////////////////
- local void init(Arena *arena)
- {
- int i,j;
- invalidshot = FALSE;
- ok_Doormode = cs->GetOverrideKey("Door", "Doormode");
- for (i = 0; i < N_TEAMS; i++)
- {
- LLInit(&ll_indefcrease[i]);
- for (j = 0; j < N_TEAMS; j++)
- LLInit(&ll_inoffcrease[i][j]);
- }
- LLInit(&ll_penalties);
- ped_sockey = pd->AllocatePlayerData(sizeof(ped_sockey_t));
- state = SOCKEY_WAITING;
- resetgame(arena, FALSE, FALSE);
- }
- local void cleanup(Arena *arena)
- {
- int i,j;
- ml->ClearTimer(endpenalty, NULL);
- ml->ClearTimer(startgame, arena);
- ml->ClearTimer(endgame, arena);
- ml->ClearTimer(updatetime, arena);
- pd->FreePlayerData(ped_sockey);
- pd->Lock();
- for (i = 0; i < N_TEAMS; i++)
- {
- LLEmpty(&ll_indefcrease[i]);
- for (j = 0; j < N_TEAMS; j++)
- LLEmpty(&ll_inoffcrease[i][j]);
- }
- LLEmpty(&ll_penalties);
- pd->Unlock();
- }
- EXPORT int MM_sockey(int action, Imodman *mm_, Arena *arena)
- {
- if (action == MM_LOAD)
- {
- mm = mm_;
- lm = mm->GetInterface(I_LOGMAN, ALLARENAS);
- aman = mm->GetInterface(I_ARENAMAN, ALLARENAS);
- cfg = mm->GetInterface(I_CONFIG, ALLARENAS);
- chat = mm->GetInterface(I_CHAT, ALLARENAS);
- cmd = mm->GetInterface(I_CMDMAN, ALLARENAS);
- balls = mm->GetInterface(I_BALLS, ALLARENAS);
- color = mm->GetInterface(I_COLOR, ALLARENAS);
- pd = mm->GetInterface(I_PLAYERDATA,ALLARENAS);
- ml = mm->GetInterface(I_MAINLOOP,ALLARENAS);
- game = mm->GetInterface(I_GAME,ALLARENAS);
- objs = mm->GetInterface(I_OBJECTS,ALLARENAS);
- mapdata = mm->GetInterface(I_MAPDATA,ALLARENAS);
- cs = mm->GetInterface(I_CLIENTSET, ALLARENAS);
- stats = mm->GetInterface(I_STATS, ALLARENAS);
- persist = mm->GetInterface(I_PERSIST, ALLARENAS);
- hud = mm->GetInterface(I_LVZHUD, ALLARENAS);
- if (!lm || !chat || !cmd || !balls || !color || !pd
- || !ml || !game || !objs || !mapdata || !cs
- || !stats || !persist || !hud || !aman || !cfg)
- return MM_FAIL;
- adkey = aman->AllocateArenaData(sizeof(sockey_config_t));
- if (adkey == -1) return MM_FAIL;
- return MM_OK;
- }
- else if (action == MM_UNLOAD)
- {
- //Release interfaces
- mm->ReleaseInterface(hud);
- mm->ReleaseInterface(persist);
- mm->ReleaseInterface(stats);
- mm->ReleaseInterface(cs);
- mm->ReleaseInterface(mapdata);
- mm->ReleaseInterface(objs);
- mm->ReleaseInterface(game);
- mm->ReleaseInterface(ml);
- mm->ReleaseInterface(pd);
- mm->ReleaseInterface(color);
- mm->ReleaseInterface(balls);
- mm->ReleaseInterface(cmd);
- mm->ReleaseInterface(chat);
- mm->ReleaseInterface(cfg);
- mm->ReleaseInterface(aman);
- mm->ReleaseInterface(lm);
- aman->FreeArenaData(adkey);
- return MM_OK;
- }
- else if (action == MM_ATTACH)
- {
- //Register callbacks
- mm->RegCallback(CB_GOAL, goal, arena);
- mm->RegCallback(CB_BALLPICKUP, ballpickup, arena);
- mm->RegCallback(CB_BALLFIRE, ballfire, arena);
- mm->RegCallback(CB_REGION, region, arena);
- mm->RegCallback(CB_PLAYERACTION, playeraction, arena);
- mm->RegCallback(CB_SPAWN, spawn, arena);
- mm->RegCallback(CB_SHIPFREQCHANGE, shipfreqchange, arena);
- mm->RegCallback(CB_KILL, kill, arena);
- mm->RegCallback(CB_PPK, playermove, arena);
- mm->RegCallback(CB_ARENAACTION, arenaaction, arena);
- mm->RegAdviser(&adv_balls, arena);
- //Add commands
- cmd->AddCommand("sockey", cSockey, arena, cmd_sockey);
- cmd->AddCommand("setscore", cSetscore, arena, cmd_setscore);
- lm->LogA(L_DRIVEL, "sockey", arena, "Starting init");
- init(arena);
- return MM_OK;
- }
- else if (action == MM_DETACH)
- {
- cleanup(arena);
- cmd->RemoveCommand("sockey", cSockey, arena);
- cmd->RemoveCommand("setscore", cSetscore, arena);
- //Unregister callbacks
- mm->UnregAdviser(&adv_balls, arena);
- mm->UnregCallback(CB_ARENAACTION, arenaaction, arena);
- mm->UnregCallback(CB_PPK, playermove, arena);
- mm->UnregCallback(CB_KILL, kill, arena);
- mm->UnregCallback(CB_SHIPFREQCHANGE, shipfreqchange, arena);
- mm->UnregCallback(CB_SPAWN, spawn, arena);
- mm->UnregCallback(CB_PLAYERACTION, playeraction, arena);
- mm->UnregCallback(CB_REGION, region, arena);
- mm->UnregCallback(CB_BALLFIRE, ballfire, arena);
- mm->UnregCallback(CB_BALLPICKUP, ballpickup, arena);
- mm->UnregCallback(CB_GOAL, goal, arena);
- return MM_OK;
- }
- return MM_OK;
- }
- /*
- typedef struct
- {
- Arena * arena;
- int bid;
- } respawnball_params_t;
- local void respawnball_cleanup(void *param)
- {
- if (param)
- afree(param);
- }
- local int respawnball(void *param)
- {
- respawnball_params_t * myparam = (respawnball_params_t*)param;
- if (myparam)
- {
- ballinplay[myparam->bid] = TRUE;
- //balls->SpawnBall(myparam->arena, myparam->bid);
- afree(param);
- }
- return FALSE;
- }
- local void delayedballspawn(Arena* arena, int bid, int delay)
- {
- //Phase the ball, and have it respawn in a few seconds
- struct BallData newpos;
- newpos.x = 1;
- newpos.y = 1;
- newpos.xspeed = 0;
- newpos.yspeed = 0;
- newpos.carrier = NULL;
- newpos.freq = 0;
- newpos.last_update = current_ticks();
- newpos.state = BALL_ONMAP;
- respawnball_params_t * myparams = amalloc(sizeof(respawnball_params_t));
- if (myparams)
- {
- myparams->arena = arena;
- myparams->bid = bid;
- ml->SetTimer(respawnball, delay, 0, (void*)myparams, NULL);
- //balls->PlaceBall(arena, 0, &newpos);
- }
- }
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement