TbBool move_creature_to_nearest_valid_position(struct Thing *thing)
{
    struct Coord3d pos;
    pos.x.val = thing->mappos.x.val;
    pos.y.val = thing->mappos.y.val;
    pos.z.val = thing->mappos.z.val;
    if (!get_nearest_valid_position_for_creature_at(thing, &pos))
    {
        return false;
    }
    move_thing_in_map(thing, &pos);
    return true;
}
short creature_scavenged_disappear(struct Thing *thing)
{
    struct CreatureControl *cctrl;
    struct Dungeon *dungeon;
    struct Room *room;
    struct Coord3d pos;
    long stl_x, stl_y;
    long i;
    //return _DK_creature_scavenged_disappear(thing);
    cctrl = creature_control_get_from_thing(thing);
    cctrl->byte_9A--;
    if (cctrl->byte_9A > 0)
    {
      if ((cctrl->byte_9A == 7) && (cctrl->byte_9B < PLAYERS_COUNT))
      {
        create_effect(&thing->mappos, get_scavenge_effect_element(cctrl->byte_9B), thing->owner);
      }
      return 0;
    }
    // We don't really have to convert coordinates into numbers and back to XY.
    i = get_subtile_number(cctrl->scavenge.stl_9D_x, cctrl->scavenge.stl_9D_y);
    stl_x = stl_num_decode_x(i);
    stl_y = stl_num_decode_y(i);
    room = subtile_room_get(stl_x, stl_y);
    if (room_is_invalid(room) || (room->kind != RoK_SCAVENGER))
    {
        ERRORLOG("Room %s at (%d,%d) disappeared.",room_code_name(RoK_SCAVENGER),(int)stl_x,(int)stl_y);
        kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects);
        return -1;
    }
    if (find_random_valid_position_for_thing_in_room(thing, room, &pos))
    {
        move_thing_in_map(thing, &pos);
        anger_set_creature_anger_all_types(thing, 0);
        dungeon = get_dungeon(cctrl->byte_9B);
        dungeon->creatures_scavenge_gain++;
        if (is_my_player_number(thing->owner))
          output_message(SMsg_MinionScanvenged, 0, true);
        cctrl->byte_9C = thing->owner;
        change_creature_owner(thing, cctrl->byte_9B);
        internal_set_thing_state(thing, CrSt_CreatureScavengedReappear);
        return 0;
    } else
    {
        ERRORLOG("No valid position inside %s room for %s.",room_code_name(room->kind),thing_model_name(thing));
        kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects);
        return -1;
    }
}
Beispiel #3
0
void process_armageddon_influencing_creature(struct Thing *creatng)
{
    if (game.armageddon_cast_turn != 0)
    {
        struct CreatureControl *cctrl;
        cctrl = creature_control_get_from_thing(creatng);
        // If Armageddon is on, teleport creature to its position
        if ((cctrl->armageddon_teleport_turn != 0) && (cctrl->armageddon_teleport_turn <= game.play_gameturn))
        {
            cctrl->armageddon_teleport_turn = 0;
            create_effect(&creatng->mappos, imp_spangle_effects[creatng->owner], creatng->owner);
            move_thing_in_map(creatng, &game.armageddon.mappos);
        }
    }
}
Beispiel #4
0
void set_room_playing_ambient_sound(struct Coord3d *pos, long sample_idx)
{
    struct Thing *thing;
    long i;
    //_DK_set_room_playing_ambient_sound(pos, sample_idx);return;
    if (game.ambient_sound_thing_idx == 0)
    {
        ERRORLOG("No room ambient sound object");
        return;
    }
    thing = thing_get(game.ambient_sound_thing_idx);
    if ( thing_is_invalid(thing) )
    {
        ERRORLOG("Invalid room ambient sound object");
        return;
    }
    if (sample_idx != 0)
    {
        move_thing_in_map(thing, pos);
        i = thing->snd_emitter_id;
        if (i != 0)
        {
            if ( !S3DEmitterIsPlayingSample(i, sample_idx, 0) )
            {
                S3DDeleteAllSamplesFromEmitter(thing->snd_emitter_id);
                thing_play_sample(thing, sample_idx, NORMAL_PITCH, -1, 3, 0, 6, FULL_LOUDNESS);
            }
        } else
        {
            thing_play_sample(thing, sample_idx, NORMAL_PITCH, -1, 3, 0, 6, FULL_LOUDNESS);
        }
    } else
    {
        i = thing->snd_emitter_id;
        if (i != 0)
        {
            S3DDestroySoundEmitterAndSamples(i);
            thing->snd_emitter_id = 0;
        }
    }
}
TbBool steal_hero(struct PlayerInfo *player, struct Coord3d *pos)
{
    //TODO CONFIG creature models dependency; put them in config files
    static ThingModel skip_steal_models[] = {6, 7};
    static ThingModel prefer_steal_models[] = {3, 12};
    struct Thing *herotng;
    herotng = INVALID_THING;
    int heronum;
    struct Dungeon *herodngn;
    struct CreatureControl *cctrl;
    unsigned long k;
    int i;
    SYNCDBG(8,"Starting");
    herodngn = get_players_num_dungeon(game.hero_player_num);
    k = 0;
    if (herodngn->num_active_creatrs > 0) {
        heronum = ACTION_RANDOM(herodngn->num_active_creatrs);
        i = herodngn->creatr_list_start;
        SYNCDBG(4,"Selecting random creature %d out of %d heroes",(int)heronum,(int)herodngn->num_active_creatrs);
    } else {
        heronum = 0;
        i = 0;
        SYNCDBG(4,"No heroes on map, skipping selection");
    }
    while (i != 0)
    {
        struct Thing *thing;
        thing = thing_get(i);
        TRACE_THING(thing);
        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
        TbBool heroallow;
        heroallow = true;
        ThingModel skipidx;
        for (skipidx=0; skipidx < sizeof(skip_steal_models)/sizeof(skip_steal_models[0]); skipidx++)
        {
            if (thing->model == skip_steal_models[skipidx]) {
                heroallow = false;
            }
        }
        if (heroallow) {
            herotng = thing;
        }
        // If we've reached requested hero number, return either current hero on previously selected one
        if ((heronum <= 0) && thing_is_creature(herotng)) {
            break;
        }
        heronum--;
        if (i == 0) {
            i = herodngn->creatr_list_start;
        }
        // Thing list loop body ends
        k++;
        if (k > CREATURES_COUNT)
        {
            ERRORLOG("Infinite loop detected when sweeping creatures list");
            erstat_inc(ESE_InfChainTngPerOwner);
            break;
        }
    }
    if (!thing_is_invalid(herotng))
    {
        move_thing_in_map(herotng, pos);
        change_creature_owner(herotng, player->id_number);
        SYNCDBG(3,"Converted %s to owner %d",thing_model_name(herotng),(int)player->id_number);
    }
    else
    {
        i = ACTION_RANDOM(sizeof(prefer_steal_models)/sizeof(prefer_steal_models[0]));
        struct Thing *creatng;
        creatng = create_creature(pos, prefer_steal_models[i], player->id_number);
        if (thing_is_invalid(creatng))
            return false;
        SYNCDBG(3,"Created %s owner %d",thing_model_name(creatng),(int)player->id_number);
    }
    return true;
}
TbBool create_workshop_object_in_workshop_room(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel)
{
    struct Coord3d pos;
    struct Thing *cratetng;
    struct Room *room;
    struct Dungeon *dungeon;
    SYNCDBG(7,"Making player %d new %s",(int)plyr_idx,thing_class_code_name(tngclass));
    pos.x.val = 0;
    pos.y.val = 0;
    pos.z.val = 0;
    switch (tngclass)
    {
    case TCls_Trap:
        cratetng = create_object(&pos, trap_crate_object_model(tngmodel), plyr_idx, -1);
        break;
    case TCls_Door:
        cratetng = create_object(&pos, door_crate_object_model(tngmodel), plyr_idx, -1);
        break;
    default:
        cratetng = INVALID_THING;
        ERRORLOG("No known workshop crate can represent %s model %d",thing_class_code_name(tngclass),(int)tngmodel);
        break;
    }
    if (thing_is_invalid(cratetng))
    {
        ERRORLOG("Could not create workshop crate thing for %s",thing_class_code_name(tngclass));
        return false;
    }
    room = find_random_room_for_thing_with_spare_room_item_capacity(cratetng, plyr_idx, RoK_WORKSHOP, 0);
    if (room_is_invalid(room))
    {
        ERRORLOG("No %s room found which would accept %s crate",room_code_name(RoK_WORKSHOP),thing_class_code_name(tngclass));
        destroy_object(cratetng);
        return false;
    }
    if (!find_random_valid_position_for_thing_in_room_avoiding_object(cratetng, room, &pos))
    {
        ERRORLOG("Could not find a place in %s index %d for the new %s crate",
            room_code_name(room->kind),(int)room->index,thing_class_code_name(tngclass));
        destroy_object(cratetng);
        return false;
    }
    pos.z.val = get_thing_height_at(cratetng, &pos);
    move_thing_in_map(cratetng, &pos);
    if (!add_workshop_object_to_workshop(room, cratetng)) {
        ERRORLOG("Could not fit %s crate in %s index %d",
            thing_class_code_name(tngclass),room_code_name(room->kind),(int)room->index);
        destroy_object(cratetng);
        return false;
    }
    dungeon = get_players_num_dungeon(plyr_idx);
    switch (tngclass)
    {
    case TCls_Trap:
        if ((dungeon->trap_build_flags[tngmodel] & MnfBldF_Built) == 0) {
            event_create_event(cratetng->mappos.x.val, cratetng->mappos.y.val, EvKind_NewTrap, plyr_idx, tngmodel);
        }
        break;
    case TCls_Door:
        if ((dungeon->door_build_flags[tngmodel] & MnfBldF_Built) == 0) {
          event_create_event(cratetng->mappos.x.val, cratetng->mappos.y.val, EvKind_NewDoor, plyr_idx, tngmodel);
        }
        break;
    default:
        break;
    }
    create_effect(&pos, TngEff_Unknown56, cratetng->owner);
    thing_play_sample(cratetng, 89, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS);
    return true;
}