예제 #1
0
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);
    }
}
예제 #2
0
TbBool can_thing_be_possessed(const struct Thing *thing, PlayerNumber plyr_idx)
{
    //return _DK_can_thing_be_possessed(thing, plyr_idx);
    if (thing->owner != plyr_idx)
        return false;
    if (thing_is_creature(thing))
    {
        if (thing_is_picked_up(thing))  {
            return false;
        }
        if ((thing->active_state == CrSt_CreatureUnconscious)
          || creature_affected_by_spell(thing, SplK_Teleport))  {
            return false;
        }
        if (creature_is_being_sacrificed(thing) || creature_is_being_summoned(thing))  {
            return false;
        }
        if (creature_is_kept_in_custody_by_enemy(thing))  {
            return false;
        }
        return true;
    }
    if (thing_is_object(thing))
    {
        if (object_is_mature_food(thing))  {
            return true;
        }
        return false;
    }
    return false;
}
예제 #3
0
short creature_arrived_at_prison(struct Thing *creatng)
{
    struct CreatureControl *cctrl;
    struct Room *room;
    TRACE_THING(creatng);
    cctrl = creature_control_get_from_thing(creatng);
    cctrl->target_room_id = 0;
    room = get_room_thing_is_on(creatng);
    if (!room_initially_valid_as_type_for_thing(room, RoK_PRISON, creatng))
    {
        WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->index);
        set_start_state(creatng);
        return 0;
    }
    if (!add_creature_to_work_room(creatng, room))
    {
        output_message_room_related_from_computer_or_player_action(room->owner, room->kind, OMsg_RoomTooSmall);
        cctrl->flgfield_1 &= ~CCFlg_NoCompControl;
        set_start_state(creatng);
        return 0;
    }
    cctrl->field_82 = game.play_gameturn;
    cctrl->flgfield_1 |= CCFlg_NoCompControl;
    internal_set_thing_state(creatng, CrSt_CreatureInPrison);
    if (creature_affected_by_spell(creatng, SplK_Speed)) {
        terminate_thing_spell_effect(creatng, SplK_Speed);
    }
    if (creature_affected_by_spell(creatng, SplK_Invisibility)) {
        terminate_thing_spell_effect(creatng, SplK_Invisibility);
    }
    if (creatng->light_id != 0) {
        light_delete_light(creatng->light_id);
        creatng->light_id = 0;
    }
    return 1;

}
예제 #4
0
void update_creature_graphic_tint(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    cctrl = creature_control_get_from_thing(thing);
    if (creature_affected_by_spell(thing, SplK_Freeze))
    {
        tint_thing(thing, colours[4][4][15], 1);
    } else
    if (((cctrl->combat_flags & CmbtF_Melee) == 0) && ((cctrl->combat_flags & CmbtF_Ranged) == 0))
    {
        untint_thing(thing);
    } else
    if ((game.play_gameturn % 3) == 0)
    {
        untint_thing(thing);
    } else
    {
        switch (thing->owner)
        {
        case 0:
            tint_thing(thing, colours[15][0][0], 1);
            break;
        case 1:
            tint_thing(thing, colours[0][0][15], 1);
            break;
        case 2:
            tint_thing(thing, colours[0][15][0], 1);
            break;
        case 3:
            tint_thing(thing, colours[13][13][2], 1);
            break;
        default:
            untint_thing(thing);
            break;
        }
    }
}
예제 #5
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;
}
예제 #6
0
/** Returns if a creature can do specific job for the player.
 *
 * @param creatng The creature which is planned for the job.
 * @param plyr_idx Player for whom the job is to be done.
 * @param new_job Job selection with single job flag set.
 * @param flags Function behavior adjustment flags.
 * @return True if the creature can do the job specified, false otherwise.
 * @note this should be used instead of person_will_do_job_for_room()
 * @note this function will never change state of the input thing, even if appropriate flags are set
 * @see creature_can_do_job_near_position() similar function for use when target position is known
 */
