- [+] vault:pub
- [+] has lots of recruitable people - [+] plants, magic creatures, etc shoudl have infinite staina - [+] severed fingers/heads are no longer considered "corpses". - [+] new kind of bed: pile of straw - [+] closed shops now work properly. - [+] stench skillcheck (in makenauseated) - announce this differenlty to 'nothing happen's - [+] monsters won't turn to face sounds when fleeing. - [+] increase accuracy for spear, but reduce accuracy when adjacent - [+] why didn't cyborg warrior start with bullwhip equiped?? - [+] isbetterwepthan() should take EXTRADAM flag into account - [+] monster starting skill levels should depend on iq - [+] no sprinting with injured legs - [+] more restructions when stunned: - [+] no throwing - [+] no operating - [+] no firearms - [+] tombstone text: Eaten by a snow troll's halberd - [+] bug: ekrub gained MASSIVE piety when i sacrificed a soldier ant corpse! reduced. - [+] learning certain lore skills should please gods - [+] repairing should take a lot longer. ie. shoudlbn't be able to do it during a fight. - [+] workhelpobs (spanner/needle) should have F_HELPSREPAIR, v0=material, v1=howmuch - [+] continuerepairing() should only fix <skill + helpsrepair> hp per turn. - [+] announce helpsrepair in obdesc - [+] coldroom vault: - [+] ice floor - [+] ice walls - [+] ice pillar - [+] frozen corpses - [+] new job: gladiator - [+] sword - [+] shield - [+] high shield skill - [+] high evasion skill - [+] limited armour skill - [+] net - [+] war cry fairly early on - [+] gust of wind and airblast should drop flying creatures - [+] fall_from_air(). - [+] trigger then when wind-based effects hit. - [+] chance of falling depends on size. - [+] if you polymorph a monster, it should NOT turn back to its original form! - [+] criticals dont seem to be happening any more... fixed - [+] when picking first askcoords target lf, pick the closest - [+] sakcs etc should contain rarer objects. - [+] intelligent ai: if exhausted and in battle, and faster than opponent, flee.??? - [+] easy way to fix reachability: - [+] is there a solid cell which is: - [+] adjacent to both a filled and an unfilled area? - [+] not a fixed vault wall? - [+] if so, just clear it. - [+] genericise getrandomrace flags - [+] some containers should have mini/tiny monsters inside! - [+] f_hashidinglf, v0=rid - [+] if you loot it, monster jumps out - [+] ...and gets a free hit! - [+] perception lets you see the container moving (only if it weighs less than what is inside it) - [+] genericise getrandomcell() with conditionsets. * [+] condset_t - [+] then replace all getrandomadjcell() calls... - [+] remove getrandomroomcells - [+] then remove WE_xxx
This commit is contained in:
parent
64412035bb
commit
98ba363e8a
33
ai.c
33
ai.c
|
@ -23,9 +23,10 @@ extern int playerhasmoved;
|
|||
int wantdb = B_TRUE;
|
||||
|
||||
void addignorecell(lifeform_t *lf, cell_t *c) {
|
||||
if (!c) return;
|
||||
int howmany = 0;
|
||||
if (!c || !lf) return;
|
||||
// TEST: just have one ignorecell at once.
|
||||
killflagsofid(lf->flags, F_IGNORECELL);
|
||||
howmany = killflagsofid(lf->flags, F_IGNORECELL);
|
||||
addtempflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL, 10);
|
||||
//if (c && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
|
||||
// addtempflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL, 10);
|
||||
|
@ -509,8 +510,6 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
|
|||
return OT_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (missingspellcastob(lf)) {
|
||||
if (db) dblog(".oO { Cannot cast spell, I don't have my spellcast object }");
|
||||
return OT_NONE;
|
||||
|
@ -739,6 +738,12 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
|
|||
object_t *o;
|
||||
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
|
||||
|
||||
|
||||
if (lfhasflag(lf, F_STUNNED)) {
|
||||
if (db) dblog(".oO { no ranged attack because i am stunned }");
|
||||
if (ra) *ra = RA_NONE;
|
||||
return NULL;
|
||||
}
|
||||
if (lfhasflag(lf, F_RAGE)) {
|
||||
if (db) dblog(".oO { no ranged attack because i am enraged }");
|
||||
if (ra) *ra = RA_NONE;
|
||||
|
@ -762,7 +767,7 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
|
|||
}
|
||||
|
||||
o = getfirearm(lf);
|
||||
if (o && getammo(o)) {
|
||||
if (o && getammo(o) && canshoot(lf, NULL)) {
|
||||
if (db) {
|
||||
char gunname[BUFLEN];
|
||||
getobname(o, gunname, o->amt);
|
||||
|
@ -780,8 +785,7 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
|
|||
} else {
|
||||
o = aigetwand(lf, F_AICASTTOATTACK);
|
||||
}
|
||||
if (o) {
|
||||
|
||||
if (o && canoperate(lf, o, NULL)) {
|
||||
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name);
|
||||
|
||||
if (ra) *ra = RA_WAND;
|
||||
|
@ -791,7 +795,7 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
|
|||
}
|
||||
|
||||
// can we attack by throwing something?
|
||||
if (hasbp(lf, BP_HANDS)) {
|
||||
if (hasbp(lf, BP_HANDS) && !lfhasflag(lf, F_STUNNED)) {
|
||||
o = getbestthrowmissile(lf, target);
|
||||
if (o) {
|
||||
if (db) dblog(".oO { will throw %s at my target }", o->type->name);
|
||||
|
@ -1093,7 +1097,7 @@ object_t *aigetwand(lifeform_t *lf, enum FLAG purpose) {
|
|||
// wand with charges left?
|
||||
if ((o->type->obclass->id == OC_WAND) && (getcharges(o) > 0)) {
|
||||
// do we know how to use it?
|
||||
if (hasflag(o->flags, purpose)) {
|
||||
if (canoperate(lf, o, NULL) && hasflag(o->flags, purpose)) {
|
||||
// TODO: if castatself, check whether we actually need to (ie. healing, invis, etc)
|
||||
poss[nposs] = o;
|
||||
nposs++;
|
||||
|
@ -1871,7 +1875,7 @@ int ai_premovement(lifeform_t *lf) {
|
|||
if (lfproduceslight(lf, NULL) && (lf->cell->map->illumination != IL_FULLLIT)) {
|
||||
object_t *lamp;
|
||||
lamp = hasobwithflagval(lf->pack, F_ACTIVATECONFER, F_PRODUCESLIGHT, NA, NA, NULL);
|
||||
if (lamp && !isactivated(lamp)) {
|
||||
if (lamp && !isactivated(lamp) && canoperate(lf, lamp, NULL)) {
|
||||
if (db) dblog(".oO { it's dark and i have an inactive light source (%s) }", lamp->type->name);
|
||||
if (!operate(lf, lamp, NULL)) {
|
||||
if (db) dblog(".oO { successfully turned it on. }");
|
||||
|
@ -3491,8 +3495,11 @@ int lookforobs(lifeform_t *lf) {
|
|||
}
|
||||
if (cancast(lf, OT_A_SNATCH, NULL) && haslofknown(lf->cell, c, LOF_NEED, NULL) &&
|
||||
(getcelldist(lf->cell, c) == 1)) {
|
||||
if (!useability(lf, OT_A_SNATCH, NULL, c)) {
|
||||
success = B_TRUE;
|
||||
// only snatch those things which we can carry
|
||||
if (canpickup(lf, o, 1)) {
|
||||
if (!useability(lf, OT_A_SNATCH, NULL, c)) {
|
||||
success = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
|
@ -3646,7 +3653,7 @@ int useitemwithflag(lifeform_t *lf, enum FLAG whichflag) {
|
|||
if (!readsomething(lf, o)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
} else if ((o->type->obclass->id == OC_WAND) && getcharges(o)) {
|
||||
} else if ((o->type->obclass->id == OC_WAND) && getcharges(o) && canoperate(lf, o, NULL)) {
|
||||
// if wand, use it on ourself
|
||||
if (!operate(lf, o, lf->cell)) {
|
||||
return B_FALSE;
|
||||
|
|
69
attack.c
69
attack.c
|
@ -2979,6 +2979,15 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
|
|||
int gothit = B_FALSE;
|
||||
enum SKILLLEVEL lorelev = PR_INEPT;
|
||||
flag_t *f;
|
||||
int db = B_FALSE;
|
||||
char lfname[BUFLEN];
|
||||
char vicname[BUFLEN];
|
||||
|
||||
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
|
||||
real_getlfname(lf, lfname, NULL, B_SHOWALL, B_CURRACE);
|
||||
real_getlfname(victim, vicname, NULL, B_SHOWALL, B_CURRACE);
|
||||
|
||||
if (db) dblog("%s: rolling to hit %s", lfname, vicname);
|
||||
|
||||
// default
|
||||
if (critical) *critical = 0;
|
||||
|
@ -2987,6 +2996,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
|
|||
|
||||
// anticipate action spell?
|
||||
if (lfhasflagval(victim, F_ANTICIPATE, lf->id, NA, NA, NULL)) {
|
||||
if (db) dblog("%s: victim has anticipate action - MISS.", lfname);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -3001,9 +3011,11 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
|
|||
killflag(f);
|
||||
}
|
||||
gothit = B_TRUE;
|
||||
if (db) dblog("%s: we have truestrike - HIT.", lfname);
|
||||
} else if (critical && *critical) {
|
||||
// forced critical?
|
||||
// critical already set = forced critical
|
||||
gothit = B_TRUE;
|
||||
if (db) dblog("%s: pre-determined critical - HIT.", lfname);
|
||||
} else {
|
||||
int myroll;
|
||||
int reachpenalty = 0;
|
||||
|
@ -3011,29 +3023,46 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
|
|||
baseacc = getlfaccuracy(lf, wep);
|
||||
acc = baseacc;
|
||||
|
||||
if (db) dblog("%s: base accuracy: %d", lfname, baseacc);
|
||||
|
||||
// size difference (penalty for attacking smaller ones)
|
||||
modifyforsize(&acc, lf, victim, -5, M_VAL);
|
||||
if (db) dblog("%s: modified for victim size -> %d", lfname, acc);
|
||||
|
||||
// easier to hit victims who are prone.
|
||||
if (isprone(victim)) {
|
||||
acc += 30;
|
||||
if (db) dblog("%s: +30 for prone victim -> %d", lfname, acc);
|
||||
}
|
||||
|
||||
if (lfhasflag(lf, F_AIMEDSTRIKE)) {
|
||||
acc -= 20;
|
||||
if (db) dblog("%s: -20 for aimed strike -> %d", lfname, acc);
|
||||
}
|
||||
|
||||
// easier to hit things which have grabbed you
|
||||
if (lfhasflagval(lf, F_GRABBEDBY, victim->id, NA, NA, NULL)) {
|
||||
acc += 30;
|
||||
if (db) dblog("%s: +30 as victim is holding us -> %d", lfname, acc);
|
||||
}
|
||||
// MUCH easier to hit things which you have grabbed
|
||||
if (lfhasflagval(lf, F_GRABBING, victim->id, NA, NA, NULL)) {
|
||||
acc += 50;
|
||||
if (db) dblog("%s: +50 as we are holding victim -> %d", lfname, acc);
|
||||
}
|
||||
|
||||
if (wep && (getcelldist(lf->cell, victim->cell) <= 1)) {
|
||||
f = hasflag(wep->flags, F_ADJACCMOD);
|
||||
if (f) {
|
||||
acc += f->val[0];
|
||||
if (db) dblog("%s: %s%d for weapon adjacency modifier -> %d", lfname,
|
||||
(f->val[0] < 0) ? "" : "+", f->val[0], acc);
|
||||
}
|
||||
}
|
||||
|
||||
if (!canreach(lf, victim, &reachpenalty)) {
|
||||
acc -= (10*reachpenalty);
|
||||
if (db) dblog("%s: -%d reach penalty -> %d", lfname, (10*reachpenalty), acc);
|
||||
}
|
||||
|
||||
// modify for defender's evasion
|
||||
|
@ -3044,15 +3073,28 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
|
|||
}
|
||||
|
||||
acc -= ev;
|
||||
if (db) dblog("%s: minus victim's evaion (%d) -> %d", lfname, ev, acc);
|
||||
|
||||
// modify if we can't see the victim
|
||||
if (!cansee(lf, victim)) acc -= 30;
|
||||
if (!cansee(lf, victim)) {
|
||||
acc -= 30;
|
||||
if (db) dblog("%s: -30 for not being able to see victim -> %d", lfname, acc);
|
||||
}
|
||||
// metal weapon versus magnetic shield?
|
||||
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) acc -= 45;
|
||||
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
|
||||
acc -= 45;
|
||||
if (db) dblog("%s: -45 for metal weapon vs magshield -> %d", lfname, acc);
|
||||
}
|
||||
// victim immobile or asleep?
|
||||
if (isimmobile(victim) || lfhasflag(victim, F_EATING)) acc += 50;
|
||||
if (isimmobile(victim) || lfhasflag(victim, F_EATING)) {
|
||||
acc += 50;
|
||||
if (db) dblog("%s: +50 for immobile victim -> %d", lfname, acc);
|
||||
}
|
||||
// modify for lore level
|
||||
if (lorelev != PR_INEPT) acc += (lorelev*10);
|
||||
if (lorelev != PR_INEPT) {
|
||||
acc += (lorelev*10);
|
||||
if (db) dblog("%s: +%d for knowledge about victim's race -> %d", lfname, lorelev*10, acc);
|
||||
}
|
||||
|
||||
// modify for attacking while climbing
|
||||
if (isclimbing(lf) && !lfhasflag(lf, F_SPIDERCLIMB)) {
|
||||
|
@ -3066,10 +3108,15 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
|
|||
default:
|
||||
case PR_MASTER: break;
|
||||
}
|
||||
if (db) dblog("%s: modified for attacking while climbing -> %d", lfname, acc);
|
||||
}
|
||||
|
||||
limit(&acc, 0, 100);
|
||||
|
||||
if (db) dblog("%s: FINAL ACCURACY: %d%%", lfname, acc);
|
||||
if (db) {
|
||||
msg("%s vs. %s - %d%% hit chance", lfname, vicname, acc);
|
||||
}
|
||||
//if (aidb) dblog(".oO { my modified chance to hit is %d %% }", acc);
|
||||
myroll = rnd(1,100);
|
||||
if (myroll <= acc) {
|
||||
|
@ -3083,9 +3130,9 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
|
|||
// critical chance
|
||||
if (critical && gothit) {
|
||||
int critpossible = B_TRUE;
|
||||
if (lf && !lfhasflag(lf, F_NOGIVECRITS)) {
|
||||
if (lf && lfhasflag(lf, F_NOGIVECRITS)) {
|
||||
critpossible = B_FALSE;
|
||||
} else if (victim && !lfhasflag(victim, F_NOTAKECRITS)) {
|
||||
} else if (victim && lfhasflag(victim, F_NOTAKECRITS)) {
|
||||
critpossible = B_FALSE;
|
||||
}
|
||||
if (critpossible) {
|
||||
|
@ -3112,11 +3159,17 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
|
|||
if (isexhausted(lf) || (baseacc <= 60) || !getweaponskill(lf, wep)) {
|
||||
int nfailed = 0, i;
|
||||
int nrolls = 1;
|
||||
int newacc;
|
||||
if (getskill(lf, SK_COMBAT) >= PR_BEGINNER) {
|
||||
newacc = pctof(150, baseacc);
|
||||
} else {
|
||||
newacc = baseacc;
|
||||
}
|
||||
// chance to fumble
|
||||
// if you miss, make more attack rolls. if you fail
|
||||
// all of them, you fumble..
|
||||
for (i = 0; i < nrolls; i++) {
|
||||
if (!pctchance(acc)) nfailed++;
|
||||
if (!pctchance(newacc)) nfailed++;
|
||||
}
|
||||
if (nfailed >= nrolls) {
|
||||
*fumble = B_TRUE;
|
||||
|
|
148
data.c
148
data.c
|
@ -1,5 +1,6 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "data.h"
|
||||
|
@ -27,6 +28,7 @@ extern obmod_t *firstobmod,*lastobmod;
|
|||
extern material_t *material,*lastmaterial;
|
||||
extern lifeform_t *player;
|
||||
extern plural_t *firstplural,*lastplural;
|
||||
extern int totalraces;
|
||||
|
||||
extern hiddennamewithcol_t colour[];
|
||||
extern char *bookadjective[];
|
||||
|
@ -40,6 +42,9 @@ extern char *amuletnoun[];
|
|||
|
||||
extern objecttype_t *lastot;
|
||||
|
||||
|
||||
extern condset_t ccwalkable;
|
||||
|
||||
void addbonustext(flagpile_t *fp, enum FLAG fid, char *text) {
|
||||
int idx = -1;
|
||||
flag_t *f;
|
||||
|
@ -283,7 +288,7 @@ void initjobs(void) {
|
|||
}
|
||||
addflag(lastjob->flags, F_NOSCORE, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addjob(J_ADVENTURER, "Adventurer", "Adventurers are a versatile jack-of-all-trades type job. They can learn all skills, and already have basic Cartography and Lore skills. They also start the game with three healing potions. Recommended for beginners.", JC_FIGHTERTHIEF);
|
||||
addjob(J_ADVENTURER, "Adventurer", "Adventurers are a versatile jack-of-all-trades type job. They can learn all skills, and already have basic Cartography and Lore skills. They also start the game with three healing potions. Recommended for beginners.", JC_GENERAL);
|
||||
// stat mods
|
||||
addflag(lastjob->flags, F_ALIGNMENT, AL_NONE, NA, NA, "gne"); // ie. select
|
||||
// initial objects
|
||||
|
@ -493,7 +498,7 @@ void initjobs(void) {
|
|||
f = addflag(lastjob->flags, F_RNDSPELLSCHOOL, SS_NATURE, 1, 6, NULL); addcondition(f, FC_IFMONSTER, 100);
|
||||
|
||||
///////////////////////////////////////
|
||||
addjob(J_MONK, "Monk", "A life of strict self-discipline from an early age makes Monks masters of unarmed combat. This discipline extends to their minds, sometimes allowing them to develop powerful psionic abilities over time. On the downside, they are useless with most weapons and are strict vegetarians.", JC_FIGHTERMAGE);
|
||||
addjob(J_MONK, "Monk", "A life of strict self-discipline from an early age makes Monks masters of unarmed combat. This discipline extends to their minds, sometimes allowing them to develop powerful psionic abilities over time. On the downside, they are useless with most weapons and are strict vegetarians.", JC_FIGHTERSPEC);
|
||||
// stats
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 20, NA, NULL);
|
||||
|
@ -654,7 +659,7 @@ void initjobs(void) {
|
|||
// abilities
|
||||
addflag(lastjob->flags, F_OBESE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
|
||||
addjob(J_NINJA, "Ninja", "A dark warrior-assassin dedicated to the art of ninjutsu. Ninjas are skilled with exotic weapons, and gain special martial arts abilities at higher levels.", JC_FIGHTER);
|
||||
addjob(J_NINJA, "Ninja", "A dark warrior-assassin dedicated to the art of ninjutsu. Ninjas are skilled with exotic weapons, and gain special martial arts abilities at higher levels.", JC_FIGHTERSPEC);
|
||||
// stats
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 5, NA, NULL);
|
||||
|
@ -859,7 +864,7 @@ void initjobs(void) {
|
|||
// abilities
|
||||
addflag(lastjob->flags, F_MPDICE, 1, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
|
||||
addjob(J_ASSASSIN, "Assassin", "Rogues of a darker dispoistion sometimes become Assassins, famed for their skill at taking lives. Assassins have less ability in lockpicking or thievery than regular rogues, prefering to tackle their enemies head on.", JC_THIEF);
|
||||
addjob(J_ASSASSIN, "Assassin", "Rogues of a darker dispoistion sometimes become Assassins, famed for their skill at taking lives. Assassins have less ability in lockpicking or thievery than regular rogues, prefering to tackle their enemies head on.", JC_FIGHTERTHIEF);
|
||||
// stats
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 15, NA, NULL);
|
||||
|
@ -1016,6 +1021,49 @@ void initjobs(void) {
|
|||
addflag(lastjob->flags, F_LEVABIL, 10, OT_A_HURRICANESTRIKE, NA, NULL);
|
||||
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addjob(J_GLADIATOR, "Gladiator", "A slave-warrior whose life revolves around arena combat. Even when not in battle, gladiators maintain their fitness through a constant exercise regime. They do not tend to wear body armour, instead relying on their finely-honed senses for survival, along with their evasion and shield skills.", JC_FIGHTER);
|
||||
// stats
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 15, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_IQ, 0, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_CON, 20, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_CHA, 20, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_WIS, 0, NA, NULL);
|
||||
addflag(lastjob->flags, F_ALIGNMENT, AL_NONE, NA, NA, "gne");
|
||||
// initial objects
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "gladius");
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "apsis");
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "throwing net");
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of sandals");
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "30-40 gold dollars");
|
||||
// initial skills
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_BEGINNER, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_COMBAT, PR_BEGINNER, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_ADEPT, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_EVASION, PR_BEGINNER, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_BEGINNER, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_LISTEN, PR_NOVICE, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_SEWING, PR_NOVICE, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_METALWORK, PR_NOVICE, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_THROWING, PR_BEGINNER, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_TWOWEAPON, PR_NOVICE, NA, NULL);
|
||||
addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_BEGINNER, NA, NULL);
|
||||
// learnable skills
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_ARMOUR, PR_NOVICE, NA, NULL); // limited
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, PR_BEGINNER, NA, NULL); // limited
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_ARMOUR, PR_NOVICE, NA, NULL); // limit
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_LORE_LANGUAGE, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_SWIMMING, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, NA, NA, NULL);
|
||||
// abilities
|
||||
addflag(lastjob->flags, F_MPDICE, 1, -1, NA, NULL);
|
||||
addflag(lastjob->flags, F_LEVABIL, 4, OT_A_WARCRY, NA, NULL);
|
||||
//addflag(lastjob->flags, F_MAXHPMOD, 120, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addjob(J_BATTLEMAGE, "Battlemage", "Unlike other warriors Battlemages are minimally skilled in magic, but at the expense of the regular warrior abilities.", JC_FIGHTERMAGE);
|
||||
// stats
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 10, NA, NULL);
|
||||
|
@ -1143,7 +1191,7 @@ void initjobs(void) {
|
|||
addflag(lastjob->flags, F_LEVABIL, 5, OT_S_DISRUPTUNDEAD, NA, NULL);
|
||||
addflag(lastjob->flags, F_LEVABIL, 7, OT_S_EXORCISE, NA, "pw:1;");
|
||||
|
||||
addjob(J_SCOURGE, "Scourge", "Scourges have dedicated their life to ridding the world of magic. Strict training has granted them an innate immunity to magic, but this immunity also extends to beneficial effects.", JC_FIGHTER);
|
||||
addjob(J_SCOURGE, "Scourge", "Scourges have dedicated their life to ridding the world of magic. Strict training has granted them an innate immunity to magic, but this immunity also extends to beneficial effects.", JC_FIGHTERSPEC);
|
||||
// stats
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 10, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 10, NA, NULL);
|
||||
|
@ -1627,7 +1675,6 @@ void initobjects(void) {
|
|||
flag_t *f;
|
||||
int i,n;
|
||||
|
||||
|
||||
// init poison types
|
||||
addpoisontype(P_MIGRAINE, "a migraine", "Sick", "have developed", "", OT_NONE, 0, 0, PS_DISEASE,20);
|
||||
addpoisontype(P_COLD, "hypothermia", "Sick", "are sick with", "^bYOU cough#S violently.", OT_NONE, 1, 25, PS_DISEASE, 30);
|
||||
|
@ -3363,7 +3410,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 90, NA, "");
|
||||
addflag(lastot->flags, F_ISMEAT, B_TRUE, 80, NA, "");
|
||||
addot(OT_MUSHROOMSHI, "shiitake mushroom", "A large brown mushroom.", MT_FOOD, 0.2, OC_FOOD, SZ_TINY);
|
||||
addot(OT_MUSHROOMSHI, "shiitake mushroom", "A large brown mushroom.", MT_FOOD, 0.05, OC_FOOD, SZ_TINY);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 30, NA, "");
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_COMMON, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, NULL);
|
||||
|
@ -3372,7 +3419,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_RARITY, H_ANTNEST, 100, RR_COMMON, NULL);
|
||||
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, "");
|
||||
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "mushroom");
|
||||
addot(OT_MUSHROOMTOAD, "toadstool", "A poisonous variety of mushroom.", MT_FOOD, 0.2, OC_FOOD, SZ_TINY);
|
||||
addot(OT_MUSHROOMTOAD, "toadstool", "A poisonous variety of mushroom.", MT_FOOD, 0.05, OC_FOOD, SZ_TINY);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, NULL);
|
||||
addflag(lastot->flags, F_TAINTED, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_COMMON, NULL);
|
||||
|
@ -3385,7 +3432,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "mushroom");
|
||||
|
||||
|
||||
addot(OT_MUSHROOMGREY, "greycap", "A strange mushroom with a greyish-white tip.", MT_FOOD, 0.2, OC_FOOD, SZ_TINY);
|
||||
addot(OT_MUSHROOMGREY, "greycap", "A strange mushroom with a greyish-white tip.", MT_FOOD, 0.05, OC_FOOD, SZ_TINY);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, NULL);
|
||||
addflag(lastot->flags, F_TAINTED, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_UNCOMMON, NULL);
|
||||
|
@ -3396,7 +3443,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "mushroom");
|
||||
|
||||
|
||||
addot(OT_MUSHROOMSTUFFED, "stuffed mushroom", "A large brown mushroom stuffed with breadcrumbs. This healthy food slightly increases your maximum hit points..", MT_FOOD, 0.2, OC_FOOD, SZ_TINY);
|
||||
addot(OT_MUSHROOMSTUFFED, "stuffed mushroom", "A large brown mushroom stuffed with breadcrumbs. This healthy food slightly increases your maximum hit points..", MT_FOOD, 0.1, OC_FOOD, SZ_TINY);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 30, NA, "");
|
||||
addot(OT_NUT, "peanut", "A species in the legume family.", MT_FOOD, 0.1, OC_FOOD, SZ_TINY);
|
||||
addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL);
|
||||
|
@ -3465,7 +3512,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL); // will be overridden
|
||||
addflag(lastot->flags, F_ISMEAT, B_TRUE, 80, NA, "");
|
||||
addot(OT_HEAD, "head", "xxx", MT_FLESH, 1, OC_CORPSE, SZ_SMALL);
|
||||
addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL); // will be overridden
|
||||
//addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL); // will be overridden
|
||||
addflag(lastot->flags, F_ISMEAT, B_TRUE, 80, NA, "");
|
||||
addot(OT_FLESHCHUNK, "chunk of flesh", "A chunk of flesh from something.", MT_FLESH, 1, OC_FOOD, SZ_SMALL);
|
||||
addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL);
|
||||
|
@ -3739,7 +3786,7 @@ void initobjects(void) {
|
|||
|
||||
addot(OT_SCR_MAPPING, "scroll of sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
|
||||
addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, 4, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_UNCOMMON, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_COMMON, NULL);
|
||||
|
||||
/*
|
||||
addot(OT_SCR_MINDSCAN, "scroll of mind scan", "Allows you to view the world through another creature's eyes.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
|
||||
|
@ -5823,6 +5870,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, '^', NA, NULL);
|
||||
addflag(lastot->flags, F_SHARP, 2, 5, NA, NULL);
|
||||
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_PIERCE, FALLTHRU, "1d4");
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
||||
addflag(lastot->flags, F_VALUE, 20, NA, NA, NULL);
|
||||
|
||||
|
@ -5948,6 +5996,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_STARTOBRND, 30, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_STARTOBRND, 10, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GROWSTO, OT_SACKLARGE, VT_OB, NA, NULL);
|
||||
addflag(lastot->flags, F_CANHAVELFINSIDE, 5, 5, 50, NULL);
|
||||
|
||||
addot(OT_SACKLARGE, "large sack", "A large cloth sack.", MT_CLOTH, 1, OC_TOOLS, SZ_MEDIUM);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
|
||||
|
@ -5964,6 +6013,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GROWSTO, OT_SACKHUGE, VT_OB, NA, NULL);
|
||||
addflag(lastot->flags, F_SHRINKSTO, OT_SACK, VT_OB, NA, NULL);
|
||||
addflag(lastot->flags, F_CANHAVELFINSIDE, 5, 5, 50, NULL);
|
||||
|
||||
addot(OT_SACKHUGE, "huge sack", "An enormous cloth sack.", MT_CLOTH, 1, OC_TOOLS, SZ_LARGE);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
|
||||
|
@ -5983,6 +6033,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SHRINKSTO, OT_SACKLARGE, VT_OB, NA, NULL);
|
||||
addflag(lastot->flags, F_CANHAVELFINSIDE, 5, 5, 50, NULL);
|
||||
|
||||
|
||||
addot(OT_BAGOFHOLDING, "bag of holding", "A magical sack which causes items placed inside it to become weightless.", MT_CLOTH, 0.5, OC_TOOLS, SZ_SMALL);
|
||||
|
@ -6965,6 +7016,15 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_GROWSTO, OT_DOORWOOD, VT_OB, NA, NULL);
|
||||
addflag(lastot->flags, F_SHRINKSTO, OT_WOODENTABLE, VT_OB, NA, NULL);
|
||||
|
||||
addot(OT_BEDSTRAW, "pile of straw", "A large pile of straw. Looks like it would be mildly more comfortable to sleep on than the floor.", MT_PLANT, 10, OC_FURNITURE, SZ_HUMAN);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_YELLOW, '_', NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_HELPSREST, 15, 0, NA, NULL);
|
||||
addflag(lastot->flags, F_GROWSTO, OT_TREE, VT_OB, NA, NULL);
|
||||
addflag(lastot->flags, F_SHRINKSTO, OT_SHRUB, VT_OB, NA, NULL);
|
||||
|
||||
addot(OT_BOOKSHELF, "bookshelf", "A set of wooden shelves, sized for book storage.", MT_WOOD, 150, OC_FURNITURE, SZ_HUMAN);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_BROWN, '\\', NA, NULL);
|
||||
|
@ -7914,7 +7974,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
|
||||
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GROWSTO, OT_WOODENTABLE, VT_OB, NA, NULL);
|
||||
addflag(lastot->flags, F_GROWSTO, OT_APSIS, VT_OB, NA, NULL);
|
||||
// similar to a buckler, but repairable, lighter, and less durable
|
||||
addot(OT_SHIELDHIDE, "hide shield", "A small shield constructed out of animal skin.", MT_LEATHER, 2.00, OC_ARMOUR, SZ_SMALL);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
|
||||
|
@ -7925,6 +7985,17 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_OBHP, 18, 18, NA, NULL);
|
||||
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GROWSTO, OT_CORPSE, VT_OB, NA, NULL);
|
||||
//
|
||||
addot(OT_APSIS, "apsis", "A sturdy, bowl-shaped leather shield. Slightly more durable than a buckler.", MT_LEATHER, 4.00, OC_ARMOUR, SZ_SMALL);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
|
||||
addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_CANBLOCK, DT_ALL, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 10, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 25, 25, NA, NULL);
|
||||
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GROWSTO, OT_ARMOURLEATHER, VT_OB, NA, NULL);
|
||||
|
||||
addot(OT_SHIELD, "shield", "A medium-sized metal shield.", MT_METAL, 4.00, OC_ARMOUR, SZ_MEDIUM);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
|
||||
addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL);
|
||||
|
@ -8475,6 +8546,8 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 25, NA, NULL);
|
||||
addflag(lastot->flags, F_MISSILEALWAYSDIES, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_HELPSREPAIR, MT_LEATHER, 2, 15, NULL);
|
||||
addflag(lastot->flags, F_HELPSREPAIR, MT_CLOTH, 3, 15, NULL);
|
||||
|
||||
addot(OT_NET, "throwing net", "A grid of strong cords, weighted at the edges. Made for throwing over a target.", MT_CLOTH, 2, OC_MISSILE, SZ_MEDIUM);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
|
@ -9067,7 +9140,8 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_DAM, DT_PIERCE, 11, NA, NULL);
|
||||
addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, "butt bash");
|
||||
addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ADJACCMOD, -15, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTREQ, A_AGI, 65, 80, "10");
|
||||
addflag(lastot->flags, F_CRITCHANCE, 1, NA, NA, NULL);
|
||||
|
@ -9090,7 +9164,8 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_DAM, DT_PIERCE, 11, NA, NULL);
|
||||
addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, "butt bash");
|
||||
addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ADJACCMOD, -10, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTREQ, A_STR, 45, 65, "1");
|
||||
addflag(lastot->flags, F_ATTREQ, A_AGI, 65, 80, "5");
|
||||
|
@ -9110,7 +9185,8 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_DAM, DT_PIERCE, 10, NA, NULL);
|
||||
addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, "butt bash");
|
||||
addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 65, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); // less when adjacent
|
||||
addflag(lastot->flags, F_ADJACCMOD, -10, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
|
||||
|
@ -9334,6 +9410,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OPERNEEDDIR, B_TRUE, NA, NA, "Use your spanner in which direction");
|
||||
addflag(lastot->flags, F_HELPSDISARM, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_HELPSREPAIR, MT_METAL, 2, 15, NULL);
|
||||
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL);
|
||||
addot(OT_SHILLELAGH, "shillelagh", "An small cudgel with a strap, lightweight yet surprisingly effective. Irish in origin.", MT_WOOD, 2, OC_WEAPON, SZ_MEDIUM);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
|
||||
|
@ -10370,7 +10447,7 @@ void initrace(void) {
|
|||
noarmouron(lastrace, BP_EARS);
|
||||
addflag(lastrace->flags, F_PLAYABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_VLOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_AVERAGE, NA, NULL);
|
||||
|
@ -10401,7 +10478,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_STARTSKILL, SK_LISTEN, PR_NOVICE, NA, NULL);
|
||||
// penalties
|
||||
addbonustext(lastrace->flags, F_PENDESC, "Can never learn Athletics.");
|
||||
addflag(lastrace->flags, F_VISRANGEMOD, -2, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_VISRANGEMOD, -3, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_DTVULN, DT_SONIC, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_VEGETARIAN, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOSKILL, SK_ATHLETICS, NA, NA, NULL);
|
||||
|
@ -11032,7 +11109,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking plants");
|
||||
addflag(lastrace->flags, F_HATESRACECLASS, RC_DRAGON, NA, NA, NULL);
|
||||
// sacrifices
|
||||
addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, RC_ANIMAL, 10, "Writhing vines sprout up and drag OB underground.");
|
||||
addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, RC_ANIMAL, 5, "Writhing vines sprout up and drag OB underground.");
|
||||
addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, RC_DRAGON, 25, "Writhing vines sprout up and tear OB to pieces!");
|
||||
addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_FOOD, NA, 3, "Writhing vines sprout up and drag OB underground.");
|
||||
addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_FLORA, NA, 2, "OB transforms into a beautiful butterfly!");
|
||||
|
@ -11720,7 +11797,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_HITDICE, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
|
||||
//addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_NATURALFLIGHT, B_TRUE, NA, NA, "");
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_VERYSLOW, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLSPEED, SP_VERYSLOW, NA, NA, NULL);
|
||||
|
@ -11837,7 +11914,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_RARE, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
|
||||
|
@ -11879,7 +11956,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 2, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 20, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_NATURALFLIGHT, B_TRUE, NA, NA, "");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL);
|
||||
|
@ -12214,7 +12291,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
//addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
|
||||
|
@ -12338,7 +12415,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL);
|
||||
|
@ -12385,7 +12462,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL);
|
||||
|
@ -12460,7 +12537,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 6, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL);
|
||||
|
@ -12532,7 +12609,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 3, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
|
@ -12566,7 +12643,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_UNCOMMON, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 20, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
|
||||
|
@ -12644,7 +12721,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ARMOURRATING, 8, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 8, NA, NULL);
|
||||
|
@ -12689,7 +12766,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_HITDICE, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
//addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 10, NA, NULL);
|
||||
|
@ -12812,7 +12889,6 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_UNCOMMON, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL);
|
||||
|
@ -12952,7 +13028,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_NATURALFLIGHT, B_TRUE, NA, NA, "");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL);
|
||||
|
@ -17685,7 +17761,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 1, NA, 4, NULL);
|
||||
addflag(lastrace->flags, F_TR, 1, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_FLIGHTEVASION, 50, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_FLIGHTEVASION, 15, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_ZAPPER, 1, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_FLASH, 15, 15, "pw:4;");
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "pulses");
|
||||
|
@ -18885,6 +18961,7 @@ void initrace(void) {
|
|||
// now do final steps in race initialisation:
|
||||
// - add flags based on raceclass, etc
|
||||
// - fill in missing alignments
|
||||
totalraces = 0;
|
||||
for (r = firstrace ; r ; r = r->next) {
|
||||
if (hasflag(r->flags, F_PLAYABLE)) {
|
||||
r->known = B_TRUE;
|
||||
|
@ -19000,6 +19077,7 @@ void initrace(void) {
|
|||
if (!hasflag(r->flags, F_ALIGNMENT)) {
|
||||
addflag(r->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
|
||||
}
|
||||
totalraces++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19080,6 +19158,7 @@ void initskills(void) {
|
|||
addskilldesc(SK_COMBAT, PR_NOVICE, "Unskilled weapon penalties are greatly reduced.", B_FALSE);
|
||||
addskillabil(SK_COMBAT, PR_NOVICE, OT_A_STRIKETOKO, NA, NULL, B_TRUE);
|
||||
addskilldesc(SK_COMBAT, PR_BEGINNER, "Eliminates penalties for being prone or nauseated.", B_FALSE);
|
||||
addskilldesc(SK_COMBAT, PR_BEGINNER, "Reduced chance of fumbling attacks.", B_FALSE);
|
||||
addskilldesc(SK_COMBAT, PR_ADEPT, "Eliminates penalties when fighting unseen enemies.", B_FALSE);
|
||||
addskillabil(SK_COMBAT, PR_ADEPT, OT_A_DISARMLF, NA, NULL, B_TRUE);
|
||||
addskillabil(SK_COMBAT, PR_SKILLED, OT_A_FLIP, NA, NULL, B_TRUE);
|
||||
|
@ -19214,7 +19293,8 @@ void initskills(void) {
|
|||
addskilldesc(SK_TECHUSAGE, PR_EXPERT, "^gYou can now recognise level 5 Tech.^n", B_TRUE);
|
||||
addskilldesc(SK_TECHUSAGE, PR_MASTER, "^gYou can now recognise level 6 Tech.^n", B_TRUE);
|
||||
addskill(SK_THIEVERY, "Thievery", "Your ability to pick pockets and steal items.", 50);
|
||||
addskilldesc(SK_THIEVERY, PR_NOVICE, "^gYou gain the 'steal' ability, usable on enemies or in shops.^n", B_FALSE);
|
||||
//addskilldesc(SK_THIEVERY, PR_NOVICE, "^gYou gain the 'steal' ability, usable on enemies or in shops.^n", B_FALSE);
|
||||
addskillabil(SK_THIEVERY, PR_NOVICE, OT_A_STEAL, NA, NULL, B_TRUE);
|
||||
addskilldesc(SK_THIEVERY, PR_BEGINNER, "^gYour accuracy penalty when stealing is reduced.^n", B_TRUE);
|
||||
addskilldesc(SK_THIEVERY, PR_ADEPT, "^gYou can now choose which items to steal.^n", B_TRUE);
|
||||
addskilldesc(SK_THIEVERY, PR_SKILLED, "^gYou can now steal heavy items.", B_TRUE);
|
||||
|
|
BIN
data/hiscores.db
BIN
data/hiscores.db
Binary file not shown.
|
@ -12,6 +12,7 @@
|
|||
.:cell:carpetted floor
|
||||
#:cell:SOLID
|
||||
b:ob:wooden bed
|
||||
b:mon:sleeping humanoid:75
|
||||
t:ob:wooden table
|
||||
a:ob:armour rack
|
||||
c:ob:candelabrum
|
||||
|
|
57
defs.h
57
defs.h
|
@ -73,6 +73,7 @@
|
|||
#define UNI_TREE 0x2042
|
||||
|
||||
// getrandomemptycell() params
|
||||
/*
|
||||
#define WE_NONE 0
|
||||
#define WE_WALKABLE 1
|
||||
#define WE_EMPTY 2
|
||||
|
@ -80,6 +81,7 @@
|
|||
#define WE_NOTWALL 4
|
||||
#define WE_NOLF 5
|
||||
#define WE_SOLID 6
|
||||
*/
|
||||
|
||||
// Booleans
|
||||
#define B_FALSE (0)
|
||||
|
@ -367,6 +369,31 @@
|
|||
|
||||
#define MAXDIR_MAP 15
|
||||
|
||||
|
||||
enum CELLCONDITION {
|
||||
CC_NONE, //
|
||||
|
||||
// CELLS
|
||||
CC_CELLTYPE, // arg is celltype id
|
||||
CC_DANGEROUSFOR, // arg is lf id
|
||||
CC_EMPTY, // no arg
|
||||
CC_OKFORPORTAL, // no arg
|
||||
CC_OKFORSTAIRS, // no arg
|
||||
CC_HASLF, // no arg
|
||||
CC_HASMATERIAL, // arg is material id
|
||||
CC_HASOBTYPE, // arg is ob id
|
||||
CC_HASROOMID, // arg is room id
|
||||
CC_IMPASSABLE, // no arg
|
||||
CC_ISROOM, // arg is ob id
|
||||
CC_SOLID, // no arg
|
||||
CC_WALKABLE, // no arg
|
||||
CC_WALKABLEFOR, // arg is lfid
|
||||
// RACES
|
||||
CC_HASFLAG, // arg is flagid
|
||||
CC_HASCORPSE, // no arg
|
||||
CC_HASSIZE, // arg is enum lfsize
|
||||
};
|
||||
|
||||
enum GODBONUS {
|
||||
GB_DTRESIST, // resist damtype 'arg'
|
||||
GB_DTIMMUNE, // immune to damtype 'arg'
|
||||
|
@ -893,6 +920,7 @@ enum CELLTYPE {
|
|||
CT_WALLDIRT,
|
||||
CT_WALLFLESH,
|
||||
CT_WALLGLASS,
|
||||
CT_WALLICE,
|
||||
CT_WALLMETAL,
|
||||
CT_WALLTREE,
|
||||
CT_WALLWOOD,
|
||||
|
@ -1347,6 +1375,7 @@ enum JOB {
|
|||
J_ALLOMANCER,
|
||||
J_WARRIOR,
|
||||
J_BATTLEMAGE,
|
||||
J_GLADIATOR,
|
||||
J_PALADIN,
|
||||
J_SCOURGE,
|
||||
J_CHEF,
|
||||
|
@ -1380,6 +1409,7 @@ enum JOBCATEGORY {
|
|||
JC_NONE,
|
||||
JC_FIGHTER,
|
||||
JC_FIGHTERRANGED,
|
||||
JC_FIGHTERSPEC,
|
||||
JC_MAGE,
|
||||
JC_THIEF,
|
||||
JC_FIGHTERMAGE,
|
||||
|
@ -2085,6 +2115,7 @@ enum OBTYPE {
|
|||
// furniture
|
||||
OT_ARMOURRACK,
|
||||
OT_BED,
|
||||
OT_BEDSTRAW,
|
||||
OT_BOOKSHELF,
|
||||
OT_CANDELABRUM,
|
||||
OT_COFFIN,
|
||||
|
@ -2214,6 +2245,7 @@ enum OBTYPE {
|
|||
OT_EYEPATCH,
|
||||
OT_SUNGLASSES,
|
||||
// armour - shields
|
||||
OT_APSIS,
|
||||
OT_BUCKLER,
|
||||
OT_SHIELD,
|
||||
OT_SHIELDHIDE,
|
||||
|
@ -2822,9 +2854,12 @@ enum FLAG {
|
|||
F_HELPSCLIMB, // object gives v0 bonus to sc_climb checks.
|
||||
F_HELPSDIG, // object can dig. does v0 dam to cells.
|
||||
F_HELPSDISARM, // object gives v0 bonus to disarm trap checks.
|
||||
F_HELPSREPAIR, // object gives v1 bonus to repairing obejcts
|
||||
// made of material v0. Also decreases the
|
||||
// damage cutoff by v2.
|
||||
F_HELPSREST, // makes you heal mp/hp faster when using 'R'
|
||||
// reduces skillcheck difficulty by v0.
|
||||
// optional v1 = how many less turns between
|
||||
// optional v1 = how many fewer turns between
|
||||
// skillchecks. should not go more than
|
||||
// DEFAULTRESTHEALTIME.
|
||||
F_DONTSHOWDEST, // don't show destination of this stair
|
||||
|
@ -2872,6 +2907,11 @@ enum FLAG {
|
|||
// vulnerable to, the object's material will be
|
||||
// automatically changed to the first listed.
|
||||
// CANBEDIFFMAT.
|
||||
F_CANHAVELFINSIDE, // this object might start with a monster
|
||||
// hiding inside it.
|
||||
// v0 = base pct chance
|
||||
// v1 = extra pct chance every 5 levels
|
||||
// v2 = max chance
|
||||
F_CANBETRAPPED, // this object might start with a trap
|
||||
// v0 = base pct chance
|
||||
// v1 = extra pct chance every 5 levels
|
||||
|
@ -3039,6 +3079,7 @@ enum FLAG {
|
|||
// if V1/V2 are set, then F_RESTRICTMOVEMENT
|
||||
// v1->v0, v2->v1 is added to this object after it hits.
|
||||
F_ACCURACY, // 100 - val0 = modify to tohit% (ie. higher is better)
|
||||
F_ADJACCMOD, // +v0% tohit adjacent enemies
|
||||
F_UNARMEDWEP, // this is not a real weapon, ie. claws, teeth etc
|
||||
F_ARMOURIGNORE, // armour has no effect
|
||||
F_ARMOURPIERCE, // goes through armour. armour can't reduce the
|
||||
|
@ -3087,6 +3128,8 @@ enum FLAG {
|
|||
F_LINKOB, // val0 = linked object id
|
||||
F_LINKRACE, // val0 = linked race id
|
||||
F_LINKGOD, // val0 = linked god race id
|
||||
// container flags
|
||||
F_LFINSIDE, // lf of race v0 is inside.
|
||||
// scroll flags
|
||||
F_LINKSPELL, // val0 = spell this scroll will cast when read
|
||||
// v1 = spell power (optional)
|
||||
|
@ -3881,7 +3924,8 @@ enum FLAG {
|
|||
// creatures within v0 gain f_nauseated = v1
|
||||
// on objects:
|
||||
// creatures standing on it gain f_nauseated = v1
|
||||
F_STUNNED, // cannot attack or cast spells
|
||||
F_STUNNED, // cannot attack or cast spells
|
||||
// or use firearms, or throw, or operate stuff
|
||||
F_TREMORSENSE, // doesn't need eyes to see, can see in dark with v0
|
||||
F_PRODUCESLIGHT, // produces light of val0 radius.
|
||||
// (but not for obs in pack)
|
||||
|
@ -4147,10 +4191,12 @@ enum ERROR {
|
|||
E_WEARINGSOMETHINGELSE,
|
||||
E_NOUNARMEDATTACK,
|
||||
E_NOTEQUIPPED,
|
||||
E_EQUIPPED,
|
||||
E_NOPICKUP,
|
||||
E_STUCK,
|
||||
E_MONSTERNEARBY,
|
||||
E_NOEFFECT,
|
||||
E_RESISTED,
|
||||
E_FAILED,
|
||||
E_WRONGCELLTYPE,
|
||||
E_OBINWAY,
|
||||
|
@ -4193,6 +4239,7 @@ enum ERROR {
|
|||
E_LOWWIS,
|
||||
E_WONT,
|
||||
E_OFFMAP,
|
||||
E_RAGE,
|
||||
E_STUNNED,
|
||||
// charm failure reasons
|
||||
// LOWIQ
|
||||
|
@ -4289,6 +4336,12 @@ enum COMMAND {
|
|||
CMD_EXCHANGE,
|
||||
};
|
||||
|
||||
typedef struct condset_s {
|
||||
enum CELLCONDITION cond[MAXCANDIDATES];
|
||||
int arg[MAXCANDIDATES];
|
||||
int val[MAXCANDIDATES];
|
||||
int nconds;
|
||||
} condset_t;
|
||||
|
||||
typedef struct behaviour_s {
|
||||
enum BEHAVIOUR id;
|
||||
|
|
81
flag.c
81
flag.c
|
@ -58,12 +58,13 @@ flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
|
||||
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid) {
|
||||
lifeform_t *lf;
|
||||
flag_t *f;
|
||||
flag_t *f = NULL;
|
||||
//map_t *redolight = NULL;
|
||||
int redrawscreenatend = B_FALSE;
|
||||
int redrawstatatend = B_FALSE;
|
||||
int i;
|
||||
int rv;
|
||||
enum { NONE, FIRST, FIRST2, MIDDLE, LAST } fml = NONE;
|
||||
|
||||
//checkflagpile(fp);
|
||||
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
|
||||
|
@ -150,7 +151,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
////////////////////////////////
|
||||
|
||||
if (fp->first == NULL) {
|
||||
fp->first = malloc(sizeof(flag_t));
|
||||
fp->first = (flag_t *)calloc(1, sizeof(flag_t));
|
||||
f = fp->first;
|
||||
f->prev = NULL;
|
||||
|
||||
|
@ -158,6 +159,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
fp->last = f;
|
||||
f->next = NULL;
|
||||
|
||||
fml = FIRST;
|
||||
} else {
|
||||
flag_t *ff;
|
||||
// we will keep flags sorted.
|
||||
|
@ -166,35 +168,58 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
while (ff && (ff->id < id)) {
|
||||
ff = ff->next;
|
||||
}
|
||||
|
||||
if (ff) {
|
||||
// start or middle of list
|
||||
// insert BEFORE this one
|
||||
flag_t *newone = NULL;
|
||||
flag_t *prev;
|
||||
|
||||
|
||||
prev = ff->prev;
|
||||
|
||||
// allocate new flag
|
||||
newone = (flag_t *)calloc(1, sizeof(flag_t));
|
||||
assert(newone != NULL);
|
||||
|
||||
// link to previous element
|
||||
if (prev) {
|
||||
prev->next = malloc(sizeof(flag_t));
|
||||
f = prev->next;
|
||||
flag_t *origpn;
|
||||
//f = (flag_t *)malloc(sizeof(flag_t)); assert(f);
|
||||
//prev->next = f;
|
||||
origpn = prev->next;
|
||||
|
||||
prev->next = newone;
|
||||
assert(prev->next != origpn);
|
||||
assert(prev->next != ff);
|
||||
//f = prev->next;
|
||||
f = newone;
|
||||
fml = MIDDLE;
|
||||
} else {
|
||||
// first one
|
||||
fp->first = malloc(sizeof(flag_t));
|
||||
f = fp->first;
|
||||
//fp->first = (flag_t *)calloc(1, sizeof(flag_t));
|
||||
fp->first = newone;
|
||||
assert(fp->first != NULL);
|
||||
//f = fp->first;
|
||||
f = newone;
|
||||
fml = FIRST2;
|
||||
}
|
||||
assert(prev != f);
|
||||
f->prev = prev;
|
||||
|
||||
// link to next element
|
||||
assert(ff != f);
|
||||
f->next = ff;
|
||||
ff->prev = f;
|
||||
} else {
|
||||
// last one. insert at end of list.
|
||||
f = fp->last;
|
||||
f->next = malloc(sizeof(flag_t)); /// <- died here!
|
||||
f->next = (flag_t *)malloc(sizeof(flag_t)); /// <- died here!
|
||||
f->next->prev = f;
|
||||
f = f->next;
|
||||
fp->last = f;
|
||||
f->next = NULL;
|
||||
|
||||
fml = LAST;
|
||||
}
|
||||
/*
|
||||
// go to end of list
|
||||
|
@ -205,6 +230,8 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
*/
|
||||
}
|
||||
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
|
||||
assert(f->prev != f);
|
||||
assert(f->next != f);
|
||||
|
||||
// fill in props
|
||||
f->id = id;
|
||||
|
@ -979,10 +1006,12 @@ int istransitoryflag(flag_t *f) {
|
|||
}
|
||||
|
||||
|
||||
// returns true if we did something
|
||||
// returns # flags killed
|
||||
int killflagsofid(flagpile_t *fp, enum FLAG fid) {
|
||||
flag_t *f,*nextf;
|
||||
int donesomething = B_FALSE;
|
||||
flag_t *f;
|
||||
//,*nextf;
|
||||
int ndone = 0;
|
||||
/*
|
||||
for (f = fp->first ; f ; f = nextf) {
|
||||
nextf = f->next;
|
||||
|
||||
|
@ -994,7 +1023,14 @@ int killflagsofid(flagpile_t *fp, enum FLAG fid) {
|
|||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
return donesomething;
|
||||
*/
|
||||
f = hasflag(fp, fid);
|
||||
while (f) {
|
||||
killflag(f);
|
||||
ndone++;
|
||||
f = hasflag(fp, fid);
|
||||
}
|
||||
return ndone;
|
||||
}
|
||||
|
||||
// returns # flags removed if we did something
|
||||
|
@ -1034,9 +1070,14 @@ void killflag(flag_t *f) {
|
|||
int redostat = B_FALSE;
|
||||
int redoscreen = B_FALSE;
|
||||
int i,dopleasegod[MAXGODS];
|
||||
flagpile_t *newflags = NULL;
|
||||
|
||||
//checkflagpile(f->pile);
|
||||
|
||||
|
||||
// remember the pile so that we can re-index
|
||||
pile = f->pile;
|
||||
|
||||
fid = f->id;
|
||||
|
||||
for (i = 0; i < ngodlfs; i++) {
|
||||
|
@ -1099,7 +1140,8 @@ void killflag(flag_t *f) {
|
|||
// once you recover from fleeing from something,
|
||||
// you don't find it scary for a little while.
|
||||
if (!lfhasflagval(lf, F_NOFLEEFROM, f->val[0], NA, NA, NULL)) {
|
||||
addtempflag(lf->flags, F_NOFLEEFROM, f->val[0], NA, NA, NULL, 10);
|
||||
if (!newflags) newflags = addflagpile(NULL, NULL);
|
||||
addtempflag(newflags, F_NOFLEEFROM, f->val[0], NA, NA, NULL, 10);
|
||||
}
|
||||
} else if (f->id == F_RAGE) {
|
||||
if (!isdead(lf)) {
|
||||
|
@ -1114,8 +1156,9 @@ void killflag(flag_t *f) {
|
|||
|
||||
// announce
|
||||
if (announceflagloss(lf, f)) {
|
||||
if (flagcausesinterrupt(f, GL_LOSS)) {
|
||||
addflag(lf->flags, F_INTERRUPTED, B_TRUE, NA, NA, NULL);
|
||||
if (flagcausesinterrupt(f, GL_LOSS) && !hasflag(lf->flags, F_INTERRUPTED)) {
|
||||
if (!newflags) newflags = addflagpile(NULL, NULL);
|
||||
addflag(newflags, F_INTERRUPTED, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
/*
|
||||
// don't include flags which interrupt will kill!
|
||||
|
@ -1159,9 +1202,6 @@ void killflag(flag_t *f) {
|
|||
// now we are actually removing the flag.
|
||||
/////////////////////////////////////////////
|
||||
|
||||
// remember the pile so that we can re-index
|
||||
pile = f->pile;
|
||||
|
||||
// free mem
|
||||
if (f->text) {
|
||||
free(f->text);
|
||||
|
@ -1249,6 +1289,11 @@ void killflag(flag_t *f) {
|
|||
}
|
||||
}
|
||||
//checkflagpile(pile);
|
||||
// NOW add the new flags.
|
||||
if (newflags) {
|
||||
copyflags(pile, newflags, NA);
|
||||
killflagpile(newflags);
|
||||
}
|
||||
}
|
||||
|
||||
void killflagpile(flagpile_t *fp) {
|
||||
|
|
18
god.c
18
god.c
|
@ -31,6 +31,8 @@ extern skill_t *firstskill, *lastskill;
|
|||
extern objecttype_t *objecttype;
|
||||
extern lifeform_t *player;
|
||||
|
||||
extern condset_t ccwalkable;
|
||||
|
||||
lifeform_t *godlf[MAXGODS];
|
||||
int ngodlfs = 0;
|
||||
|
||||
|
@ -520,6 +522,7 @@ void askforworship(enum RACE rid) {
|
|||
lifeform_t *god;
|
||||
char yn;
|
||||
|
||||
if (lfhasflag(player, F_NOPRAY)) return;
|
||||
|
||||
// make sure the player knows about it!
|
||||
killtransitoryflags(player->flags, F_BLIND);
|
||||
|
@ -686,7 +689,7 @@ void dooffer(void) {
|
|||
// special effect sacrificing flora to ekrub makes it turn into a
|
||||
// butterfly
|
||||
if ((god->race->id == R_GODNATURE) && (o->type->obclass->id == OC_FLORA)) {
|
||||
newcell = getrandomadjcell(player->cell, B_FALSE, B_NOEXPAND);
|
||||
newcell = getrandomadjcell(player->cell, &ccwalkable, B_NOEXPAND);
|
||||
}
|
||||
|
||||
if (haslos(player, player->cell)) {
|
||||
|
@ -1041,13 +1044,16 @@ lifeform_t *godappears(enum RACE rid, cell_t *where) {
|
|||
real_getlfname(god, godname, NULL, B_NOSHOWALL, B_REALRACE);
|
||||
strcpy(killedname, "");
|
||||
if (!where) {
|
||||
condset_t cs;
|
||||
// somewhere next to the player.
|
||||
where = real_getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, player, MT_NOTHING);
|
||||
where = real_getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, player);
|
||||
if (!where) {
|
||||
where = real_getrandomadjcell(player->cell, WE_NOTWALL, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, player, MT_NOTHING);
|
||||
initcond(&cs); addcond(&cs, CC_IMPASSABLE, B_FALSE, NA);
|
||||
where = real_getrandomadjcell(player->cell, &cs, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, player);
|
||||
}
|
||||
if (!where) {
|
||||
where = real_getrandomadjcell(player->cell, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, player, MT_NOTHING);
|
||||
initcond(&cs); addcond(&cs, CC_IMPASSABLE, B_FALSE, NA);
|
||||
where = real_getrandomadjcell(player->cell, &cs, B_ALLOWEXPAND, LOF_DONTNEED, NULL, player);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2196,7 +2202,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
break;
|
||||
case R_GODPURITY:
|
||||
msg("\"Witness the holy radiance of purity!\"");
|
||||
c = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (c) {
|
||||
dospelleffects(god, OT_S_LIGHT, 10, NULL, NULL, c, B_BLESSED, NULL, B_TRUE, NULL);
|
||||
}
|
||||
|
@ -2324,7 +2330,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
who->hp = 0;
|
||||
} else if (n != OT_NONE) {
|
||||
if (n == OT_S_HECTASSERVANT) {
|
||||
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (c) {
|
||||
castspell(god, n, player, NULL, c, NULL, NULL);
|
||||
}
|
||||
|
|
53
io.c
53
io.c
|
@ -81,6 +81,8 @@ extern job_t *firstjob;
|
|||
extern enum GAMEMODE gamemode;
|
||||
extern long curtime;
|
||||
|
||||
extern condset_t ccwalkable;
|
||||
|
||||
char msgbuf[HUGEBUFLEN];
|
||||
char lastmsgbuf[HUGEBUFLEN];
|
||||
char prevmsg[HUGEBUFLEN];
|
||||
|
@ -667,8 +669,22 @@ cell_t *real_askcoords(char *prompt, char *subprompt, int targettype, lifeform_t
|
|||
}
|
||||
|
||||
if ((curtarget == -1) && ntargets) {
|
||||
int closest = -1,i;
|
||||
// set to the closest one.
|
||||
//curtarget = ntargets;
|
||||
curtarget = 0;
|
||||
for (i = 0; i < ntargets; i++) {
|
||||
if (closest == -1) {
|
||||
closest = i;
|
||||
} else if (getcelldist(srclf->cell, target[i]) <
|
||||
getcelldist(srclf->cell, target[closest])) {
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
if (closest != -1) {
|
||||
curtarget = closest;
|
||||
} else {
|
||||
curtarget = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// start prompting
|
||||
|
@ -4567,7 +4583,7 @@ void docomms(lifeform_t *lf) {
|
|||
break;
|
||||
}
|
||||
// find adjacent cell
|
||||
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (c) {
|
||||
aigoto(lf, c, MR_OTHER, NULL, DEF_AIFOLLOWTIME);
|
||||
}
|
||||
|
@ -6592,6 +6608,13 @@ char *makedesc_ob(object_t *o, char *retbuf) {
|
|||
sprintf(buf, "It gives a +%d%% bonus when disarming traps.\n", f->val[0] * 5);
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
getflags(o->flags, retflag, &nretflags, F_HELPSREPAIR, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
material_t *m;
|
||||
m = findmaterial(retflag[i]->val[0]);
|
||||
sprintf(buf, "It provides a +%d bonus whenrepairing %s objects.", retflag[i]->val[1], m->name);
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
f = hasflag(o->flags, F_HELPSREST);
|
||||
if (f) {
|
||||
sprintf(buf, "It provides a %d%% bonus to health regeneration when resting.", f->val[0] * 5);
|
||||
|
@ -8722,9 +8745,10 @@ void dofinaloblist(obpile_t *op) {
|
|||
}
|
||||
|
||||
void dofire(void) {
|
||||
if (shoot(player)) {
|
||||
enum ERROR why;
|
||||
if (!canshoot(player, &why)) {
|
||||
// why not?
|
||||
switch (reason) {
|
||||
switch (why) {
|
||||
case E_NOTEQUIPPED:
|
||||
msg("You have no firearm equipped!");
|
||||
break;
|
||||
|
@ -8738,7 +8762,10 @@ void dofire(void) {
|
|||
msg("You cannot fire for some reason!");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
shoot(player);
|
||||
}
|
||||
|
||||
void dohelp(char helpmode) {
|
||||
|
@ -9132,7 +9159,6 @@ int dotakeoff(obpile_t *op) {
|
|||
// returns B_TRUE on failure.
|
||||
int dothrow(obpile_t *op, object_t *o) {
|
||||
char buf[BUFLEN],buf2[BUFLEN];
|
||||
flag_t *f;
|
||||
|
||||
if (!hasbp(player, BP_HANDS)) {
|
||||
msg("You have no hands to throw with!");
|
||||
|
@ -9147,22 +9173,23 @@ int dothrow(obpile_t *op, object_t *o) {
|
|||
int maxdist;
|
||||
char subprompt[BUFLEN],oidbuf[BUFLENSMALL];
|
||||
cell_t *where;
|
||||
enum ERROR why;
|
||||
getobname(o, buf, 1);
|
||||
|
||||
f = hasflag(o->flags, F_EQUIPPED);
|
||||
if (f && (f->val[0] != BP_WEAPON)) {
|
||||
msg("You'll need to take it off first.");
|
||||
if (!canthrow(player, o, &why)) {
|
||||
switch (why) {
|
||||
case E_EQUIPPED: msg("You'll need to take it off first."); break;
|
||||
case E_RAGE: msg("You are too enraged to throw anything!"); break;
|
||||
case E_STUNNED: msg("You cannot throw anything while stunned."); break;
|
||||
case E_LOWSTR: msg("You are not strong enough to throw that."); break;
|
||||
default: msg("For some reason, you can't throw that."); break;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// calculate throw range
|
||||
maxdist = getmaxthrowrange(player, o);
|
||||
|
||||
if (maxdist < 1) {
|
||||
msg("You are not strong enough to throw that.");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// ask where to throw it
|
||||
snprintf(buf2, BUFLEN, "Throw %s where?",buf);
|
||||
snprintf(subprompt, BUFLEN, "%s->Throw->",buf);
|
||||
|
|
17
lf.h
17
lf.h
|
@ -56,6 +56,7 @@ int canhear(lifeform_t *lf, cell_t *c, int volume, int *numwalls);
|
|||
int canlearn(lifeform_t *lf, enum SKILL skid);
|
||||
int canmakerecipe(lifeform_t *lf, recipe_t *rec);
|
||||
int canopendoors(lifeform_t *lf);
|
||||
int canoperate(lifeform_t *lf, object_t *o, enum ERROR *why);
|
||||
int canpickup(lifeform_t *lf, object_t *o, int amt);
|
||||
int canpolymorphto(enum RACE rid);
|
||||
int canpush(lifeform_t *lf, object_t *o, int dir);
|
||||
|
@ -64,7 +65,9 @@ int canreach(lifeform_t *lf, lifeform_t *victim, int *reachpenalty);
|
|||
int canreachbp(lifeform_t *lf, lifeform_t *victim, enum BODYPART bp);
|
||||
int cansee(lifeform_t *viewer, lifeform_t *viewee);
|
||||
int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos);
|
||||
int canshoot(lifeform_t *lf, enum ERROR *why);
|
||||
int cansleep(lifeform_t *lf);
|
||||
int canthrow(lifeform_t *lf, object_t *o, enum ERROR *why);
|
||||
int canuseweapons(lifeform_t *lf);
|
||||
int canwear(lifeform_t *lf, object_t *o, enum BODYPART where);
|
||||
int canweild(lifeform_t *lf, object_t *o);
|
||||
|
@ -112,6 +115,7 @@ object_t *eyesshaded(lifeform_t *lf);
|
|||
int fall(lifeform_t *lf, lifeform_t *fromlf, int announce);
|
||||
int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong);
|
||||
int fall_from_air(lifeform_t *lf);
|
||||
int real_fall_from_air(lifeform_t *lf, enum LFSIZE leqsize);
|
||||
void fightback(lifeform_t *lf, lifeform_t *attacker);
|
||||
behaviour_t *findbehaviour(enum BEHAVIOUR bid);
|
||||
job_t *findjob(enum JOB jobid);
|
||||
|
@ -121,7 +125,7 @@ lifeform_t *findlfunique(enum RACE rid);
|
|||
cell_t *findnearbylifeob(cell_t *src, int maxdist, flag_t *lifeobflag, object_t **retlifeob);
|
||||
poisontype_t *findpoisontype(enum POISONTYPE id);
|
||||
race_t *findrace(enum RACE id);
|
||||
race_t *findracebyname(char *name);
|
||||
race_t *findracebyname(char *name, condset_t *cs);
|
||||
raceclass_t *findraceclass(enum RACECLASS id);
|
||||
//lifeform_t *findshopkeeper(map_t *m, int roomid);
|
||||
skill_t *findskill(enum SKILL id);
|
||||
|
@ -163,6 +167,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, /*@null@*/cha
|
|||
int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset);
|
||||
int getavgdam(lifeform_t *lf, int forxp);
|
||||
enum CASTTYPE getcasttype(lifeform_t *lf, enum OBTYPE sid);
|
||||
int getdistspotmod(lifeform_t *lf, cell_t *c);
|
||||
int getdrunkattrmod(lifeform_t *lf, enum ATTRIB att, int drunkamt);
|
||||
int getengineeringwallmod(lifeform_t *lf);
|
||||
float getequippedweight(lifeform_t *lf);
|
||||
|
@ -268,9 +273,10 @@ enum BODYPART getrandomcorebp(lifeform_t *lf, lifeform_t *attacker);
|
|||
race_t *getrandomcorpserace(cell_t *c);
|
||||
job_t *getrandomjob(int onlyplayerjobs);
|
||||
int getrandommonlevel(race_t *r, map_t *m);
|
||||
race_t *getrandomrace(cell_t *c, int forcedepth);
|
||||
race_t *getrandomrace(cell_t *c, int forcedepth, condset_t *cs);
|
||||
race_t *getrandomraceofsize(enum LFSIZE wantsize);
|
||||
race_t *getrandomracewithflag(enum FLAG fid);
|
||||
race_t *getreallyrandomrace(enum RACECLASS wantrc);
|
||||
race_t *getreallyrandomrace(enum RACECLASS wantrc, condset_t *cs);
|
||||
enum SKILL getrandomskill(void);
|
||||
object_t *getrestob(lifeform_t *lf);
|
||||
enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id);
|
||||
|
@ -311,6 +317,7 @@ flag_t *hasbleedinginjury(lifeform_t *lf, enum BODYPART bp);
|
|||
int hasfreeaction(lifeform_t *lf);
|
||||
int real_hasfreeaction(lifeform_t *lf, enum FLAG exception);
|
||||
int hashealableinjuries(lifeform_t *lf);
|
||||
flag_t *hasinjuredbp(lifeform_t *lf, enum BODYPART bp);
|
||||
job_t *hasjob(lifeform_t *lf, enum JOB job);
|
||||
int hasjobcat(lifeform_t *lf, enum JOBCATEGORY jcid);
|
||||
flag_t *hasname(lifeform_t *lf);
|
||||
|
@ -414,7 +421,7 @@ void magicwoods_warn(lifeform_t *who);
|
|||
void makefriendly(lifeform_t *lf, int howlong);
|
||||
void makeheard(lifeform_t *listener, lifeform_t *noisemaker, int showglyph, char *noisetext, int howlong);
|
||||
int makelearnable(lifeform_t *lf, enum SKILL skid);
|
||||
int makenauseated(lifeform_t *lf, int amt, int howlong);
|
||||
int makenauseated(lifeform_t *lf, int amt, int howlong, enum ERROR *why);
|
||||
void makenoise(lifeform_t *lf, enum NOISETYPE nid);
|
||||
void makepeaceful(lifeform_t *lf, lifeform_t *causedby);
|
||||
lifeform_t *makezombie(object_t *o);
|
||||
|
@ -450,6 +457,8 @@ void precalclos(lifeform_t *lf);
|
|||
void preparecorpse(lifeform_t *lf, object_t *corpse);
|
||||
int push(lifeform_t *lf, object_t *o, int dir);
|
||||
int racecantalk(enum RACE rid);
|
||||
int racemeetscondition(race_t *r, enum CELLCONDITION cond, int arg, int val);
|
||||
int racemeets(enum RACE rid, condset_t *cs);
|
||||
int readytotrain(lifeform_t *lf);
|
||||
int recruit(lifeform_t *lf);
|
||||
void refreshlevelabilities(lifeform_t *lf);
|
||||
|
|
417
map.c
417
map.c
|
@ -53,6 +53,10 @@ extern int notime;
|
|||
|
||||
extern long curtime;
|
||||
|
||||
extern condset_t ccwalkable;
|
||||
extern condset_t ccwalkableroom;
|
||||
extern condset_t ccroom;
|
||||
|
||||
cell_t *addcell(map_t *m, int x, int y) {
|
||||
cell_t *cell;
|
||||
|
||||
|
@ -133,7 +137,7 @@ void addhomeobs(lifeform_t *lf, int dolevelobs) {
|
|||
cell_t *c;
|
||||
o = addob(homeobloc->obpile, f->text);
|
||||
if (o && (homeobloc == lf->cell) && isimpassableob(o, lf, SZ_ANY)) {
|
||||
c = real_getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
|
||||
c = real_getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
|
||||
if (c) {
|
||||
homeobloc = c; // future obs will go here too.
|
||||
moveob(o, homeobloc->obpile, o->amt);
|
||||
|
@ -160,9 +164,11 @@ void addhomeobs(lifeform_t *lf, int dolevelobs) {
|
|||
for (i = 0; i < amt; i++) {
|
||||
object_t *o = NULL;
|
||||
cell_t *c;
|
||||
//condset_t cs;
|
||||
if (range == NA) { // ie. anywhere on level
|
||||
// pick new EMPTY random spot. try rooms first.
|
||||
c = getrandomroomcell(lf->cell->map, ANYROOM, WE_WALKABLE);
|
||||
//c = getrandomroomcell(lf->cell->map, ANYROOM, WE_WALKABLE);
|
||||
c = getcell_cond(lf->cell->map, &ccwalkableroom);
|
||||
if (!c) {
|
||||
// if no rooms, get any walkable cell.
|
||||
c = getrandomcell(lf->cell->map);
|
||||
|
@ -266,18 +272,19 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
|
||||
if (rid != R_SPECIFIED) {
|
||||
if (rid == R_RANDOM) {
|
||||
r = getrandomrace(c, NA);
|
||||
r = getrandomrace(c, NA, NULL);
|
||||
} else {
|
||||
r = findrace(rid);
|
||||
}
|
||||
} else {
|
||||
condset_t cs;
|
||||
|
||||
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
|
||||
rid = parserace(racename, wantflags, &wantjob, &wantbehaviour);
|
||||
rid = parserace(racename, wantflags, &cs, &wantjob, &wantbehaviour);
|
||||
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
|
||||
|
||||
if (rid == R_RANDOM) {
|
||||
r = getrandomrace(c, NA);
|
||||
r = getrandomrace(c, NA, &cs);
|
||||
} else {
|
||||
r = findrace(rid);
|
||||
}
|
||||
|
@ -454,7 +461,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
lifeform_t *newlf;
|
||||
// find an adjacent cell to one of the newly added monsters,
|
||||
// starting with the first one
|
||||
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, NULL, MT_NOTHING);
|
||||
adjcell = real_getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
|
||||
// did we find one?
|
||||
if (!adjcell) break;
|
||||
|
||||
|
@ -503,11 +510,12 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
lifeform_t *newlf;
|
||||
enum RACE newrid;
|
||||
race_t *newr;
|
||||
condset_t cs;
|
||||
|
||||
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, NULL, MT_NOTHING);
|
||||
adjcell = real_getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
|
||||
if (!adjcell) break;
|
||||
|
||||
newrid = parserace(f->text, NULL, NULL, NULL);
|
||||
newrid = parserace(f->text, NULL, &cs, NULL, NULL);
|
||||
newr = findrace(newrid);
|
||||
if (!newr) break;
|
||||
|
||||
|
@ -1290,6 +1298,7 @@ int adjcellokforreachability(cell_t *c, int srcroomid, int dir, int wantfilled)
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
int cellmatchescondition(cell_t *c, int wecond) {
|
||||
int ok = B_FALSE;
|
||||
if (wecond == WE_EMPTY) {
|
||||
|
@ -1322,6 +1331,154 @@ int cellmatchescondition(cell_t *c, int wecond) {
|
|||
}
|
||||
return ok;
|
||||
}
|
||||
*/
|
||||
|
||||
int cellmeetscondition(cell_t *c, enum CELLCONDITION cond, int arg, int value) {
|
||||
int ok = B_FALSE,vok = B_FALSE;
|
||||
object_t *o;
|
||||
lifeform_t *lf;
|
||||
assert(c);
|
||||
switch (cond) {
|
||||
case CC_CELLTYPE:
|
||||
if (value && (c->type->id == arg)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!value && (c->type->id != arg)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_DANGEROUSFOR:
|
||||
lf = findlf(NULL, arg);
|
||||
if (value == B_TRUE) {
|
||||
if (celldangerous(lf, c, B_FALSE, NULL)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!celldangerous(lf, c, B_FALSE, NULL)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CC_EMPTY:
|
||||
if (value && isempty(c)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!value && !isempty(c)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_OKFORPORTAL:
|
||||
if (value == B_TRUE) {
|
||||
if (cellwalkable(NULL, c, NULL) && !hasenterableobject(c) && !hasobwithflag(c->obpile, F_DOOR)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!cellwalkable(NULL, c, NULL) || hasenterableobject(c) || hasobwithflag(c->obpile, F_DOOR)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CC_OKFORSTAIRS:
|
||||
if (getcellvault(c) && hasflag(c->room->vault->flags, F_NOSTAIRS)) {
|
||||
vok = B_FALSE;
|
||||
} else {
|
||||
vok = B_TRUE;
|
||||
}
|
||||
if (value == B_TRUE) {
|
||||
if (vok && cellwalkable(NULL, c, NULL) && !hasenterableobject(c) && !hasobwithflag(c->obpile, F_DOOR) ) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!vok || !cellwalkable(NULL, c, NULL) || hasenterableobject(c) || hasobwithflag(c->obpile, F_DOOR)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CC_HASLF:
|
||||
if (value && c->lf) {
|
||||
ok = B_TRUE;
|
||||
} else if (!value && !c->lf) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_HASMATERIAL:
|
||||
if (value && (c->type->material->id == arg)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!value && (c->type->material->id != arg)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_HASOBTYPE:
|
||||
o = hasob(c->obpile, arg);
|
||||
if ((o && value) || (!o && !value)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_HASROOMID:
|
||||
if (value && isroom(c) && (getroomid(c) == arg)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!value && (!isroom(c) || (getroomid(c) != arg)) ) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_IMPASSABLE:
|
||||
if (value) {
|
||||
if (c->type->solid || hasobwithflag(c->obpile, F_IMPASSABLE)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!c->type->solid && !hasobwithflag(c->obpile, F_IMPASSABLE)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CC_ISROOM:
|
||||
if (value) {
|
||||
if (isroom(c)) ok = B_TRUE;
|
||||
} else {
|
||||
if (!isroom(c)) ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_SOLID:
|
||||
if (value) {
|
||||
if (issolid(c)) ok = B_TRUE;
|
||||
} else {
|
||||
if (!issolid(c)) ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_WALKABLE:
|
||||
if (value == B_TRUE) {
|
||||
if (cellwalkable(NULL, c, NULL)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!cellwalkable(NULL, c, NULL)) ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_WALKABLEFOR:
|
||||
lf = findlf(NULL, arg);
|
||||
if (value == B_TRUE) {
|
||||
if (cellwalkable(lf, c, NULL)) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!cellwalkable(lf, c, NULL)) ok = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case CC_NONE: ok = B_TRUE; break;
|
||||
default: break;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
int cellmeets(cell_t *c, condset_t *cs) {
|
||||
int i;
|
||||
if (!cs) return B_TRUE;
|
||||
for (i = 0; i < cs->nconds; i++ ){
|
||||
if (!cellmeetscondition(c, cs->cond[i], cs->arg[i], cs->val[i])) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// returns B_TRUE, B_FALSE or B_MAYBE
|
||||
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom) {
|
||||
|
@ -1377,7 +1534,6 @@ int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir,
|
|||
// kill everything in the given cell (lifeforms && objects)
|
||||
// but DONT remove the cell itself.
|
||||
void clearcell(cell_t *c) {
|
||||
|
||||
if (c->lf && !isplayer(c->lf)) {
|
||||
killlf(c->lf);
|
||||
}
|
||||
|
@ -2167,26 +2323,40 @@ int fix_reachability(map_t *m) {
|
|||
}
|
||||
// try to fix unreachable areas.
|
||||
if (nunreach) {
|
||||
int nadded = 0,nportals = 0;
|
||||
int idx,ntries = 0,maxtries = 5;
|
||||
int nadded = 0,nportals = 0, ndoors = 0;
|
||||
cell_t *ucell;
|
||||
// pick one of the unreachable cells
|
||||
while (ntries < maxtries) {
|
||||
idx = rnd(0,nunreach-1);
|
||||
ucell = unreachcell[idx];
|
||||
// try to link it back to a filled cell.
|
||||
if (db) dblog(" attempting to fix unreachable area at %d,%d.",
|
||||
ucell->x, ucell->y);
|
||||
ucell = unreachcell[0];
|
||||
if (db) dblog(" attempting to fix unreachable area at %d,%d.",
|
||||
ucell->x, ucell->y);
|
||||
|
||||
if (!linkexit(ucell, B_TRUE, &nadded)) {
|
||||
// fixed.
|
||||
if (db) dblog(" successfully fixed by digging tunnels.");
|
||||
break;
|
||||
} else {
|
||||
if (db) dblog("failed, trying new cell.");
|
||||
ntries++;
|
||||
// first: try to link up the two areas.
|
||||
ndoors = fix_unreach_via_doors(m);
|
||||
if (!ndoors) {
|
||||
int idx,firstidx = -1,ntries = 0;
|
||||
//,maxtries = 5;
|
||||
// pick one of the unreachable cells
|
||||
idx = rnd(0,nunreach-1);
|
||||
//while (ntries < maxtries) {
|
||||
while (idx != firstidx) {
|
||||
if (firstidx == -1) firstidx = idx;
|
||||
ucell = unreachcell[idx];
|
||||
// try to link it back to a filled cell.
|
||||
if (db) dblog(" looking for fixes at %d,%d...",
|
||||
ucell->x, ucell->y);
|
||||
|
||||
if (!linkexit(ucell, B_TRUE, &nadded)) {
|
||||
// fixed.
|
||||
if (db) dblog(" successfully fixed by digging tunnels.");
|
||||
break;
|
||||
} else {
|
||||
if (db) dblog("failed, trying new cell.");
|
||||
ntries++;
|
||||
// loop around to start
|
||||
if (++idx == nunreach) idx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (ntries >= maxtries) {
|
||||
cell_t *rcell;
|
||||
int ptries = 0;
|
||||
|
@ -2204,9 +2374,10 @@ int fix_reachability(map_t *m) {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (nadded || nportals) {
|
||||
if (db) dblog(" fixed unreachable area by adding %d cells and %d portals.", nadded,nportals);
|
||||
if (ndoors || nadded || nportals) {
|
||||
if (db) dblog(" fixed unreachable area by adding %d doors, %d cells, %d portals.", ndoors, nadded,nportals);
|
||||
} else {
|
||||
// didn't add anything - fail!
|
||||
if (db) dblog(" fix_reachability failed.");
|
||||
|
@ -2219,11 +2390,52 @@ int fix_reachability(map_t *m) {
|
|||
nfixed++;
|
||||
}
|
||||
}
|
||||
if (db) dblog(" fix_reachability complete. fixed %d unreachable areas.", nfixed);
|
||||
if (nfixed) {
|
||||
if (db) dblog(" fix_reachability complete. found and fixed %d unreachable areas.", nfixed);
|
||||
} else {
|
||||
if (db) dblog(" fix_reachability complete. no unreachable areas found.");
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
// returns # doors added
|
||||
int fix_unreach_via_doors(map_t *m) {
|
||||
int i,dir;
|
||||
cell_t *c,*adjcell;
|
||||
for (i = 0; i < m->w*m->h; i++) {
|
||||
c = m->cell[i];
|
||||
if (issolid(c) && !cellisfixedvaultwall(c)) {
|
||||
int gotreach = B_FALSE,gotunreach = B_FALSE;
|
||||
// is there an adjacent reachable cell?
|
||||
for (dir = DC_N; dir <= DC_NW; dir++) {
|
||||
adjcell = getcellindir(c, dir);
|
||||
if (adjcell && !issolid(adjcell) && adjcell->filled) {
|
||||
gotreach = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// is there an adjacent unreachable cell?
|
||||
for (dir = DC_N; dir <= DC_NW; dir++) {
|
||||
adjcell = getcellindir(c, dir);
|
||||
if (adjcell && !issolid(adjcell) && !adjcell->filled) {
|
||||
gotunreach = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gotreach && gotunreach) {
|
||||
// this cell links reachable and unreachable areas.
|
||||
setcelltype(c, getmapempty(m));
|
||||
makedoor(c, 0);
|
||||
setcellreason(c, "making door to link seperated areas");
|
||||
dblog(" successfully fixed by creating a door.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void floodfill(cell_t *startcell) {
|
||||
int d;
|
||||
object_t *o;
|
||||
|
@ -2311,6 +2523,31 @@ int getbranchlinks(regionthing_t **thing, int *nthings, ...) {
|
|||
return *nthings;
|
||||
}
|
||||
|
||||
cell_t *getcell_cond(map_t *map, condset_t *cs ) {
|
||||
cell_t **poss,*c;
|
||||
int nposs = 0,i;
|
||||
|
||||
poss = calloc(map->w * map->h, sizeof(cell_t *));
|
||||
|
||||
// get a list of all possible cells
|
||||
nposs = 0;
|
||||
for (i = 0; i < map->w*map->h; i++) {
|
||||
c = map->cell[i];
|
||||
if (cellmeets(c, cs)) {
|
||||
poss[nposs++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (nposs) {
|
||||
c = poss[rnd(0,nposs-1)];
|
||||
} else {
|
||||
c = NULL;
|
||||
}
|
||||
free(poss);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
cell_t *getcellat(map_t *map, int x, int y) {
|
||||
if (!isonmap(map, x, y)) return NULL;
|
||||
return map->cell[y*map->w + x];
|
||||
|
@ -3744,7 +3981,11 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
if (db) dblog("--> Will add %d pillars",numpillars);
|
||||
for (n = 0; n < numpillars;n++ ) {
|
||||
//dblog("----> Adding pillar %d/%d",n+1,numpillars);
|
||||
c = getrandomroomcell(map, i, WE_EMPTY);
|
||||
condset_t cs;
|
||||
initcondv(&cs, CC_HASROOMID, B_TRUE, i,
|
||||
CC_EMPTY, B_TRUE, NA, CC_NONE);
|
||||
//c = getrandomroomcell(map, i, WE_EMPTY);
|
||||
c = getcell_cond(map, &cs);
|
||||
|
||||
if (c && !countobs(c->obpile, B_TRUE)) {
|
||||
setcelltype(c, solidcell);
|
||||
|
@ -3768,7 +4009,8 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
int nmonsters = 0;
|
||||
done = B_FALSE;
|
||||
while (!done) {
|
||||
c = getrandomroomcell(map, i, WE_WALKABLE);
|
||||
//c = getrandomroomcell(map, i, WE_WALKABLE);
|
||||
c = getcell_cond(map, &ccwalkable);
|
||||
// if nothing there
|
||||
if (c) {
|
||||
int obchance;
|
||||
|
@ -4390,16 +4632,18 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
|
|||
break;
|
||||
case RT_OBJECT:
|
||||
if (db) dblog(" adding forced regionthing object: %s", thing[i]->what);
|
||||
c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
|
||||
//c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
|
||||
c = getcell_cond(map, &ccwalkableroom);
|
||||
if (!c) c = getrandomcell(map);
|
||||
c = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
|
||||
c = real_getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
|
||||
addob(c->obpile, thing[i]->what);
|
||||
break;
|
||||
case RT_LF:
|
||||
if (db) dblog(" adding forced regionthing lifeform: %s", thing[i]->what);
|
||||
c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
|
||||
//c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
|
||||
c = getcell_cond(map, &ccwalkableroom);
|
||||
if (!c) c = getrandomcell(map);
|
||||
c = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
|
||||
c = real_getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
|
||||
addmonster(c, R_SPECIFIED, thing[i]->what, B_FALSE, thing[i]->value, B_TRUE, NULL);
|
||||
break;
|
||||
case RT_BRANCHLINK:
|
||||
|
@ -4442,6 +4686,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
|
|||
unmakemap(map);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
} // end while failed)
|
||||
|
||||
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
|
||||
|
@ -4628,7 +4873,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
|
|||
nstairslinked++;
|
||||
} else {
|
||||
if (db) {
|
||||
dblog(" FAILED to link stairs: '%s'",o->type->name);
|
||||
dblog(" couldn't link stairs: '%s' (probably no lower level yet)",o->type->name);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4940,7 +5185,8 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
|
|||
c = NULL;
|
||||
// infinite loop here.
|
||||
while (!c || (countadjwalls(c) == 0) || getcellwaterdepth(c, NULL)) {
|
||||
c = getrandomroomcell(map, ANYROOM, WE_NONE);
|
||||
//c = getrandomroomcell(map, ANYROOM, WE_NONE);
|
||||
c = getcell_cond(map, &ccroom);
|
||||
assert(c);
|
||||
}
|
||||
//////////
|
||||
|
@ -5643,6 +5889,7 @@ int linkexits(map_t *m, int roomid) {
|
|||
int minx = -1, miny = -1, maxx = -1, maxy = -1;
|
||||
int roomidx = -1;
|
||||
vault_t *v;
|
||||
condset_t cs;
|
||||
|
||||
// figure out room coords
|
||||
for (i = 0; i < m->nrooms; i++) {
|
||||
|
@ -5658,7 +5905,9 @@ int linkexits(map_t *m, int roomid) {
|
|||
assert(roomidx != -1);
|
||||
|
||||
// does this roomid actually exist??
|
||||
c = getrandomroomcell(m, roomid, WE_NONE);
|
||||
//c = getrandomroomcell(m, roomid, WE_NONE);
|
||||
initcondv(&cs, CC_HASROOMID, B_TRUE, roomid, CC_NONE);
|
||||
c = getcell_cond(m, &cs);
|
||||
if (!c) return B_FALSE;
|
||||
|
||||
v = getcellvault(c);
|
||||
|
@ -5794,8 +6043,12 @@ void createmastervaults(map_t *map, int depth, map_t *parentmap, int exitdir, ob
|
|||
// place chests
|
||||
for (i = 0; i < map->nrooms; i++) {
|
||||
int nchests;
|
||||
condset_t cs;
|
||||
nchests = rnd(1,5);
|
||||
c = getrandomroomcell(map, i, WE_WALKABLE);
|
||||
initcondv(&cs, CC_HASROOMID, B_TRUE, i,
|
||||
CC_WALKABLE, B_TRUE, NA, CC_NONE);
|
||||
//c = getrandomroomcell(map, i, WE_WALKABLE);
|
||||
c = getcell_cond(map, &cs);
|
||||
if (c) {
|
||||
addob(c->obpile, "random container");
|
||||
}
|
||||
|
@ -6337,6 +6590,13 @@ void finalisemap(map_t *map, object_t *entryob, int exitdir) {
|
|||
int nupstairsneeded = 0,ndownstairsneeded = 0;
|
||||
cell_t *c;
|
||||
object_t *o,*nexto;
|
||||
condset_t okforstairs;
|
||||
|
||||
initcondv(&okforstairs, CC_EMPTY, B_TRUE, NA,
|
||||
CC_OKFORSTAIRS, B_TRUE, NA,
|
||||
CC_ISROOM, B_TRUE, NA,
|
||||
CC_NONE);
|
||||
|
||||
// make sure this map has sufficient up/down staircases as defined by its
|
||||
// region type.
|
||||
//
|
||||
|
@ -6371,7 +6631,8 @@ void finalisemap(map_t *map, object_t *entryob, int exitdir) {
|
|||
// first dungeon level. just one exit stairs
|
||||
c = NULL;
|
||||
while (!c || countobs(c->obpile, B_TRUE)) {
|
||||
c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
|
||||
//c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
|
||||
c = getcell_cond(map, &okforstairs);
|
||||
}
|
||||
o = addobfast(c->obpile, upstairtype);
|
||||
if (entryob) {
|
||||
|
@ -6399,12 +6660,21 @@ void finalisemap(map_t *map, object_t *entryob, int exitdir) {
|
|||
for (i = 0; i < nupstairsneeded; i++) {
|
||||
c = NULL;
|
||||
while (!c || countobs(c->obpile, B_TRUE)) {
|
||||
c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
|
||||
//c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
|
||||
c = getcell_cond(map, &okforstairs);
|
||||
/*
|
||||
while (!c || (getcellvault(c) && hasflag(c->room->vault->flags, F_NOSTAIRS))) {
|
||||
// ANY cell at all, doesn't have to be a room.
|
||||
c = getrandomcell(map);
|
||||
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
if (!cellwalkable(NULL, c, NULL)) {
|
||||
trytokillobs(c->obpile);
|
||||
}
|
||||
// still not walkable? find something nearby.
|
||||
if (!cellwalkable(NULL, c, NULL)) {
|
||||
c = getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND);
|
||||
}
|
||||
}
|
||||
*/
|
||||
trytokillobs(c->obpile);
|
||||
}
|
||||
o = addobfast(c->obpile, upstairtype);
|
||||
|
@ -6429,12 +6699,8 @@ void finalisemap(map_t *map, object_t *entryob, int exitdir) {
|
|||
for (i = 0; i < ndownstairsneeded; i++) {
|
||||
c = NULL;
|
||||
while (!c || countobs(c->obpile, B_TRUE)) {
|
||||
c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
|
||||
while (!c || (getcellvault(c) && hasflag(c->room->vault->flags, F_NOSTAIRS))) {
|
||||
// ANY cell at all, doesn't have to be a room.
|
||||
c = getrandomcell(map);
|
||||
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
}
|
||||
//c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
|
||||
c = getcell_cond(map, &okforstairs);
|
||||
trytokillobs(c->obpile);
|
||||
}
|
||||
o = addobfast(c->obpile, downstairtype);
|
||||
|
@ -7219,12 +7485,11 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) {
|
||||
return real_getrandomadjcell(c, wantempty, allowexpand, LOF_NEED, NULL, NULL, NULL, MT_NOTHING);
|
||||
cell_t *getrandomadjcell(cell_t *c, condset_t *cs, int allowexpand) {
|
||||
return real_getrandomadjcell(c, cs, allowexpand, LOF_NEED, NULL, NULL);
|
||||
}
|
||||
|
||||
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob, cell_t *dontwantcell, lifeform_t *preferlos, enum MATERIAL wantmat) {
|
||||
cell_t *real_getrandomadjcell(cell_t *c, condset_t *cs, int allowexpand, enum LOFTYPE needlof, cell_t *dontwantcell, lifeform_t *preferlos) {
|
||||
int radius = 1;
|
||||
int x,y;
|
||||
cell_t *poss[MAXCANDIDATES];
|
||||
|
@ -7247,13 +7512,13 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
|
|||
(new != c) &&
|
||||
(getcelldist(c,new) == radius) &&
|
||||
(new != dontwantcell) && gotlof) {
|
||||
enum OBTYPE *badoid;
|
||||
int ok = B_FALSE;
|
||||
numwithlof++;
|
||||
|
||||
ok = cellmatchescondition(new, wantempty);
|
||||
ok = cellmeets(new, cs);
|
||||
|
||||
// obs we dont want?
|
||||
/*
|
||||
if (dontwantob) {
|
||||
for (badoid = dontwantob; (*badoid != OT_NONE) ; badoid++) {
|
||||
if (hasob(new->obpile, *badoid)) {
|
||||
|
@ -7262,11 +7527,14 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if (wantmat != MT_NOTHING) {
|
||||
if (new->type->material->id != wantmat) {
|
||||
ok = B_FALSE;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (ok) {
|
||||
if (preferlos && haslos(preferlos, new)) {
|
||||
|
@ -7288,6 +7556,8 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
|
|||
if (numwithlof) {
|
||||
// increment radius
|
||||
radius++;
|
||||
// more than map width? fail.
|
||||
if (radius >= MAXOF(MAX_MAPH,MAX_MAPW)) return NULL;
|
||||
} else {
|
||||
if (preferlos) {
|
||||
// start again without preferlos
|
||||
|
@ -7328,6 +7598,7 @@ cell_t *getrandomcell(map_t *map) {
|
|||
return cell;
|
||||
}
|
||||
|
||||
|
||||
cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id) {
|
||||
cell_t *cell;
|
||||
cell = getrandomcell(map);
|
||||
|
@ -7337,6 +7608,8 @@ cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id) {
|
|||
return cell;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int compassdir(int orthdir) {
|
||||
switch (orthdir) {
|
||||
case D_N:
|
||||
|
@ -7374,6 +7647,7 @@ int getrandomdirexcept(int dirtype, int exception) {
|
|||
return dir;
|
||||
}
|
||||
|
||||
/*
|
||||
cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty) {
|
||||
int npossible = 0;
|
||||
int selidx;
|
||||
|
@ -7417,6 +7691,7 @@ cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty) {
|
|||
free(poss);
|
||||
return c;
|
||||
}
|
||||
*/
|
||||
|
||||
// popuplates retcell[] with all cells from room
|
||||
void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells) {
|
||||
|
@ -7697,6 +7972,7 @@ void initmap(void) {
|
|||
addcelltype(CT_WALLDWOOD, "wyrmwood wall", UNI_SOLID, C_BROWN, NA, B_SOLID, B_OPAQUE, MT_DRAGONWOOD, 0, 100, 0, B_NOABSORB);
|
||||
addcelltype(CT_WALLFLESH, "flesh wall", UNI_SOLID, C_RED, NA, B_SOLID, B_OPAQUE, MT_FLESH, 0, 25, 0, B_NOABSORB);
|
||||
addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, NA, B_SOLID, B_TRANS, MT_GLASS, 0, 20, 0, B_NOABSORB);
|
||||
addcelltype(CT_WALLICE, "ice wall", UNI_SHADEDARK, C_CYAN, NA, B_SOLID, B_TRANS, MT_ICE, 0, 30, 0, B_NOABSORB);
|
||||
//addcelltype(CT_WALLTREE, "dense bushland", UNI_SHADEDARK, C_GREEN, B_SOLID, B_OPAQUE, MT_PLANT, 0, 100);
|
||||
addcelltype(CT_WALLTREE, "dense bushland", UNI_TREELOTS, C_GREEN, NA, B_SOLID, B_OPAQUE, MT_PLANT, 0, 100, 0, B_NOABSORB);
|
||||
addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, NA, B_SOLID, B_OPAQUE, MT_METAL, 0, 75, 0, B_NOABSORB);
|
||||
|
@ -8304,10 +8580,14 @@ int linkholes(map_t *map) {
|
|||
// make a link to it in this map, as close as possible to same pos
|
||||
c2 = getcellat(map, x, y);
|
||||
if (c2->lf || hasobid(c2->obpile, ot->id)) {
|
||||
condset_t cs;
|
||||
// this will automatically avoid lifeforms since we're using
|
||||
// we_walkable rather than we_notwall. this saves problems
|
||||
// with someine coming up underneath you!
|
||||
c2 = real_getrandomadjcell(c2, WE_NOLF, B_ALLOWEXPAND, LOF_DONTNEED, &ot->id, NULL, NULL, MT_NOTHING);
|
||||
initcondv(&cs, CC_HASLF, B_FALSE, NA,
|
||||
CC_HASOBTYPE, B_FALSE, ot->id,
|
||||
CC_NONE);
|
||||
c2 = real_getrandomadjcell(c2, &cs, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
|
||||
}
|
||||
// clear out the cell if required
|
||||
if (c2->type->solid) {
|
||||
|
@ -8720,10 +9000,14 @@ void mapentereffects(map_t *m) {
|
|||
// chosen cell is not near stairs
|
||||
if (dowandering) {
|
||||
int monchance;
|
||||
condset_t cs;
|
||||
monchance = getmapdifficulty(m)*5;
|
||||
for (i = 0; i < m->nrooms; i++) {
|
||||
if (pctchance(monchance)) {
|
||||
c = getrandomroomcell(m, m->room[i].id, WE_WALKABLE);
|
||||
initcondv(&cs, CC_HASROOMID, B_TRUE, m->room[i].id,
|
||||
CC_WALKABLE, B_TRUE, NA, CC_NONE);
|
||||
//c = getrandomroomcell(m, m->room[i].id, WE_WALKABLE);
|
||||
c = getcell_cond(m, &cs);
|
||||
if (c && !hasobflagwithin(c, F_STAIRS, 15, DT_COMPASS)) {
|
||||
addmonster(c, R_RANDOM, NULL, B_TRUE, 1, B_TRUE, NULL);
|
||||
}
|
||||
|
@ -8785,7 +9069,7 @@ int orthdir(int compassdir) {
|
|||
return D_NONE;
|
||||
}
|
||||
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour) {
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, condset_t *cs, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour) {
|
||||
int donesomething;
|
||||
char *p,*suff;
|
||||
job_t *j;
|
||||
|
@ -8794,6 +9078,9 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum B
|
|||
char *namestart;
|
||||
behaviour_t *b;
|
||||
|
||||
assert(cs);
|
||||
initcond(cs);
|
||||
|
||||
// get params
|
||||
donesomething = B_TRUE;
|
||||
|
||||
|
@ -8821,6 +9108,11 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum B
|
|||
if (wantflags) addflag(wantflags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
if (strstarts(p, "hirable ")) {
|
||||
p += strlen("hirable ");
|
||||
addcond(cs, CC_HASFLAG, B_TRUE, F_PLAYABLE);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
if (wantbehaviour && (*wantbehaviour != BH_NONE)) {
|
||||
} else {
|
||||
// try removing prefixes for behaviours
|
||||
|
@ -8937,15 +9229,17 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum B
|
|||
race_t *baser,*r;
|
||||
// ie. "random xxx_baseraceid_xxx"
|
||||
p += strlen("random ");
|
||||
baser = findracebyname(p);
|
||||
baser = findracebyname(p, NULL);
|
||||
if (baser) {
|
||||
enum RACE poss[MAXCANDIDATES];
|
||||
int nposs = 0;
|
||||
// find all races with this baseid
|
||||
for (r = firstrace ; r ; r = r->next) {
|
||||
if (r->baseid == baser->id) {
|
||||
poss[nposs++] = r->id;
|
||||
if (nposs == MAXCANDIDATES) break;
|
||||
if (racemeets(r->id, cs)) {
|
||||
poss[nposs++] = r->id;
|
||||
if (nposs == MAXCANDIDATES) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nposs) {
|
||||
|
@ -8954,7 +9248,7 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum B
|
|||
}
|
||||
} else {
|
||||
race_t *r;
|
||||
r = findracebyname(p);
|
||||
r = findracebyname(p, cs);
|
||||
if (r) {
|
||||
return r->id;
|
||||
}
|
||||
|
@ -9384,6 +9678,7 @@ int validateregionthing(regionthing_t *thing) {
|
|||
int goterrors = B_FALSE;
|
||||
object_t *o;
|
||||
enum RACE rid;
|
||||
condset_t cs;
|
||||
createfakes(&fakemap, &fakecell);
|
||||
switch (thing->whatkind) {
|
||||
case RT_HABITAT:
|
||||
|
@ -9393,7 +9688,7 @@ int validateregionthing(regionthing_t *thing) {
|
|||
}
|
||||
break;
|
||||
case RT_LF:
|
||||
rid = parserace(thing->what, NULL, NULL, NULL);
|
||||
rid = parserace(thing->what, NULL, &cs, NULL, NULL);
|
||||
if (rid == R_NONE) {
|
||||
dblog("Invalid lifeform '%s' specified in regionthing.", thing->what);
|
||||
goterrors = B_TRUE;
|
||||
|
|
15
map.h
15
map.h
|
@ -16,7 +16,9 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
|
|||
void breakwall(cell_t *c, char *why, ...);
|
||||
int cellhaslos(cell_t *c1, cell_t *dest);
|
||||
int cellisfixedvaultwall(cell_t *c);
|
||||
int cellmatchescondition(cell_t *c, int wecond);
|
||||
//int cellmatchescondition(cell_t *c, int wecond);
|
||||
int cellmeetscondition(cell_t *c, enum CELLCONDITION cond, int arg, int value);
|
||||
int cellmeets(cell_t *c, condset_t *cs);
|
||||
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom);
|
||||
void clearcell(cell_t *c);
|
||||
void clearcell_exceptflags(cell_t *c, ...);
|
||||
|
@ -33,9 +35,10 @@ int doelementspread(cell_t *c);
|
|||
int dodoorfill(cell_t *c);
|
||||
void doorfill_r(cell_t *startcell, cell_t *c, int *nfilled);
|
||||
int fix_reachability(map_t *m);
|
||||
int fix_unreachable_cell(cell_t *badcell);
|
||||
int fix_unreach_via_doors(map_t *m);
|
||||
void floodfill(cell_t *startcell);
|
||||
int getbranchlinks(regionthing_t **thing, int *nthings, ...);
|
||||
cell_t *getcell_cond(map_t *map, condset_t *cs );
|
||||
cell_t *getcellat(map_t *map, int x, int y);
|
||||
int getcellclimbdifficulty(cell_t *c);
|
||||
int getcellclimbdifficultyavg(cell_t *c);
|
||||
|
@ -135,13 +138,13 @@ cell_t *getclosestroomcell(lifeform_t *lf, int roomid);
|
|||
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
|
||||
int getobchance(int habitat);
|
||||
int getthingchance(int habitat);
|
||||
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
|
||||
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob, cell_t *dontwantcell, lifeform_t *preferlos, enum MATERIAL wantmat);
|
||||
cell_t *getrandomadjcell(cell_t *c, condset_t *cs, int allowexpand);
|
||||
cell_t *real_getrandomadjcell(cell_t *c, condset_t *cs, int allowexpand, enum LOFTYPE needlof, cell_t *dontwantcell, lifeform_t *preferlos);
|
||||
cell_t *getrandomcell(map_t *map);
|
||||
cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id);
|
||||
int getrandomdir(int dirtype);
|
||||
int getrandomdirexcept(int dirtype, int exception);
|
||||
cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty);
|
||||
//cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty);
|
||||
void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells);
|
||||
int getslipperyness(cell_t *c, object_t **slipob);
|
||||
cell_t *getstairdestination(object_t *o, int *madenewmap);
|
||||
|
@ -191,7 +194,7 @@ void mapentereffects(map_t *m);
|
|||
void modillumination(map_t *m, int dir);
|
||||
void moveobtoclearcell(object_t *o);
|
||||
int orthdir(int compassdir);
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour);
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, condset_t *cs, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour);
|
||||
int remove_deadends(map_t *m, int howmuch);
|
||||
int remove_baddoors(map_t *m);
|
||||
void selectcelltypes(map_t *map);
|
||||
|
|
8
move.c
8
move.c
|
@ -31,6 +31,8 @@ extern int noredraw;
|
|||
|
||||
extern long curtime;
|
||||
|
||||
extern condset_t ccwalkable;
|
||||
|
||||
extern WINDOW *gamewin, *msgwin;
|
||||
|
||||
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
|
@ -1723,7 +1725,7 @@ int movelfsoutofway(cell_t *newcell) {
|
|||
if (newcell->lf) {
|
||||
cell_t *c;
|
||||
// if they are, find somewhere to move them.
|
||||
c = getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(newcell, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (c) {
|
||||
// move them there
|
||||
movelf(newcell->lf, c, B_FALSE);
|
||||
|
@ -2794,7 +2796,7 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
|
|||
// can't teleport on top of something else
|
||||
if (c->lf) {
|
||||
// go somewhere nearby
|
||||
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (!c) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You feel a wrenching sensation.");
|
||||
|
@ -3588,7 +3590,7 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
|
|||
if (onpurpose) {
|
||||
for (n = 0; n < nadjallies; n++) {
|
||||
cell_t *c;
|
||||
c = getrandomadjcell(dst, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(dst, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (c) {
|
||||
if (!initiatemove(adjally[n], NULL, B_TRUE, NULL)) {
|
||||
movelf(adjally[n], c, B_FALSE);
|
||||
|
|
78
nexus.c
78
nexus.c
|
@ -46,6 +46,11 @@ knowledge_t *knowledge = NULL, *lastknowledge = NULL;
|
|||
hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
|
||||
npcname_t *npcname;
|
||||
int numnpcnames;
|
||||
int totalraces = 0;
|
||||
|
||||
condset_t ccwalkable;
|
||||
condset_t ccwalkableroom;
|
||||
condset_t ccroom;
|
||||
|
||||
extern lifeform_t *godlf[];
|
||||
extern int ngodlfs;
|
||||
|
@ -411,15 +416,25 @@ int main(int argc, char **argv) {
|
|||
race_t *r;
|
||||
lifeform_t *pet;
|
||||
enum OBTYPE avoidob = OT_WATERDEEP;
|
||||
condset_t cs,cs2;
|
||||
initcondv(&cs, CC_WALKABLE, B_TRUE, NA,
|
||||
CC_HASOBTYPE, B_FALSE, avoidob,
|
||||
CC_NONE
|
||||
);
|
||||
initcondv(&cs2, CC_SOLID, B_TRUE, NA,
|
||||
CC_HASOBTYPE, B_FALSE, avoidob,
|
||||
CC_NONE
|
||||
);
|
||||
|
||||
f = retflag[i];
|
||||
r = findracebyname(f->text);
|
||||
r = findracebyname(f->text, NULL);
|
||||
assert(r);
|
||||
|
||||
// create pet, in view of player if possible.
|
||||
c = real_getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, &avoidob, NULL, player, MT_NOTHING);
|
||||
// create pet, in view of player if possible.
|
||||
c = real_getrandomadjcell(player->cell, &cs, B_ALLOWEXPAND, LOF_NEED, NULL, player);
|
||||
if (!c) {
|
||||
c = real_getrandomadjcell(player->cell, WE_SOLID, B_NOEXPAND, LOF_DONTNEED, &avoidob, NULL, player, MT_NOTHING);
|
||||
// if no valid spaces, try to make one.
|
||||
c = real_getrandomadjcell(player->cell, &cs2, B_NOEXPAND, LOF_DONTNEED, NULL, player);
|
||||
assert(c);
|
||||
setcelltype(c, getmapempty(player->cell->map));
|
||||
}
|
||||
|
@ -737,6 +752,15 @@ celltype_t *addcelltype(int id, char *name, int glyph, int colour, int altcol, i
|
|||
return a;
|
||||
}
|
||||
|
||||
int addcond(condset_t *cs, enum CELLCONDITION cond, int val, int arg) {
|
||||
cs->cond[cs->nconds] = cond;
|
||||
cs->arg[cs->nconds] = arg;
|
||||
cs->val[cs->nconds] = val;
|
||||
(cs->nconds)++;
|
||||
return cs->nconds;
|
||||
}
|
||||
|
||||
|
||||
warning_t *addwarning(char *text, int lifetime) {
|
||||
warning_t *a;
|
||||
|
||||
|
@ -982,7 +1006,7 @@ void donextturn(map_t *map) {
|
|||
if (isplayer(who)) {
|
||||
msg("You feel a change coming over your body!");
|
||||
}
|
||||
r = findracebyname(changerace);
|
||||
r = findracebyname(changerace, NULL);
|
||||
//polymorphto(who, r->id, rnd(mintime,maxtime));
|
||||
polymorphto(who, r->id, PERMENANT);
|
||||
donormalmove = B_FALSE;
|
||||
|
@ -1446,6 +1470,17 @@ int init(void) {
|
|||
// random numbers
|
||||
srand(time(NULL));
|
||||
|
||||
// preset conditions
|
||||
initcondv(&ccwalkable, CC_WALKABLE, B_TRUE, NA,
|
||||
CC_NONE);
|
||||
initcondv(&ccroom, CC_ISROOM, B_TRUE, NA,
|
||||
CC_NONE);
|
||||
initcondv(&ccwalkableroom, CC_WALKABLE, B_TRUE, NA,
|
||||
CC_ISROOM, B_TRUE, NA,
|
||||
CC_NONE);
|
||||
|
||||
|
||||
|
||||
// precalc sin/cos
|
||||
for (i = 0; i < 360; i++) {
|
||||
double rads;
|
||||
|
@ -1503,6 +1538,29 @@ int init(void) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
void initcond(condset_t *cs) {
|
||||
cs->nconds = 0;
|
||||
}
|
||||
|
||||
void initcondv(condset_t *cs, ...) {
|
||||
enum CELLCONDITION condition;
|
||||
va_list args;
|
||||
int value,arg;
|
||||
|
||||
va_start(args, cs);
|
||||
cs->nconds = 0;
|
||||
condition = va_arg(args, enum CELLCONDITION);
|
||||
while (condition != CC_NONE) {
|
||||
value = va_arg(args, int);
|
||||
assert((value == B_TRUE) || (value == B_FALSE));
|
||||
arg = va_arg(args, int);
|
||||
addcond(cs, condition, value, arg);
|
||||
condition = va_arg(args, enum CELLCONDITION);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
void inctime(long nunits) {
|
||||
curtime += (nunits*(TIMECONST));
|
||||
// don't let it get higher than 23:59
|
||||
|
@ -2220,9 +2278,15 @@ void timeeffectsworld(map_t *map, int updategametime) {
|
|||
// midnight
|
||||
if (h == 0) {
|
||||
cell_t *c;
|
||||
condset_t cs;
|
||||
initcondv(&cs, CC_WALKABLE, B_TRUE, NA,
|
||||
CC_ISROOM, B_TRUE, NA,
|
||||
CC_NONE
|
||||
);
|
||||
// lunar gate appears in a random spot on the player's level
|
||||
c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
|
||||
//c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
|
||||
//c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
|
||||
c = getcell_cond(map, &cs);
|
||||
if (c) {
|
||||
o = addobfast(c->obpile, OT_LUNARGATE);
|
||||
if (o) {
|
||||
|
|
3
nexus.h
3
nexus.h
|
@ -1,6 +1,7 @@
|
|||
#include "defs.h"
|
||||
|
||||
celltype_t *addcelltype(int id, char *name, int glyph, int colour, int altcol, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp, int volumemod, int absobent);
|
||||
int addcond(condset_t *cs, enum CELLCONDITION cond, int arg, int val);
|
||||
warning_t *addwarning(char *text, int lifetime);
|
||||
void checkdeath(void);
|
||||
void checkendgame(void);
|
||||
|
@ -20,6 +21,8 @@ enum COLOUR getpctcol(float num, float max);
|
|||
char getpctletter(float num, float max);
|
||||
void getrarityrange(int depth, int *min, int *max, int range, int oodok);
|
||||
int init(void);
|
||||
void initcond(condset_t *cs);
|
||||
void initcondv(condset_t *cs, ...);
|
||||
void inctime(long nunits);
|
||||
void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels);
|
||||
void initbresnham(int x1, int y1, int x2, int y2, int *xinc1, int *yinc1, int *dinc1, int *xinc2, int *yinc2, int *dinc2, int *numpixels, int *d);
|
||||
|
|
245
objects.c
245
objects.c
|
@ -61,6 +61,8 @@ extern int statdirty;
|
|||
|
||||
extern int obdb;
|
||||
|
||||
extern condset_t ccwalkable;
|
||||
extern condset_t ccwalkableroom;
|
||||
|
||||
char letorder[MAXPILEOBS] = {
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
|
@ -738,7 +740,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
|
|||
p += strlen("linkrace:");
|
||||
// read next
|
||||
p = readuntil(racename, p, ' ');
|
||||
linkrace = findracebyname(racename);
|
||||
linkrace = findracebyname(racename, NULL);
|
||||
donesomething = B_TRUE;
|
||||
// condition flags
|
||||
} else if (strstarts(p, "battered ")) {
|
||||
|
@ -917,7 +919,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
|
|||
p2 += 6;
|
||||
p2 = readuntil(racename, p2, ' ');
|
||||
|
||||
corpserace = findracebyname(racename);
|
||||
corpserace = findracebyname(racename, NULL);
|
||||
ot = findot(OT_ROASTMEAT);
|
||||
} else if (strstr(p, "water fountain")) {
|
||||
wantfountaintype = OT_POT_WATER;
|
||||
|
@ -938,7 +940,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
|
|||
len = p2 - p;
|
||||
snprintf(racename, len, "%s",p);
|
||||
|
||||
corpserace = findracebyname(racename);
|
||||
corpserace = findracebyname(racename, NULL);
|
||||
ot = findot(OT_CORPSE);
|
||||
} else if (strstr(p, "map to ")) {
|
||||
branch_t *rt;
|
||||
|
@ -968,7 +970,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
|
|||
// now at start of name
|
||||
snprintf(racename, BUFLEN, "%s",p2);
|
||||
|
||||
corpserace = findracebyname(racename);
|
||||
corpserace = findracebyname(racename, NULL);
|
||||
ot = findot(OT_STATUE);
|
||||
} else if (strstr(p, " head")) {
|
||||
int len;
|
||||
|
@ -977,7 +979,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
|
|||
len = p2 - p + 1;
|
||||
snprintf(racename, len, "%s",p);
|
||||
|
||||
corpserace = findracebyname(racename);
|
||||
corpserace = findracebyname(racename, NULL);
|
||||
ot = findot(OT_HEAD);
|
||||
} else if (strstarts(p, "portal to lv")) {
|
||||
char *pp;
|
||||
|
@ -995,10 +997,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
|
|||
targetmap = addmap();
|
||||
createmap(targetmap, dlev, c->map->region, NULL, D_NONE, NULL);
|
||||
}
|
||||
targetcell = getrandomroomcell(targetmap, ANYROOM, WE_WALKABLE);
|
||||
//targetcell = getrandomroomcell(targetmap, ANYROOM, WE_WALKABLE);
|
||||
targetcell = getcell_cond(targetmap, &ccwalkableroom);
|
||||
|
||||
if (!targetcell) targetcell = getrandomcell(targetmap);
|
||||
while (!cellwalkable(NULL, targetcell, NULL)) {
|
||||
targetcell = getrandomadjcell(targetcell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
targetcell = getrandomadjcell(targetcell, &ccwalkable, B_ALLOWEXPAND);
|
||||
}
|
||||
} else {
|
||||
// ie. adding to dummy cell
|
||||
|
@ -2186,6 +2190,25 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
|
|||
traptype = getrandomtrapforob(o);
|
||||
addflag(o->flags, F_TRAPPED, traptype, NA, NA, NULL);
|
||||
}
|
||||
|
||||
// monster hiding inside?
|
||||
f = hasflag(o->flags, F_CANHAVELFINSIDE);
|
||||
if (f) {
|
||||
enum LFSIZE maxsize;
|
||||
maxsize = getobsize(o);
|
||||
if (maxsize != SZ_MINI) {
|
||||
int hidingchance;
|
||||
hidingchance = f->val[0] + (f->val[1] * (obloc->map->depth/5));
|
||||
limit(&hidingchance, f->val[0], f->val[2]);
|
||||
if (pctchance(hidingchance)) {
|
||||
race_t *r;
|
||||
r = getrandomraceofsize(maxsize-1);
|
||||
if (r) {
|
||||
addflag(o->flags, F_LFINSIDE, r->id, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (o->pile->where) {
|
||||
|
@ -4127,7 +4150,6 @@ int getobaccuracy(object_t *wep, lifeform_t *weilder, int forthrow) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (wep) {
|
||||
// blessed weapons have better base accuracy
|
||||
if (wep->blessed == B_BLESSED) acc += 10;
|
||||
|
@ -5304,6 +5326,18 @@ char *getshopobname(object_t *o, char *buf, int count) {
|
|||
return getobnametrue(o, buf, o->amt);
|
||||
}
|
||||
|
||||
enum SKILL getskilltorepair(object_t *o) {
|
||||
switch (o->material->id) {
|
||||
case MT_CLOTH:
|
||||
case MT_LEATHER:
|
||||
return SK_SEWING;
|
||||
case MT_METAL:
|
||||
return SK_METALWORK;
|
||||
default: break;
|
||||
}
|
||||
return SK_NONE;
|
||||
}
|
||||
|
||||
char *getobname(object_t *o, char *buf, int count) {
|
||||
return real_getobname(o, buf, count, B_PREMODS, B_CONDITION, B_BLINDADJUST, B_BLESSINGS, B_USED, B_NOSHOWALL);
|
||||
}
|
||||
|
@ -7320,7 +7354,8 @@ int isblessknown(object_t *o) {
|
|||
|
||||
|
||||
int iscorpse(object_t *o) {
|
||||
if (o->type->obclass->id == OC_CORPSE) {
|
||||
//if (o->type->obclass->id == OC_CORPSE) {
|
||||
if (o->type->id == OT_CORPSE) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
|
@ -8219,7 +8254,7 @@ lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level) {
|
|||
flag_t *f;
|
||||
lifeform_t *newlf;
|
||||
|
||||
where = getrandomadjcell(lf->cell, WE_EMPTY, B_NOEXPAND);
|
||||
where = getrandomadjcell(lf->cell, &ccwalkable, B_NOEXPAND);
|
||||
if (!where) return NULL;
|
||||
|
||||
newlf = addlf(where, R_DANCINGWEAPON, level);
|
||||
|
@ -8542,12 +8577,23 @@ void makewet(object_t *o, int amt) {
|
|||
|
||||
void modifybetterwepdam(object_t *o, lifeform_t *owner, int *dam) {
|
||||
flag_t *f;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0,i;
|
||||
if (hasflag(o->flags, F_HASBRAND)) {
|
||||
*dam *= 3;
|
||||
}
|
||||
if (hasflag(o->flags, F_ONFIRE)) {
|
||||
*dam += 8;
|
||||
}
|
||||
getflags(o->flags, retflag, &nretflags, F_EXTRADAM, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
if (f->val[2] == NA) {
|
||||
*dam += real_roll(f->text, B_TRUE);
|
||||
} else {
|
||||
*dam += f->val[2];
|
||||
}
|
||||
}
|
||||
// prefer weapons "...of xxxslaying" which match our targets
|
||||
if (owner) {
|
||||
f = hasflag(o->flags, F_RACESLAY);
|
||||
|
@ -9392,6 +9438,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
flag_t *f;
|
||||
int willid = B_FALSE;
|
||||
int wastech = B_FALSE;
|
||||
enum ERROR why;
|
||||
|
||||
if (!lfhasflag(lf, F_HUMANOID) || !hasbp(lf, BP_HANDS)) {
|
||||
if (!hasflag(o->flags, F_OPERWITHOUTHANDS)) {
|
||||
|
@ -9403,6 +9450,18 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!canoperate(lf, o, &why)) {
|
||||
if (isplayer(lf)) {
|
||||
switch (why) {
|
||||
case E_NOHANDS: msg("You lack the manual dexterity to operate this."); break;
|
||||
case E_RAGE: msg("You are too enraged to operate anything!"); break;
|
||||
case E_STUNNED: msg("You cannot operate anything while stunned."); break;
|
||||
default: msg("For some reason, you can't operate this."); break;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (lfhasflag(lf, F_RAGE)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You are too enraged to operate anything!");
|
||||
|
@ -9677,42 +9736,77 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
msg("The %s seems to be locked.", noprefix(obname));
|
||||
return B_TRUE;
|
||||
}
|
||||
snprintf(buf, BUFLEN, "Looting %s. Will you:",obname);
|
||||
initprompt(&prompt, buf);
|
||||
if (countobs(lf->pack, B_FALSE)) {
|
||||
snprintf(buf, BUFLEN, "Put items in %s",obname);
|
||||
addchoice(&prompt, 'i', buf, NULL, NULL, NULL);
|
||||
}
|
||||
if (countobs(o->contents, B_FALSE)) {
|
||||
snprintf(buf, BUFLEN, "Take items out of %s",obname);
|
||||
addchoice(&prompt, 'o', buf, NULL, NULL, NULL);
|
||||
}
|
||||
if (haschoice(&prompt, 'i') && haschoice(&prompt, 'o')) {
|
||||
snprintf(buf, BUFLEN, "Both");
|
||||
addchoice(&prompt, 'b', buf, NULL, NULL, NULL);
|
||||
snprintf(buf, BUFLEN, "Neither");
|
||||
addchoice(&prompt, 'n', buf, NULL, NULL, NULL);
|
||||
|
||||
// monster inside?
|
||||
f = hasflag(o->flags, F_LFINSIDE);
|
||||
if (f) {
|
||||
char theob[BUFLEN];
|
||||
cell_t *where;
|
||||
lifeform_t *mon = NULL;
|
||||
|
||||
if (o->pile->owner) {
|
||||
char ownername[BUFLEN];
|
||||
getlfname(o->pile->owner,ownername);
|
||||
sprintf(theob, "%s%s %s",ownername,getpossessive(ownername),
|
||||
noprefix(obname));
|
||||
} else {
|
||||
sprintf(theob, "the %s", noprefix(obname));
|
||||
}
|
||||
|
||||
|
||||
where = getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (where) {
|
||||
mon = addmonster(where, f->val[0], NULL, B_TRUE, 1, B_FALSE, NULL);
|
||||
}
|
||||
if (mon) {
|
||||
char monname[BUFLEN];
|
||||
getlfnamea(mon, monname);
|
||||
msg("^w%s leaps out of %s!", monname, theob);
|
||||
// it gets a free attack
|
||||
if (isadjacent(mon->cell, player->cell)) {
|
||||
attackcell(mon, player->cell, B_TRUE);
|
||||
}
|
||||
} else {
|
||||
msg("^vSomething swipes at you as you open %s!", theob);
|
||||
}
|
||||
} else {
|
||||
snprintf(buf, BUFLEN, "Do nothing");
|
||||
addchoice(&prompt, 'n', buf, NULL, NULL, NULL);
|
||||
}
|
||||
prompt.maycancel = B_TRUE;
|
||||
ch = getchoice(&prompt);
|
||||
switch (ch) {
|
||||
case 'i':
|
||||
dodrop(player->pack, B_MULTIPLE, o->contents);
|
||||
break;
|
||||
case 'o':
|
||||
dopickup(o->contents, B_TRUE);
|
||||
break;
|
||||
case 'b':
|
||||
dodrop(player->pack, B_MULTIPLE, o->contents);
|
||||
dopickup(o->contents, B_TRUE);
|
||||
break;
|
||||
default:
|
||||
case 'n':
|
||||
msg("Cancelled.");
|
||||
return B_FALSE;
|
||||
snprintf(buf, BUFLEN, "Looting %s. Will you:",obname);
|
||||
initprompt(&prompt, buf);
|
||||
if (countobs(lf->pack, B_FALSE)) {
|
||||
snprintf(buf, BUFLEN, "Put items in %s",obname);
|
||||
addchoice(&prompt, 'i', buf, NULL, NULL, NULL);
|
||||
}
|
||||
if (countobs(o->contents, B_FALSE)) {
|
||||
snprintf(buf, BUFLEN, "Take items out of %s",obname);
|
||||
addchoice(&prompt, 'o', buf, NULL, NULL, NULL);
|
||||
}
|
||||
if (haschoice(&prompt, 'i') && haschoice(&prompt, 'o')) {
|
||||
snprintf(buf, BUFLEN, "Both");
|
||||
addchoice(&prompt, 'b', buf, NULL, NULL, NULL);
|
||||
snprintf(buf, BUFLEN, "Neither");
|
||||
addchoice(&prompt, 'n', buf, NULL, NULL, NULL);
|
||||
} else {
|
||||
snprintf(buf, BUFLEN, "Do nothing");
|
||||
addchoice(&prompt, 'n', buf, NULL, NULL, NULL);
|
||||
}
|
||||
prompt.maycancel = B_TRUE;
|
||||
ch = getchoice(&prompt);
|
||||
switch (ch) {
|
||||
case 'i':
|
||||
dodrop(player->pack, B_MULTIPLE, o->contents);
|
||||
break;
|
||||
case 'o':
|
||||
dopickup(o->contents, B_TRUE);
|
||||
break;
|
||||
case 'b':
|
||||
dodrop(player->pack, B_MULTIPLE, o->contents);
|
||||
dopickup(o->contents, B_TRUE);
|
||||
break;
|
||||
default:
|
||||
case 'n':
|
||||
msg("Cancelled.");
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (hasflag(o->flags, F_OPERONOFF)) { // operating toggles on/off
|
||||
|
@ -9805,7 +9899,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
switch (rnd(0,22)) {
|
||||
case 0: // butterflies around user
|
||||
willid = B_TRUE;
|
||||
where = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
where = getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND);
|
||||
addmonster(where, R_BUTTERFLY, NULL, B_FALSE, rnd(10,20), B_FALSE, NULL);
|
||||
if (haslos(player, where)) {
|
||||
msg("A swarm of butterflies appears!");
|
||||
|
@ -10158,7 +10252,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
r = poss[rnd(0,nposs-1)];
|
||||
sprintf(wname, "%s warrior", r->name);
|
||||
|
||||
c = real_getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, lf, MT_NOTHING);
|
||||
c = real_getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, lf);
|
||||
if (c) {
|
||||
summonmonster(lf, c, R_SPECIFIED, wname, rnd(50,90), B_TRUE);
|
||||
}
|
||||
|
@ -10300,7 +10394,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
}
|
||||
}
|
||||
// summon treant
|
||||
c = real_getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, lf, MT_NOTHING);
|
||||
c = real_getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, lf);
|
||||
if (c) {
|
||||
summonmonster(lf, c, R_TREANT, NULL, rnd(50,90), B_TRUE);
|
||||
}
|
||||
|
@ -10338,7 +10432,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
where = lf->cell;
|
||||
if (!moveob(oo, where->obpile, ALL) ){
|
||||
// try somewhere nearby
|
||||
where = getrandomadjcell(where, WE_WALKABLE, B_NOEXPAND);
|
||||
where = getrandomadjcell(where, &ccwalkable, B_NOEXPAND);
|
||||
if (where) {
|
||||
moveob(oo, where->obpile, ALL);
|
||||
}
|
||||
|
@ -14509,6 +14603,8 @@ void timeeffectsob(object_t *o) {
|
|||
char sgname[BUFLEN];
|
||||
cell_t *newc;
|
||||
int canseeloc = B_FALSE;
|
||||
condset_t cs;
|
||||
initcondv(&cs, CC_IMPASSABLE, B_FALSE, NA, CC_NONE);
|
||||
|
||||
if (haslos(player, location) && canseeob(player, sg)) {
|
||||
getobname(sg, sgname, sg->amt);
|
||||
|
@ -14518,7 +14614,7 @@ void timeeffectsob(object_t *o) {
|
|||
}
|
||||
|
||||
// object gets thrown away
|
||||
newc = getrandomadjcell(location, WE_NOTWALL, B_ALLOWEXPAND);
|
||||
newc = getrandomadjcell(location, &cs, B_ALLOWEXPAND);
|
||||
if (newc) {
|
||||
//flag_t *inv;
|
||||
object_t *newob = NULL;
|
||||
|
@ -14694,8 +14790,9 @@ void timeeffectsob(object_t *o) {
|
|||
|
||||
|
||||
// check each flag for this object...
|
||||
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_EXPLODEONDEATH, F_MATCONVERT, F_HOT, F_KNOCKAWAY, F_OBHPDRAIN, F_ONFIRE,
|
||||
F_RECHARGE, F_REVIVETIMER, F_WALKDAM, F_WET, F_NONE);
|
||||
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_EXPLODEONDEATH, F_MATCONVERT,
|
||||
F_HOT, F_KNOCKAWAY, F_LFINSIDE, F_OBHPDRAIN, F_ONFIRE, F_RECHARGE, F_REVIVETIMER,
|
||||
F_WALKDAM, F_WET, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
object_t *oo,*nextoo;
|
||||
f = retflag[i];
|
||||
|
@ -14945,7 +15042,7 @@ void timeeffectsob(object_t *o) {
|
|||
cell_t *lfloc = NULL;
|
||||
if (obloc) {
|
||||
if (obloc->lf) {
|
||||
lfloc = getrandomadjcell(obloc, WE_WALKABLE, B_NOEXPAND);
|
||||
lfloc = getrandomadjcell(obloc, &ccwalkable, B_NOEXPAND);
|
||||
} else {
|
||||
lfloc = obloc;
|
||||
}
|
||||
|
@ -14973,12 +15070,27 @@ void timeeffectsob(object_t *o) {
|
|||
} else if ((f->val[1] - f->val[0]) <= 10) {
|
||||
if (haslos(player, obloc)) {
|
||||
// pass a perception chekc to see it moving...
|
||||
if (skillcheck(player, SC_SEARCH, 100, 0)) {
|
||||
if (skillcheck(player, SC_SEARCH, 100 + getdistspotmod(player, obloc), 0)) {
|
||||
msg("%s twitches.", obname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// lf hiding inside?
|
||||
if (f->id == F_LFINSIDE) {
|
||||
cell_t *obloc = NULL;
|
||||
obloc = getoblocation(o);
|
||||
if (haslos(player, obloc) && (o->pile->owner == player)) {
|
||||
// pass a perception chekc to see it moving...
|
||||
if (skillcheck(player, SC_SEARCH, 100 + getdistspotmod(player, obloc), 0)) {
|
||||
if (o->pile->owner == player) {
|
||||
msg("%s moves slightly.", obname);
|
||||
} else {
|
||||
msg("Your %s moves slightly.", noprefix(obname));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// damaging objects here will damage other objects
|
||||
if (f->id == F_WALKDAM) {
|
||||
|
@ -15328,7 +15440,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
|
|||
|
||||
if (lf) {
|
||||
if (avoided) {
|
||||
escapeto = getrandomadjcell(lf->cell, WE_WALKABLE, B_NOEXPAND);
|
||||
escapeto = getrandomadjcell(lf->cell, &ccwalkable, B_NOEXPAND);
|
||||
if (!escapeto) avoided = B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -15403,7 +15515,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
|
|||
dospelleffects(NULL, OT_S_FLAMEPILLAR, 3, NULL, NULL, c, B_UNCURSED, NULL, B_TRUE, NULL);
|
||||
if (lf && avoided) {
|
||||
cell_t *escapeto = NULL;
|
||||
escapeto = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND);
|
||||
escapeto = getrandomadjcell(c, &ccwalkable, B_NOEXPAND);
|
||||
if (escapeto) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You leap out of the way!");
|
||||
|
@ -15432,7 +15544,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
|
|||
} else if (oid == OT_TRAPSUMMON) {
|
||||
cell_t *cc;
|
||||
// can't be dodged
|
||||
cc = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
cc = getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (cc) {
|
||||
summonmonster(NULL, cc, R_SPECIFIED, "random", PERMENANT, B_FALSE);
|
||||
}
|
||||
|
@ -15456,18 +15568,21 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
|
|||
// kill all objcts in the pile, as long as it doesn't contain
|
||||
// anything important like stairs.
|
||||
//
|
||||
// returns FALSE if we cleared objects, or didn't need to.
|
||||
// returns FALSE if we cleared all objects, or didn't need to.
|
||||
// returns TRUE if there were objects which we couldn't clear
|
||||
int trytokillobs(obpile_t *op) {
|
||||
object_t *o, *nexto;
|
||||
int failed = B_FALSE;
|
||||
// objects here? destroy them if we can.
|
||||
if (countobs(op, B_TRUE)) {
|
||||
if (hasobwithflag(op, F_IMPORTANT)) {
|
||||
return B_TRUE;
|
||||
for (o = op->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
if (hasflag(o->flags, F_IMPORTANT)) {
|
||||
failed = B_TRUE;
|
||||
continue;
|
||||
}
|
||||
killallobs(op);
|
||||
return B_FALSE;
|
||||
}
|
||||
return B_FALSE;
|
||||
killob(o);
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
void turnoff(lifeform_t *lf, object_t *o) {
|
||||
|
|
|
@ -136,6 +136,7 @@ cell_t *getobpilelocation(obpile_t *op);
|
|||
char *getobname(object_t *o, char *buf, int count);
|
||||
char *getshardobname(enum MATERIAL mid, char *buf);
|
||||
char *getshopobname(object_t *o, char *buf, int count);
|
||||
enum SKILL getskilltorepair(object_t *o);
|
||||
char *getobnametrue(object_t *o, char *buf, int count);
|
||||
char *getobnametruebase(object_t *o, char *buf, int count);
|
||||
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int wanttried, int showall);
|
||||
|
|
1
shops.c
1
shops.c
|
@ -177,6 +177,7 @@ void shop(lifeform_t *lf, object_t *vm) {
|
|||
if (!timeisbetween(h, f->val[0], f->val[1])) {
|
||||
sayphrase(NULL, f->val[2], SV_TALK, hoursto12(f->val[0]), NULL, player);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (lfhasflag(lf, F_STENCH)) {
|
||||
|
|
220
spell.c
220
spell.c
|
@ -49,6 +49,9 @@ extern enum ERROR reason;
|
|||
|
||||
extern int needredraw, statdirty;
|
||||
|
||||
extern condset_t ccwalkable;
|
||||
extern condset_t ccwalkableroom;
|
||||
|
||||
// return value of FALSE means that stamina costs should be charged.
|
||||
// TRUE is a cancellation - don't change stamina
|
||||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target, flag_t *cwflag) {
|
||||
|
@ -1657,7 +1660,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
getlfname(victim,victimname);
|
||||
|
||||
// move them out of the way
|
||||
c = getrandomadjcell(victim->cell, WE_EMPTY, B_NOEXPAND);
|
||||
c = getrandomadjcell(victim->cell, &ccwalkable, B_NOEXPAND);
|
||||
// nowhere to move? move to where the lf jumped from!
|
||||
if (c) {
|
||||
movelf(victim, c, B_FALSE);
|
||||
|
@ -2143,6 +2146,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
if (isplayer(user)) msg("You can't sprint with a crushed windpipe.");
|
||||
return B_TRUE;
|
||||
}
|
||||
if (hasinjuredbp(user, BP_LEGS)) {
|
||||
if (isplayer(user)) msg("You can't sprint with injured legs.");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
|
||||
if (isplayer(user)) msg("You can't sprint while swimming!");
|
||||
|
@ -2395,6 +2402,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
cell_t *c,*entry;
|
||||
flag_t *lflinkflag;
|
||||
int x,y;
|
||||
condset_t cs;
|
||||
|
||||
|
||||
lflinkflag = hasflag(user->flags, F_MAPLINK);
|
||||
|
@ -2415,10 +2423,17 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
}
|
||||
|
||||
// find a random empty cell here
|
||||
entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
|
||||
//entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
|
||||
initcondv(&cs, CC_ISROOM, B_TRUE, NA,
|
||||
CC_WALKABLEFOR, B_TRUE, target->id, CC_NONE);
|
||||
entry = getcell_cond(newmap, &cs);
|
||||
|
||||
/*
|
||||
while (!cellwalkable(target, entry, NULL)) {
|
||||
entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
|
||||
//entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
|
||||
entry = getcell_cond(newmap, &ccwalkableroom);
|
||||
}
|
||||
*/
|
||||
|
||||
// link the map to this lf
|
||||
if (!lflinkflag) {
|
||||
|
@ -4201,6 +4216,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
targcell = nextc;
|
||||
target = targcell->lf;
|
||||
knockback(target, dir, power, caster, 0, B_TRUE);
|
||||
real_fall_from_air(targcell->lf, SZ_HUMAN + (power/4));
|
||||
} else if (firstobcell) {
|
||||
// objects
|
||||
for (o = firstobcell->obpile->first ;o ; o = nexto) {
|
||||
|
@ -5241,7 +5257,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else if (spellid == OT_S_CLONE) {
|
||||
// duplicate the caster
|
||||
targcell = getrandomadjcell(caster->cell, WE_WALKABLE, B_NOEXPAND);
|
||||
targcell = getrandomadjcell(caster->cell, &ccwalkable, B_NOEXPAND);
|
||||
if (!targcell) {
|
||||
if (isplayer(caster)) fizzle(caster);
|
||||
return B_TRUE;
|
||||
|
@ -5650,7 +5666,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else {
|
||||
// get random adjacent cell
|
||||
targcell = getrandomadjcell(caster->cell, WE_EMPTY, B_ALLOWEXPAND);
|
||||
targcell = getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5665,7 +5681,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// ask what kind of monster
|
||||
askstring("Create what kind of monster", '?', buf, BUFLEN, NULL);
|
||||
} else {
|
||||
r = getreallyrandomrace(RC_ANY);
|
||||
r = getreallyrandomrace(RC_ANY, NULL);
|
||||
snprintf(buf, BUFLEN, "%s", r->name);
|
||||
}
|
||||
|
||||
|
@ -5720,14 +5736,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
needredraw = B_TRUE;
|
||||
ch = askchar("Teleport to the new vault", "yn","y", B_TRUE, B_FALSE);
|
||||
if (ch == 'y') {
|
||||
int ntries = 0;
|
||||
c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1, WE_WALKABLE);
|
||||
if (!c || !cellwalkable(caster, c, NULL)) {
|
||||
if (++ntries >= 10) {
|
||||
msg("Oops, couldn't find a free space.");
|
||||
return B_FALSE;
|
||||
}
|
||||
c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1, WE_WALKABLE);
|
||||
condset_t cs;
|
||||
initcondv(&cs, CC_WALKABLEFOR, B_TRUE, caster->id,
|
||||
CC_HASROOMID, B_TRUE, caster->cell->map->nrooms-1,
|
||||
CC_NONE);
|
||||
//c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1, WE_WALKABLE);
|
||||
c = getcell_cond(caster->cell->map, &cs);
|
||||
if (!c) {
|
||||
msg("Oops, couldn't find a free space.");
|
||||
return B_FALSE;
|
||||
}
|
||||
teleportto(caster, c, B_TRUE);
|
||||
return B_FALSE;
|
||||
|
@ -6821,7 +6838,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else if (spellid == OT_S_FLOATINGDISC) {
|
||||
lifeform_t *newlf;
|
||||
// get random adjacent cell
|
||||
targcell = getrandomadjcell(caster->cell, WE_EMPTY, B_ALLOWEXPAND);
|
||||
targcell = getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (!targcell) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
|
@ -6847,19 +6864,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
object_t *o;
|
||||
o = addob(targcell->obpile, "water");
|
||||
if (o) {
|
||||
enum OBTYPE badoid[2];
|
||||
enum OBTYPE badoid;
|
||||
int i,amt;
|
||||
int depth;
|
||||
condset_t cs;
|
||||
depth = DP_SHOULDERS + power;
|
||||
|
||||
//amt = ((power+1) * (power+1)) - 1;
|
||||
//amt = power;
|
||||
amt = power*2;
|
||||
badoid[0] = OT_WATERDEEP;
|
||||
badoid[1] = OT_NONE;
|
||||
badoid = OT_WATERDEEP;
|
||||
for (i = 0; i < amt; i++) {
|
||||
cell_t *c;
|
||||
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_WALLSTOP, badoid, NULL, NULL, MT_NOTHING);
|
||||
|
||||
initcondv(&cs, CC_SOLID, B_FALSE, NA,
|
||||
CC_HASOBTYPE, B_FALSE, badoid,
|
||||
CC_NONE);
|
||||
|
||||
c = real_getrandomadjcell(targcell, &cs, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
|
||||
if (c) {
|
||||
object_t *water;
|
||||
water = addob(c->obpile, "water");
|
||||
|
@ -7987,6 +8009,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else if (spellid == OT_S_HOLDPORTAL) {
|
||||
object_t *o,*oo;
|
||||
cell_t *c;
|
||||
condset_t cs;
|
||||
o = hasobwithflag(targcell->obpile, F_DOOR);
|
||||
|
||||
if (!o) {
|
||||
|
@ -7995,9 +8018,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
|
||||
// move any objects which are in the way (but not lfs)
|
||||
initcondv(&cs, CC_SOLID, B_FALSE, NA,
|
||||
CC_NONE);
|
||||
for (oo = targcell->obpile->first ; oo ; oo = oo->next) {
|
||||
if ((oo != o) && (getmaterialstate(oo->material->id) == MS_SOLID)) {
|
||||
c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(targcell, &cs, B_ALLOWEXPAND);
|
||||
if (c) moveob(oo, c->obpile, ALL);
|
||||
}
|
||||
}
|
||||
|
@ -8162,7 +8187,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// knock lfs away
|
||||
if (targcell->lf) {
|
||||
cell_t *c;
|
||||
c = getrandomadjcell(targcell, WE_WALKABLE, B_NOEXPAND);
|
||||
c = getrandomadjcell(targcell, &ccwalkable, B_NOEXPAND);
|
||||
if (c) {
|
||||
knockback(targcell->lf, getdirtowards(targcell, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, 100+(power*10), B_TRUE);
|
||||
} else {
|
||||
|
@ -8527,7 +8552,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
job_t *j;
|
||||
object_t *o;
|
||||
// create a mirror image
|
||||
targcell = real_getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL, NULL, caster, MT_NOTHING);
|
||||
targcell = real_getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
|
||||
if (!targcell) break;
|
||||
lf = clonelf(caster, targcell);
|
||||
if (!lf) break;
|
||||
|
@ -9072,7 +9097,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
|
||||
if (dstcell && !cellwalkable(caster, dstcell, NULL)) {
|
||||
dstcell = real_getrandomadjcell(dstcell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
|
||||
dstcell = real_getrandomadjcell(dstcell, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
|
||||
}
|
||||
|
||||
if (dstcell) {
|
||||
|
@ -9111,18 +9136,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
m = heaven;
|
||||
}
|
||||
if (m) {
|
||||
int ntries = 0;
|
||||
condset_t cs;
|
||||
// find random free cell in map
|
||||
//targcell = getrandomcell(m);
|
||||
targcell = getrandomroomcell(m, ANYROOM, WE_WALKABLE);
|
||||
while (!cellwalkable(target, targcell, NULL) || celldangerous(target, targcell, B_FALSE, NULL)) {
|
||||
//targcell = getrandomcell(m);
|
||||
targcell = getrandomroomcell(m, ANYROOM, WE_WALKABLE);
|
||||
ntries++;
|
||||
if (ntries >= 5) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
//targcell = getrandomroomcell(m, ANYROOM, WE_WALKABLE);
|
||||
initcondv(&cs, CC_ISROOM, B_TRUE, NA,
|
||||
CC_WALKABLEFOR, B_TRUE, target->id,
|
||||
CC_DANGEROUSFOR, B_FALSE, target->id,
|
||||
CC_NONE);
|
||||
targcell = getcell_cond(m, &ccwalkableroom);
|
||||
if (!targcell) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
teleportto(target, targcell, B_TRUE);
|
||||
} else {
|
||||
|
@ -9197,7 +9222,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
|
||||
if (!cellwalkable(caster, targcell, NULL)) {
|
||||
targcell = real_getrandomadjcell(targcell, WE_WALKABLE, B_NOEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
|
||||
targcell = real_getrandomadjcell(targcell, &ccwalkable, B_NOEXPAND, LOF_DONTNEED, NULL, NULL);
|
||||
if (!targcell) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
|
@ -9597,7 +9622,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
object_t *srcportal,*dstportal;
|
||||
|
||||
// find adjacent cell for portal
|
||||
srccell = real_getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL, NULL, caster, MT_NOTHING);
|
||||
srccell = real_getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
|
||||
if (!srccell) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
|
@ -9661,7 +9686,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
|
||||
// find cell next to caster
|
||||
newcell = getrandomadjcell(targcell, WE_WALKABLE, B_NOEXPAND);
|
||||
newcell = getrandomadjcell(targcell, &ccwalkable, B_NOEXPAND);
|
||||
if (!newcell) {
|
||||
newcell = targcell;
|
||||
}
|
||||
|
@ -10228,9 +10253,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
for (i = 0; i < nblowobs; i++) {
|
||||
char obname[BUFLEN];
|
||||
cell_t *c;
|
||||
condset_t cs;
|
||||
initcondv(&cs, CC_SOLID, B_FALSE, NA, CC_NONE);
|
||||
|
||||
getobname(blowob[i], obname, 1);
|
||||
c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(targcell, &cs, B_ALLOWEXPAND);
|
||||
if (c && ((rnd(1,100)-power) <= 33)) {
|
||||
// move it
|
||||
fireat(NULL, blowob[i], 1, c, 4, NULL);
|
||||
|
@ -10238,22 +10265,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
|
||||
if (target) {
|
||||
int pen = 0;
|
||||
// easyish save to avoid falling
|
||||
switch (getlfsize(target)) {
|
||||
case SZ_MEDIUM:
|
||||
pen = -15; break;
|
||||
case SZ_SMALL:
|
||||
pen = -25; break;
|
||||
case SZ_TINY:
|
||||
pen = -35; break;
|
||||
case SZ_MINI:
|
||||
pen = -45; break;
|
||||
break;
|
||||
default: pen = 0; break;
|
||||
}
|
||||
if (!skillcheck(target, SC_FALL, 60 + (power*5), pen)) {
|
||||
fall(target, NULL, B_TRUE);
|
||||
if (!real_fall_from_air(target, SZ_SMALL + (power/4))) {
|
||||
int pen = 0;
|
||||
// easyish save to avoid falling
|
||||
switch (getlfsize(target)) {
|
||||
case SZ_MEDIUM:
|
||||
pen = -15; break;
|
||||
case SZ_SMALL:
|
||||
pen = -25; break;
|
||||
case SZ_TINY:
|
||||
pen = -35; break;
|
||||
case SZ_MINI:
|
||||
pen = -45; break;
|
||||
break;
|
||||
default: pen = 0; break;
|
||||
}
|
||||
if (!skillcheck(target, SC_FALL, 60 + (power*5), pen)) {
|
||||
fall(target, NULL, B_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
needredraw = B_TRUE;
|
||||
|
@ -10478,7 +10507,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
//if ((caster == target) && getforcedspellrace(caster, spellid, buf)) {
|
||||
if (getforcedspellrace(target, spellid, buf, NULL)) {
|
||||
r = findracebyname(buf);
|
||||
r = findracebyname(buf, NULL);
|
||||
} else {
|
||||
if (spellid == OT_S_POLYMORPH) {
|
||||
int dorandom = B_FALSE;
|
||||
|
@ -10499,7 +10528,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
snprintf(buf2, BUFLEN, "What will you transform %s into", targname);
|
||||
askstring(buf2, '?', buf, BUFLEN, NULL);
|
||||
}
|
||||
r = findracebyname(buf);
|
||||
r = findracebyname(buf, NULL);
|
||||
} else {
|
||||
// TODO: select based on player damage, etc
|
||||
dorandom = B_TRUE;
|
||||
|
@ -10507,7 +10536,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else { // random
|
||||
if (isplayer(target) && lfhasflag(target, F_CONTROL)) {
|
||||
askstring("What will you become", '?', buf, BUFLEN, NULL);
|
||||
r = findracebyname(buf);
|
||||
r = findracebyname(buf, NULL);
|
||||
|
||||
// make sure race is valid:
|
||||
if (r && !canpolymorphto(r->id)) r = NULL;
|
||||
|
@ -10529,7 +10558,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
forcedepth = gettr(target)*2;
|
||||
r = target->race;
|
||||
while ((r == target->race) || !canpolymorphto(r->id)) {
|
||||
r = getrandomrace(NULL, forcedepth);
|
||||
r = getrandomrace(NULL, forcedepth, NULL);
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_SHAPESHIFT) {
|
||||
|
@ -10601,6 +10630,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
howlong = PERMENANT;
|
||||
}
|
||||
polymorphto(target, r->id, howlong);
|
||||
if (isplayer(caster) && !isplayer(target) && !lfhasflag(target, F_UNIQUE)) {
|
||||
// permenant
|
||||
killflagsofid(target->flags, F_POLYMORPHED);
|
||||
killflagsofid(target->flags, F_ORIGRACE);
|
||||
}
|
||||
|
||||
// if someone cast the spell at themself and it's controlled, they can change back at will.
|
||||
if (target == caster) {
|
||||
|
@ -11642,7 +11676,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// ask for a target cell
|
||||
if (targcell) {
|
||||
object_t *o,*oo;
|
||||
enum OBTYPE badoid[2];
|
||||
int i;
|
||||
|
||||
oo = hasob(targcell->obpile, OT_BOULDER);
|
||||
|
@ -11674,15 +11707,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (targcell->type->id != CT_DIRT) setcelltype(targcell, CT_DIRT);
|
||||
o = addob(targcell->obpile, "pool of mud");
|
||||
if (o) {
|
||||
condset_t cs;
|
||||
initcondv(&cs, CC_SOLID, B_FALSE, NA,
|
||||
CC_HASOBTYPE, B_FALSE, OT_MUDPOOL,
|
||||
CC_HASMATERIAL, B_TRUE, MT_STONE,
|
||||
CC_NONE);
|
||||
ndone++;
|
||||
powerleft--;
|
||||
if (haslos(player, targcell)) seenground = B_TRUE;
|
||||
// do the rest
|
||||
badoid[0] = OT_MUDPOOL;
|
||||
badoid[1] = OT_NONE;
|
||||
for (i = 0; i < powerleft; i++) {
|
||||
cell_t *c;
|
||||
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, badoid, NULL, NULL, MT_STONE);
|
||||
c = real_getrandomadjcell(targcell, &cs, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
|
||||
if (c) {
|
||||
if (targcell->type->id != CT_DIRT) setcelltype(targcell, CT_DIRT);
|
||||
o = addob(c->obpile, "pool of mud");
|
||||
|
@ -11857,6 +11893,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
real_fireat(caster, o, 1, targcell, 6, NULL, B_FALSE, OT_S_SPIKEVOLLEY, NULL);
|
||||
} else if (spellid == OT_S_STENCH) {
|
||||
int howlong;
|
||||
enum ERROR why;
|
||||
|
||||
target = targcell->lf;
|
||||
if (!target) {
|
||||
|
@ -11880,8 +11917,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (isplayer(target) || haslos(player, target->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
if (makenauseated(target, power, howlong)) {
|
||||
if (isplayer(caster)) nothinghappens();
|
||||
if (makenauseated(target, power, howlong, &why)) {
|
||||
// if 'why' was 'resisted', then makenauseated()
|
||||
// will ahve already announced the failure.
|
||||
if (isplayer(caster) && (why != E_RESISTED)) {
|
||||
char buf[BUFLEN];
|
||||
getlfname(target, buf);
|
||||
msg("%s seems unaffected.", buf);
|
||||
}
|
||||
// failed
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -11932,7 +11975,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
char lfname[BUFLEN];
|
||||
getobname(o, obname, o->amt);
|
||||
getlfname(c->lf, lfname);
|
||||
newcell = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND);
|
||||
newcell = getrandomadjcell(c, &ccwalkable, B_NOEXPAND);
|
||||
if (newcell) {
|
||||
lifeform_t *snake;
|
||||
// add a snake there.
|
||||
|
@ -11977,7 +12020,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
// add to current cell or new one?
|
||||
if (c->lf) { // ie. if a previous object made a snake here
|
||||
newcell = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND);
|
||||
newcell = getrandomadjcell(c, &ccwalkable, B_NOEXPAND);
|
||||
} else {
|
||||
newcell = c;
|
||||
}
|
||||
|
@ -12209,7 +12252,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// next to a random monster
|
||||
for (lf = target->cell->map->lf ; lf ; lf = lf->next) {
|
||||
if (areenemies(lf, target)) {
|
||||
c = getrandomadjcell(lf->cell, WE_WALKABLE, B_NOEXPAND);
|
||||
c = getrandomadjcell(lf->cell, &ccwalkable, B_NOEXPAND);
|
||||
if (c) break;
|
||||
}
|
||||
}
|
||||
|
@ -12346,7 +12389,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// ok, but you'll die!
|
||||
} else if (!cellwalkable(caster, c, NULL)) {
|
||||
// go somewhere nearby...
|
||||
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (!c) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
|
@ -12374,7 +12417,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (nallies) {
|
||||
int i;
|
||||
for (i = 0; i < nallies; i++) {
|
||||
c = getrandomadjcell(targcell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(targcell, &ccwalkable, B_ALLOWEXPAND);
|
||||
if (c) {
|
||||
teleportto(ally[i], c, B_TRUE);
|
||||
}
|
||||
|
@ -12661,7 +12704,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// override with forced race?
|
||||
if (caster && getforcedspellrace(caster, spellid, racename, &tempcount)) {
|
||||
race_t *r;
|
||||
r = findracebyname(racename);
|
||||
r = findracebyname(racename, NULL);
|
||||
if (r) {
|
||||
wantrace = r->id;
|
||||
wantrc = RC_ANY;
|
||||
|
@ -13185,7 +13228,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (i == 0) {
|
||||
c = targcell;
|
||||
} else {
|
||||
c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND);
|
||||
condset_t cs;
|
||||
initcondv(&cs, CC_SOLID, B_FALSE, NA, CC_NONE);
|
||||
c = getrandomadjcell(targcell, &cs, B_ALLOWEXPAND);
|
||||
}
|
||||
if (c) {
|
||||
if (c->lf && (c->lf->race->baseid != R_SPIDER)) {
|
||||
|
@ -13447,7 +13492,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
job_t *j;
|
||||
char *p,lfname[BUFLEN];
|
||||
// summon a human
|
||||
c = getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
c = getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND);
|
||||
j = getrandomjob(B_TRUE);
|
||||
lf = addlf(c, R_HUMAN, target->level);
|
||||
givejob(lf, j->id);
|
||||
|
@ -13556,7 +13601,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (strlen(buf)) {
|
||||
if (appearonground) {
|
||||
cell_t *where;
|
||||
where = real_getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, target, MT_NOTHING);
|
||||
where = real_getrandomadjcell(target->cell, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, target);
|
||||
if (!where) {
|
||||
where = target->cell;
|
||||
}
|
||||
|
@ -13637,7 +13682,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
cell_t *newloc;
|
||||
// if so, don't put it where the player is!
|
||||
newloc = real_getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, target, MT_NOTHING);
|
||||
newloc = real_getrandomadjcell(target->cell, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED,
|
||||
NULL, target);
|
||||
o = relinkob(o, newloc->obpile);
|
||||
}
|
||||
if (o) {
|
||||
|
@ -14511,7 +14557,7 @@ char *getspelldesc(enum OBTYPE spellid, int power, char *buf) {
|
|||
// returns the number of materials/cutoffs which were appended.
|
||||
int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repairablemats, int *cutoffpct, int *nmats) {
|
||||
enum SKILLLEVEL slev;
|
||||
int cutoff,nworkable = 0;
|
||||
int cutoff,cutoffmod = 0,nworkable = 0;
|
||||
object_t *helpob = NULL;
|
||||
|
||||
// note: we DONT initialise nmats to zero.
|
||||
|
@ -14527,11 +14573,13 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair
|
|||
default: cutoff = 100; break;
|
||||
}
|
||||
if (skid == SK_METALWORK) {
|
||||
helpob = getworkhelpob(lf->pack, MT_METAL);
|
||||
helpob = getworkhelpob(lf->pack, MT_METAL, NULL, &cutoffmod);
|
||||
} else if (skid == SK_SEWING) {
|
||||
helpob = getworkhelpob(lf->pack, MT_CLOTH);
|
||||
helpob = getworkhelpob(lf->pack, MT_CLOTH, NULL, &cutoffmod);
|
||||
}
|
||||
if (helpob) {
|
||||
cutoff -= cutoffmod;
|
||||
}
|
||||
if (helpob) cutoff -= 15;
|
||||
|
||||
limit(&cutoff, 0, NA);
|
||||
|
||||
|
@ -14558,12 +14606,18 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair
|
|||
}
|
||||
|
||||
// returns an object from 'op' which will help with work on the given material
|
||||
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat) {
|
||||
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat, int *howmuch, int *cutoffmod) {
|
||||
object_t *helpob = NULL;
|
||||
if ((mat == MT_LEATHER) || (mat == MT_CLOTH)) {
|
||||
helpob = hasob(op, OT_NEEDLE);
|
||||
} else if (mat == MT_METAL) {
|
||||
helpob = hasob(op, OT_SPANNER);
|
||||
if (howmuch) *howmuch = 0;
|
||||
if (cutoffmod) *cutoffmod = 0;
|
||||
helpob = hasobwithflagval(op, F_HELPSREPAIR, mat, NA, NA, NULL);
|
||||
if (helpob) {
|
||||
flag_t *f;
|
||||
f = hasflagval(helpob->flags, F_HELPSREPAIR, mat, NA, NA, NULL);
|
||||
if (f) {
|
||||
if (howmuch) *howmuch = f->val[1];
|
||||
if (cutoffmod) *cutoffmod = f->val[2];
|
||||
}
|
||||
}
|
||||
return helpob;
|
||||
}
|
||||
|
@ -14964,7 +15018,7 @@ int summonlfs(lifeform_t *caster, cell_t *where, enum RACE wantrace, enum RACECL
|
|||
for (i = 0; i < howmany; i++) {
|
||||
// get random adjacent cell
|
||||
// (prefer cells in sight of caster)
|
||||
c = real_getrandomadjcell(where, WE_EMPTY, B_ALLOWEXPAND, LOF_NEED, NULL, NULL, caster, MT_NOTHING);
|
||||
c = real_getrandomadjcell(where, &ccwalkable, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
|
||||
if (!c) {
|
||||
return ncreated;
|
||||
}
|
||||
|
|
2
spell.h
2
spell.h
|
@ -33,7 +33,7 @@ int getspellrange(lifeform_t *lf, enum OBTYPE spellid, int power, int *minrange)
|
|||
int getstamcost(lifeform_t *lf, enum OBTYPE oid);
|
||||
char *getspelldesc(enum OBTYPE spellid, int power, char *buf);
|
||||
int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repairablemats, int *cutoffpct, int *nmats);
|
||||
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat);
|
||||
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat, int *howmuch, int *cutoffmod);
|
||||
void pullobto(object_t *o, lifeform_t *lf);
|
||||
int schoolappearsinbooks(enum SPELLSCHOOL ss);
|
||||
void spellcloud(cell_t *srcloc, int radius, int dirtype, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext, int aimedateyes, object_t *fromob, int includecentre);
|
||||
|
|
5
text.c
5
text.c
|
@ -1240,6 +1240,8 @@ char *getjobcatname(enum JOBCATEGORY jc) {
|
|||
return "Fighter/Thief";
|
||||
case JC_FIGHTERRANGED:
|
||||
return "Ranged Fighter";
|
||||
case JC_FIGHTERSPEC:
|
||||
return "Specialist Fighter";
|
||||
case JC_MAGE:
|
||||
return "Mage";
|
||||
case JC_THIEF:
|
||||
|
@ -2500,8 +2502,9 @@ char *strrep(char *text, char *oldtok, char *newtok, int *rv) {
|
|||
// returns TRUE if any replacements made
|
||||
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv) {
|
||||
char *temp;
|
||||
char *found = strstr(in, oldtok);
|
||||
char *found;
|
||||
int idx;
|
||||
found = strstr(in, oldtok);
|
||||
if(!found) {
|
||||
*out = realloc(*out, strlen(in) + 1); // oooooooo crashing in realloc
|
||||
strcpy(*out, in);
|
||||
|
|
15
vault.c
15
vault.c
|
@ -1162,7 +1162,7 @@ int handleline(vault_t *v, char *line) {
|
|||
addflag(v->flags, F_VAULTBOX, thingtype, pct, B_FALSE, buf);
|
||||
ok = B_TRUE;
|
||||
} else {
|
||||
dblog("invalid box() definition: '%s'", line);
|
||||
dblog("thingok() failed in box definition: '%s'", line);
|
||||
}
|
||||
|
||||
} else if (strstarts(line, "fill(")) { // fill region
|
||||
|
@ -1213,7 +1213,8 @@ int handleline(vault_t *v, char *line) {
|
|||
addflag(v->flags, F_VAULTBOX, thingtype, pct, B_TRUE, buf);
|
||||
ok = B_TRUE;
|
||||
} else {
|
||||
dblog("invalid box() definition: '%s'", line);
|
||||
dblog("thingok failed in fill() definition: '%s'", line);
|
||||
dblog("failed thingname: '%s'", thingname);
|
||||
}
|
||||
} else if (strstarts(line, "scatter(")) { // fill region
|
||||
// scatter(x,y,x2,y2) type:what:howmany[:pct]
|
||||
|
@ -1631,6 +1632,11 @@ vault_t *loadvault(char *dir, char *filename) {
|
|||
while (!feof(f)) {
|
||||
// strip newline
|
||||
line[strlen(line)-1] = '\0';
|
||||
// strip trailing spaces
|
||||
while (line[strlen(line)-1] == ' ') {
|
||||
line[strlen(line)-1] = '\0';
|
||||
}
|
||||
|
||||
// handle it
|
||||
if (handleline(v, line)) {
|
||||
goterrors = B_TRUE;
|
||||
|
@ -1752,7 +1758,7 @@ int real_vaultthingok(enum VAULTTHING vt, char *what, int *hasfire) {
|
|||
if (streq(what, "random")) {
|
||||
return B_TRUE;
|
||||
} else {
|
||||
r = findracebyname(what);
|
||||
r = findracebyname(what, NULL);
|
||||
if (r) {
|
||||
if (r->material->id == MT_FIRE) {
|
||||
*hasfire = B_TRUE;
|
||||
|
@ -1760,7 +1766,8 @@ int real_vaultthingok(enum VAULTTHING vt, char *what, int *hasfire) {
|
|||
return B_TRUE;
|
||||
} else {
|
||||
enum RACE rid;
|
||||
rid = parserace(what, NULL, NULL, NULL);
|
||||
condset_t cs;
|
||||
rid = parserace(what, NULL, &cs, NULL, NULL);
|
||||
if (rid) {
|
||||
if (hasfire) {
|
||||
r = findrace(rid);
|
||||
|
|
Loading…
Reference in New Issue