示例#1
0
文件: skills.c 项目: Xolgrim/server
int rc_skillmod(const struct race *rc, const region * r, skill_t sk)
{
    int mods = 0;

    if (!skill_enabled(sk)) {
        return 0;
    }
#ifdef FASTER_SKILLMOD
    unsigned int index = hashstring(rc->_name) % RCMODMAXHASH;
    struct skillmods **imods = &modhash[index];
    while (*imods && (*imods)->race != rc) {
        imods = &(*imods)->next;
    }
    if (*imods == NULL) {
        *imods = init_skills(rc);
    }
    mods = (*imods)->mod[rterrain(r)].value[sk];
#else
    if (r) {
        mods = skill_mod(rc, sk, r->terrain);
    }
#endif
    if (rc == get_race(RC_ELF) && r && r_isforest(r)) {
        if (sk == SK_PERCEPTION || sk == SK_STEALTH) {
            ++mods;
        }
        else if (sk == SK_TACTICS) {
            mods += 2;
        }
    }
    return mods;
}
示例#2
0
int lighthouse_view_distance(const building * b, const unit *u)
{
    if (b->size >= 10 && (b->flags & BLD_MAINTAINED)) {
        int maxd = lighthouse_range(b);

        if (maxd > 0 && u && skill_enabled(SK_PERCEPTION)) {
            int sk = effskill(u, SK_PERCEPTION, NULL) / 3;
            assert(u->building == b);
            if (maxd > sk) maxd = sk;
        }
        return maxd;
    }
    return 0;
}
示例#3
0
bool check_leuchtturm(region * r, faction * f)
{
    attrib *a;

    if (!fval(r->terrain, SEA_REGION)) {
        return false;
    }
    for (a = a_find(r->attribs, &at_lighthouse); a && a->type == &at_lighthouse;
        a = a->next) {
        building *b = (building *)a->data.v;

        assert(is_building_type(b->type, "lighthouse"));
        if (fval(b, BLD_MAINTAINED) && b->size >= 10) {
            int maxd = (int)log10(b->size) + 1;

            if (skill_enabled(SK_PERCEPTION) && f) {
                region *r2 = b->region;
                unit *u;
                int c = 0;
                int d = 0;

                for (u = r2->units; u; u = u->next) {
                    if (u->building == b) {
                        c += u->number;
                        if (c > buildingcapacity(b))
                            break;
                        if (u->faction == f) {
                            if (!d)
                                d = distance(r, r2);
                            if (maxd < d)
                                break;
                            if (effskill(u, SK_PERCEPTION, 0) >= d * 3)
                                return true;
                        }
                    }
                    else if (c)
                        break;              /* first unit that's no longer in the house ends the search */
                }
            }
            else {
                /* E3A rule: no perception req'd */
                return true;
            }
        }
    }

    return false;
}
示例#4
0
int lighthouse_range(const building * b, const faction * f)
{
    int d = 0;
    if (fval(b, BLD_MAINTAINED) && b->size >= 10) {
        int maxd = (int)log10(b->size) + 1;

        if (skill_enabled(SK_PERCEPTION)) {
            region *r = b->region;
            int c = 0;
            int cap = buildingcapacity(b);
            unit *u, *uown = building_owner(b);

            for (u = r->units; u; u = u->next) {
                if (u->building == b || u == uown) {
                    c += u->number;
                    if (c > cap) {
                        break;
                    }
                    else if (f == NULL || u->faction == f) {
                        int sk = effskill(u, SK_PERCEPTION, 0) / 3;
                        d = _max(d, sk);
                        d = _min(maxd, d);
                        if (d == maxd)
                            break;
                    }
                }
                else if (c)
                    break;                /* first unit that's no longer in the house ends the search */
            }
        }
        else {
            /* E3A rule: no perception req'd */
            return maxd;
        }
    }
    return d;
}
示例#5
0
void plan_monsters(faction * f)
{
    region *r;
    
    assert(f);
    attack_chance = get_param_flt(global.parameters, "rules.monsters.attack_chance", 0.4);
    f->lastorders = turn;

    for (r = regions; r; r = r->next) {
        unit *u;
        bool attacking = false;

        for (u = r->units; u; u = u->next) {
            attrib *ta;
            order *long_order = NULL;

            /* Ab hier nur noch Befehle für NPC-Einheiten. */
            if (!is_monsters(u->faction))
                continue;

            /* Befehle müssen jede Runde neu gegeben werden: */
            free_orders(&u->orders);
            if (skill_enabled(SK_PERCEPTION)) {
                /* Monster bekommen jede Runde ein paar Tage Wahrnehmung dazu */
                /* TODO: this only works for playerrace */
                produceexp(u, SK_PERCEPTION, u->number);
            }

            if (!attacking) {
                if (chance(attack_chance)) attacking = true;
            }
            if (u->status > ST_BEHIND) {
                setstatus(u, ST_FIGHT);
                /* all monsters fight */
            }
            if (attacking && (!r->land || is_guard(u, GUARD_TAX))) {
                monster_attacks(u);
            }
            /* units with a plan to kill get ATTACK orders: */
            ta = a_find(u->attribs, &at_hate);
            if (ta && !monster_is_waiting(u)) {
                unit *tu = (unit *)ta->data.v;
                if (tu && tu->region == r) {
                    order * ord = monster_attack(u, tu);
                    if (ord) {
                        addlist(&u->orders, ord);
                    }
                }
                else if (tu) {
                    tu = findunitg(ta->data.i, NULL);
                    if (tu != NULL) {
                        long_order = make_movement_order(u, tu->region, 2, allowed_walk);
                    }
                }
                else
                    a_remove(&u->attribs, ta);
            }

            /* All monsters guard the region: */
            if (!monster_is_waiting(u) && r->land) {
                addlist(&u->orders, create_order(K_GUARD, u->faction->locale, NULL));
            }

            /* Einheiten mit Bewegungsplan kriegen ein NACH: */
            if (long_order == NULL) {
                attrib *ta = a_find(u->attribs, &at_targetregion);
                if (ta) {
                    if (u->region == (region *)ta->data.v) {
                        a_remove(&u->attribs, ta);
                    }
                }
                else if (u_race(u)->flags & RCF_MOVERANDOM) {
                    if (rng_int() % 100 < MOVECHANCE || check_overpopulated(u)) {
                        long_order = monster_move(r, u);
                    }
                }
            }

            if (long_order == NULL && unit_can_study(u)) {
                /* Einheiten, die Waffenlosen Kampf lernen könnten, lernen es um
                 * zu bewachen: */
                if (u_race(u)->bonus[SK_WEAPONLESS] != -99) {
                    if (effskill(u, SK_WEAPONLESS, 0) < 1) {
                        long_order =
                            create_order(K_STUDY, f->locale, "'%s'",
                            skillname(SK_WEAPONLESS, f->locale));
                    }
                }
            }

            if (long_order == NULL) {
                /* Ab hier noch nicht generalisierte Spezialbehandlungen. */

                if (!u->orders) {
                    handle_event(u->attribs, "ai_move", u);
                }

                switch (old_race(u_race(u))) {
                case RC_SEASERPENT:
                    long_order = create_order(K_PIRACY, f->locale, NULL);
                    break;
#ifdef TODO_ALP
                case RC_ALP:
                    long_order = monster_seeks_target(r, u);
                    break;
#endif
                case RC_FIREDRAGON:
                case RC_DRAGON:
                case RC_WYRM:
                    long_order = plan_dragon(u);
                    break;
                default:
                    if (u_race(u)->flags & RCF_LEARN) {
                        long_order = monster_learn(u);
                    }
                    break;
                }
            }
            if (long_order) {
                addlist(&u->orders, long_order);
            }
        }
    }
    pathfinder_cleanup();
}
示例#6
0
static order *plan_dragon(unit * u)
{
    attrib *ta = a_find(u->attribs, &at_targetregion);
    region *r = u->region;
    region *tr = NULL;
    bool move = false;
    order *long_order = NULL;

    if (ta == NULL) {
        move |= (r->land == 0 || r->land->peasants == 0);   /* when no peasants, move */
        move |= (r->land == 0 || r->land->money == 0);      /* when no money, move */
    }
    move |= chance(0.04);         /* 4% chance to change your mind */

    if (u_race(u) == get_race(RC_WYRM) && !move) {
        unit *u2;
        for (u2 = r->units; u2; u2 = u2->next) {
            /* wyrme sind einzelgänger */
            if (u2 == u) {
                /* we do not make room for newcomers, so we don't need to look at them */
                break;
            }
            if (u2 != u && u_race(u2) == u_race(u) && chance(0.5)) {
                move = true;
                break;
            }
        }
    }

    if (move) {
        /* dragon gets bored and looks for a different place to go */
        ta = set_new_dragon_target(u, u->region, DRAGON_RANGE);
    }
    else
        ta = a_find(u->attribs, &at_targetregion);
    if (ta != NULL) {
        tr = (region *)ta->data.v;
        if (tr == NULL || !path_exists(u->region, tr, DRAGON_RANGE, allowed_dragon)) {
            ta = set_new_dragon_target(u, u->region, DRAGON_RANGE);
            if (ta)
                tr = findregion(ta->data.sa[0], ta->data.sa[1]);
        }
    }
    if (tr != NULL) {
        assert(long_order == NULL);
        switch (old_race(u_race(u))) {
        case RC_FIREDRAGON:
            long_order = make_movement_order(u, tr, 4, allowed_dragon);
            break;
        case RC_DRAGON:
            long_order = make_movement_order(u, tr, 3, allowed_dragon);
            break;
        case RC_WYRM:
            long_order = make_movement_order(u, tr, 1, allowed_dragon);
            break;
        default:
            break;
        }
        if (long_order) {
            reduce_weight(u);
        }
        if (rng_int() % 100 < 15) {
            const struct locale *lang = u->faction->locale;
            /* do a growl */
            if (rname(tr, lang)) {
                addlist(&u->orders,
                    create_order(K_MAIL, lang, "%s '%s... %s %s %s'",
                    LOC(lang, parameters[P_REGION]),
                    random_growl(),
                    u->number ==
                    1 ? "Ich rieche" : "Wir riechen",
                    "etwas in", rname(tr, u->faction->locale)));
            }
        }
    }
    else {
        /* we have no target. do we like it here, then? */
        long_order = get_money_for_dragon(u->region, u, income(u));
        if (long_order == NULL) {
            /* money is gone, need a new target */
            set_new_dragon_target(u, u->region, DRAGON_RANGE);
        }
        else if (u_race(u) != get_race(RC_FIREDRAGON)) {
            /* neue dracoiden! */
            if (r->land && !fval(r->terrain, FORBIDDEN_REGION)) {
                int ra = 20 + rng_int() % 100;
                if (get_money(u) > ra * 50 + 100 && rng_int() % 100 < 50) {
                    recruit_dracoids(u, ra);
                }
            }
        }
    }
    if (long_order == NULL) {
        skill_t sk = SK_PERCEPTION;
        /* study perception (or a random useful skill) */
        while (!skill_enabled(sk) || u_race(u)->bonus[sk] < -5) {
            sk = (skill_t)(rng_int() % MAXSKILLS);
        }
        long_order = create_order(K_STUDY, u->faction->locale, "'%s'",
            skillname(sk, u->faction->locale));
    }
    return long_order;
}