Advertisement
Guest User

Untitled

a guest
Feb 20th, 2011
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 40.99 KB | None | 0 0
  1. #include "asss.h"
  2. #include "clientset.h"
  3.  
  4. #include "statcodes.h"
  5. #include "stats.h"
  6. #include "persist.h"
  7.  
  8. #include "lvzhud.h"
  9. #include "colors.h"
  10.  
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14.  
  15. #define N_TEAMS 2
  16. #define N_BALLS 1
  17.  
  18. #define TILE_WIDTH 16
  19. #define TILE_HEIGHT 16
  20.  
  21.  
  22. #define DELAY_BALLSPAWN 400
  23.  
  24.  
  25.  
  26. //Time before a ball becomes neutral after being fired
  27. #define DELAY_BALLNEUT 500
  28.  
  29. #define DEFAULT_WARP_X 512
  30. #define DEFAULT_WARP_Y 490
  31.  
  32.  
  33. #define INFRACTION_DEF_CR "illegal goaltending"
  34. #define INFRACTION_OFF_CR "creasing"
  35. #define INFRACTION_GOALIE_KILL "goalie interference"
  36.  
  37. ////////////////////////////////////
  38. //
  39. //INTERFACES
  40. //
  41. ////////////////////////////////////
  42.  
  43. local Imodman *mm;
  44. local Ilogman *lm;
  45. local Icmdman *cmd;
  46. local Ichat *chat;
  47. local Iballs *balls;
  48. local Icolor *color;
  49. local Iplayerdata *pd;
  50. local Imainloop *ml;
  51. local Igame *game;
  52. local Iobjects *objs;
  53. local Imapdata *mapdata;
  54. local Iclientset *cs;
  55. local Istats *stats;
  56. local Ipersist *persist;
  57. local Iarenaman *aman;
  58. local Iconfig *cfg;
  59. local Ilvzhud *hud;
  60.  
  61. ////////////////////////////////////
  62. //
  63. //TYPEDEFS
  64. //
  65. ////////////////////////////////////
  66. typedef enum
  67. {
  68.     SOCKEY_WAITING,
  69.     SOCKEY_STARTING,
  70.     SOCKEY_PLAYING,
  71.     SOCKEY_TIMEOUT,
  72. } SockeyState;
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79. typedef struct
  80. {
  81.     int dummy;
  82. } ped_sockey_t;
  83.  
  84.  
  85. typedef struct
  86. {
  87.     int gametime;
  88.     int maxgoals;
  89.     int winby;
  90.  
  91.     int penalty_offcrease;
  92.     int penalty_defcrease;
  93.     int penalty_goalieinterference;
  94. } sockey_config_t;
  95.  
  96. ////////////////////////////////////
  97. //
  98. //GLOBAL DATA
  99. //
  100. ////////////////////////////////////
  101.  
  102.  
  103.  
  104. local override_key_t ok_Doormode;
  105.  
  106. //PlayerExtraData keys
  107. local int ped_sockey;
  108.  
  109. //ArenaData keys
  110. local int adkey;
  111.  
  112.  
  113. //
  114. local SockeyState state;
  115. local ticks_t   gamestarttime;
  116. local ticks_t   gametime;
  117. local ticks_t   pausedcumultime; //total time during which the game was paused
  118. local ticks_t   pausetime; //time at which the game was paused (timeout)
  119.  
  120. local int       gameistimed;
  121.  
  122. local Player*   carrier[N_BALLS];
  123. local Player*   lastcarrier[N_BALLS];
  124.  
  125. local ticks_t   lastthrowtime[N_BALLS];
  126. local int       invalidshot;
  127.  
  128. local int       score[N_TEAMS];
  129.  
  130. // ll_indefcrease[i] is a list of all the players of freq <i> who are in their own crease
  131. // The first of this list should be goalie, and all the others are considered to be creasing.
  132. LinkedList      ll_indefcrease[N_TEAMS];
  133.  
  134. // ll_inoffcrease[i][j] is a list of all the players of freq <i> who are in freq <j>'s crease.
  135. LinkedList      ll_inoffcrease[N_TEAMS][N_TEAMS];
  136.  
  137. LinkedList      ll_penalties;
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144. ////////////////////////////////////
  145. //
  146. //FUNCTIONS
  147. //
  148. ////////////////////////////////////
  149.  
  150.  
  151. local void SetDoors(Arena* arena, int doormode)
  152. {
  153.     Player *g;
  154.     Link *link;
  155.  
  156.     cs->ArenaOverride(arena, ok_Doormode, doormode);
  157.  
  158.  
  159.     pd->Lock();
  160.     FOR_EACH_PLAYER(g)
  161.     {
  162.         if (g->arena == arena)
  163.             cs->SendClientSettings(g);
  164.     }
  165.     pd->Unlock();
  166.  
  167. }
  168.  
  169.  
  170. local void getscorestr(char* str, int maxlen)
  171. {
  172.     if (N_TEAMS > 2)
  173.     {
  174.         StringBuffer sb;
  175.         int i;
  176.  
  177.         SBInit(&sb);
  178.  
  179.         for (i = 0; i < N_TEAMS; i++)
  180.             SBPrintf(&sb, " %3i", score[i]);
  181.  
  182.         snprintf(str, maxlen, "%s", sb.start);
  183.  
  184.         SBDestroy(&sb);
  185.     }
  186.     else if (N_TEAMS == 2)
  187.     {
  188.         snprintf(str, maxlen, " %3i - %i", score[0], score[1]);
  189.         //chat->SendArenaMessage(arena, "Score: %i  -  %i", score[0], score[1]);
  190.     }
  191. }
  192. local void showscore(Arena * arena, int inchat)
  193. {
  194.     char buf[256];
  195.     Target t;
  196.     t.type = T_ARENA;
  197.     t.u.arena = arena;
  198.  
  199.     if (inchat)
  200.     {
  201.         getscorestr(buf, sizeof(buf));
  202.  
  203.         //chat->SendArenaMessage(arena, sb.start);
  204.         color->ColorA(COLOR_PINK, arena, "Score: %s", buf);
  205.     }
  206.  
  207.     hud->SetValueNum(arena, "score0", &t, score[0]);
  208.     hud->SetValueNum(arena, "score1", &t, score[1]);
  209. }
  210.  
  211.  
  212.  
  213. local char* addindex(char * str, int index)
  214. {
  215.     char buf[8];
  216.  
  217.     snprintf(buf, sizeof(buf), "%i", index);
  218.  
  219.     strcat(str, buf);
  220.  
  221.     return str;
  222. }
  223.  
  224. local int playerisinregion(Player* p, const char* regnname)
  225. {
  226.     if (!p)
  227.         return FALSE;
  228.  
  229.     Region * rgn = mapdata->FindRegionByName(p->arena, regnname);
  230.  
  231.     if (rgn)
  232.         return mapdata->Contains(rgn, p->position.x / TILE_WIDTH, p->position.y / TILE_HEIGHT);
  233.  
  234.     return FALSE;
  235. }
  236.  
  237.  
  238. local int warpinregion(Arena* arena, Target* target, const char* regnname)
  239. {
  240.     int x,y;
  241.     Region * rgn = mapdata->FindRegionByName(arena, regnname);
  242.  
  243.     if (rgn)
  244.     {
  245.         mapdata->FindRandomPoint(rgn, &x, &y);
  246.  
  247.         if (x >= 0 && y >= 0)
  248.         {
  249.             game->WarpTo(target, x, y);
  250.             return TRUE;
  251.         }
  252.     }
  253.  
  254.     return FALSE;
  255. }
  256.  
  257.  
  258.  
  259.  
  260. local void endpenalty_cleanup(void *param)
  261. {
  262.     Player * p = (Player*)param;
  263.  
  264.     if (p)
  265.         LLRemove(&ll_penalties, p);
  266.  
  267.  
  268.     Target t;
  269.     t.type = T_PLAYER;
  270.     t.u.p = p;
  271.  
  272.     char regnname[32] = "PenaltyExit";
  273.     addindex(regnname, p->p_freq);
  274.  
  275.     if (warpinregion(p->arena, &t, regnname))
  276.     {
  277.         //Warp successful
  278.     }
  279.     else
  280.         game->WarpTo(&t, DEFAULT_WARP_X, DEFAULT_WARP_Y);
  281.  
  282. }
  283.  
  284. local int updatetime(void *param)
  285. {
  286.     static int lastvalue = -1;
  287.  
  288.     ticks_t curtime;
  289.     Target t;
  290.     t.type = T_ARENA;
  291.     t.u.arena = (Arena*)param;
  292.  
  293.     int value = 0;
  294.  
  295.     if (state == SOCKEY_PLAYING)
  296.     {
  297.  
  298.         if (gameistimed)
  299.             //Show remaining time
  300.             curtime = TICK_DIFF(gametime, TICK_DIFF(TICK_DIFF(current_ticks(), gamestarttime), pausedcumultime));
  301.         else
  302.             //Show elapsed time
  303.             curtime = TICK_DIFF(TICK_DIFF(current_ticks(), gamestarttime), pausedcumultime);
  304.  
  305.         value = (curtime / 100)%60 + 100*(curtime / 6000);
  306.  
  307.     }
  308.     else if (state == SOCKEY_TIMEOUT)
  309.     {
  310.         if (gameistimed)
  311.             //Show remaining time
  312.             curtime = TICK_DIFF(gametime, TICK_DIFF(pausetime, gamestarttime));
  313.         else
  314.             //Show elapsed time
  315.             curtime = TICK_DIFF(pausetime, gamestarttime);
  316.         curtime = TICK_DIFF(curtime, pausedcumultime);
  317.  
  318.         value = (curtime / 100)%60 + 100*(curtime / 6000);
  319.     }
  320.     else if (state == SOCKEY_STARTING)
  321.     {
  322.         if (gameistimed)
  323.             value = (gametime / 100)%60 + 100*(gametime / 6000);
  324.         else
  325.             value = 0;
  326.     }
  327.  
  328.     if (value != lastvalue)
  329.     {
  330.         hud->SetValueNum((Arena*)param, "time", &t, value);
  331.         lastvalue = value;
  332.     }
  333.  
  334.     return 1;
  335. }
  336.  
  337. local int endpenalty(void *param)
  338. {
  339.     endpenalty_cleanup(param);
  340.  
  341.     return FALSE;
  342. }
  343.  
  344. local void warptopenalty(Player *p)
  345. {
  346.     Target t;
  347.     t.type = T_PLAYER;
  348.     t.u.p = p;
  349.  
  350.     char regnname[32] = "Penalty";
  351.     addindex(regnname, p->p_freq);
  352.  
  353.     if (warpinregion(p->arena, &t, regnname))
  354.     {
  355.         //Warp successful
  356.     }
  357.  
  358. }
  359.  
  360. local void givepenalty(Player *p, const char* infraction)
  361. {
  362.     int time = 0;
  363.     sockey_config_t *ad = P_ARENA_DATA(p->arena, adkey);
  364.  
  365.     if (!strcmp(infraction, INFRACTION_DEF_CR))
  366.         time = ad->penalty_defcrease;
  367.     else if (!strcmp(infraction, INFRACTION_OFF_CR))
  368.         time = ad->penalty_offcrease;
  369.     else if (!strcmp(infraction, INFRACTION_GOALIE_KILL))
  370.         time = ad->penalty_goalieinterference;
  371.     else
  372.         lm->LogA(L_ERROR, "sockey", p->arena, "Invalid penalty '%s' given to %s", infraction, p->name);
  373.  
  374.     if (time > 0)
  375.     {
  376.         LLAdd(&ll_penalties, p);
  377.  
  378.         ml->SetTimer(endpenalty, time*100, 0, p, p);
  379.  
  380.         stats->IncrementStat(p, STAT_PENALTY_TIME, time);
  381.  
  382.         warptopenalty(p);
  383.  
  384.         color->ColorASound(COLOR_PINK, p->arena, SOUND_SCREAM, "%i seconds penalty given to %s for %s", time, p->name, infraction);
  385.     }
  386. }
  387.  
  388. local int endgame(void* param);
  389. local int startgame(void *param);
  390. local void resetgame(Arena* arena, int warpplayers, int spawnballs);
  391.  
  392. local void updatesettings(Arena *arena)
  393. {
  394.     sockey_config_t *ad = P_ARENA_DATA(arena, adkey);
  395.  
  396.     ConfigHandle ch = arena->cfg;
  397.  
  398.     /* cfghelp: Sockey:GameTime, arena, int, def: 600
  399.      * The duration of a game (in seconds). No time limit if 0 or negative. */
  400.     ad->gametime                    = cfg->GetInt(ch, "Sockey", "GameTime", 600);
  401.  
  402.     /* cfghelp: Sockey:GoalsToWin, arena, int, def: -1
  403.      * Goals needed to win the game. Game ends at time limit only if 0 or negative. */
  404.     ad->maxgoals                    = cfg->GetInt(ch, "Sockey", "GoalsToWin", -1);
  405.  
  406.     /* cfghelp: Sockey:WinBy, arena, int, def: 0
  407.      * Minimum goal difference needed to win. */
  408.     ad->winby                       = cfg->GetInt(ch, "Sockey", "WinBy", 0);
  409.  
  410.     /* cfghelp: Sockey:PenaltyOffCrease, arena, int, def: 10
  411.      * Penalty time for shooting from the offensive crease (in seconds). */
  412.     ad->penalty_offcrease           = cfg->GetInt(ch, "Sockey", "PenaltyOffCrease", 10);
  413.  
  414.     /* cfghelp: Sockey:PenaltyDefCrease, arena, int, def: 10
  415.      * Penalty time for defensive creasing (in seconds). */
  416.     ad->penalty_defcrease           = cfg->GetInt(ch, "Sockey", "PenaltyDefCrease", 10);
  417.  
  418.     /* cfghelp: Sockey:PenaltyGoalieKill, arena, int, def: 10
  419.      * Penalty time for goalie interference (in seconds). */
  420.     ad->penalty_goalieinterference  = cfg->GetInt(ch, "Sockey", "PenaltyGoalieKill", 10);
  421. }
  422.  
  423.  
  424. local void cancelgame(Arena* a)
  425. {
  426.     lm->LogA(L_INFO, "sockey", a, "Game cancelled");
  427.  
  428.     ml->ClearTimer(startgame, a);
  429.     ml->ClearTimer(endgame, a);
  430.     ml->ClearTimer(updatetime, a);
  431.  
  432.     state = SOCKEY_WAITING;
  433.  
  434.     balls->EndGame(a);
  435.  
  436.     SetDoors(a, 0);
  437.  
  438.     chat->SendArenaSoundMessage(a, SOUND_DING, "Game cancelled");
  439.  
  440.  
  441. }
  442.  
  443.  
  444. local void showstats(Arena* arena)
  445. {
  446.     Link *link;
  447.     Player *p;
  448.     int i;
  449.  
  450.     stats->SendUpdates(NULL);
  451.  
  452.  
  453.     for (i = 0; i < N_TEAMS; i++)
  454.     {
  455.         chat->SendArenaMessage(arena," ________");
  456.         chat->SendArenaMessage(arena,"| Team %d |", i);
  457.         chat->SendArenaMessage(arena,"|------------------------------------------------------------------------------|");
  458.         chat->SendArenaMessage(arena,"| Player                   G    A    Sh   Sa   TO   St   K    D    GT    Pen   |");
  459.         chat->SendArenaMessage(arena,"|------------------------------------------------------------------------------|");
  460.  
  461.         pd->Lock();
  462.  
  463.         FOR_EACH_PLAYER(p)
  464.         {
  465.             stats->StopTimer(p, STAT_GOALIE_TIME);
  466.  
  467.             /* Only list players who've played. */
  468.             if (p->p_freq == i && p->p_ship != SHIP_SPEC && p->arena == arena)
  469.             {
  470.                 chat->SendArenaMessage(arena,"| %-24s %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %02d:%02d %02d:%02d |",
  471.                       p->name,
  472.                       stats->GetStat(p, STAT_BALL_GOALS, INTERVAL_GAME),
  473.                       stats->GetStat(p, STAT_BALL_ASSISTS, INTERVAL_GAME),
  474.                       stats->GetStat(p, STAT_BALL_SHOTS, INTERVAL_GAME),
  475.                       stats->GetStat(p, STAT_BALL_SAVES, INTERVAL_GAME),
  476.                       stats->GetStat(p, STAT_BALL_TURNOVERS, INTERVAL_GAME),
  477.                       stats->GetStat(p, STAT_BALL_STEALS, INTERVAL_GAME),
  478.                       stats->GetStat(p, STAT_KILLS, INTERVAL_GAME),
  479.                       stats->GetStat(p, STAT_DEATHS, INTERVAL_GAME),
  480.                       stats->GetStat(p, STAT_GOALIE_TIME, INTERVAL_GAME) / 60,
  481.                       stats->GetStat(p, STAT_GOALIE_TIME, INTERVAL_GAME) % 60,
  482.                       stats->GetStat(p, STAT_PENALTY_TIME, INTERVAL_GAME) / 60,
  483.                       stats->GetStat(p, STAT_PENALTY_TIME, INTERVAL_GAME) % 60);
  484.             }
  485.  
  486.         }
  487.  
  488.         pd->Unlock();
  489.  
  490.         chat->SendArenaMessage(arena,"|------------------------------------------------------------------------------|");
  491.     }
  492. }
  493.  
  494.  
  495. local int endgame(void* param)
  496. {
  497.     Arena* arena = (Arena*)param;
  498.     int winfreq = 0;
  499.     int i;
  500.  
  501.     lm->LogA(L_INFO, "sockey", arena, "Game ending");
  502.  
  503.  
  504.     if (!arena || state == SOCKEY_WAITING)
  505.         return FALSE;
  506.  
  507.     if (state == SOCKEY_STARTING)
  508.     {
  509.         cancelgame(arena);
  510.         return FALSE;
  511.     }
  512.  
  513.  
  514.     //Find winning freq
  515.     if (N_TEAMS == 2)
  516.     {
  517.         if (score[0] == score[1])
  518.         {
  519.             //Tie!
  520.             winfreq = -1;
  521.         }
  522.         else
  523.             winfreq = (score[0] > score[1] ? 0:1 );
  524.  
  525.     }
  526.     else
  527.     {
  528.         int highestscore = -1;
  529.         for (i = 0; i < N_TEAMS; i++)
  530.             if (score[i] > highestscore)
  531.             {
  532.                 winfreq = i;
  533.                 highestscore = score[i];
  534.             }
  535.             else if (score[i] == highestscore)
  536.             {
  537.                 //Multi-team tie?!
  538.                 winfreq = -1;
  539.             }
  540.     }
  541.  
  542.     Link *link;
  543.     Player *p;
  544.  
  545.     pd->Lock();
  546.     FOR_EACH_PLAYER(p)
  547.         if (p->status == S_PLAYING &&
  548.             p->arena == arena &&
  549.             p->p_ship != SHIP_SPEC)
  550.         {
  551.             if (p->p_freq == winfreq)
  552.                 stats->IncrementStat(p, STAT_BALL_GAMES_WON, 1);
  553.             else
  554.                 stats->IncrementStat(p, STAT_BALL_GAMES_LOST, 1);
  555.         }
  556.  
  557.     pd->Unlock();
  558.  
  559.     char buf[256];
  560.     getscorestr(buf, sizeof(buf));
  561.  
  562.     if (winfreq >= 0)
  563.         color->ColorASound(COLOR_GREEN, arena, SOUND_HALLELLULA, "Game over! Team %i won   Final score: %s", winfreq, buf);
  564.     else
  565.         color->ColorASound(COLOR_GREEN, arena, SOUND_GAMESUCKS, "Game over! It's a TIE!!!  Final score: %s", buf);
  566.  
  567.     state = SOCKEY_WAITING;
  568.  
  569.  
  570.     persist->EndInterval("", arena, INTERVAL_GAME);
  571.  
  572.  
  573.     showstats(arena);
  574.  
  575.  
  576.     balls->EndGame(arena);
  577.  
  578.     resetgame(arena, FALSE, FALSE);
  579.  
  580.     return FALSE;
  581. }
  582.  
  583.  
  584. local int startgame(void *param)
  585. {
  586.     Arena* arena = (Arena*)param;
  587.     int i;
  588.     Link * link;
  589.     Player * p;
  590.  
  591.     Target t;
  592.     t.type = T_ARENA;
  593.     t.u.arena = arena;
  594.  
  595.  
  596.  
  597.     lm->LogA(L_INFO, "sockey", arena, "Starting new game");
  598.  
  599.     gamestarttime = current_ticks();
  600.     pausedcumultime = 0;
  601.     state = SOCKEY_PLAYING;
  602.  
  603.     SetDoors(arena, 0);
  604.     chat->SendArenaSoundMessage(arena, SOUND_GOAL, "Go!");
  605.  
  606.     for (i = 0; i < N_BALLS; i++)
  607.         balls->SpawnBall(arena, i);
  608.  
  609.  
  610.     pd->Lock();
  611.     FOR_EACH_PLAYER_IN_ARENA(p,arena)
  612.         stats->ScoreReset(p, INTERVAL_GAME);
  613.     pd->Unlock();
  614.  
  615.     if (gameistimed)
  616.         ml->SetTimer(endgame, gametime, 0, arena, arena);
  617.  
  618.     ml->SetTimer(updatetime, 0, 5, arena, arena);
  619.     objs->Toggle(&t, 10, 1);
  620.  
  621.     showscore(arena, FALSE);
  622.  
  623.     return FALSE;
  624. }
  625.  
  626. local void newgame(Arena *a, int delaysecs)
  627. {
  628.     lm->LogA(L_INFO, "sockey", a, "New game starting in %i seconds", delaysecs);
  629.  
  630.     chat->SendArenaSoundMessage(a, SOUND_PHONE, "GET READY! Game starting in %i seconds...", delaysecs);
  631.  
  632.     Target t;
  633.     t.type = T_ARENA;
  634.     t.u.arena = a;
  635.  
  636.     SetDoors(a, 255);
  637.     game->GivePrize(&t, PRIZE_WARP, 1);
  638.  
  639.     state = SOCKEY_STARTING;
  640.  
  641.     ml->SetTimer(startgame, delaysecs*100, 0, a, a);
  642.  
  643.  
  644.     updatesettings(a);
  645.  
  646.     sockey_config_t *ad = P_ARENA_DATA(a, adkey);
  647.     gameistimed = (ad->gametime > 0);
  648.     gametime = ad->gametime * 100;
  649.  
  650.     objs->Toggle(&t, 10, 0);
  651.     updatetime((void*)a);
  652.  
  653.     showscore(a, FALSE);
  654. }
  655.  
  656.  
  657.  
  658. local void resetgame(Arena* arena, int warpplayers, int spawnballs)
  659. {
  660.     Target t;
  661.     t.type = T_ARENA;
  662.     t.u.arena = arena;
  663.     objs->Toggle(&t, 10, 0);
  664.  
  665.     lm->LogA(L_INFO, "sockey", arena, "Reseting game");
  666.  
  667.     ml->CleanupTimer(endpenalty, NULL, endpenalty_cleanup);
  668.  
  669.     int i,j;
  670.  
  671.  
  672.     lm->LogA(L_DRIVEL, "sockey", arena, "Emptying lists");
  673.     for (i = 0; i < N_TEAMS; i++)
  674.     {
  675.         score[i] = 0;
  676.  
  677.         LLEmpty(&ll_indefcrease[i]);
  678.  
  679.         for (j = 0; j < N_TEAMS; j++)
  680.         {
  681.             LLEmpty(&ll_inoffcrease[i][j]);
  682.         }
  683.     }
  684.     LLEmpty(&ll_penalties);
  685.  
  686.     lm->LogA(L_DRIVEL, "sockey", arena, "Initializing balls");
  687.     for (i = 0; i < N_BALLS; i++)
  688.     {
  689.         carrier[i] = NULL;
  690.         lastcarrier[i] = NULL;
  691.         lastthrowtime[i] = current_ticks();
  692.  
  693.         if (spawnballs)
  694.         {
  695.             lm->LogA(L_DRIVEL, "sockey", arena, "Spawning ball %i", i);
  696.             balls->SpawnBall(arena, i);
  697.         }
  698.     }
  699.  
  700.  
  701.     //chat->SendArenaMessage(arena, "Sockey game reset");
  702.  
  703.     updatesettings(arena);
  704.  
  705.     sockey_config_t *ad = P_ARENA_DATA(arena, adkey);
  706.     gametime = ad->gametime *100; //100 ticks/s
  707.  
  708.     if (state == SOCKEY_PLAYING || state == SOCKEY_STARTING || state == SOCKEY_TIMEOUT)
  709.         cancelgame(arena);
  710.  
  711.  
  712.  
  713.     ml->ClearTimer(updatetime, arena);
  714.     updatetime((void*)arena);
  715. }
  716.  
  717.  
  718.  
  719.  
  720. /*
  721.  * Checks if the (x,y) coordinate (in pixels) is in <creaseteam>'s crease
  722.  */
  723. local int coordincrease(Arena* a, int x, int y, int creaseteam)
  724. {
  725.     Region * rgn;
  726.     char     regionname[32];
  727.  
  728.     snprintf(regionname, sizeof(regionname), "crease%i", creaseteam);
  729.  
  730.     rgn = mapdata->FindRegionByName(a, regionname);
  731.  
  732.     if (!rgn)
  733.         return FALSE;
  734.  
  735.     return mapdata->Contains(rgn, x / TILE_WIDTH, y / TILE_HEIGHT);
  736.  
  737. }
  738.  
  739. /*
  740.  * Checks if player <p> is in <creaseteam>'s crease
  741.  * Updates the corresponding linked list
  742.  */
  743. local int checkcrease(Player* p, int creaseteam)
  744. {
  745.     int     playerteam = p->p_freq;
  746.     int     isinregion;
  747.  
  748.     LinkedList * listtocheck = NULL;
  749.  
  750.     if ((playerteam >= N_TEAMS) || (p->p_ship == SHIP_SPEC))
  751.         return FALSE;
  752.  
  753.     isinregion = coordincrease(p->arena, p->position.x, p->position.y, creaseteam);
  754.  
  755.  
  756.     if (creaseteam == playerteam)
  757.         //Checking defensive crease
  758.         listtocheck = &ll_indefcrease[creaseteam];
  759.     else
  760.         //Checking offensive crease
  761.         listtocheck = &ll_inoffcrease[playerteam][creaseteam];
  762.  
  763.  
  764.     if (isinregion)
  765.     {
  766.         if (creaseteam == playerteam)
  767.         {
  768.             //Manage goaltending time stat
  769.             if (LLCount(listtocheck) == 0)
  770.                 stats->StartTimer(p, STAT_GOALIE_TIME);
  771.         }
  772.  
  773.         //Add the player to the list if he is not in it already
  774.         if (!LLMember(listtocheck, p))
  775.             LLAdd(listtocheck, p);
  776.     }
  777.     else
  778.     {
  779.  
  780.  
  781.         if (creaseteam == playerteam)
  782.             stats->StopTimer(p, STAT_GOALIE_TIME);
  783.  
  784.  
  785.         //Remove the player from the list if he is in it
  786.         LLRemove(listtocheck, p);
  787.     }
  788.  
  789.  
  790.     return isinregion;
  791. }
  792.  
  793.  
  794.  
  795. /*
  796.  *
  797.  */
  798. local void clearplayerrefs(Player *p)
  799. {
  800.     int i,j;
  801.  
  802.     pd->Lock();
  803.     for (i = 0; i < N_TEAMS; i++)
  804.     {
  805.         LLRemove(&ll_indefcrease[i], p);
  806.         for (j = 0; j < N_TEAMS; j++)
  807.             LLRemove(&ll_inoffcrease[i][j], p);
  808.     }
  809.     for (i = 0; i < N_BALLS; i++)
  810.     {
  811.         if (carrier[i] == p)
  812.             carrier[i] = NULL;
  813.  
  814.         if (lastcarrier[i] == p)
  815.             lastcarrier[i] = NULL;
  816.     }
  817.  
  818.     LLRemove(&ll_penalties, p);
  819.     pd->Unlock();
  820.  
  821.     ml->ClearTimer(endpenalty, p);
  822. }
  823.  
  824. /*
  825.  * Update the status of player <p> for all creases
  826.  */
  827. local void checkallcreases(Player *p)
  828. {
  829.     int i;
  830.  
  831.     if ((p->p_freq >= N_TEAMS) || (p->p_ship == SHIP_SPEC))
  832.     {
  833.         lm->LogA(L_WARN, "sockey", p->arena, "Called checkallcreases for invalid player (ship %i, freq %i)", p->p_ship, p->p_freq);
  834.         clearplayerrefs(p);
  835.  
  836.     }
  837.     else
  838.         for (i = 0; i < N_TEAMS; i++)
  839.             checkcrease(p, i);
  840. }
  841.  
  842.  
  843. local Player* getgoalie(int team)
  844. {
  845.     if (team >= 0 && team < N_TEAMS)
  846.         if (LLCount(&ll_indefcrease[team]) > 0)
  847.             return ((Player*)LLGetHead(&ll_indefcrease[team])->data);
  848.  
  849.     return NULL;
  850. }
  851.  
  852.  
  853.  
  854. local void showgoal(Player* scorer, Player* assist, int incorner)
  855. {
  856.     char sound = (incorner ? SOUND_INCONCEIVABLE : SOUND_GOAL);
  857.  
  858.     if (assist)
  859.         color->ColorASound(COLOR_GREY, scorer->arena, sound, "%sGoal by %s! Assisted by %s", incorner?"Top corner!!! ":"", scorer->name, assist->name);
  860.     else
  861.         color->ColorASound(COLOR_GREY, scorer->arena, sound, "%sGoal by %s!", incorner?"Top corner!!! ":"", scorer->name);
  862.  
  863. }
  864.  
  865. local void warpaftergoal(Arena* arena, int scoredteam, int scoringteam, int bid)
  866. {
  867.     int i;
  868.     char regnname[32];
  869.     Link * link;
  870.     Player * p;
  871.     Target t;
  872.     t.type = T_PLAYER;
  873.  
  874.     for (i = 0; i< N_TEAMS; i++)
  875.     {
  876.         pd->Lock();
  877.  
  878.         FOR_EACH_PLAYER_IN_ARENA(p, arena)
  879.         {
  880.             if (p->p_freq >= 0 && p->p_freq < N_TEAMS)
  881.             {
  882.                 if (!LLMember(&ll_penalties, p))
  883.                 {
  884.                     snprintf(regnname, sizeof(regnname), "Zone%i", p->p_freq);
  885.                     if (!playerisinregion(p, regnname))
  886.                     {
  887.                         t.u.p = p;
  888.                         snprintf(regnname, sizeof(regnname), "Faceoff%i", p->p_freq);
  889.                         warpinregion(arena, &t, regnname);
  890.                     }
  891.                 }
  892.             }
  893.         }
  894.  
  895.         pd->Unlock();
  896.  
  897.     }
  898.  
  899.  
  900.     //Give ball to scored team
  901.     snprintf(regnname, sizeof(regnname), "CenterCrease%i", scoredteam);
  902.  
  903.     lm->LogA(L_DRIVEL, "sockey", arena, "Giving ball to freq %i", scoredteam);
  904.  
  905.     Region *rgn = mapdata->FindRegionByName(arena, regnname);
  906.     if (rgn)
  907.     {
  908.         int x,y;
  909.         mapdata->FindRandomPoint(rgn, &x, &y);
  910.         if (x >= 0 && y >= 0)
  911.         {
  912.             struct BallData newbd;
  913.  
  914.             newbd.x = x * TILE_WIDTH + TILE_WIDTH / 2;
  915.             newbd.y = y * TILE_HEIGHT + TILE_HEIGHT / 2;
  916.  
  917.             newbd.carrier = NULL;
  918.             newbd.freq = scoredteam;
  919.             newbd.last_update = current_ticks();
  920.             newbd.time = current_ticks();
  921.             newbd.xspeed = 0;
  922.             newbd.yspeed = 0;
  923.             newbd.state = BALL_ONMAP;
  924.  
  925.             lm->LogA(L_DRIVEL, "sockey", arena, "Placing ball at %i %i", newbd.x, newbd.y);
  926.  
  927.             balls->PlaceBall(arena, bid, &newbd);
  928.         }
  929.  
  930.  
  931.  
  932.     }
  933. }
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940. ////////////////////////////////////
  941. //
  942. //ADVISORS
  943. //
  944. ////////////////////////////////////
  945.  
  946.  
  947.  
  948. /* called on a pickup request.
  949.  * returning FALSE disallows the ballpickup entirely.
  950.  * returning TRUE changes the ball state to the data pointed to by newbd.
  951.  * by default newbd is the usual state of the player carrying the ball, but other advisers might change this.
  952.  */
  953. int AllowBallPickup(Arena *a, Player *p, int bid, struct BallData *newbd)
  954. {
  955.     int i;
  956.     Link   *link;
  957.     Player *pp;
  958.  
  959.     if (state == SOCKEY_TIMEOUT)
  960.         return FALSE;
  961.  
  962.     if (state != SOCKEY_PLAYING)
  963.         return TRUE;
  964.  
  965.     int playerteam = p->p_freq;
  966.  
  967.     //Do not allow players outside the game to touch the ball
  968.     if (playerteam < 0 || playerteam >= N_TEAMS)
  969.         return FALSE;
  970.  
  971.  
  972.     //Do not allow players in penalty to pick up the ball
  973.     if (LLMember(&ll_penalties, p))
  974.         return FALSE;
  975.  
  976.     //Do not allow player to pick up ball from enemy crease if there is at least one enemy in it
  977.     //Unless it's a pass; otherwise the player could intentionaly make a teammate's shot phase
  978.     //and get in the goal
  979.     if (!carrier[bid] || (carrier[bid] && carrier[bid]->p_freq != p->p_freq))
  980.     {
  981.         for (i = 0; i < N_TEAMS; i++)
  982.             if (i != playerteam)
  983.  
  984.                 //if (checkcrease(p, i) || coordincrease(a, curballx, curbally, i))
  985.                 //Apparently the current ball position is always the same as the player's position... We can't check
  986.                 //for a player grabbing the ball in the crease, while the player is just outside of it
  987.                 if (checkcrease(p, i))
  988.                 {
  989.                     if (getgoalie(i))
  990.                     {
  991.  
  992.                         //chat->SendArenaMessage(a, "%s attempted to pick up ball in team %i crease", p->name, i);
  993.  
  994.                         return FALSE;
  995.                     }
  996.                 }
  997.     }
  998.     //Do not allow non-goalie player in defensive crease to pick up ball
  999.     //Ball belonged to someone else before...
  1000.     if (checkcrease(p, p->p_freq))
  1001.     {
  1002.         //Check if he's alone in his crease (check crease status of his entire team)
  1003.         pd->Lock();
  1004.         FOR_EACH_PLAYER_IN_ARENA(pp, a)
  1005.         {
  1006.             if (pp->p_freq == playerteam && pp != p && checkcrease(pp, pp->p_freq))
  1007.             {
  1008.                 //Don't bother if the other team is not in control
  1009.                 if (carrier[bid] && carrier[bid]->p_freq != playerteam)
  1010.                 {
  1011.                     //We have a defensive creasing
  1012.                     Player *penalized, *designatedgoalie;
  1013.  
  1014.                     if (p == getgoalie(p->p_freq))
  1015.                     {
  1016.                         penalized = pp;
  1017.                         designatedgoalie = p;
  1018.                     }
  1019.                     else
  1020.                     {
  1021.                         penalized = p;
  1022.                         designatedgoalie = pp;
  1023.                     }
  1024.  
  1025.                     givepenalty(penalized, INFRACTION_DEF_CR);
  1026.  
  1027.                     color->ColorFSound(COLOR_RED, a, p->p_freq, SOUND_LISTEN, "Only ONE goalie at a time is allowed in your own crease!");
  1028.                     lm->LogA(L_DRIVEL, "sockey", a, "Defensive crease for team %i: <%s> and %s", p->p_freq, penalized->name, designatedgoalie->name);
  1029.  
  1030.                     //chat->SendArenaMessage(a, "Defensive creasing! %s and %s", p->name, pp->name);
  1031.  
  1032.                     /*
  1033.                     currentballs = balls->GetBallData(a);
  1034.  
  1035.                     currentballs->balls[bid].carrier = NULL;
  1036.                     currentballs->balls[bid].xspeed = 0;
  1037.                     currentballs->balls[bid].yspeed = 0;
  1038.  
  1039.                     balls->ReleaseBallData(a);
  1040.                     */
  1041.  
  1042.                     //Let the ball go through!!!
  1043.                     return FALSE;
  1044.                 }
  1045.             }
  1046.         }
  1047.         pd->Unlock();
  1048.  
  1049.     }
  1050.  
  1051.     //Catch / Pick-up is allowed
  1052.  
  1053.     if (carrier[bid])
  1054.     {
  1055.         //Ball belonged to someone else before...
  1056.         if (carrier[bid]->p_freq != playerteam)
  1057.         {
  1058.             if (current_ticks() - lastthrowtime[bid] < DELAY_BALLNEUT)
  1059.             {
  1060.                 //If p is goalie, it's a save
  1061.                 if (getgoalie(playerteam) == p)
  1062.                 {
  1063.                     //Save
  1064.                     color->ColorASound(COLOR_GREY, a, SOUND_GEE, "Saved by %s!", p->name);
  1065.                     //chat->SendArenaMessage(a, "Saved by %s", p->name);
  1066.                     stats->IncrementStat(p, STAT_BALL_SAVES, 1);
  1067.  
  1068.                     //Shot on goal for carrier[bid]
  1069.                     stats->IncrementStat(p, STAT_BALL_SHOTS, 1);
  1070.                 }
  1071.                 else
  1072.                 {
  1073.                     //Turnover
  1074.                     //snprintf(msg, sizeof(msg), "Turnover! %s -> %s", carrier[bid]->name, p->name);
  1075.                     //chat->SendArenaMessage(a, msg);
  1076.                     stats->IncrementStat(p, STAT_BALL_STEALS, 1);
  1077.                     stats->IncrementStat(carrier[bid], STAT_BALL_TURNOVERS, 1);
  1078.                 }
  1079.             }
  1080.             lastcarrier[bid] = NULL;
  1081.  
  1082.         }
  1083.         else
  1084.         {
  1085.             if (carrier[bid] != p)
  1086.             {
  1087.                 //Pass
  1088.                 //snprintf(msg, sizeof(msg), "Pass %s -> %s", carrier[bid]->name, p->name);
  1089.                 //chat->SendArenaMessage(a, msg);
  1090.  
  1091.                 lastcarrier[bid] = carrier[bid];
  1092.             }
  1093.             else
  1094.             {
  1095.                 //Player passed to himself, cancel assist for previous guy
  1096.                 lastcarrier[bid] = NULL;
  1097.             }
  1098.  
  1099.         }
  1100.  
  1101.     }
  1102.  
  1103.     carrier[bid] = p;
  1104.  
  1105.     //Already handled
  1106.     //stats->IncrementStat(p, STAT_BALL_CARRIES, 1);
  1107.     //stats->StartTimer(p, STAT_BALL_CARRY_TIME);
  1108.  
  1109.     return TRUE;
  1110. }
  1111.  
  1112. /* called when a player tries to fire a ball.
  1113.  * returning FALSE diallows the ball fire, causing the ball to be restuck to the player.
  1114.  * note that there will be no ball timer using this behavior.
  1115.  * returning TRUE changes the ball state to the data pointed to by newbd.
  1116.  * by default newbd is the state of the ball as if no advisers interfered (traveling on the map)
  1117.  * isForced specifies whether the client is firing the ball or the module is forcing a ball fire.
  1118.  */
  1119. int AllowBallFire(Arena *a, Player *p, int bid, int isForced, struct BallData *newbd)
  1120. {
  1121.     int i;
  1122.  
  1123.     invalidshot = FALSE;
  1124.  
  1125.     if (state == SOCKEY_TIMEOUT)
  1126.     {
  1127.         //Leave ball there
  1128.         newbd->xspeed = 0;
  1129.         newbd->yspeed = 0;
  1130.         carrier[bid] = NULL;
  1131.         lastcarrier[bid] = NULL;
  1132.         return TRUE;
  1133.     }
  1134.     if (state != SOCKEY_PLAYING)
  1135.         return TRUE;
  1136.  
  1137.     //Do not allow player to fire ball from enemy crease
  1138.     for (i = 0; i < N_TEAMS; i++)
  1139.         if (i != p->p_freq)
  1140.             if (coordincrease(a, newbd->x, newbd->y, i))
  1141.             {
  1142.                 //This shot cannot result in a goal
  1143.                 invalidshot = TRUE;
  1144.  
  1145.                 if (newbd->xspeed == 0 && newbd->yspeed == 0)
  1146.                 {
  1147.                     //chat->SendArenaMessage(a, "%s died with the ball in team %i crease", p->name, i);
  1148.  
  1149.                 }
  1150.                 else
  1151.                 {
  1152.                     //Penalize player
  1153.                     givepenalty(p, INFRACTION_OFF_CR);
  1154.                     //chat->SendArenaMessage(a, "%s attempted to fire ball in team %i crease", p->name, i);
  1155.                 }
  1156.  
  1157.                 //Leave ball there
  1158.                 newbd->xspeed = 0;
  1159.                 newbd->yspeed = 0;
  1160.  
  1161.                 //Don't leave it in the goal!
  1162.                 if (mapdata->GetTile(a, newbd->x / TILE_WIDTH, newbd->y / TILE_HEIGHT) == TILE_GOAL)
  1163.                 {
  1164.  
  1165.  
  1166.                     char regnname[32] = "CenterCrease";
  1167.                     addindex(regnname, i);
  1168.  
  1169.                     Region *rgn = mapdata->FindRegionByName(a, regnname);
  1170.                     if (rgn)
  1171.                     {
  1172.                         int x,y;
  1173.                         mapdata->FindRandomPoint(rgn, &x, &y);
  1174.                         if (x >= 0 && y >= 0)
  1175.                         {
  1176.                             newbd->x = x * TILE_WIDTH + TILE_WIDTH / 2;
  1177.                             newbd->y = y * TILE_HEIGHT + TILE_HEIGHT / 2;
  1178.                         }
  1179.                     }
  1180.  
  1181.                 }
  1182.  
  1183.  
  1184.                 carrier[bid] = NULL;
  1185.                 lastcarrier[bid] = NULL;
  1186.  
  1187.                 return TRUE;
  1188.             }
  1189.  
  1190.     carrier[bid] = p;
  1191.  
  1192.  
  1193.     lastthrowtime[bid] = current_ticks();
  1194.  
  1195.     return TRUE;
  1196. }
  1197.  
  1198. /* called when a client attempts to score a goal.
  1199.  * returning TRUE disallows the ball goal. note that continuum will continue sending goal packets
  1200.  * several times in this case. the ball state may be changed by modifying newbd.
  1201.  * returning FALSE allows the ball to be scored.
  1202.  */
  1203. int BlockBallGoal(Arena *a, Player *p, int bid, int x, int y, struct BallData *newbd)
  1204. {
  1205.     if (state != SOCKEY_PLAYING || invalidshot == TRUE)
  1206.         return TRUE;
  1207.  
  1208.     if (!p || p->p_freq < 0 || p->p_freq >= N_TEAMS)
  1209.         return TRUE;
  1210.  
  1211.     //Do not allow a penalized player to score
  1212.     if (LLMember(&ll_penalties, p))
  1213.         return TRUE;
  1214.  
  1215.     //Block own goals...
  1216.  
  1217.     //Find team who got scored on
  1218.     char regnname[32] = "Crease";
  1219.     addindex(regnname, p->p_freq);
  1220.  
  1221.     Region * rgn = mapdata->FindRegionByName(a, regnname);
  1222.     if (rgn)
  1223.         if (mapdata->Contains(rgn, x, y))
  1224.             return TRUE;
  1225.  
  1226.     //Check if someone from the scoring team is in the crease
  1227.  
  1228.  
  1229.  
  1230.     return FALSE;
  1231. }
  1232.  
  1233.  
  1234. local Aballs adv_balls =
  1235. {
  1236.     ADVISER_HEAD_INIT(A_BALLS)
  1237.     AllowBallPickup, AllowBallFire, BlockBallGoal
  1238. };
  1239.  
  1240.  
  1241.  
  1242. ////////////////////////////////////
  1243. //
  1244. //CALLBACKS
  1245. //
  1246. ////////////////////////////////////
  1247.  
  1248. local void spawn(Player *p, int reason)
  1249. {
  1250.     //char message[256];
  1251.  
  1252.     //snprintf(message,sizeof(message),"%s spawned for reason %i", p->name, reason);
  1253.  
  1254.     //chat->SendArenaMessage(p->arena, message);
  1255.  
  1256.     checkallcreases(p);
  1257.  
  1258.  
  1259.     switch(reason)
  1260.     {
  1261.     case SPAWN_AFTERDEATH:
  1262.         break;
  1263.     case SPAWN_SHIPRESET:
  1264.         break;
  1265.     case SPAWN_FLAGVICTORY:
  1266.         break;
  1267.     case SPAWN_SHIPCHANGE:
  1268.         break;
  1269.     case SPAWN_INITIAL:
  1270.         break;
  1271.     default:
  1272.         break;
  1273.     }
  1274.  
  1275. }
  1276.  
  1277.  
  1278. local void playeraction(Player *p, int action, Arena *arena)
  1279. {
  1280.     switch(action)
  1281.     {
  1282.     case PA_ENTERARENA:
  1283.         break;
  1284.     case PA_LEAVEARENA:
  1285.         clearplayerrefs(p);
  1286.         break;
  1287.  
  1288.     default:
  1289.         break;
  1290.     }
  1291. }
  1292.  
  1293. //Player entered or left a region
  1294. local void region(Player *p, Region *rgn, int x, int y, int entering)
  1295. {
  1296.     int i;
  1297.  
  1298.     char regnname[32];
  1299.     char creasename[32];
  1300.  
  1301.  
  1302.     LinkedList * listtocheck;
  1303.  
  1304.     if (p->p_freq >= N_TEAMS ||
  1305.             p->p_ship == SHIP_SPEC ||
  1306.             state != SOCKEY_PLAYING)
  1307.         return;
  1308.  
  1309.  
  1310.  
  1311.  
  1312.     astrncpy(regnname, mapdata->RegionName(rgn), sizeof(regnname));
  1313.  
  1314.     //If a penalized player leaves PenaltyArea, warp him back
  1315.     if (!entering && !strcmp(regnname, "PenaltyArea"))
  1316.         if (LLMember(&ll_penalties, p))
  1317.         {
  1318.             color->ColorPSound(COLOR_RED, p, SOUND_GAMESUCKS, "You have to stay in the penalty box until your penalty is over!");
  1319.  
  1320.             //chat->SendSoundMessage(p, SOUND_GAMESUCKS, "You have to stay in the penalty box until your penalty is over!");
  1321.             warptopenalty(p);
  1322.             return;
  1323.         }
  1324.  
  1325.     /*
  1326.     snprintf(zonename, sizeof(zonename), "Zone%i", p->p_freq);
  1327.     if (!entering && !ballinplay[0] && !strcmp(regnname, zonename))
  1328.     {
  1329.         //Player is exiting his zone while ball is not in play
  1330.         t.type = T_PLAYER;
  1331.         t.u.p = p;
  1332.         chat->SendSoundMessage(p, SOUND_PHONE, "You have to stay in your zone for the faceoff until the ball respawns!");
  1333.  
  1334.         if (warpinregion(p->arena, &t, zonename))
  1335.             return;
  1336.     }
  1337.     */
  1338.  
  1339.     for (i = 0; i < N_TEAMS; i++)
  1340.     {
  1341.         snprintf(creasename, sizeof(creasename), "Crease%i", i);
  1342.  
  1343.         if (!strcmp(regnname, creasename))
  1344.         {
  1345.             if (i == p->p_freq)
  1346.                 //Checking defensive crease
  1347.                 listtocheck = &ll_indefcrease[i];
  1348.             else
  1349.                 //Checking offensive crease
  1350.                 listtocheck = &ll_inoffcrease[p->p_freq][i];
  1351.  
  1352.  
  1353.             if (entering)
  1354.             {
  1355.  
  1356.  
  1357.                 if (i == p->p_freq)
  1358.                 {
  1359.  
  1360.                     //Manage goaltending time stat
  1361.                     if (LLCount(listtocheck) == 0)
  1362.                         stats->StartTimer(p, STAT_GOALIE_TIME);
  1363.                 }
  1364.                 //Add the player to the list if he is not in it already
  1365.                 if (!LLMember(listtocheck, p))
  1366.                     LLAdd(listtocheck, p);
  1367.             }
  1368.             else
  1369.             {
  1370.  
  1371.                 if (i == p->p_freq)
  1372.                     stats->StopTimer(p, STAT_GOALIE_TIME);
  1373.  
  1374.                 //Remove the player from the list if he is in it
  1375.                 LLRemove(listtocheck, p);
  1376.             }
  1377.         }
  1378.  
  1379.     }
  1380. }
  1381.  
  1382.  
  1383.  
  1384. /* called when a player picks up a ball */
  1385. local void ballpickup(Arena *arena, Player *p, int bid)
  1386. {
  1387.     /*
  1388.     char message[256];
  1389.  
  1390.     snprintf(message,sizeof(message),"%s picked up ball %i", p->name, bid);
  1391.  
  1392.     chat->SendArenaMessage(arena, message);
  1393.     */
  1394. }
  1395.  
  1396.  
  1397. /* called when a player fires a ball */
  1398. local void ballfire(Arena *arena, Player *p, int bid)
  1399. {
  1400.  
  1401. }
  1402.  
  1403.  
  1404. /* called when a player scores a goal */
  1405. local void goal(Arena *arena, Player *p, int bid, int x, int y)
  1406. {
  1407.     if (state != SOCKEY_PLAYING)
  1408.         return;
  1409.  
  1410.     int i;
  1411.     int scoredfreq = -1;
  1412.  
  1413.     int scoringfreq = p->p_freq;
  1414.  
  1415.  
  1416.     //If goal is allowed...
  1417.  
  1418.     int  incorner;
  1419.  
  1420.  
  1421.     if (scoringfreq >= 0 && scoringfreq < N_TEAMS)
  1422.         score[scoringfreq]++;
  1423.  
  1424.  
  1425.     //Perfect corner shots
  1426.     Region * rgn = mapdata->FindRegionByName(arena, "GoalCorner");
  1427.     incorner = rgn && (mapdata->Contains(rgn, x, y));
  1428.  
  1429.  
  1430.  
  1431.     //Find team who got scored on
  1432.     char regnname[32];
  1433.     for (i = 0; i < N_TEAMS; i++)
  1434.     {
  1435.         snprintf(regnname, sizeof(regnname), "Crease%i", i);
  1436.         Region * rgn = mapdata->FindRegionByName(arena, regnname);
  1437.         if (rgn)
  1438.         {
  1439.             if (mapdata->Contains(rgn, x, y))
  1440.             {
  1441.                 scoredfreq = i;
  1442.                 break;
  1443.             }
  1444.         }
  1445.         else
  1446.             lm->LogA(L_ERROR, "sockey", arena, "Region Crease%i not found", i);
  1447.     }
  1448.  
  1449.     //Goal stat handled by default
  1450.     //stats->IncrementStat(p, STAT_BALL_GOALS, 1);
  1451.     if (lastcarrier[bid])
  1452.         stats->IncrementStat(lastcarrier[bid], STAT_BALL_ASSISTS, 1);
  1453.     showgoal(p, lastcarrier[bid], incorner);
  1454.  
  1455.     showscore(arena, TRUE);
  1456.  
  1457.     lastcarrier[bid] = NULL;
  1458.     carrier[bid] = NULL;
  1459.  
  1460.  
  1461.     warpaftergoal(arena, scoredfreq, scoringfreq, bid);
  1462.  
  1463.     //Check victory conditions
  1464.     sockey_config_t *ad = P_ARENA_DATA(arena, adkey);
  1465.     if (ad->maxgoals > 0)
  1466.     {
  1467.         if (score[scoringfreq] >= ad->maxgoals)
  1468.         {
  1469.             if (ad->winby > 0)
  1470.             {
  1471.                 for (i = 0; i < N_TEAMS; i++)
  1472.                     if (i != scoringfreq && score[scoringfreq] < score[i]+ad->winby)
  1473.                         return; //cannot win yet
  1474.  
  1475.                 endgame(arena); //Win!
  1476.             }
  1477.             else
  1478.                 endgame(arena); //Win!
  1479.  
  1480.         }
  1481.     }
  1482.  
  1483.     //delayedballspawn(arena, bid, DELAY_BALLSPAWN);
  1484.  
  1485.  
  1486. }
  1487.  
  1488.  
  1489. void kill(Arena *arena, Player *killer, Player *killed, int bounty, int flags, int *pts, int *green)
  1490. {
  1491.     if (state != SOCKEY_PLAYING)
  1492.         return;
  1493.  
  1494.     Link *link;
  1495.     Player*p;
  1496.  
  1497.     if (!killed || !killer)
  1498.         return;
  1499.  
  1500.     int killedteam = killed->p_freq;
  1501.  
  1502.  
  1503.     //Update all killed's team crease status
  1504.     pd->Lock();
  1505.     FOR_EACH_PLAYER_IN_ARENA(p, arena)
  1506.     {
  1507.         if (p->p_freq == killedteam)
  1508.             checkcrease(p, killedteam);
  1509.     }
  1510.  
  1511.     pd->Unlock();
  1512.  
  1513.  
  1514.     if (killed == getgoalie(killedteam))
  1515.     {
  1516.  
  1517.         Target t;
  1518.         t.type = T_PLAYER;
  1519.         t.u.p = killed;
  1520.         //killer just murdered a goalie... not good.
  1521.         game->ShipReset(&t);
  1522.  
  1523.         givepenalty(killer, INFRACTION_GOALIE_KILL);
  1524.     }
  1525.  
  1526.     /*
  1527.     for (i = 0; i < N_BALLS; i++)
  1528.         if (killed == carrier[i])
  1529.         {
  1530.             for (j = 0; j < N_TEAMS; j++)
  1531.                 if (j != killed->p_freq)
  1532.                     if (checkcrease(killed, j))
  1533.                     {
  1534.                         //The player was killed in the enemy crease while carrying the ball
  1535.                         chat->SendArenaMessage(arena, "%s killed in crease with ball", killed->name);
  1536.  
  1537.                         char regnname[32] = "Spawn";
  1538.                         Target t;
  1539.                         t.type = T_PLAYER;
  1540.                         t.u.p = killed;
  1541.  
  1542.                         addindex(regnname, killed->p_freq);
  1543.                         warpinregion(arena, &t, regnname);
  1544.  
  1545.  
  1546.                     }
  1547.  
  1548.  
  1549.  
  1550.         }
  1551.  
  1552.      */
  1553. }
  1554.  
  1555.  
  1556. void shipfreqchange(Player *p, int newship, int oldship, int newfreq, int oldfreq)
  1557. {
  1558.     /*
  1559.     if (state != SOCKEY_PLAYING)
  1560.         return;
  1561.     */
  1562.  
  1563.     if (newship == SHIP_SPEC || newfreq != oldfreq)
  1564.         clearplayerrefs(p);
  1565.  
  1566.     if (newship != SHIP_SPEC)
  1567.         checkallcreases(p);
  1568. }
  1569.  
  1570. void playermove(Player *p, const struct C2SPosition *pos)
  1571. {
  1572.  
  1573. }
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579. local void arenaaction(Arena *arena, int action)
  1580. {
  1581.  
  1582.     if (action == AA_CREATE || action == AA_CONFCHANGED)
  1583.     {
  1584.         lm->LogA(L_INFO, "sockey", arena, "Reloading settings");
  1585.  
  1586.         updatesettings(arena);
  1587.     }
  1588. }
  1589.  
  1590.  
  1591. local void timeout(Player* p, Arena* arena)
  1592. {
  1593.     if (state == SOCKEY_PLAYING)
  1594.     {
  1595.         chat->SendArenaSoundMessage(arena, SOUND_DING, "Timeout called by %s", p->name);
  1596.  
  1597.         pausetime = current_ticks();
  1598.         state = SOCKEY_TIMEOUT;
  1599.  
  1600.         chat->SendCmdMessage(p, "Game paused. Type '?sockey timeout' again to resume the game.");
  1601.     }
  1602.     else if (state == SOCKEY_TIMEOUT)
  1603.     {
  1604.         pausedcumultime += TICK_DIFF(current_ticks(), pausetime);
  1605.         state = SOCKEY_PLAYING;
  1606.  
  1607.         chat->SendArenaSoundMessage(arena, SOUND_GOAL, "Game resumed!");
  1608.         showscore(arena, TRUE);
  1609.     }
  1610.     else
  1611.         chat->SendCmdMessage(p, "You cannot call a timeout at this time.");
  1612.  
  1613. }
  1614.  
  1615. ////////////////////////////////////
  1616. //
  1617. //COMMANDS
  1618. //
  1619. ////////////////////////////////////
  1620.  
  1621.  
  1622. local helptext_t cmd_setscore=
  1623.     "Targets: none\n"
  1624.     "Args: <score0> <score1>\n"
  1625.     "Sets the score of the current game. Example: ?setscore 3 2\n";
  1626.  
  1627.  
  1628. local void cSetscore(const char *command, const char *params, Player *p, const Target *target)
  1629. {
  1630.  
  1631.     char split[64];
  1632.     const char *tmp = NULL;
  1633.  
  1634.     int i = 0;
  1635.     while (i < N_TEAMS && strsplit(params, " ,:-;", split, sizeof(split), &tmp))
  1636.     {
  1637.         score[i] = atoi(split);
  1638.         i++;
  1639.     }
  1640.  
  1641.     showscore(p->arena, TRUE);
  1642. }
  1643.  
  1644. local helptext_t cmd_sockey=
  1645.     "Targets: none\n"
  1646.     "Args: start | new, end | cancel, timeout\n"
  1647.     "Changes the state of the game.\n";
  1648.  
  1649. local void cSockey(const char *command, const char *params, Player *p, const Target *target)
  1650. {
  1651.     if (!stricmp(params, "reset"))
  1652.         resetgame(p->arena, TRUE, TRUE);
  1653.     else if (!stricmp(params, "start") || !stricmp(params, "new"))
  1654.         newgame(p->arena, 5);
  1655.     else if (!stricmp(params, "end") || !stricmp(params, "cancel"))
  1656.         endgame(p->arena);
  1657.     else if (!stricmp(params, "timeout") || !stricmp(params, "pause"))
  1658.         timeout(p, p->arena);
  1659.     else if (!stricmp(params, "resume") && state == SOCKEY_TIMEOUT)
  1660.         timeout(p, p->arena);
  1661.  
  1662. }
  1663.  
  1664.  
  1665. ////////////////////////////////////
  1666. //
  1667. //MODULE INIT
  1668. //
  1669. ////////////////////////////////////
  1670. local void init(Arena *arena)
  1671. {
  1672.     int i,j;
  1673.     invalidshot = FALSE;
  1674.  
  1675.     ok_Doormode = cs->GetOverrideKey("Door", "Doormode");
  1676.  
  1677.  
  1678.     for (i = 0; i < N_TEAMS; i++)
  1679.     {
  1680.         LLInit(&ll_indefcrease[i]);
  1681.  
  1682.         for (j = 0; j < N_TEAMS; j++)
  1683.             LLInit(&ll_inoffcrease[i][j]);
  1684.  
  1685.     }
  1686.     LLInit(&ll_penalties);
  1687.  
  1688.     ped_sockey = pd->AllocatePlayerData(sizeof(ped_sockey_t));
  1689.  
  1690.  
  1691.     state = SOCKEY_WAITING;
  1692.  
  1693.  
  1694.  
  1695.     resetgame(arena, FALSE, FALSE);
  1696. }
  1697.  
  1698. local void cleanup(Arena *arena)
  1699. {
  1700.     int i,j;
  1701.  
  1702.     ml->ClearTimer(endpenalty, NULL);
  1703.  
  1704.     ml->ClearTimer(startgame, arena);
  1705.     ml->ClearTimer(endgame, arena);
  1706.     ml->ClearTimer(updatetime, arena);
  1707.  
  1708.  
  1709.  
  1710.     pd->FreePlayerData(ped_sockey);
  1711.  
  1712.     pd->Lock();
  1713.     for (i = 0; i < N_TEAMS; i++)
  1714.     {
  1715.         LLEmpty(&ll_indefcrease[i]);
  1716.  
  1717.         for (j = 0; j < N_TEAMS; j++)
  1718.             LLEmpty(&ll_inoffcrease[i][j]);
  1719.  
  1720.     }
  1721.     LLEmpty(&ll_penalties);
  1722.     pd->Unlock();
  1723.  
  1724.  
  1725.  
  1726. }
  1727.  
  1728.  
  1729. EXPORT int MM_sockey(int action, Imodman *mm_, Arena *arena)
  1730. {
  1731.     if (action == MM_LOAD)
  1732.     {
  1733.         mm = mm_;
  1734.         lm = mm->GetInterface(I_LOGMAN, ALLARENAS);
  1735.  
  1736.         aman = mm->GetInterface(I_ARENAMAN, ALLARENAS);
  1737.         cfg = mm->GetInterface(I_CONFIG, ALLARENAS);
  1738.  
  1739.         chat = mm->GetInterface(I_CHAT, ALLARENAS);
  1740.         cmd = mm->GetInterface(I_CMDMAN, ALLARENAS);
  1741.         balls = mm->GetInterface(I_BALLS, ALLARENAS);
  1742.  
  1743.         color = mm->GetInterface(I_COLOR, ALLARENAS);
  1744.         pd = mm->GetInterface(I_PLAYERDATA,ALLARENAS);
  1745.         ml = mm->GetInterface(I_MAINLOOP,ALLARENAS);
  1746.         game = mm->GetInterface(I_GAME,ALLARENAS);
  1747.         objs = mm->GetInterface(I_OBJECTS,ALLARENAS);
  1748.         mapdata = mm->GetInterface(I_MAPDATA,ALLARENAS);
  1749.         cs = mm->GetInterface(I_CLIENTSET, ALLARENAS);
  1750.  
  1751.         stats = mm->GetInterface(I_STATS, ALLARENAS);
  1752.         persist = mm->GetInterface(I_PERSIST, ALLARENAS);
  1753.  
  1754.         hud = mm->GetInterface(I_LVZHUD, ALLARENAS);
  1755.  
  1756.  
  1757.         if (!lm || !chat || !cmd || !balls || !color || !pd
  1758.                 || !ml || !game || !objs || !mapdata || !cs
  1759.                 || !stats || !persist || !hud || !aman || !cfg)
  1760.             return MM_FAIL;
  1761.  
  1762.         adkey = aman->AllocateArenaData(sizeof(sockey_config_t));
  1763.         if (adkey == -1) return MM_FAIL;
  1764.  
  1765.         return MM_OK;
  1766.  
  1767.     }
  1768.     else if (action == MM_UNLOAD)
  1769.     {
  1770.  
  1771.  
  1772.  
  1773.         //Release interfaces
  1774.         mm->ReleaseInterface(hud);
  1775.         mm->ReleaseInterface(persist);
  1776.         mm->ReleaseInterface(stats);
  1777.         mm->ReleaseInterface(cs);
  1778.         mm->ReleaseInterface(mapdata);
  1779.         mm->ReleaseInterface(objs);
  1780.         mm->ReleaseInterface(game);
  1781.         mm->ReleaseInterface(ml);
  1782.         mm->ReleaseInterface(pd);
  1783.         mm->ReleaseInterface(color);
  1784.         mm->ReleaseInterface(balls);
  1785.         mm->ReleaseInterface(cmd);
  1786.         mm->ReleaseInterface(chat);
  1787.  
  1788.         mm->ReleaseInterface(cfg);
  1789.         mm->ReleaseInterface(aman);
  1790.  
  1791.         mm->ReleaseInterface(lm);
  1792.  
  1793.         aman->FreeArenaData(adkey);
  1794.  
  1795.         return MM_OK;
  1796.     }
  1797.     else if (action == MM_ATTACH)
  1798.     {
  1799.  
  1800.         //Register callbacks
  1801.  
  1802.  
  1803.  
  1804.  
  1805.         mm->RegCallback(CB_GOAL, goal, arena);
  1806.         mm->RegCallback(CB_BALLPICKUP, ballpickup, arena);
  1807.         mm->RegCallback(CB_BALLFIRE, ballfire, arena);
  1808.         mm->RegCallback(CB_REGION, region, arena);
  1809.         mm->RegCallback(CB_PLAYERACTION, playeraction, arena);
  1810.         mm->RegCallback(CB_SPAWN, spawn, arena);
  1811.         mm->RegCallback(CB_SHIPFREQCHANGE, shipfreqchange, arena);
  1812.         mm->RegCallback(CB_KILL, kill, arena);
  1813.         mm->RegCallback(CB_PPK, playermove, arena);
  1814.         mm->RegCallback(CB_ARENAACTION, arenaaction, arena);
  1815.  
  1816.         mm->RegAdviser(&adv_balls, arena);
  1817.  
  1818.         //Add commands
  1819.  
  1820.         cmd->AddCommand("sockey", cSockey, arena, cmd_sockey);
  1821.         cmd->AddCommand("setscore", cSetscore, arena, cmd_setscore);
  1822.  
  1823.  
  1824.         lm->LogA(L_DRIVEL, "sockey", arena, "Starting init");
  1825.         init(arena);
  1826.  
  1827.  
  1828.         return MM_OK;
  1829.     }
  1830.     else if (action == MM_DETACH)
  1831.     {
  1832.         cleanup(arena);
  1833.  
  1834.  
  1835.         cmd->RemoveCommand("sockey", cSockey, arena);
  1836.         cmd->RemoveCommand("setscore", cSetscore, arena);
  1837.  
  1838.         //Unregister callbacks
  1839.  
  1840.         mm->UnregAdviser(&adv_balls, arena);
  1841.  
  1842.         mm->UnregCallback(CB_ARENAACTION, arenaaction, arena);
  1843.         mm->UnregCallback(CB_PPK, playermove, arena);
  1844.         mm->UnregCallback(CB_KILL, kill, arena);
  1845.         mm->UnregCallback(CB_SHIPFREQCHANGE, shipfreqchange, arena);
  1846.         mm->UnregCallback(CB_SPAWN, spawn, arena);
  1847.         mm->UnregCallback(CB_PLAYERACTION, playeraction, arena);
  1848.         mm->UnregCallback(CB_REGION, region, arena);
  1849.         mm->UnregCallback(CB_BALLFIRE, ballfire, arena);
  1850.         mm->UnregCallback(CB_BALLPICKUP, ballpickup, arena);
  1851.         mm->UnregCallback(CB_GOAL, goal, arena);
  1852.  
  1853.  
  1854.         return MM_OK;
  1855.     }
  1856.  
  1857.  
  1858.  
  1859.  
  1860.     return MM_OK;
  1861. }
  1862.  
  1863.  
  1864.  
  1865.  
  1866.  
  1867.  
  1868.  
  1869.  
  1870.  
  1871.  
  1872.  
  1873. /*
  1874. typedef struct
  1875. {
  1876.     Arena * arena;
  1877.     int     bid;
  1878. } respawnball_params_t;
  1879.  
  1880.  
  1881.  
  1882.  
  1883. local void respawnball_cleanup(void *param)
  1884. {
  1885.     if (param)
  1886.         afree(param);
  1887. }
  1888.  
  1889. local int respawnball(void *param)
  1890. {
  1891.     respawnball_params_t * myparam = (respawnball_params_t*)param;
  1892.  
  1893.     if (myparam)
  1894.     {
  1895.         ballinplay[myparam->bid] = TRUE;
  1896.         //balls->SpawnBall(myparam->arena, myparam->bid);
  1897.         afree(param);
  1898.     }
  1899.  
  1900.     return FALSE;
  1901. }
  1902.  
  1903.  
  1904. local void delayedballspawn(Arena* arena, int bid, int delay)
  1905. {
  1906.     //Phase the ball, and have it respawn in a few seconds
  1907.     struct BallData newpos;
  1908.     newpos.x = 1;
  1909.     newpos.y = 1;
  1910.     newpos.xspeed = 0;
  1911.     newpos.yspeed = 0;
  1912.     newpos.carrier = NULL;
  1913.     newpos.freq = 0;
  1914.     newpos.last_update = current_ticks();
  1915.     newpos.state = BALL_ONMAP;
  1916.  
  1917.  
  1918.  
  1919.     respawnball_params_t * myparams = amalloc(sizeof(respawnball_params_t));
  1920.  
  1921.     if (myparams)
  1922.     {
  1923.         myparams->arena = arena;
  1924.         myparams->bid = bid;
  1925.  
  1926.         ml->SetTimer(respawnball, delay, 0, (void*)myparams, NULL);
  1927.         //balls->PlaceBall(arena, 0, &newpos);
  1928.     }
  1929. }
  1930. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement