static order *monster_move(region * r, unit * u) { direction_t d = NODIRECTION; if (monster_is_waiting(u)) { return NULL; } switch (old_race(u_race(u))) { case RC_FIREDRAGON: case RC_DRAGON: case RC_WYRM: d = richest_neighbour(r, u->faction, 1); break; case RC_TREEMAN: d = treeman_neighbour(r); break; default: d = random_neighbour(r, u); break; } /* falls kein geld gefunden wird, zufaellig verreisen, aber nicht in * den ozean */ if (d == NODIRECTION) return NULL; reduce_weight(u); return create_order(K_MOVE, u->faction->locale, "%s", LOC(u->faction->locale, directions[d])); }
static order *monster_attack(unit * u, const unit * target) { assert(u->region == target->region); assert(u->faction != target->faction); if (!cansee(u->faction, u->region, target, 0)) return NULL; if (monster_is_waiting(u)) return NULL; return create_order(K_ATTACK, u->faction->locale, "%i", target->no); }
void monster_kills_peasants(unit * u) { if (!monster_is_waiting(u)) { if (u_race(u)->flags & RCF_SCAREPEASANTS) { scared_by_monster(u); } if (u_race(u)->flags & RCF_KILLPEASANTS) { eaten_by_monster(u); } if (u_race(u)->flags & RCF_ABSORBPEASANTS) { absorbed_by_monster(u); } } }
static order *make_movement_order(unit * u, const region * target, int moves, bool(*allowed) (const region *, const region *)) { region *r = u->region; region **plan; int bytes, position = 0; char zOrder[128], *bufp = zOrder; size_t size = sizeof(zOrder) - 1; if (monster_is_waiting(u)) return NULL; plan = path_find(r, target, DRAGON_RANGE * 5, allowed); if (plan == NULL) return NULL; bytes = (int)strlcpy(bufp, (const char *)LOC(u->faction->locale, keyword(K_MOVE)), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); while (position != moves && plan[position + 1]) { region *prev = plan[position]; region *next = plan[++position]; direction_t dir = reldirection(prev, next); assert(dir != NODIRECTION && dir != D_SPECIAL); if (size > 1) { *bufp++ = ' '; --size; } bytes = (int)strlcpy(bufp, (const char *)LOC(u->faction->locale, directions[dir]), size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); } *bufp = 0; return parse_order(zOrder, u->faction->locale); }
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(); }