|
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 00030 #include <global.h> 00031 00034 const char *const party_loot_modes[PARTY_LOOT_MAX] = 00035 { 00036 "normal", "leader", "random" 00037 }; 00038 00041 const char *const party_loot_modes_help[PARTY_LOOT_MAX] = 00042 { 00043 "everyone is able to loot the corpse", 00044 "only the leader can loot the corpse", 00045 "loot is randomly split between party members when the corpse is opened" 00046 }; 00047 00049 party_struct *first_party = NULL; 00050 00055 void add_party_member(party_struct *party, object *op) 00056 { 00057 objectlink *ol = get_objectlink(); 00058 unsigned char buf[MAX_BUF]; 00059 SockList sl; 00060 00061 /* Add the player to the party's linked list of members. */ 00062 ol->objlink.ob = op; 00063 objectlink_link(&party->members, NULL, NULL, party->members, ol); 00064 /* And set up player's pointer to the party. */ 00065 CONTR(op)->party = party; 00066 00067 /* Tell the client what party we have joined. */ 00068 sl.buf = buf; 00069 SOCKET_SET_BINARY_CMD(&sl, BINARY_CMD_PARTY); 00070 SockList_AddChar(&sl, CMD_PARTY_JOIN); 00071 SockList_AddString(&sl, party->name); 00072 Send_With_Handling(&CONTR(op)->socket, &sl); 00073 00074 CONTR(op)->last_party_hp = 0; 00075 CONTR(op)->last_party_sp = 0; 00076 CONTR(op)->last_party_grace = 0; 00077 } 00078 00083 void remove_party_member(party_struct *party, object *op) 00084 { 00085 objectlink *ol; 00086 unsigned char buf[MAX_BUF]; 00087 SockList sl; 00088 00089 /* Go through the party members, and remove the player that is 00090 * leaving. */ 00091 for (ol = party->members; ol; ol = ol->next) 00092 { 00093 if (ol->objlink.ob == op) 00094 { 00095 objectlink_unlink(&party->members, NULL, ol); 00096 break; 00097 } 00098 } 00099 00100 sl.buf = buf; 00101 00102 if (party->members) 00103 { 00104 SOCKET_SET_BINARY_CMD(&sl, BINARY_CMD_PARTY); 00105 SockList_AddChar(&sl, CMD_PARTY_REMOVE_MEMBER); 00106 SockList_AddString(&sl, op->name); 00107 00108 for (ol = party->members; ol; ol = ol->next) 00109 { 00110 if (CONTR(ol->objlink.ob)->socket.socket_version >= 1054) 00111 { 00112 Send_With_Handling(&CONTR(ol->objlink.ob)->socket, &sl); 00113 } 00114 } 00115 } 00116 00117 /* If no members left, remove the party. */ 00118 if (!party->members) 00119 { 00120 remove_party(CONTR(op)->party); 00121 } 00122 /* Otherwise choose a new leader, if the old one left. */ 00123 else if (op->name == party->leader) 00124 { 00125 FREE_AND_ADD_REF_HASH(party->leader, party->members->objlink.ob->name); 00126 new_draw_info_format(0, COLOR_WHITE, party->members->objlink.ob, "You are the new leader of party %s!", party->name); 00127 } 00128 00129 SOCKET_SET_BINARY_CMD(&sl, BINARY_CMD_PARTY); 00130 SockList_AddChar(&sl, CMD_PARTY_LEAVE); 00131 Send_With_Handling(&CONTR(op)->socket, &sl); 00132 00133 CONTR(op)->party = NULL; 00134 } 00135 00140 static party_struct *make_party(const char *name) 00141 { 00142 party_struct *party = (party_struct *) get_poolchunk(pool_parties); 00143 00144 memset(party, 0, sizeof(party_struct)); 00145 FREE_AND_COPY_HASH(party->name, name); 00146 00147 party->next = first_party; 00148 first_party = party; 00149 00150 return party; 00151 } 00152 00157 void form_party(object *op, const char *name) 00158 { 00159 party_struct *party = make_party(name); 00160 00161 add_party_member(party, op); 00162 new_draw_info_format(0, COLOR_WHITE, op, "You have formed party: %s", name); 00163 FREE_AND_ADD_REF_HASH(party->leader, op->name); 00164 CONTR(op)->stat_formed_party++; 00165 } 00166 00171 party_struct *find_party(const char *name) 00172 { 00173 party_struct *tmp; 00174 00175 for (tmp = first_party; tmp; tmp = tmp->next) 00176 { 00177 if (!strcmp(tmp->name, name)) 00178 { 00179 return tmp; 00180 } 00181 } 00182 00183 return NULL; 00184 } 00185 00202 sint16 party_member_get_skill(object *op, object *skill) 00203 { 00204 sint16 skill_id = skill->stats.sp; 00205 00206 switch (skill_id) 00207 { 00208 /* Handle weapon types. */ 00209 case SK_MELEE_WEAPON: 00210 case SK_SLASH_WEAP: 00211 case SK_CLEAVE_WEAP: 00212 case SK_PIERCE_WEAP: 00213 if (CONTR(op)->set_skill_weapon != NO_SKILL_READY) 00214 { 00215 return CONTR(op)->set_skill_weapon; 00216 } 00217 00218 break; 00219 00220 /* Handle archery weapon types. */ 00221 case SK_MISSILE_WEAPON: 00222 case SK_XBOW_WEAP: 00223 case SK_SLING_WEAP: 00224 if (CONTR(op)->set_skill_archery != NO_SKILL_READY) 00225 { 00226 return CONTR(op)->set_skill_archery; 00227 } 00228 00229 break; 00230 00231 /* Everything else. */ 00232 default: 00233 if (CONTR(op)->skill_ptr[skill_id]) 00234 { 00235 return skill_id; 00236 } 00237 } 00238 00239 return NO_SKILL_READY; 00240 } 00241 00246 static void party_loot_random(object *pl, object *corpse) 00247 { 00248 int count = 0, pl_id; 00249 party_struct *party = CONTR(pl)->party; 00250 objectlink *ol; 00251 object *tmp, *tmp_next; 00252 00253 for (ol = party->members; ol; ol = ol->next) 00254 { 00255 if (on_same_map(ol->objlink.ob, pl)) 00256 { 00257 count++; 00258 } 00259 } 00260 00261 if (count == 1) 00262 { 00263 return; 00264 } 00265 00266 for (tmp = corpse->inv; tmp; tmp = tmp_next) 00267 { 00268 int num = 1; 00269 00270 tmp_next = tmp->below; 00271 00272 /* Skip unpickable objects. */ 00273 if (!can_pick(pl, tmp)) 00274 { 00275 continue; 00276 } 00277 00278 pl_id = rndm(1, count); 00279 00280 for (ol = party->members; ol; ol = ol->next) 00281 { 00282 if (on_same_map(ol->objlink.ob, pl)) 00283 { 00284 if (num == pl_id) 00285 { 00286 if (player_can_carry(ol->objlink.ob, WEIGHT_NROF(tmp, tmp->nrof))) 00287 { 00288 new_draw_info_format(0, COLOR_BLUE, ol->objlink.ob, "You receive the %s.", query_name(tmp, NULL)); 00289 esrv_del_item(CONTR(pl), tmp->count, tmp->env); 00290 remove_ob(tmp); 00291 tmp = insert_ob_in_ob(tmp, ol->objlink.ob); 00292 esrv_send_item(ol->objlink.ob, tmp); 00293 } 00294 00295 break; 00296 } 00297 00298 num++; 00299 } 00300 } 00301 } 00302 } 00303 00309 int party_can_open_corpse(object *pl, object *corpse) 00310 { 00311 /* Check if the player is in the same party. */ 00312 if (!CONTR(pl)->party || corpse->slaying != CONTR(pl)->party->name) 00313 { 00314 new_draw_info(0, COLOR_WHITE, pl, "It's not your party's bounty."); 00315 return 0; 00316 } 00317 00318 switch (CONTR(pl)->party->loot) 00319 { 00320 /* Normal: anyone can access it. */ 00321 case PARTY_LOOT_NORMAL: 00322 default: 00323 return 1; 00324 00325 /* Only leader can access it. */ 00326 case PARTY_LOOT_LEADER: 00327 if (pl->name != CONTR(pl)->party->leader) 00328 { 00329 new_draw_info(0, COLOR_WHITE, pl, "You're not the party's leader."); 00330 return 0; 00331 } 00332 00333 return 1; 00334 } 00335 } 00336 00341 void party_handle_corpse(object *pl, object *corpse) 00342 { 00343 /* Sanity check. */ 00344 if (!CONTR(pl)->party) 00345 { 00346 return; 00347 } 00348 00349 switch (CONTR(pl)->party->loot) 00350 { 00351 case PARTY_LOOT_RANDOM: 00352 party_loot_random(pl, corpse); 00353 break; 00354 } 00355 } 00356 00364 void send_party_message(party_struct *party, const char *msg, int flag, object *op) 00365 { 00366 objectlink *ol; 00367 00368 for (ol = party->members; ol; ol = ol->next) 00369 { 00370 if (ol->objlink.ob == op) 00371 { 00372 continue; 00373 } 00374 00375 if (flag == PARTY_MESSAGE_STATUS) 00376 { 00377 new_draw_info(0, COLOR_YELLOW, ol->objlink.ob, msg); 00378 } 00379 else if (flag == PARTY_MESSAGE_CHAT) 00380 { 00381 new_draw_info(NDI_PLAYER, COLOR_YELLOW, ol->objlink.ob, msg); 00382 } 00383 } 00384 } 00385 00389 void remove_party(party_struct *party) 00390 { 00391 objectlink *ol; 00392 party_struct *tmp, *prev = NULL; 00393 00394 for (ol = party->members; ol; ol = ol->next) 00395 { 00396 CONTR(ol->objlink.ob)->party = NULL; 00397 objectlink_unlink(&party->members, NULL, ol); 00398 return_poolchunk(ol, pool_objectlink); 00399 } 00400 00401 for (tmp = first_party; tmp; prev = tmp, tmp = tmp->next) 00402 { 00403 if (tmp == party) 00404 { 00405 if (!prev) 00406 { 00407 first_party = tmp->next; 00408 } 00409 else 00410 { 00411 prev->next = tmp->next; 00412 } 00413 00414 break; 00415 } 00416 } 00417 00418 FREE_AND_CLEAR_HASH(party->name); 00419 FREE_AND_CLEAR_HASH(party->leader); 00420 return_poolchunk(party, pool_parties); 00421 } 00422 00426 void party_update_who(player *pl) 00427 { 00428 unsigned char sockbuf[HUGE_BUF]; 00429 uint8 hp, sp, grace; 00430 SockList sl; 00431 00432 if (!pl->party) 00433 { 00434 return; 00435 } 00436 00437 sl.buf = sockbuf; 00438 SOCKET_SET_BINARY_CMD(&sl, BINARY_CMD_PARTY); 00439 SockList_AddChar(&sl, CMD_PARTY_UPDATE); 00440 00441 hp = MAX(1, MIN((double) pl->ob->stats.hp / pl->ob->stats.maxhp * 100.0f, 100)); 00442 sp = MAX(1, MIN((double) pl->ob->stats.sp / pl->ob->stats.maxsp * 100.0f, 100)); 00443 grace = MAX(1, MIN((double) pl->ob->stats.grace / pl->ob->stats.maxgrace * 100.0f, 100)); 00444 00445 if (hp != pl->last_party_hp || sp != pl->last_party_sp || grace != pl->last_party_grace) 00446 { 00447 objectlink *ol; 00448 00449 SockList_AddString(&sl, pl->ob->name); 00450 SockList_AddChar(&sl, hp); 00451 SockList_AddChar(&sl, sp); 00452 SockList_AddChar(&sl, grace); 00453 00454 for (ol = pl->party->members; ol; ol = ol->next) 00455 { 00456 if (CONTR(ol->objlink.ob)->socket.socket_version >= 1054) 00457 { 00458 Send_With_Handling(&CONTR(ol->objlink.ob)->socket, &sl); 00459 } 00460 } 00461 } 00462 }
1.7.4