|
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 00031 #include <global.h> 00032 00042 void apply_player_light_refill(object *who, object *op) 00043 { 00044 object *item = find_marked_object(who); 00045 int tmp; 00046 00047 if (!item) 00048 { 00049 new_draw_info_format(0, COLOR_WHITE, who, "You need to mark a light source you want refill."); 00050 return; 00051 } 00052 00053 if (item->type != LIGHT_APPLY || !item->race || !strstr(item->race, op->race)) 00054 { 00055 new_draw_info_format(0, COLOR_WHITE, who, "You can't refill the %s with the %s.", query_name(item, NULL), query_name(op, NULL)); 00056 return; 00057 } 00058 00059 tmp = (int) item->stats.maxhp - item->stats.food; 00060 00061 if (!tmp) 00062 { 00063 new_draw_info_format(0, COLOR_WHITE, who, "The %s is full and can't be refilled.", query_name(item, NULL)); 00064 return; 00065 } 00066 00067 if (op->stats.food <= tmp) 00068 { 00069 item->stats.food += op->stats.food; 00070 new_draw_info_format(0, COLOR_WHITE, who, "You refill the %s with %d units of %s.", query_name(item, NULL), op->stats.food, query_name(op, NULL)); 00071 decrease_ob(op); 00072 } 00073 else 00074 { 00075 object *filler = op; 00076 00077 if (filler->nrof > 1) 00078 { 00079 filler = get_split_ob(filler, 1, NULL, 0); 00080 filler->stats.food -= tmp; 00081 insert_ob_in_ob(filler, who); 00082 00083 if (QUERY_FLAG(op, FLAG_REMOVED)) 00084 { 00085 esrv_del_item(CONTR(who), op->count, op->env); 00086 } 00087 else 00088 { 00089 esrv_send_item(who, op); 00090 } 00091 } 00092 else 00093 { 00094 filler->stats.food -= tmp; 00095 } 00096 00097 item->stats.food += tmp; 00098 new_draw_info_format(0, COLOR_WHITE, who, "You refill the %s with %d units of %s.", query_name(item, NULL), tmp, query_name(filler, NULL)); 00099 esrv_send_item(who, filler); 00100 } 00101 00102 esrv_send_item(who, item); 00103 fix_player(who); 00104 } 00105 00110 void apply_player_light(object *who, object *op) 00111 { 00112 object *tmp; 00113 00114 if (QUERY_FLAG(op, FLAG_APPLIED)) 00115 { 00116 if ((QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))) 00117 { 00118 new_draw_info_format(0, COLOR_WHITE, who, "No matter how hard you try, you just can't remove it!"); 00119 return; 00120 } 00121 00122 if (QUERY_FLAG(op, FLAG_PERM_CURSED)) 00123 { 00124 SET_FLAG(op, FLAG_CURSED); 00125 } 00126 00127 if (QUERY_FLAG(op, FLAG_PERM_DAMNED)) 00128 { 00129 SET_FLAG(op, FLAG_DAMNED); 00130 } 00131 00132 new_draw_info_format(0, COLOR_WHITE, who, "You extinguish the %s.", query_name(op, NULL)); 00133 00134 if (!op->env && op->glow_radius) 00135 { 00136 adjust_light_source(op->map, op->x, op->y, -(op->glow_radius)); 00137 } 00138 00139 op->glow_radius = 0; 00140 CLEAR_FLAG(op, FLAG_APPLIED); 00141 CLEAR_FLAG(op, FLAG_CHANGING); 00142 00143 if (op->other_arch && op->other_arch->clone.sub_type & 1) 00144 { 00145 op->animation_id = op->other_arch->clone.animation_id; 00146 SET_ANIMATION(op, (NUM_ANIMATIONS(op) / NUM_FACINGS(op)) * op->direction); 00147 } 00148 else 00149 { 00150 CLEAR_FLAG(op, FLAG_ANIMATE); 00151 op->face = op->arch->clone.face; 00152 } 00153 00154 update_object(who, UP_OBJ_FACE); 00155 fix_player(who); 00156 } 00157 else 00158 { 00159 /* now the tricky thing: with the first apply cmd, we enlight the light source. 00160 * with the second, we apply it. if we unapply a light source, we always extinguish 00161 * them implicit. */ 00162 00163 /* LIGHT_APPLY light sources with last_sp (aka glow_radius) 0 are useless - 00164 * for example burnt out torches. The burnt out lights are still from same type 00165 * because they are perhaps applied from the player as they burnt out 00166 * and we don't want a player applying an illegal item. */ 00167 if (!op->last_sp) 00168 { 00169 new_draw_info_format(0, COLOR_WHITE, who, "The %s can't be lit.", query_name(op, NULL)); 00170 return; 00171 } 00172 00173 /* if glow_radius == 0, we have a extinguish light source. 00174 * before we can put it in the hand to use it, we have to turn 00175 * the light on. */ 00176 if (!op->glow_radius) 00177 { 00178 object *op_old; 00179 /* to delay insertion of object - or it simple re-merge! */ 00180 int tricky_flag = 0; 00181 00182 /* we have a non permanent source */ 00183 if (op->last_eat) 00184 { 00185 /* if not permanent, this is "filled" counter */ 00186 if (!op->stats.food) 00187 { 00188 /* no food charges, we can't light it up. 00189 * Note that light sources with other_arch set are 00190 * non rechargeable lights - like torches. */ 00191 new_draw_info_format(0, COLOR_WHITE, who, "You must first refill or recharge the %s.", query_name(op, NULL)); 00192 return; 00193 } 00194 } 00195 00196 /* now we have a filled or permanent, extinguish light source 00197 * lets light it - BUT we still have light_radius not active 00198 * when we not drop or apply the source. */ 00199 00200 /* the old split code has some side effects - 00201 * i force now first a split of #1 per hand */ 00202 op_old = op; 00203 00204 if (op->nrof > 1) 00205 { 00206 object *one = get_object(); 00207 copy_object(op, one, 0); 00208 op->nrof -= 1; 00209 one->nrof = 1; 00210 00211 if (op->env && (op->env->type == PLAYER || op->env->type == CONTAINER)) 00212 { 00213 esrv_update_item(UPD_NROF, op->env, op); 00214 } 00215 else if (!op->env) 00216 { 00217 update_object(op, UP_OBJ_FACE); 00218 } 00219 00220 tricky_flag = 1; 00221 op = one; 00222 } 00223 00224 /* light is applied in player inventory - so we 00225 * start the 3 apply chain - because it can be taken 00226 * in hand. */ 00227 if (op_old->env && op_old->env->type == PLAYER) 00228 { 00229 new_draw_info_format(0, COLOR_WHITE, who, "You prepare %s to light.", query_name(op, NULL)); 00230 00231 /* we have a non permanent source */ 00232 if (op->last_eat) 00233 { 00234 SET_FLAG(op, FLAG_CHANGING); 00235 } 00236 00237 if (op->speed) 00238 { 00239 SET_FLAG(op, FLAG_ANIMATE); 00240 /* be sure to get the right anim */ 00241 op->animation_id = op->arch->clone.animation_id; 00242 SET_ANIMATION(op, (NUM_ANIMATIONS(op) / NUM_FACINGS(op)) * op->direction); 00243 } 00244 00245 if (tricky_flag) 00246 { 00247 op = insert_ob_in_ob(op, op_old->env); 00248 } 00249 00250 op->glow_radius = (sint8) op->last_sp; 00251 fix_player(who); 00252 } 00253 /* we are not in a player inventory - so simple turn it on */ 00254 else 00255 { 00256 new_draw_info_format(0, COLOR_WHITE, who, "You light the %s.", query_name(op, NULL)); 00257 00258 /* we have a non permanent source */ 00259 if (op->last_eat) 00260 { 00261 SET_FLAG(op, FLAG_CHANGING); 00262 } 00263 00264 if (op->speed) 00265 { 00266 SET_FLAG(op, FLAG_ANIMATE); 00267 op->animation_id = op->arch->clone.animation_id; 00268 SET_ANIMATION(op, (NUM_ANIMATIONS(op) / NUM_FACINGS(op)) * op->direction); 00269 } 00270 00271 if (QUERY_FLAG(op, FLAG_PERM_CURSED)) 00272 { 00273 SET_FLAG(op, FLAG_CURSED); 00274 } 00275 00276 if (QUERY_FLAG(op, FLAG_PERM_DAMNED)) 00277 { 00278 SET_FLAG(op, FLAG_DAMNED); 00279 } 00280 00281 if (tricky_flag) 00282 { 00283 if (!op_old->env) 00284 { 00285 /* the item WAS before this on this spot - we only turn it on but we don't moved it */ 00286 insert_ob_in_map(op, op_old->map, op_old, INS_NO_WALK_ON); 00287 } 00288 else 00289 { 00290 op = insert_ob_in_ob(op, op_old->env); 00291 } 00292 } 00293 00294 op->glow_radius = (sint8) op->last_sp; 00295 00296 if (!op->env && op->glow_radius) 00297 { 00298 adjust_light_source(op->map, op->x, op->y, op->glow_radius); 00299 } 00300 00301 update_object(op, UP_OBJ_FACE); 00302 } 00303 } 00304 else 00305 { 00306 if (op->env && op->env->type == PLAYER) 00307 { 00308 /* remove any other applied light source first */ 00309 for (tmp = who->inv; tmp != NULL; tmp = tmp->below) 00310 { 00311 if (tmp->type == op->type && QUERY_FLAG(tmp, FLAG_APPLIED) && tmp != op) 00312 { 00313 if ((QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))) 00314 { 00315 new_draw_info(0, COLOR_WHITE, who, "No matter how hard you try, you just can't remove it!"); 00316 return; 00317 } 00318 00319 if (QUERY_FLAG(tmp, FLAG_PERM_CURSED)) 00320 { 00321 SET_FLAG(tmp, FLAG_CURSED); 00322 } 00323 00324 if (QUERY_FLAG(tmp, FLAG_PERM_DAMNED)) 00325 { 00326 SET_FLAG(tmp, FLAG_DAMNED); 00327 } 00328 00329 new_draw_info_format(0, COLOR_WHITE, who, "You extinguish the %s.", query_name(tmp, NULL)); 00330 00331 /* on map */ 00332 if (!tmp->env && tmp->glow_radius) 00333 { 00334 adjust_light_source(tmp->map, tmp->x, tmp->y, -(tmp->glow_radius)); 00335 } 00336 00337 tmp->glow_radius = 0; 00338 CLEAR_FLAG(tmp, FLAG_APPLIED); 00339 CLEAR_FLAG(tmp, FLAG_CHANGING); 00340 00341 if (op->other_arch && op->other_arch->clone.sub_type & 1) 00342 { 00343 op->animation_id = op->other_arch->clone.animation_id; 00344 SET_ANIMATION(op, (NUM_ANIMATIONS(op) / NUM_FACINGS(op)) * op->direction); 00345 } 00346 else 00347 { 00348 CLEAR_FLAG(op, FLAG_ANIMATE); 00349 op->face = op->arch->clone.face; 00350 } 00351 00352 update_object(tmp, UP_OBJ_FACE); 00353 esrv_send_item(who, tmp); 00354 } 00355 } 00356 00357 new_draw_info_format(0, COLOR_WHITE, who, "You apply %s as light.", query_name(op, NULL)); 00358 SET_FLAG(op, FLAG_APPLIED); 00359 fix_player(who); 00360 update_object(who, UP_OBJ_FACE); 00361 } 00362 /* not part of player inv - turn light off ! */ 00363 else 00364 { 00365 if (QUERY_FLAG(op, FLAG_PERM_CURSED)) 00366 { 00367 SET_FLAG(op, FLAG_CURSED); 00368 } 00369 00370 if (QUERY_FLAG(op, FLAG_PERM_DAMNED)) 00371 { 00372 SET_FLAG(op, FLAG_DAMNED); 00373 } 00374 00375 new_draw_info_format(0, COLOR_WHITE, who, "You extinguish the %s.", query_name(op, NULL)); 00376 00377 /* on map */ 00378 if (!op->env && op->glow_radius) 00379 { 00380 adjust_light_source(op->map, op->x, op->y, -(op->glow_radius)); 00381 } 00382 00383 op->glow_radius = 0; 00384 CLEAR_FLAG(op, FLAG_APPLIED); 00385 CLEAR_FLAG(op, FLAG_CHANGING); 00386 00387 if (op->other_arch && op->other_arch->clone.sub_type & 1) 00388 { 00389 op->animation_id = op->other_arch->clone.animation_id; 00390 SET_ANIMATION(op, (NUM_ANIMATIONS(op) / NUM_FACINGS(op)) * op->direction); 00391 } 00392 else 00393 { 00394 CLEAR_FLAG(op, FLAG_ANIMATE); 00395 op->face = op->arch->clone.face; 00396 } 00397 00398 update_object(op, UP_OBJ_FACE); 00399 } 00400 } 00401 } 00402 00403 if (op->env && (op->env->type == PLAYER || op->env->type == CONTAINER)) 00404 { 00405 esrv_send_item(op->env, op); 00406 } 00407 } 00408 00416 void apply_lighter(object *who, object *lighter) 00417 { 00418 object *item; 00419 tag_t count; 00420 uint32 nrof; 00421 int is_player_env = 0; 00422 char item_name[MAX_BUF]; 00423 00424 item = find_marked_object(who); 00425 00426 if (item) 00427 { 00428 /* lighter gets used up */ 00429 if (lighter->last_eat && lighter->stats.food) 00430 { 00431 /* Split multiple lighters if they're being used up. Otherwise * 00432 * one charge from each would be used up. --DAMN */ 00433 if (lighter->nrof > 1) 00434 { 00435 object *oneLighter = get_object(); 00436 copy_object(lighter, oneLighter, 0); 00437 lighter->nrof -= 1; 00438 oneLighter->nrof = 1; 00439 oneLighter->stats.food--; 00440 esrv_send_item(who, lighter); 00441 oneLighter=insert_ob_in_ob(oneLighter, who); 00442 esrv_send_item(who, oneLighter); 00443 } 00444 else 00445 { 00446 lighter->stats.food--; 00447 } 00448 } 00449 /* no charges left in lighter */ 00450 else if (lighter->last_eat) 00451 { 00452 new_draw_info_format(0, COLOR_WHITE, who, "You attempt to light the %s with a used up %s.", item->name, lighter->name); 00453 return; 00454 } 00455 00456 /* Perhaps we should split what we are trying to light on fire? 00457 * I can't see many times when you would want to light multiple 00458 * objects at once. */ 00459 nrof = item->nrof; 00460 count = item->count; 00461 00462 /* If the item is destroyed, we don't have a valid pointer to the 00463 * name object, so make a copy so the message we print out makes 00464 * some sense. */ 00465 strcpy(item_name, item->name); 00466 00467 if (who == is_player_inv(item)) 00468 { 00469 is_player_env = 1; 00470 } 00471 00472 /* Change to check count and not freed, since the object pointer 00473 * may have gotten recycled */ 00474 if ((nrof != item->nrof ) || (count != item->count)) 00475 { 00476 new_draw_info_format(0, COLOR_WHITE, who, "You light the %s with the %s.", item_name, lighter->name); 00477 00478 if (is_player_env) 00479 { 00480 fix_player(who); 00481 } 00482 } 00483 else 00484 { 00485 new_draw_info_format(0, COLOR_WHITE, who, "You attempt to light the %s with the %s and fail.", item->name, lighter->name); 00486 } 00487 } 00488 /* nothing to light */ 00489 else 00490 { 00491 new_draw_info(0, COLOR_WHITE, who, "You need to mark a lightable object."); 00492 } 00493 }
1.7.4