TbBool creature_can_do_job_for_player(const struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job, unsigned long flags)
{
    SYNCDBG(16,"Starting for %s (owner %d) and job %s",thing_model_name(creatng),(int)creatng->owner,creature_job_code_name(new_job));
    if (creature_will_reject_job(creatng, new_job))
    {
        SYNCDBG(13,"Cannot assign %s for %s index %d owner %d; in not do jobs list",creature_job_code_name(new_job),thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    if (!is_correct_owner_to_perform_job(creatng, plyr_idx, new_job))
    {
        SYNCDBG(13,"Cannot assign %s for %s index %d owner %d; not correct owner for job",creature_job_code_name(new_job),thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        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(13,"Cannot assign %s for %s index %d owner %d; under chicken spell",creature_job_code_name(new_job),thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
        return false;
    }
    // Check if the job is related to correct player
    struct CreatureJobConfig *jobcfg;
    jobcfg = get_config_for_job(new_job);
    if (jobcfg->func_plyr_check == NULL)
    {
        return false;
    }
    if (!jobcfg->func_plyr_check(creatng, plyr_idx, new_job))
    {
        return false;
    }
    RoomKind job_rkind;
    job_rkind = get_room_for_job(new_job);
    if (job_rkind != RoK_NONE)
    {
        if (!player_has_room(plyr_idx, job_rkind))
        {
            SYNCDBG(3,"Cannot assign %s in player %d room for %s index %d owner %d; no required room built",creature_job_code_name(new_job),(int)plyr_idx,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
            if ((flags & JobChk_PlayMsgOnFail) != 0) {
                const struct RoomConfigStats *roomst;
                roomst = get_room_kind_stats(get_room_for_job(new_job));
                if (is_my_player_number(plyr_idx) && (roomst->msg_needed > 0)) {
                    output_message_room_related_from_computer_or_player_action(roomst->msg_needed);
                }
            }
            return false;
        }
        if ((get_flags_for_job(new_job) & JoKF_NeedsCapacity) != 0)
        {
            struct Room *room;
            room = find_room_with_spare_capacity(plyr_idx, job_rkind, 1);
            if (room_is_invalid(room))
            {
                SYNCDBG(3,"Cannot assign %s in player %d room for %s index %d owner %d; not enough room capacity",creature_job_code_name(new_job),(int)plyr_idx,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner);
                if ((flags & JobChk_PlayMsgOnFail) != 0) {
                    const struct RoomConfigStats *roomst;
                    roomst = get_room_kind_stats(get_room_for_job(new_job));
                    if (is_my_player_number(plyr_idx) && (roomst->msg_too_small > 0)) {
                        output_message_room_related_from_computer_or_player_action(roomst->msg_too_small);
                    }
                }
                return false;
            }
        }
    }
    return true;
}
예제 #7
0
struct Thing *find_prisoner_for_thing(struct Thing *creatng)
{
    struct CreatureControl *cctrl;
    struct Thing *thing;
    unsigned long k;
    long i;
    TRACE_THING(creatng);
    struct Room *room;
    room = INVALID_ROOM;
    if (!is_neutral_thing(creatng)) {
        room = find_nearest_room_for_thing_with_used_capacity(creatng, creatng->owner, RoK_PRISON, NavRtF_Default, 1);
    }
    if (room_exists(room)) {
        i = room->creatures_list;
    } else {
        i = 0;
    }
    struct Thing *out_creatng;
    long out_delay;
    out_creatng = INVALID_THING;
    out_delay = LONG_MAX;
    k = 0;
    while (i != 0)
    {
        thing = thing_get(i);
        TRACE_THING(thing);
        cctrl = creature_control_get_from_thing(thing);
        if (!creature_control_exists(cctrl))
        {
            ERRORLOG("Jump to invalid creature %ld detected",i);
            break;
        }
        i = cctrl->next_in_room;
        // Per creature code
        long dist, durt;
        dist = get_2d_box_distance(&creatng->mappos, &thing->mappos);
        if (out_delay < 0)
        {
            // If we have a victim which isn't frozen, accept only other unfrozen creatures
            if ((dist <= LONG_MAX) && !creature_affected_by_spell(thing, SplK_Freeze)) {
                out_creatng = thing;
                out_delay = -1;
            }
        } else
        if (creature_affected_by_spell(thing, SplK_Freeze))
        {
            // If the victim is frozen, select one which will unfreeze sooner
            durt = get_spell_duration_left_on_thing(thing, SplK_Freeze);
            if ((durt > 0) && (out_delay > durt)) {
                out_creatng = thing;
                out_delay = durt;
            }
        } else
        {
            // Found first unfrozen victim - change out_delay to mark thet we no longer want frozen ones
            out_creatng = thing;
            out_delay = -1;
        }
        // Per creature code ends
        k++;
        if (k > THINGS_COUNT)
        {
          ERRORLOG("Infinite loop detected when sweeping creatures list");
          break;
        }
    }
    return out_creatng;
}
예제 #8
0
void update_creature_graphic_anim(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct CreatureStats *crstat;
    long i;

    TRACE_THING(thing);
    cctrl = creature_control_get_from_thing(thing);
    crstat = creature_stats_get_from_thing(thing);

    if ((thing->field_50 & 0x01) != 0)
    {
      thing->field_50 &= ~0x01;
    } else
    if ((thing->active_state == CrSt_CreatureHeroEntering) && (cctrl->countdown_282 >= 0))
    {
      thing->field_4F |= TF4F_Unknown01;
    } else
    if (!creature_affected_by_spell(thing, SplK_Chicken))
    {
        if (cctrl->instance_id != CrInst_NULL)
        {
          if (cctrl->instance_id == CrInst_TORTURED)
          {
              thing->field_4F &= ~(TF4F_Unknown20|TF4F_Unknown10);
          }
          struct InstanceInfo *inst_inf;
          inst_inf = creature_instance_info_get(cctrl->instance_id);
          update_creature_anim(thing, cctrl->instance_anim_step_turns, inst_inf->graphics_idx);
        } else
        if ((cctrl->field_B1 != 0) || creature_is_dying(thing) || creature_affected_by_spell(thing, SplK_Freeze))
        {
            update_creature_anim(thing, 256, 8);
        } else
        if ((cctrl->stateblock_flags & CCSpl_ChickenRel) != 0)
        {
            update_creature_anim(thing, 256, 0);
        } else
        if (thing->active_state == CrSt_CreatureSlapCowers)
        {
            update_creature_anim(thing, 256, 10);
        } else
        if ((thing->active_state == CrSt_CreaturePiss) || (thing->active_state == CrSt_CreatureRoar))
        {
            update_creature_anim(thing, 128, 4);
        } else
        if (thing->active_state == CrSt_CreatureUnconscious)
        {
            update_creature_anim(thing, 64, 16);
            thing->field_4F |= TF4F_Unknown40;
        } else
        if (thing->active_state == CrSt_CreatureSleep)
        {
            thing->field_4F &= ~(TF4F_Unknown20|TF4F_Unknown10);
            update_creature_anim(thing, 128, 12);
        } else
        if (cctrl->field_9 == 0)
        {
            update_creature_anim(thing, 256, 0);
        } else
        if (thing->field_60 < thing->mappos.z.val)
        {
            update_creature_anim(thing, 256, 0);
        } else
        if ((cctrl->dragtng_idx != 0) && (thing_get(cctrl->dragtng_idx)->state_flags & TF1_IsDragged1))
        {
            i = (((long)cctrl->field_9) << 8) / (crstat->walking_anim_speed+1);
            update_creature_anim(thing, i, 2);
        } else
        if (creatures[thing->model].field_6 == 4)
        {
            update_creature_anim(thing, 256, 1);
        } else
        {
            i = (((long)cctrl->field_9) << 8) / (crstat->walking_anim_speed+1);
            if (!update_creature_anim(thing, i, 1))
            {
                thing->field_3E = i;
            }
        }
    } else
    {
        thing->field_4F &= ~0x30;
        if (cctrl->field_9 == 0)
        {
            update_creature_anim_td(thing, 256, 820);
        } else
        if (thing->field_60 < thing->mappos.z.val)
        {
            update_creature_anim_td(thing, 256, 820);
        } else
        if (creatures[thing->model].field_6 == 4)
        {
            update_creature_anim_td(thing, 256, 819);
        } else
        {
            i = (((long)cctrl->field_9) << 8) / (crstat->walking_anim_speed+1);
            if (!update_creature_anim_td(thing, i, 819))
            {
                thing->field_3E = i;
            }
        }
    }
}
예제 #9
0
struct Thing * find_imp_for_pickup(struct Computer2 *comp, MapSubtlCoord stl_x, MapSubtlCoord stl_y)
{
    struct Dungeon *dungeon;
    int pick1_dist;
    struct Thing *pick1_tng;
    int pick2_dist;
    struct Thing *pick2_tng;
    //return _DK_find_imp_for_pickup(comp, stl_x, stl_y);
    dungeon = comp->dungeon;
    pick1_dist = INT_MAX;
    pick2_dist = INT_MAX;
    pick2_tng = INVALID_THING;
    pick1_tng = INVALID_THING;
    long i;
    unsigned long k;
    k = 0;
    i = dungeon->digger_list_start;
    while (i != 0)
    {
        struct Thing *thing;
        struct CreatureControl *cctrl;
        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
        if (cctrl->combat_flags == 0)
        {
            if (!creature_is_being_unconscious(thing) && !creature_affected_by_spell(thing, SplK_Chicken))
            {
                if (!creature_is_being_dropped(thing) && can_thing_be_picked_up_by_player(thing, dungeon->owner))
                {
                    MapSubtlDelta dist;
                    long state_type;
                    dist = abs(stl_x - (MapSubtlDelta)thing->mappos.x.stl.num) + abs(stl_y - (MapSubtlDelta)thing->mappos.y.stl.num);
                    state_type = get_creature_state_type(thing);
                    if (state_type == CrStTyp_Work)
                    {
                        if (dist < pick1_dist)
                        {
                            pick1_dist = dist;
                            pick1_tng = thing;
                        }
                    }
                    else
                    {
                        if (dist < pick2_dist)
                        {
                            pick2_dist = dist;
                            pick2_tng = thing;
                        }
                    }
                }
            }
        }
        // Thing list loop body ends
        k++;
        if (k > CREATURES_COUNT)
        {
          ERRORLOG("Infinite loop detected when sweeping creatures list");
          break;
        }
    }
    if (!thing_is_invalid(pick2_tng)) {
        return pick2_tng;
    } else {
        return pick1_tng;
    }
}