void transfer_creature(struct Thing *boxtng, struct Thing *transftng, unsigned char plyr_idx) { SYNCDBG(7,"Starting"); struct CreatureControl *cctrl; if (!thing_exists(boxtng) || (box_thing_to_special(boxtng) != SpcKind_TrnsfrCrtr) ) { ERRORMSG("Invalid transfer box object!"); return; } // Check if 'things' are correct if (!thing_exists(transftng) || !thing_is_creature(transftng) || (transftng->owner != plyr_idx)) { ERRORMSG("Invalid transfer creature thing!"); return; } cctrl = creature_control_get_from_thing(transftng); set_transfered_creature(plyr_idx, transftng->model, cctrl->explevel); remove_thing_from_power_hand_list(transftng, plyr_idx); kill_creature(transftng, INVALID_THING, -1, CrDed_NoEffects|CrDed_NotReallyDying); create_special_used_effect(&boxtng->mappos, plyr_idx); remove_events_thing_is_attached_to(boxtng); force_any_creature_dragging_owned_thing_to_drop_it(boxtng); delete_thing_structure(boxtng, 0); if (is_my_player_number(plyr_idx)) output_message(SMsg_CommonAcknowledge, 0, true); }
TbBool destroy_trap(struct Thing *traptng) { if ((traptng->trap.num_shots == 0) && !is_neutral_thing(traptng) && !is_hero_thing(traptng)) { readd_workshop_item_to_amount_placeable(traptng->owner, traptng->class_id, traptng->model); } delete_thing_structure(traptng, 0); return true; }
struct Thing *allocate_free_thing_structure_f(unsigned char allocflags, const char *func_name) { struct Thing *thing; long i; // Get a thing from "free things list" i = game.free_things_start_index; // If there is no free thing, try to free an effect if (i >= THINGS_COUNT-1) { if ((allocflags & FTAF_FreeEffectIfNoSlots) != 0) { thing = thing_get(game.thing_lists[TngList_EffectElems].index); if (!thing_is_invalid(thing)) { delete_thing_structure(thing, 0); } else { #if (BFDEBUG_LEVEL > 0) ERRORMSG("%s: Cannot free up effect element to allocate new thing!",func_name); #endif } } i = game.free_things_start_index; } // Now, if there is still no free thing (we couldn't free any) if (i >= THINGS_COUNT-1) { #if (BFDEBUG_LEVEL > 0) ERRORMSG("%s: Cannot allocate new thing, no free slots!",func_name); #endif return INVALID_THING; } // And if there is free one, allocate it thing = thing_get(game.free_things[i]); #if (BFDEBUG_LEVEL > 0) if (thing_exists(thing)) { ERRORMSG("%s: Found existing thing %d in free things list at pos %d!",func_name,(int)game.free_things[i],(int)i); } #endif LbMemorySet(thing, 0, sizeof(struct Thing)); if (thing_is_invalid(thing)) { ERRORMSG("%s: Got invalid thing slot instead of free one!",func_name); return INVALID_THING; } thing->alloc_flags |= TAlF_Exists; thing->index = game.free_things[i]; game.free_things[game.free_things_start_index] = 0; game.free_things_start_index++; TRACE_THING(thing); return thing; }
short good_wait_in_exit_door(struct Thing *thing) { struct CreatureControl *cctrl; struct Thing *tmptng; // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero thing %s index %d, owner %d - reset", thing_model_name(thing), (int)thing->index, (int)thing->owner); set_start_state(thing); erstat_inc(ESE_BadCreatrState); return 0; } //return _DK_good_wait_in_exit_door(thing); cctrl = creature_control_get_from_thing(thing); if (cctrl->field_282 <= 0) return 0; cctrl->field_282--; if (cctrl->field_282 == 0) { tmptng = find_base_thing_on_mapwho(TCls_Object, 49, thing->mappos.x.stl.num, thing->mappos.y.stl.num); if (!thing_is_invalid(tmptng)) { if (cctrl->byte_8A == tmptng->creation_turn) { remove_thing_from_creature_controlled_limbo(thing); set_start_state(thing); return 1; } } thing->creature.gold_carried = 0; tmptng = thing_get(cctrl->dragtng_idx); TRACE_THING(tmptng); if (!thing_is_invalid(tmptng)) { delete_thing_structure(tmptng, 0); } kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects|CrDed_NotReallyDying); } return 0; }
void resurrect_creature(struct Thing *boxtng, PlayerNumber owner, ThingModel crmodel, unsigned char crlevel) { struct Thing *creatng; if (!thing_exists(boxtng) || (box_thing_to_special(boxtng) != SpcKind_Resurrect) ) { ERRORMSG("Invalid resurrect box object!"); return; } creatng = create_creature(&boxtng->mappos, crmodel, owner); if (!thing_is_invalid(creatng)) { init_creature_level(creatng, crlevel); if (is_my_player_number(owner)) output_message(SMsg_CommonAcknowledge, 0, true); } create_special_used_effect(&boxtng->mappos, owner); remove_events_thing_is_attached_to(boxtng); force_any_creature_dragging_owned_thing_to_drop_it(boxtng); if ((gameadd.classic_bugs_flags & ClscBug_ResurrectForever) == 0) { remove_item_from_dead_creature_list(get_players_num_dungeon(owner), crmodel, crlevel); } delete_thing_structure(boxtng, 0); }
/** * Removes traps on the subtile and all sibling subtiles. * Either treats the action as selling and removes corresponding crate from workshop, * or treats it as destroying and updates workshop counts to skip re-arming the destroyed trap. * * @param stl_x Central subtile X coordinate. * @param stl_y Central subtile Y coordinate. * @param sell_value Value to be added to treasury if selling traps; if not selling but just removing, should be null. * @return Amount of traps removed. */ long remove_traps_around_subtile(MapSubtlCoord stl_x, MapSubtlCoord stl_y, long *sell_value) { long i,k; long total; total = 0; for (k=0; k < AROUND_TILES_COUNT; k++) { struct Thing *traptng; traptng = get_trap_for_position(stl_x+around[k].delta_x, stl_y+around[k].delta_y); if (!thing_is_invalid(traptng)) { if (sell_value != NULL) { // Do the refund only if we were able to sell armed trap i = game.traps_config[traptng->model].selling_value; if (traptng->trap.num_shots == 0) { // Trap not armed - try selling crate from workshop if (remove_workshop_item_from_amount_stored(traptng->owner, traptng->class_id, traptng->model, WrkCrtF_NoOffmap) > WrkCrtS_None) { remove_workshop_object_from_player(traptng->owner, trap_crate_object_model(traptng->model)); (*sell_value) += i; } } else { // Trap armed - we can get refund (*sell_value) += i; } // We don't want to increase trap_amount_placeable, so we'll not use destroy_trap() there delete_thing_structure(traptng, 0); } else { destroy_trap(traptng); } total++; } } return total; }
void activate_dungeon_special(struct Thing *cratetng, struct PlayerInfo *player) { SYNCDBG(6,"Starting"); short used; struct Coord3d pos; int spkindidx; // Gathering data which we'll need if the special is used and disposed. memcpy(&pos,&cratetng->mappos,sizeof(struct Coord3d)); spkindidx = cratetng->model - 86; used = 0; if (thing_exists(cratetng) && is_dungeon_special(cratetng)) { switch (cratetng->model) { case 86: reveal_whole_map(player); remove_events_thing_is_attached_to(cratetng); used = 1; delete_thing_structure(cratetng, 0); break; case 87: start_resurrect_creature(player, cratetng); break; case 88: start_transfer_creature(player, cratetng); break; case 89: if (steal_hero(player, &cratetng->mappos)) { remove_events_thing_is_attached_to(cratetng); used = 1; delete_thing_structure(cratetng, 0); } break; case 90: multiply_creatures(player); remove_events_thing_is_attached_to(cratetng); used = 1; delete_thing_structure(cratetng, 0); break; case 91: increase_level(player); remove_events_thing_is_attached_to(cratetng); used = 1; delete_thing_structure(cratetng, 0); break; case 92: make_safe(player); remove_events_thing_is_attached_to(cratetng); used = 1; delete_thing_structure(cratetng, 0); break; case 93: activate_bonus_level(player); remove_events_thing_is_attached_to(cratetng); used = 1; delete_thing_structure(cratetng, 0); break; default: ERRORLOG("Invalid dungeon special (Model %d)", (int)cratetng->model); break; } if ( used ) { if (is_my_player(player)) output_message(special_desc[spkindidx].speech_msg, 0, true); create_special_used_effect(&pos, player->id_number); } } }