|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00086 #include <global.h> 00087 #include <stdarg.h> 00088 00090 #define PLUGIN_NAME "Arena" 00091 00093 #define PLUGIN_VERSION "Arena plugin 1.0" 00094 00096 typedef struct arena_map_players 00097 { 00099 object *op; 00100 00102 struct arena_map_players *next; 00103 } arena_map_players; 00104 00106 typedef struct arena_maps_struct 00107 { 00109 char path[HUGE_BUF]; 00110 00112 int players; 00113 00115 int parties; 00116 00118 arena_map_players *player_list; 00119 00121 int max_players; 00122 00124 int max_parties; 00125 00127 uint32 flags; 00128 00130 char message_arena_full[MAX_BUF]; 00131 00133 char message_arena_party[MAX_BUF]; 00134 00136 struct arena_maps_struct *next; 00137 } arena_maps_struct; 00138 00144 #define ARENA_FLAG_NONE 0 00145 00146 #define ARENA_FLAG_PARTY 1 00147 00148 #define ARENA_FLAG_PARTY_PLAYERS 2 00149 00152 arena_maps_struct *arena_maps; 00153 00155 struct plugin_hooklist *hooks; 00156 00157 #undef LOG 00158 #define LOG hooks->LOG 00159 00160 MODULEAPI void initPlugin(struct plugin_hooklist *hooklist) 00161 { 00162 hooks = hooklist; 00163 00164 LOG(llevDebug, "Arena: Atrinik Arena Plugin loading...\n"); 00165 LOG(llevDebug, "Arena: [Done]\n"); 00166 } 00167 00168 MODULEAPI void closePlugin() 00169 { 00170 LOG(llevDebug, "Arena: Arena Plugin closing.\n"); 00171 } 00172 00173 MODULEAPI void *getPluginProperty(int *type, ...) 00174 { 00175 va_list args; 00176 const char *propname; 00177 int size; 00178 char *buf; 00179 00180 va_start(args, type); 00181 propname = va_arg(args, const char *); 00182 00183 if (!strcmp(propname, "Identification")) 00184 { 00185 buf = va_arg(args, char *); 00186 size = va_arg(args, int); 00187 va_end(args); 00188 snprintf(buf, size, PLUGIN_NAME); 00189 return NULL; 00190 } 00191 else if (!strcmp(propname, "FullName")) 00192 { 00193 buf = va_arg(args, char *); 00194 size = va_arg(args, int); 00195 va_end(args); 00196 snprintf(buf, size, PLUGIN_VERSION); 00197 return NULL; 00198 } 00199 00200 va_end(args); 00201 return NULL; 00202 } 00203 00204 MODULEAPI void postinitPlugin() 00205 { 00206 LOG(llevDebug, "Arena: Start postinitPlugin.\n"); 00207 00208 hooks->register_global_event(PLUGIN_NAME, GEVENT_LOGOUT); 00209 } 00210 00216 static int check_arena_player(object *op, arena_map_players *player_list) 00217 { 00218 arena_map_players *player_list_tmp; 00219 00220 /* Go through the list of players. */ 00221 for (player_list_tmp = player_list; player_list_tmp; player_list_tmp = player_list_tmp->next) 00222 { 00223 if (player_list_tmp->op == op) 00224 { 00225 return 1; 00226 } 00227 } 00228 00229 return 0; 00230 } 00231 00236 static void remove_arena_player(object *op, arena_map_players **player_list) 00237 { 00238 arena_map_players *currP, *prevP = NULL; 00239 00240 for (currP = *player_list; currP; prevP = currP, currP = currP->next) 00241 { 00242 if (currP->op == op) 00243 { 00244 if (!prevP) 00245 { 00246 *player_list = currP->next; 00247 } 00248 else 00249 { 00250 prevP->next = currP->next; 00251 } 00252 00253 free(currP); 00254 break; 00255 } 00256 } 00257 } 00258 00263 static void arena_map_parse_line(arena_maps_struct *arena_map, const char *line) 00264 { 00265 /* Maximum number of players */ 00266 if (strncmp(line, "max_players ", 12) == 0) 00267 { 00268 arena_map->max_players = atoi(line + 12); 00269 } 00270 /* Maximum number of parties */ 00271 else if (strncmp(line, "max_parties ", 12) == 0) 00272 { 00273 arena_map->max_parties = atoi(line + 12); 00274 } 00275 /* Whether to allow arena party mode */ 00276 else if (strncmp(line, "party ", 6) == 0) 00277 { 00278 line += 6; 00279 00280 if (!strcmp(line, "true") || *line == '1') 00281 { 00282 arena_map->flags |= ARENA_FLAG_PARTY; 00283 } 00284 } 00285 /* Or even party players? */ 00286 else if (strncmp(line, "party_players ", 14) == 0) 00287 { 00288 line += 14; 00289 00290 if (!strcmp(line, "true") || *line == '1') 00291 { 00292 arena_map->flags |= ARENA_FLAG_PARTY_PLAYERS; 00293 } 00294 } 00295 /* Message for when the arena is full */ 00296 else if (strncmp(line, "message_full ", 13) == 0) 00297 { 00298 strncpy(arena_map->message_arena_full, line + 13, sizeof(arena_map->message_arena_full) - 1); 00299 } 00300 /* Message when you need to join a party to enter */ 00301 else if (strncmp(line, "message_party ", 14) == 0) 00302 { 00303 strncpy(arena_map->message_arena_party, line + 13, sizeof(arena_map->message_arena_party) - 1); 00304 } 00305 } 00306 00312 static void arena_map_parse_script(const char *arena_script, object *exit_ob, arena_maps_struct *arena_map) 00313 { 00314 FILE *fh; 00315 char buf[MAX_BUF], tmp_path[HUGE_BUF]; 00316 char *arena_script_path; 00317 00318 /* Normalize the path to the script, allowing relative paths */ 00319 hooks->normalize_path(exit_ob->map->path, arena_script, tmp_path); 00320 00321 /* Create path name to the script in maps directory */ 00322 arena_script_path = hooks->create_pathname(tmp_path); 00323 00324 /* Initialize defaults */ 00325 arena_map->max_players = 0; 00326 arena_map->max_parties = 0; 00327 arena_map->players = 0; 00328 arena_map->parties = 0; 00329 arena_map->flags = ARENA_FLAG_NONE; 00330 strncpy(arena_map->message_arena_full, "Sorry, this arena seems to be full.", sizeof(arena_map->message_arena_full) - 1); 00331 strncpy(arena_map->message_arena_party, "You must be in a party in order to enter this arena.", sizeof(arena_map->message_arena_party) - 1); 00332 00333 fh = fopen(arena_script_path, "r"); 00334 00335 if (!fh) 00336 { 00337 LOG(llevBug, "Arena: Could not open arena script: %s\n", arena_script_path); 00338 return; 00339 } 00340 00341 while (fgets(buf, sizeof(buf), fh)) 00342 { 00343 /* Ignore comments and empty lines */ 00344 if (*buf == '#' || *buf == '\n') 00345 { 00346 continue; 00347 } 00348 00349 /* Remove newline and parse the line */ 00350 buf[strlen(buf) - 1] = '\0'; 00351 arena_map_parse_line(arena_map, buf); 00352 } 00353 00354 fclose(fh); 00355 } 00356 00363 static int arena_full(arena_maps_struct *arena_map) 00364 { 00365 /* Simple case: The map has nothing to do with parties. */ 00366 if (!(arena_map->flags & ARENA_FLAG_PARTY) && !(arena_map->flags & ARENA_FLAG_PARTY_PLAYERS) && arena_map->players == arena_map->max_players) 00367 { 00368 return 1; 00369 } 00370 /* Otherwise a party map. */ 00371 else if (arena_map->flags & ARENA_FLAG_PARTY) 00372 { 00373 /* If this is party players arena, count in players. */ 00374 if (arena_map->flags & ARENA_FLAG_PARTY_PLAYERS && arena_map->players == arena_map->max_players) 00375 { 00376 return 1; 00377 } 00378 00379 /* Always check for maximum parties, even if this is party players arena. */ 00380 if (arena_map->parties == arena_map->max_parties) 00381 { 00382 return 1; 00383 } 00384 } 00385 00386 return 0; 00387 } 00388 00395 int arena_enter(object *who, object *exit_ob, const char *arena_script) 00396 { 00397 char tmp_path[HUGE_BUF]; 00398 arena_maps_struct *arena_maps_tmp; 00399 00400 /* The exit must have a path */ 00401 if (!exit_ob->slaying) 00402 { 00403 return 0; 00404 } 00405 00406 /* Normalize the map's path */ 00407 hooks->normalize_path(exit_ob->map->path, EXIT_PATH(exit_ob), tmp_path); 00408 00409 /* Go through the list of arenas */ 00410 for (arena_maps_tmp = arena_maps; arena_maps_tmp; arena_maps_tmp = arena_maps_tmp->next) 00411 { 00412 /* If the exit's path matches this arena */ 00413 if (!strcmp(arena_maps_tmp->path, tmp_path)) 00414 { 00415 /* If the arena is full, show a message to the player */ 00416 if (arena_full(arena_maps_tmp)) 00417 { 00418 hooks->new_draw_info(0, COLOR_WHITE, who, arena_maps_tmp->message_arena_full); 00419 return 1; 00420 } 00421 /* Not full but it's party arena and the player is not in a party? */ 00422 else if (arena_maps_tmp->flags & ARENA_FLAG_PARTY && !CONTR(who)->party) 00423 { 00424 hooks->new_draw_info(0, COLOR_WHITE, who, arena_maps_tmp->message_arena_party); 00425 return 1; 00426 } 00427 /* Add the player to the list of players and increase the number of players/parties */ 00428 else 00429 { 00430 arena_map_players *player_list_tmp = (arena_map_players *) malloc(sizeof(arena_map_players)); 00431 00432 /* For party arenas, also increase the parties count */ 00433 if (arena_maps_tmp->flags & ARENA_FLAG_PARTY) 00434 { 00435 arena_map_players *player_list_party; 00436 int new_party = 1; 00437 00438 /* Loop through the player list */ 00439 for (player_list_party = arena_maps_tmp->player_list; player_list_party; player_list_party = player_list_party->next) 00440 { 00441 /* If we found a match for this party number, do not increase the count */ 00442 if (CONTR(who)->party && CONTR(who)->party == CONTR(player_list_party->op)->party) 00443 { 00444 new_party = 0; 00445 break; 00446 } 00447 } 00448 00449 /* Increase the count, if this is a new party in the arena */ 00450 if (new_party) 00451 { 00452 arena_maps_tmp->parties++; 00453 } 00454 } 00455 00456 /* Increase the number of players */ 00457 arena_maps_tmp->players++; 00458 00459 player_list_tmp->next = arena_maps_tmp->player_list; 00460 arena_maps_tmp->player_list = player_list_tmp; 00461 00462 /* Store the player object */ 00463 player_list_tmp->op = who; 00464 return 0; 00465 } 00466 } 00467 } 00468 00469 /* If we are here, the arena doesn't have an entry in the linked list -- create it */ 00470 arena_maps_tmp = (arena_maps_struct *) malloc(sizeof(arena_maps_struct)); 00471 strncpy(arena_maps_tmp->path, tmp_path, sizeof(arena_maps_tmp->path) - 1); 00472 00473 /* Parse script options */ 00474 arena_map_parse_script(arena_script, exit_ob, arena_maps_tmp); 00475 00476 /* If this arena is full, show a message and return */ 00477 if (arena_full(arena_maps_tmp)) 00478 { 00479 hooks->new_draw_info(0, COLOR_WHITE, who, arena_maps_tmp->message_arena_full); 00480 free(arena_maps_tmp); 00481 return 1; 00482 } 00483 /* Otherwise if not full and the player is not in party */ 00484 else if (arena_maps_tmp->flags & ARENA_FLAG_PARTY && !CONTR(who)->party) 00485 { 00486 hooks->new_draw_info(0, COLOR_WHITE, who, arena_maps_tmp->message_arena_party); 00487 free(arena_maps_tmp); 00488 return 1; 00489 } 00490 00491 /* Add this player to the player count */ 00492 arena_maps_tmp->players++; 00493 00494 /* Add to the party count, if this is party arena */ 00495 if (arena_maps_tmp->flags & ARENA_FLAG_PARTY) 00496 { 00497 arena_maps_tmp->parties++; 00498 } 00499 00500 /* Make a list of players in this arena */ 00501 arena_maps_tmp->player_list = (arena_map_players *) malloc(sizeof(arena_map_players)); 00502 00503 /* Store the player */ 00504 arena_maps_tmp->player_list->op = who; 00505 00506 arena_maps_tmp->player_list->next = NULL; 00507 00508 arena_maps_tmp->next = arena_maps; 00509 arena_maps = arena_maps_tmp; 00510 00511 return 0; 00512 } 00513 00519 int arena_sign(object *who, const char *path) 00520 { 00521 arena_maps_struct *arena_maps_tmp; 00522 00523 /* Sanity check */ 00524 if (!path || path[0] == '\0') 00525 { 00526 return 1; 00527 } 00528 00529 for (arena_maps_tmp = arena_maps; arena_maps_tmp; arena_maps_tmp = arena_maps_tmp->next) 00530 { 00531 /* If the path matches */ 00532 if (!strcmp(arena_maps_tmp->path, path) && arena_maps_tmp->player_list) 00533 { 00534 arena_map_players *player_list_tmp; 00535 00536 hooks->new_draw_info(0, COLOR_YELLOW, who, "This arena has the following players in:\n"); 00537 00538 /* Now go through the list of players in this arena */ 00539 for (player_list_tmp = arena_maps_tmp->player_list; player_list_tmp; player_list_tmp = player_list_tmp->next) 00540 { 00541 hooks->new_draw_info_format(0, COLOR_YELLOW, who, "%s (level %d)", player_list_tmp->op->name, player_list_tmp->op->level); 00542 } 00543 00544 if (!(arena_maps_tmp->flags & ARENA_FLAG_PARTY) || (arena_maps_tmp->flags & ARENA_FLAG_PARTY && arena_maps_tmp->flags & ARENA_FLAG_PARTY_PLAYERS)) 00545 { 00546 hooks->new_draw_info_format(0, COLOR_YELLOW, who, "\nTotal players: %d\nMaximum players: %d", arena_maps_tmp->players, arena_maps_tmp->max_players); 00547 } 00548 00549 if (arena_maps_tmp->flags & ARENA_FLAG_PARTY) 00550 { 00551 hooks->new_draw_info_format(0, COLOR_YELLOW, who, "\nTotal parties: %d\nMaximum parties: %d", arena_maps_tmp->parties, arena_maps_tmp->max_parties); 00552 } 00553 00554 return 1; 00555 } 00556 } 00557 00558 hooks->new_draw_info(0, COLOR_YELLOW, who, "This arena is currently empty."); 00559 return 1; 00560 } 00561 00565 static int arena_event(object *who, object *exit_ob, const char *event_options, const char *arena_script) 00566 { 00567 /* If the first 5 characters are "sign|", this is an arena sign */ 00568 if (event_options && !strncmp(event_options, "sign|", 5)) 00569 { 00570 event_options += 5; 00571 return arena_sign(who, event_options); 00572 } 00573 /* Otherwise arena entrance */ 00574 else 00575 { 00576 return arena_enter(who, exit_ob, arena_script); 00577 } 00578 } 00579 00585 static int arena_leave(object *who) 00586 { 00587 arena_maps_struct *arena_maps_tmp; 00588 00589 /* Sanity checks */ 00590 if (!who || !who->map || !who->map->path || !who->name) 00591 { 00592 return 0; 00593 } 00594 00595 /* Go through the list of arenas */ 00596 for (arena_maps_tmp = arena_maps; arena_maps_tmp; arena_maps_tmp = arena_maps_tmp->next) 00597 { 00598 /* If it matches, and the player really is in the arena */ 00599 if (!strcmp(arena_maps_tmp->path, who->map->path) && check_arena_player(who, arena_maps_tmp->player_list)) 00600 { 00601 /* If this is party arena, we will want to see if we have to decrease the parties count */ 00602 if (arena_maps_tmp->flags & ARENA_FLAG_PARTY) 00603 { 00604 arena_map_players *player_list_party; 00605 int do_remove = 1; 00606 00607 /* Loop through the player list for this map */ 00608 for (player_list_party = arena_maps_tmp->player_list; player_list_party; player_list_party = player_list_party->next) 00609 { 00610 /* If the party number matches, we're not going to remove this party */ 00611 if (player_list_party->op != who && CONTR(who)->party && CONTR(who)->party == CONTR(player_list_party->op)->party) 00612 { 00613 do_remove = 0; 00614 break; 00615 } 00616 } 00617 00618 /* Removing the party? Then decrease the count. */ 00619 if (do_remove) 00620 { 00621 arena_maps_tmp->parties--; 00622 } 00623 } 00624 00625 /* Decrease the count of players */ 00626 arena_maps_tmp->players--; 00627 00628 /* Remove the player from this the arena's player list */ 00629 remove_arena_player(who, &arena_maps_tmp->player_list); 00630 return 0; 00631 } 00632 } 00633 00634 return 0; 00635 } 00636 00637 MODULEAPI void *triggerEvent(int *type, ...) 00638 { 00639 object *activator, *who, *other, *event; 00640 va_list args; 00641 int eventcode, event_type; 00642 static int result = 0; 00643 00644 va_start(args, type); 00645 event_type = va_arg(args, int); 00646 eventcode = va_arg(args, int); 00647 LOG(llevDebug, "Arena: triggerEvent(): eventcode %d\n", eventcode); 00648 00649 activator = va_arg(args, object *); 00650 00651 if (event_type == PLUGIN_EVENT_NORMAL) 00652 { 00653 switch (eventcode) 00654 { 00655 case EVENT_APPLY: 00656 case EVENT_TRIGGER: 00657 { 00658 char *text, *script, *options; 00659 int parm1, parm2, parm3, parm4; 00660 00661 who = va_arg(args, object *); 00662 other = va_arg(args, object *); 00663 event = va_arg(args, object *); 00664 text = va_arg(args, char *); 00665 parm1 = va_arg(args, int); 00666 parm2 = va_arg(args, int); 00667 parm3 = va_arg(args, int); 00668 parm4 = va_arg(args, int); 00669 script = va_arg(args, char *); 00670 options = va_arg(args, char *); 00671 00672 (void) other; 00673 (void) event; 00674 (void) text; 00675 (void) parm1; 00676 (void) parm2; 00677 (void) parm3; 00678 (void) parm4; 00679 00680 result = arena_event(activator, who, options, script); 00681 break; 00682 } 00683 } 00684 } 00685 else if (event_type == PLUGIN_EVENT_MAP) 00686 { 00687 switch (eventcode) 00688 { 00689 case MEVENT_LEAVE: 00690 result = arena_leave(activator); 00691 break; 00692 } 00693 } 00694 else if (event_type == PLUGIN_EVENT_GLOBAL) 00695 { 00696 switch (eventcode) 00697 { 00698 case GEVENT_PLAYER_DEATH: 00699 case GEVENT_LOGOUT: 00700 result = arena_leave(activator); 00701 break; 00702 } 00703 } 00704 00705 va_end(args); 00706 return &result; 00707 } 00708
1.7.4