/** * Finds a safe and unused, adjacent position in room for a creature. * * @param pos Position of the creature to be moved. * @param owner Room owner to keep. * @return Coded subtiles of the new position, or 0 on failure. * @see person_get_somewhere_adjacent_in_room() */ SubtlCodedCoords find_unused_adjacent_position_in_workshop(const struct Coord3d *pos, long owner) { static const struct Around corners[] = { {1,2}, {0,1}, {1,0}, {2,1} }; long i; for (i=0; i < SMALL_AROUND_LENGTH; i++) { MapSlabCoord slb_x, slb_y; slb_x = subtile_slab_fast(pos->x.stl.num) + (long)small_around[i].delta_x; slb_y = subtile_slab_fast(pos->y.stl.num) + (long)small_around[i].delta_y; struct SlabMap *slb; slb = get_slabmap_block(slb_x, slb_y); if ((slb->kind == SlbT_WORKSHOP) && (slabmap_owner(slb) == owner)) { struct Thing *mnfc_creatng; MapSubtlCoord stl_x, stl_y; stl_x = slab_subtile(slb_x, corners[i].delta_x); stl_y = slab_subtile(slb_y, corners[i].delta_y); mnfc_creatng = get_other_creature_manufacturing_on_subtile(owner, stl_x, stl_y, INVALID_THING); if (!thing_is_invalid(mnfc_creatng)) { // Position used by another manufacturer continue; } struct Thing *objtng; objtng = get_workshop_equipment_to_work_with_on_subtile(owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y)); if (thing_is_invalid(objtng)) { // Position has no work equipment nearby continue; } // Found an acceptable position return get_subtile_number(stl_x, stl_y); } } return 0; }
long creature_add_lair_to_room(struct Thing *creatng, struct Room *room) { struct Thing *lairtng; if (!room_has_enough_free_capacity_for_creature(room, creatng)) return 0; //return _DK_creature_add_lair_to_room(thing, room); // Make sure we don't already have a lair on that position lairtng = find_creature_lair_at_subtile(creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, 0); if (!thing_is_invalid(lairtng)) return 0; struct CreatureStats *crstat; struct CreatureControl *cctrl; crstat = creature_stats_get_from_thing(creatng); cctrl = creature_control_get_from_thing(creatng); room->content_per_model[creatng->model]++; room->used_capacity += crstat->lair_size; if ((cctrl->lair_room_id > 0) && (cctrl->lairtng_idx > 0)) { struct Room *room; room = room_get(cctrl->lair_room_id); creature_remove_lair_from_room(creatng, room); } cctrl->lair_room_id = room->index; // Create the lair thing struct CreatureData *crdata; struct Coord3d pos; pos.x.val = creatng->mappos.x.val; pos.y.val = creatng->mappos.y.val; pos.z.val = creatng->mappos.z.val; crdata = creature_data_get_from_thing(creatng); lairtng = create_object(&pos, crdata->field_1, creatng->owner, -1); if (thing_is_invalid(lairtng)) { ERRORLOG("Could not create lair totem"); remove_thing_from_mapwho(creatng); place_thing_in_mapwho(creatng); return 1; // Return that so we won't try to redo the action over and over } lairtng->mappos.z.val = get_thing_height_at(lairtng, &lairtng->mappos); // Associate creature with the lair cctrl->lairtng_idx = lairtng->index; lairtng->word_13 = creatng->index; lairtng->word_15 = 1; // Lair size depends on creature level lairtng->word_17 = 300 * cctrl->explevel / 20 + 300; lairtng->field_52 = ACTION_RANDOM(0x800); struct Objects *objdat; unsigned long i; objdat = get_objects_data_for_thing(lairtng); i = convert_td_iso(objdat->field_5); set_thing_draw(lairtng, i, objdat->field_7, lairtng->word_15, 0, -1, objdat->field_11); thing_play_sample(creatng, 158, NORMAL_PITCH, 0, 3, 1, 2, FULL_LOUDNESS); create_effect(&pos, imp_spangle_effects[creatng->owner], creatng->owner); anger_set_creature_anger(creatng, 0, AngR_NoLair); remove_thing_from_mapwho(creatng); place_thing_in_mapwho(creatng); return 1; }
void increase_level(struct PlayerInfo *player) { struct Dungeon *dungeon; struct CreatureControl *cctrl; struct Thing *thing; unsigned long k; int i; dungeon = get_dungeon(player->id_number); // Increase level of normal creatures k = 0; i = dungeon->creatr_list_start; while (i != 0) { thing = thing_get(i); cctrl = creature_control_get_from_thing(thing); if (thing_is_invalid(thing) || creature_control_invalid(cctrl)) { ERRORLOG("Jump to invalid creature detected"); break; } i = cctrl->players_next_creature_idx; // Thing list loop body creature_increase_level(thing); // Thing list loop body ends k++; if (k > CREATURES_COUNT) { ERRORLOG("Infinite loop detected when sweeping creatures list"); erstat_inc(ESE_InfChainTngPerOwner); break; } } // Increase level of special workers k = 0; i = dungeon->digger_list_start; while (i != 0) { thing = thing_get(i); cctrl = creature_control_get_from_thing(thing); if (thing_is_invalid(thing) || creature_control_invalid(cctrl)) { ERRORLOG("Jump to invalid creature detected"); break; } i = cctrl->players_next_creature_idx; // Thing list loop body creature_increase_level(thing); // Thing list loop body ends k++; if (k > CREATURES_COUNT) { ERRORLOG("Infinite loop detected when sweeping creatures list"); erstat_inc(ESE_InfChainTngPerOwner); break; } } }
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; }
void init_traps(void) { struct Thing *thing; int i, k; k = 0; const struct StructureList *slist; slist = get_list_for_thing_class(TCls_Trap); i = slist->index; while (i != 0) { thing = thing_get(i); if (thing_is_invalid(thing)) { ERRORLOG("Jump to invalid thing detected"); break; } i = thing->next_of_class; // Per thing code if (thing->trap.num_shots == 0) { rearm_trap(thing); } // Per thing code ends k++; if (k > slist->index) { ERRORLOG("Infinite loop detected when sweeping things list"); break; } } }
short good_leave_through_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 %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner); set_start_state(thing); erstat_inc(ESE_BadCreatrState); return false; } //return _DK_good_leave_through_exit_door(thing); tmptng = find_base_thing_on_mapwho(TCls_Object, 49, thing->mappos.x.stl.num, thing->mappos.y.stl.num); if (thing_is_invalid(tmptng)) { return 0; } cctrl = creature_control_get_from_thing(thing); thing->creature.gold_carried = 0; cctrl->field_282 = game.hero_door_wait_time; cctrl->byte_8A = tmptng->creation_turn; place_thing_in_creature_controlled_limbo(thing); internal_set_thing_state(thing, CrSt_GoodWaitInExitDoor); return 1; }
short good_drops_gold(struct Thing *thing) { // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner); set_start_state(thing); erstat_inc(ESE_BadCreatrState); return 0; } //return _DK_good_drops_gold(thing); GoldAmount amount; amount = game.pot_of_gold_holds; if (thing->creature.gold_carried <= game.pot_of_gold_holds) amount = thing->creature.gold_carried; struct Thing *gldtng; gldtng = create_object(&thing->mappos, 6, thing->owner, -1); if (thing_is_invalid(gldtng)) { return 0; } gldtng->valuable.gold_stored = amount; thing->creature.gold_carried -= amount; // Update size of the gold object add_gold_to_pile(gldtng, 0); internal_set_thing_state(thing, CrSt_GoodBackAtStart); return 1; }
TbBool good_setup_wander_to_dungeon_heart(struct Thing *creatng, PlayerNumber plyr_idx) { struct PlayerInfo *player; SYNCDBG(18,"Starting"); TRACE_THING(creatng); if (creatng->owner == plyr_idx) { ERRORLOG("The %s tried to wander to own (%d) heart", thing_model_name(creatng), (int)plyr_idx); return false; } player = get_player(plyr_idx); if (!player_exists(player)) { WARNLOG("The %s tried to wander to inactive player (%d) heart", thing_model_name(creatng), (int)plyr_idx); return false; } struct Thing *heartng; heartng = get_player_soul_container(plyr_idx); TRACE_THING(heartng); if (thing_is_invalid(heartng)) { WARNLOG("The %s tried to wander to player %d which has no heart", thing_model_name(creatng), (int)plyr_idx); return false; } set_creature_object_combat(creatng, heartng); return true; }
struct Thing *get_trap_for_position(MapSubtlCoord stl_x, MapSubtlCoord stl_y) { struct Thing *thing; struct Map *mapblk; long i; unsigned long k; mapblk = get_map_block_at(stl_x,stl_y); k = 0; i = get_mapwho_thing_index(mapblk); while (i != 0) { thing = thing_get(i); TRACE_THING(thing); if (thing_is_invalid(thing)) { ERRORLOG("Jump to invalid thing detected"); break; } i = thing->next_on_mapblk; // Per thing code start if (thing->class_id == TCls_Trap) { return thing; } // Per thing code end k++; if (k > THINGS_COUNT) { ERRORLOG("Infinite loop detected when sweeping things list"); break; } } return INVALID_THING; }
struct Thing *create_crate_in_workshop(struct Room *room, ThingModel cratngmodel, MapSubtlCoord stl_x, MapSubtlCoord stl_y) { struct Coord3d pos; struct Thing *cratetng; if (!room_role_matches(room->kind, RoRoF_CratesStorage)) { SYNCDBG(4,"Crate %s cannot be created in a %s owned by player %d, wrong room",object_code_name(cratngmodel),room_code_name(room->kind),(int)room->owner); return INVALID_THING; } pos.x.val = subtile_coord_center(stl_x); pos.y.val = subtile_coord_center(stl_y); pos.z.val = 0; cratetng = create_object(&pos, cratngmodel, room->owner, -1); if (thing_is_invalid(cratetng)) { return INVALID_THING; } // Neutral thing do not need any more processing if (is_neutral_thing(cratetng) || !player_exists(get_player(room->owner))) { return cratetng; } if (!add_workshop_object_to_workshop(room, cratetng)) { ERRORLOG("Could not fit %s in %s index %d", thing_model_name(cratetng),room_code_name(room->kind),(int)room->index); //remove_item_from_room_capacity(room); -- no need, it was not added destroy_object(cratetng); return INVALID_THING; } ThingClass tngclass; ThingModel tngmodel; tngclass = crate_thing_to_workshop_item_class(cratetng); tngmodel = crate_thing_to_workshop_item_model(cratetng); add_workshop_item_to_amounts(cratetng->owner, tngclass, tngmodel); return cratetng; }
void thing_play_sample(struct Thing *thing, short smptbl_idx, unsigned short pitch, char a4, unsigned char a5, unsigned char a6, long a7, long loudness) { struct Coord3d rcpos; long eidx; if (SoundDisabled) return; if (GetCurrentSoundMasterVolume() <= 0) return; if (thing_is_invalid(thing)) return; rcpos.x.val = Receiver.pos.val_x; rcpos.y.val = Receiver.pos.val_y; rcpos.z.val = Receiver.pos.val_z; if (get_3d_box_distance(&rcpos, &thing->mappos) < MaxSoundDistance) { eidx = thing->snd_emitter_id; if (eidx > 0) { S3DAddSampleToEmitterPri(eidx, smptbl_idx, 0, pitch, loudness, a4, a5, a6 | 0x01, a7); } else { eidx = S3DCreateSoundEmitterPri(thing->mappos.x.val, thing->mappos.y.val, thing->mappos.z.val, smptbl_idx, 0, pitch, loudness, a4, a6 | 0x01, a7); thing->snd_emitter_id = eidx; } } }
/** * Returns a hero gate object to which given hero can navigate. * @todo CREATURE_AI It returns first hero door found, not the best one. * Maybe it should find the one he will reach faster, or at least a random one? * @param herotng The hero to be able to make it to gate. * @return The gate thing, or invalid thing. */ struct Thing *find_hero_door_hero_can_navigate_to(struct Thing *herotng) { struct Thing *thing; unsigned long k; int i; k = 0; i = game.thing_lists[TngList_Objects].index; while (i != 0) { thing = thing_get(i); if (thing_is_invalid(thing)) { ERRORLOG("Jump to invalid thing detected"); break; } i = thing->next_of_class; // Per thing code if (object_is_hero_gate(thing)) { if (creature_can_navigate_to_with_storage(herotng, &thing->mappos, NavRtF_Default)) { return thing; } } // Per thing code ends k++; if (k > THINGS_COUNT) { ERRORLOG("Infinite loop detected when sweeping things list"); break; } } return NULL; }
void redraw_creature_view(void) { SYNCDBG(6,"Starting"); TbGraphicsWindow ewnd; struct PlayerInfo *player; struct Thing *thing; //_DK_redraw_creature_view(); return; player = get_my_player(); if (player->field_45F != 2) player->field_45F = 2; update_explored_flags_for_power_sight(player); thing = thing_get(player->controlled_thing_idx); TRACE_THING(thing); if (!thing_is_invalid(thing)) draw_creature_view(thing); if (smooth_on) { store_engine_window(&ewnd,pixel_size); smooth_screen_area(lbDisplay.WScreen, ewnd.x, ewnd.y, ewnd.width, ewnd.height, lbDisplay.GraphicsScreenWidth); } remove_explored_flags_for_power_sight(player); draw_swipe_graphic(); if ((game.numfield_C & 0x20) != 0) { draw_whole_status_panel(); } draw_gui(); if ((game.numfield_C & 0x20) != 0) { draw_overlay_compass(player->minimap_pos_x, player->minimap_pos_y); } message_draw(); gui_draw_all_boxes(); draw_tooltip(); }
CrCheckRet process_scavenge_function(struct Thing *calltng) { SYNCDBG(18,"Starting for %s owner %d",thing_model_name(calltng),(int)calltng->owner); //return _DK_process_scavenge_function(thing); struct CreatureControl *callctrl; callctrl = creature_control_get_from_thing(calltng); struct Dungeon *calldngn; struct Room *room; calldngn = get_dungeon(calltng->owner); room = get_room_creature_works_in(calltng); if ( !room_still_valid_as_type_for_thing(room, RoK_SCAVENGER, calltng) ) { WARNLOG("Room %s owned by player %d is bad work place for %s owned by played %d",room_code_name(room->kind),(int)room->owner,thing_model_name(calltng),(int)calltng->owner); set_start_state(calltng); return CrCkRet_Continue; } struct CreatureStats *crstat; crstat = creature_stats_get_from_thing(calltng); if (!player_can_afford_to_scavenge_creature(calltng)) { if (is_my_player_number(calltng->owner)) output_message(SMsg_NoGoldToScavenge, 500, 1); set_start_state(calltng); return CrCkRet_Continue; } if (calldngn->scavenge_counters_turn != game.play_gameturn) { reset_scavenge_counts(calldngn); } long work_value; work_value = compute_creature_work_value(crstat->scavenge_value*256, room->efficiency, callctrl->explevel); work_value = process_work_speed_on_work_value(calltng, work_value); SYNCDBG(9,"The %s index %d owner %d produced %d scavenge points",thing_model_name(calltng),(int)calltng->index,(int)calltng->owner,(int)work_value); struct Thing *scavtng; scavtng = get_scavenger_target(calltng); if (!thing_is_invalid(scavtng)) { process_scavenge_creature_from_level(scavtng, calltng, work_value); } else if (can_scavenge_creature_from_pool(calldngn, calltng->model)) { process_scavenge_creature_from_pool(calltng, work_value); } else { if (crstat->entrance_force) { calldngn->field_1485++; } return 0; } callctrl->field_82++; if (callctrl->field_82 > game.scavenge_cost_frequency) { callctrl->field_82 -= game.scavenge_cost_frequency; if (take_money_from_dungeon(calltng->owner, crstat->scavenger_cost, 1) < 0) { ERRORLOG("Cannot take %d gold from dungeon %d",(int)crstat->scavenger_cost,(int)calltng->owner); } create_price_effect(&calltng->mappos, calltng->owner, crstat->scavenger_cost); } return 0; }
long computer_check_for_accelerate(struct Computer2 *comp, struct ComputerCheck * check) { static RoomKind workers_in_rooms[] = {RoK_LIBRARY,RoK_LIBRARY,RoK_WORKSHOP,RoK_TRAINING,RoK_SCAVENGER}; struct Thing *thing; long i,n; SYNCDBG(8,"Starting"); //return _DK_computer_check_for_accelerate(comp, check); if (computer_able_to_use_magic(comp, PwrK_SPEEDCRTR, 8, 3) != 1) { return 4; } n = check->param1 % (sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0])); if (n <= 0) n = ACTION_RANDOM(sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0])); for (i=0; i < sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]); i++) { thing = computer_check_creatures_in_dungeon_rooms_of_kind_for_accelerate(comp, workers_in_rooms[n]); if (!thing_is_invalid(thing)) { SYNCDBG(8,"Cast on thing %d",(int)thing->index); return 1; } n = (n+1) % (sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0])); } return 4; }
struct Thing *get_workshop_box_thing(PlayerNumber owner, ThingModel objmodel) { struct Thing *thing; int i,k; k = 0; i = game.thing_lists[TngList_Objects].index; while (i > 0) { thing = thing_get(i); if (thing_is_invalid(thing)) break; i = thing->next_of_class; // Per-thing code if ( ((thing->alloc_flags & TAlF_Exists) != 0) && (thing->model == objmodel) && (thing->owner == owner) ) { struct Room *room; room = get_room_thing_is_on(thing); if (!thing_is_picked_up(thing) && room_role_matches(room->kind, RoRoF_CratesStorage) && (room->owner == owner)) return thing; } // Per-thing code ends k++; if (k > THINGS_COUNT) { ERRORLOG("Infinite loop detected when sweeping things list"); break; } } return INVALID_THING; }
TbBool prison_convert_creature_to_skeleton(struct Room *room, struct Thing *thing) { struct Dungeon *dungeon; struct CreatureControl *cctrl; struct Thing *crthing; long crmodel; cctrl = creature_control_get_from_thing(thing); crmodel = get_room_create_creature_model(room->kind); // That normally returns skeleton breed crthing = create_creature(&thing->mappos, crmodel, room->owner); if (thing_is_invalid(crthing)) { ERRORLOG("Couldn't create creature %s in prison", creature_code_name(crmodel)); return false; } init_creature_level(crthing, cctrl->explevel); set_start_state(crthing); if (creature_model_bleeds(thing->model)) create_effect_around_thing(thing, TngEff_Unknown10); kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects); dungeon = get_dungeon(room->owner); if (!dungeon_invalid(dungeon)) { dungeon->lvstats.skeletons_raised++; } return true; }
short creature_freeze_prisonors(struct Thing *creatng) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); if (cctrl->instance_id != CrInst_NULL) { return 1; } if (!creature_instance_has_reset(creatng, CrInst_FREEZE)) { if (creature_choose_random_destination_on_valid_adjacent_slab(creatng)) { creatng->continue_state = CrSt_CreatureFreezePrisoners; } return 1; } struct Thing *victng; victng = find_prisoner_for_thing(creatng); if (thing_is_invalid(victng)) { set_start_state(creatng); return 0; } long dist; dist = get_combat_distance(creatng, victng); if (dist < 156) { creature_retreat_from_combat(creatng, victng, CrSt_CreatureFreezePrisoners, 0); } else if ((dist <= 2048) && (creature_can_see_combat_path(creatng, victng, dist) > AttckT_Unset)) { set_creature_instance(creatng, CrInst_FREEZE, 1, victng->index, 0); } else { creature_move_to(creatng, &victng->mappos, cctrl->max_speed, 0, 0); } return 1; }
long computer_check_for_pretty(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; SYNCDBG(8,"Starting"); dungeon = comp->dungeon; MapSubtlCoord stl_x, stl_y; if (computer_able_to_use_magic(comp, PwrK_HAND, 1, 1) != CTaskRet_Unk1) { return CTaskRet_Unk4; } { long stack_len; stack_len = dungeon->digger_stack_length; if (stack_len <= check->param1 * dungeon->total_area / 100) { return CTaskRet_Unk4; } long n; n = find_in_imp_stack_starting_at(DigTsk_ImproveDungeon, ACTION_RANDOM(stack_len), dungeon); if (n < 0) { return CTaskRet_Unk4; } const struct DiggerStack *dstack; dstack = &dungeon->digger_stack[n]; stl_x = stl_num_decode_x(dstack->stl_num); stl_y = stl_num_decode_y(dstack->stl_num); } struct Thing * creatng; creatng = find_imp_for_pickup(comp, stl_x, stl_y); if (thing_is_invalid(creatng)) { return CTaskRet_Unk4; } if (!create_task_move_creature_to_subtile(comp, creatng, stl_x, stl_y, CrSt_ImpImprovesDungeon)) { return CTaskRet_Unk4; } return CTaskRet_Unk1; }
struct Thing *create_and_control_creature_as_controller(struct PlayerInfo *player, long breed, struct Coord3d *pos) { struct CreatureStats *crstat; struct CreatureControl *cctrl; struct Dungeon *dungeon; struct Thing *thing; struct Camera *cam; struct InitLight ilght; SYNCDBG(6,"Request for model %ld at (%d,%d,%d)",breed,(int)pos->x.val,(int)pos->y.val,(int)pos->z.val); //return _DK_create_and_control_creature_as_controller(player, a2, pos); thing = create_creature(pos, breed, player->id_number); if (thing_is_invalid(thing)) return INVALID_THING; dungeon = get_dungeon(thing->owner); dungeon->num_active_creatrs--; dungeon->owned_creatures_of_model[thing->model]--; if (is_my_player(player)) { toggle_status_menu(0); turn_off_roaming_menus(); } cam = player->acamera; player->controlled_thing_idx = thing->index; player->field_31 = thing->creation_turn; player->field_4B5 = cam->field_6; thing->alloc_flags |= TAlF_IsControlled; thing->field_4F |= 0x01; cctrl = creature_control_get_from_thing(thing); cctrl->flgfield_2 |= 0x02; cctrl->max_speed = calculate_correct_creature_maxspeed(thing); set_player_mode(player, PVT_CreatureContrl); set_start_state(thing); // Preparing light object LbMemorySet(&ilght, 0, sizeof(struct InitLight)); ilght.mappos.x.val = thing->mappos.x.val; ilght.mappos.y.val = thing->mappos.y.val; ilght.mappos.z.val = thing->mappos.z.val; ilght.field_2 = 36; ilght.field_3 = 1; ilght.is_dynamic = 1; ilght.field_0 = 2560; thing->light_id = light_create_light(&ilght); if (thing->light_id != 0) { light_set_light_never_cache(thing->light_id); } else { ERRORLOG("Cannot allocate light to new hero"); } if (is_my_player_number(thing->owner)) { if (thing->class_id == TCls_Creature) { crstat = creature_stats_get_from_thing(thing); setup_eye_lens(crstat->eye_effect); } } return thing; }
TbBool thing_is_deployed_trap(const struct Thing *thing) { if (thing_is_invalid(thing)) return false; if (thing->class_id != TCls_Trap) return false; return true; }
PlayerNumber get_slab_owner_thing_is_on(const struct Thing *thing) { if (thing_is_invalid(thing)) return game.neutral_player_num; struct SlabMap *slb; slb = get_slabmap_for_subtile(thing->mappos.x.stl.num, thing->mappos.y.stl.num); return slabmap_owner(slb); }
void process_disease(struct Thing *creatng) { SYNCDBG(18,"Starting"); //_DK_process_disease(thing); struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); if (!creature_affected_by_spell(creatng, SplK_Disease)) { return; } if (ACTION_RANDOM(100) < game.disease_transfer_percentage) { SubtlCodedCoords stl_num; long n; stl_num = get_subtile_number(creatng->mappos.x.stl.num,creatng->mappos.y.stl.num); for (n=0; n < AROUND_MAP_LENGTH; n++) { struct Thing *thing; struct Map *mapblk; unsigned long k; long i; mapblk = get_map_block_at_pos(stl_num+around_map[n]); k = 0; i = get_mapwho_thing_index(mapblk); while (i != 0) { thing = thing_get(i); if (thing_is_invalid(thing)) { WARNLOG("Jump out of things array"); break; } i = thing->next_on_mapblk; // Per thing code if (thing_is_creature(thing) && ((get_creature_model_flags(thing) & CMF_IsSpecDigger) == 0) && (thing->owner != cctrl->disease_caster_plyridx) && !creature_affected_by_spell(thing, SplK_Disease)) { struct CreatureControl *tngcctrl; tngcctrl = creature_control_get_from_thing(thing); apply_spell_effect_to_thing(thing, SplK_Disease, cctrl->explevel); tngcctrl->disease_caster_plyridx = cctrl->disease_caster_plyridx; } // Per thing code ends k++; if (k > THINGS_COUNT) { ERRORLOG("Infinite loop detected when sweeping things list"); erstat_inc(ESE_InfChainTngPerMapWho); break_mapwho_infinite_chain(mapblk); break; } } } } if (((game.play_gameturn - cctrl->disease_start_turn) % game.disease_lose_health_time) == 0) { apply_damage_to_thing_and_display_health(creatng, game.disease_lose_percentage_health * cctrl->max_health / 100, DmgT_Biological, cctrl->disease_caster_plyridx); } }
void setup_workshop_search_for_post(struct Thing *creatng) { struct Room *room; struct Thing *postng; postng = INVALID_THING; room = get_room_thing_is_on(creatng); // Find a random slab in the room to be used as our starting point long i; unsigned long n; i = ACTION_RANDOM(room->slabs_count); n = room->slabs_list; while (i > 0) { n = get_next_slab_number_in_room(n); i--; } i = room->slabs_count; while (i > 0) { // Loop the slabs list if (n <= 0) { n = room->slabs_list; } MapSlabCoord slb_x, slb_y; slb_x = subtile_slab_fast(stl_num_decode_x(n)); slb_y = subtile_slab_fast(stl_num_decode_y(n)); struct Thing *objtng; objtng = get_workshop_equipment_to_work_with_on_subtile(creatng->owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y)); if (!thing_is_invalid(objtng)) { postng = objtng; } n = get_next_slab_number_in_room(n); i--; } if (thing_is_invalid(postng)) { SYNCDBG(9,"Work in %s, the %s moves to new pos",room_code_name(room->kind),thing_model_name(creatng)); setup_move_to_new_workshop_position(creatng, room, 1); } else { SYNCDBG(9,"Work in %s, the %s found a post",room_code_name(room->kind),thing_model_name(creatng)); setup_workshop_move(creatng, get_subtile_number(postng->mappos.x.stl.num, postng->mappos.y.stl.num)); } }
ThingModel crate_thing_to_workshop_item_model(const struct Thing *thing) { if (thing_is_invalid(thing) || (thing->class_id != TCls_Object)) return object_conf.object_to_door_or_trap[0]; ThingModel tngmodel; tngmodel = thing->model; if ((tngmodel <= 0) || (tngmodel >= object_conf.object_types_count)) return object_conf.object_to_door_or_trap[0]; return object_conf.object_to_door_or_trap[tngmodel]; }
struct Thing *select_scavenger_target(const struct Thing *calltng) { long weakpts; struct Thing *weaktng; weaktng = INVALID_THING; weakpts = LONG_MAX; struct Thing *thing; unsigned long k; int i; SYNCDBG(18,"Starting"); const struct StructureList *slist; slist = get_list_for_thing_class(TCls_Creature); k = 0; i = slist->index; while (i != 0) { thing = thing_get(i); if (thing_is_invalid(thing)) { ERRORLOG("Jump to invalid thing detected"); break; } i = thing->next_of_class; // Per-thing code if (thing_is_valid_scavenge_target(calltng, thing)) { SYNCDBG(18,"The %s index %d owner %d is valid target for %s index %d owner %d", thing_model_name(thing),(int)thing->index,(int)thing->owner, thing_model_name(calltng),(int)calltng->index,(int)calltng->owner); struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if (game.play_gameturn - cctrl->temple_cure_gameturn > game.temple_scavenge_protection_turns) { long thingpts; thingpts = calculate_correct_creature_scavenge_required(thing, calltng->owner); if (weakpts > thingpts) { weakpts = thingpts; weaktng = thing; } } } // Per-thing code ends k++; if (k > slist->count) { ERRORLOG("Infinite loop detected when sweeping things list"); break; } } SYNCDBG(18,"The weakest valid target for %s index %d owner %d is %s index %d owner %d", thing_model_name(calltng),(int)calltng->index,(int)calltng->owner, thing_model_name(weaktng),(int)weaktng->index,(int)weaktng->owner); return weaktng; }
long instf_fart(struct Thing *creatng, long *param) { TRACE_THING(creatng); //return _DK_instf_fart(creatng, param); struct Thing *efftng; efftng = create_effect(&creatng->mappos, 13, creatng->owner); if (!thing_is_invalid(efftng)) efftng->byte_16 = 4; thing_play_sample(creatng,94+UNSYNC_RANDOM(6), NORMAL_PITCH, 0, 3, 0, 4, FULL_LOUDNESS); return 1; }
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 activate_trap_shot_head_for_target90(struct Thing *traptng, struct Thing *creatng) { struct TrapStats *trapstat; trapstat = &trap_stats[traptng->model]; if (trapstat->field_1A <= 0) { ERRORLOG("Trap activation of bad shot kind %d",(int)trapstat->field_1A); return; } struct Thing *shotng; shotng = create_shot(&traptng->mappos, trapstat->field_1A, traptng->owner); if (!thing_is_invalid(shotng)) { { MapCoord crpos_x, crpos_y; MapCoord trpos_x, trpos_y; trpos_x = traptng->mappos.x.val; trpos_y = traptng->mappos.y.val; crpos_x = creatng->mappos.x.val; crpos_y = creatng->mappos.y.val; if (abs(trpos_x - crpos_x) <= abs(trpos_y - crpos_y)) { if (crpos_y >= trpos_y) shotng->move_angle_xy = LbFPMath_PI; else shotng->move_angle_xy = 0; } else { if (crpos_x >= trpos_x) shotng->move_angle_xy = LbFPMath_PI/2; else shotng->move_angle_xy = 3*LbFPMath_PI/2; } } shotng->move_angle_z = 0; struct ShotConfigStats *shotst; shotst = get_shot_model_stats(trapstat->field_1A); struct ComponentVector cvect; angles_to_vector(shotng->move_angle_xy, 0, shotst->old->speed, &cvect); shotng->veloc_push_add.x.val += cvect.x; shotng->veloc_push_add.y.val += cvect.y; shotng->veloc_push_add.z.val += cvect.z; shotng->state_flags |= TF1_PushAdd; shotng->byte_16 = trapstat->field_1B; if (shotst->old->firing_sound > 0) { thing_play_sample(traptng, shotst->old->firing_sound+UNSYNC_RANDOM(shotst->old->firing_sound_variants), NORMAL_PITCH, 0, 3, 0, 6, FULL_LOUDNESS); } if (shotst->old->shot_sound > 0) { thing_play_sample(shotng, shotst->old->shot_sound, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); } } }
TbBool find_combat_target_passing_by_subtile_but_having_unrelated_job(const struct Thing *creatng, CreatureJob job_kind, MapSubtlCoord stl_x, MapSubtlCoord stl_y, unsigned long *found_dist, struct Thing **found_thing) { struct Thing *thing; struct Map *mapblk; long i; unsigned long k; long dist; mapblk = get_map_block_at(stl_x,stl_y); k = 0; i = get_mapwho_thing_index(mapblk); while (i != 0) { thing = thing_get(i); TRACE_THING(thing); if (thing_is_invalid(thing)) { ERRORLOG("Jump to invalid thing detected"); break; } i = thing->next_on_mapblk; // Per thing code start if (thing_is_creature(thing) && (thing->index != creatng->index) && !creature_has_job(thing, job_kind) && !creature_is_kept_in_custody(thing) && !creature_is_being_unconscious(thing) && !creature_is_dying(thing) && !creature_is_doing_anger_job(thing)) { if (!creature_is_invisible(thing) || creature_can_see_invisible(creatng)) { dist = get_combat_distance(creatng, thing); // If we have combat sight - we want that target, don't search anymore if (creature_can_see_combat_path(creatng, thing, dist) > AttckT_Unset) { *found_dist = dist; *found_thing = thing; return true; } // No combat sight - but maybe it's at least closer than previous one if ( *found_dist > dist ) { *found_dist = dist; *found_thing = thing; } } } // Per thing code end k++; if (k > THINGS_COUNT) { ERRORLOG("Infinite loop detected when sweeping things list"); break; } } return false; }