Exemplo n.º 1
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;
}
Exemplo n.º 2
0
/** Returns if a creature can do specific job at given map position.
*
* @param creatng The creature which is planned for the job.
* @param stl_x Target map position, x coord.
* @param stl_y Target map position, y coord.
* @param new_job Job selection with single job flag set.
* @return True if the creature can do the job specified, false otherwise.
* @see creature_can_do_job_for_player() similar function for use when only target player is known
*/
TbBool creature_can_do_job_near_position(struct Thing *creatng, MapSubtlCoord stl_x, MapSubtlCoord stl_y, CreatureJob new_job, unsigned long flags)
{
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(creatng);
    SYNCDBG(6,"Starting for %s (owner %d) and job %s",thing_model_name(creatng),(int)creatng->owner,creature_job_code_name(new_job));
    struct CreatureStats *crstat;
    crstat = creature_stats_get_from_thing(creatng);
    if (creature_will_reject_job(creatng, new_job))
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; in not-do-jobs list",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        if ((flags & JobChk_SetStateOnFail) != 0) {
            anger_apply_anger_to_creature(creatng, crstat->annoy_will_not_do_job, AngR_Other, 1);
            external_set_thing_state(creatng, CrSt_CreatureMoan);
            cctrl->field_282 = 50;
        }
        return false;
    }
    // Don't allow creatures changed to chickens to have any job assigned, besides those specifically marked
    if (creature_affected_by_spell(creatng, SplK_Chicken) && ((get_flags_for_job(new_job) & JoKF_AllowChickenized) == 0))
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; under chicken spell",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    // Check if the job is related to correct map place (room,slab)
    if (!is_correct_position_to_perform_job(creatng, stl_x, stl_y, new_job))
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; not correct place for job",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    struct CreatureJobConfig *jobcfg;
    jobcfg = get_config_for_job(new_job);
    if (jobcfg->func_cord_check == NULL)
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; job has no coord check function",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    if (!jobcfg->func_cord_check(creatng, stl_x, stl_y, new_job, flags))
    {
        SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; coord check not passed",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    // If other tests pass, check if related room (if is needed) has capacity to be used for that job
    if ((get_flags_for_job(new_job) & JoKF_NeedsCapacity) != 0)
    {
        struct Room *room;
        room = subtile_room_get(stl_x, stl_y);
        if (!room_has_enough_free_capacity_for_creature(room, creatng))
        {
            SYNCDBG(3,"Cannot assign %s at (%d,%d) for %s index %d owner %d; not enough room capacity",creature_job_code_name(new_job),(int)stl_x,(int)stl_y,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
            if ((flags & JobChk_PlayMsgOnFail) != 0) {
                const struct RoomConfigStats *roomst;
                roomst = get_room_kind_stats(room->kind);
                if (is_my_player_number(room->owner) && (roomst->msg_too_small > 0)) {
                    output_message_room_related_from_computer_or_player_action(roomst->msg_too_small);
                }
            }
            return false;
        }
    }
    return true;
}