- [+] add territorial to monsters!!!

- [+] wolf
    - [+] hawk
    - [+] bear
    - [+] worker ant (but not soldier ant)
- [+] player shouldn't know if mosnters are peaceful or not
    - [+] ie. no warnings when attacking them
    - [+] no swapping places
    - [+] don't show "(peaceful)" in io.c askcoords()
    - [+] need isknownpeaceful()
    - [+] lv1 negotiation will fix this.  maybe rename it though:
        - [+] psychology
- [+] psionic spells:
    - [+] boost confidence
- [+] wild spells:
    - [+] pyrotechnics
- [+] absorb metal should give you hp if you already have ful lmana
This commit is contained in:
Rob Pearce 2012-04-07 07:18:56 +00:00
parent 0f9db848d3
commit acd641ebc0
10 changed files with 134 additions and 36 deletions

View File

@ -195,15 +195,21 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
}
}
if (!areenemies(lf,c->lf) && (getraceclass(c->lf) != RC_PLANT) && cansee(lf, c->lf)
&& !lfhasflag(lf, F_RAGE)) {
if (!areenemies(lf,c->lf) && (getraceclass(c->lf) != RC_PLANT) &&
cansee(lf, c->lf) &&
!lfhasflag(lf, F_RAGE)
) {
char ch;
char victimname[BUFLEN];
char buf[BUFLEN];
getlfname(c->lf, victimname);
strcpy(buf, "");
switch (getallegiance(c->lf)) {
case AL_PEACEFUL:
if (getlorelevel(lf, getraceclass(c->lf) >= PR_NOVICE) ||
getskill(lf, SK_SPEECH)) { // need this to KNOW whether they're peaceful
snprintf(buf, BUFLEN, "Really attack the peaceful %s?",noprefix(victimname));
}
break;
case AL_FRIENDLY:
snprintf(buf, BUFLEN, "Really attack the allied %s?",noprefix(victimname));
@ -212,11 +218,13 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
snprintf(buf, BUFLEN, "Really attack the allied %s?",noprefix(victimname));
break;
}
if (strlen(buf)) {
ch = askchar(buf, "yn","n", B_TRUE, B_FALSE);
if (ch == 'n') {
// cancel.
return B_TRUE;
}
}
attackedpeaceful = B_TRUE;
// non-evil players get no xp for attacking peaceful lfs
if ((isplayer(lf) || areallies(player, lf)) && (getalignment(lf) != AL_EVIL)) {

45
data.c
View File

@ -4021,6 +4021,12 @@ void initobjects(void) {
// mental/psionic
///////////////////
// l1
addot(OT_S_BOOSTCONFIDENCE, "boost confidence", "Instils the target with infinite courage, allowing them to (perhaps foolishly) continue fighting even when all seems lost.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER|TT_ALLY, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_MINDSCAN, "mind scan", "Reveals detailed information about the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
@ -4438,6 +4444,12 @@ void initobjects(void) {
// wild
///////////////////
// l1
addot(OT_S_FIREWORKS, "pyrotechnics", "Launches up to ^power^n bursts of dazzling fireworks around the caster, stunning those who view them.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_MANASPIKE, "mana spike", "Fires a small bolt of wild magic, dealing 1d4 magical damage per power level.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
@ -13108,9 +13120,9 @@ void initrace(void) {
addflag(lastrace->flags, F_FELINE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HATESRACEWITHFLAG, F_CANINE, NA, NA, NULL);
addrace(R_BEAR, "black bear", 150, 'Q', C_BLUE, MT_FLESH, RC_ANIMAL, "A medium sized omnivore bear.");
addrace(R_BEAR, "black bear", 150, 'Q', C_BLUE, MT_FLESH, RC_ANIMAL, "A medium sized omnivorous bear.");
setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 2, NA , NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL);
@ -13206,7 +13218,7 @@ void initrace(void) {
addrace(R_ANT, "giant ant", 20, 'a', C_BROWN, MT_FLESH, RC_ANIMAL, "Giant ants are enormous (for an ant, anyway), and keen to take avenge their smaller ancestors who were crushed by small children.");
setbodytype(lastrace, BT_QUADRAPED);
lastrace->baseid = R_ANT;
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 3, NA , NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL);
@ -13628,7 +13640,7 @@ void initrace(void) {
setbodytype(lastrace, BT_BIRD);
lastrace->baseid = R_HAWK;
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 2, NA , NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
@ -13663,6 +13675,7 @@ void initrace(void) {
setbodytype(lastrace, BT_BIRD);
lastrace->baseid = R_HAWK;
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 3, NA , NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
@ -13697,7 +13710,7 @@ void initrace(void) {
setbodytype(lastrace, BT_BIRD);
lastrace->baseid = R_HAWK;
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 5, NA , NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
@ -13727,6 +13740,7 @@ void initrace(void) {
addrace(R_HAWKFROST, "frost hawk", 1, 'A', C_CYAN, MT_FLESH, RC_ANIMAL, "A hawk imbued with the power of ice. Frost hawks can release a powerufl blast of freezing air when threatened."); // 'A' for Avian
setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 6, NA , NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
@ -14536,7 +14550,7 @@ void initrace(void) {
addrace(R_WOLFYOUNG, "young wolf", 10, 'd', C_GREY, MT_FLESH, RC_ANIMAL, "Immature wolves.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 2, NA , NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
@ -14569,7 +14583,7 @@ void initrace(void) {
addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL, "Highly intelligent members of the canine family.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 3, NA , NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
@ -16871,15 +16885,16 @@ void initskills(void) {
addskilldesc(SK_SHIELDS, PR_SKILLED, "^gShield accuracy penalties are reduced by 4.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_EXPERT, "^gShield accuracy penalties are reduced by 5.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_MASTER, "^gShield accuracy penalties are reduced by 6.^n", B_FALSE);
addskill(SK_SPEECH, "Negotiation", "Your skill at haggling prices, or swaying others through speech.", 50);
addskill(SK_SPEECH, "Psychology", "Your skill at reading others, haggling prices, and negotiation.", 50);
addskilldesc(SK_SPEECH, PR_INEPT, "- Each skill level reduces shop prices by 5%.", B_TRUE);
addskilldesc(SK_SPEECH, PR_NOVICE, "^gYou can now question people about nearby traps or monsters.", B_TRUE);
addskilldesc(SK_SPEECH, PR_NOVICE, "^gYou can now offer gems as payment in shops.", B_TRUE);
addskilldesc(SK_SPEECH, PR_BEGINNER, "^gYou can now question people about items on the current level.", B_TRUE);
addskilldesc(SK_SPEECH, PR_ADEPT, "^gYou can now recognise which items others desire.", B_TRUE);
addskilldesc(SK_SPEECH, PR_SKILLED, "^gYou can now trade knowledge and spells with other people.", B_TRUE);
addskilldesc(SK_SPEECH, PR_EXPERT, "^gYou can now persuade people to join to as followers.", B_TRUE);
addskilldesc(SK_SPEECH, PR_MASTER, "^gYou can now choose which skills to learn from people.", B_TRUE);
addskilldesc(SK_SPEECH, PR_NOVICE, "^gYou can determine when others are peaceful.^n", B_TRUE);
addskilldesc(SK_SPEECH, PR_NOVICE, "^gYou can now question people about nearby traps or monsters.^n", B_TRUE);
addskilldesc(SK_SPEECH, PR_BEGINNER, "^gYou can now offer gems as payment in shops.^n", B_TRUE);
addskilldesc(SK_SPEECH, PR_BEGINNER, "^gYou can now question people about items on the current level.^n", B_TRUE);
addskilldesc(SK_SPEECH, PR_ADEPT, "^gYou can now recognise which items others desire.^n", B_TRUE);
addskilldesc(SK_SPEECH, PR_SKILLED, "^gYou can now trade knowledge and spells with other people.^n", B_TRUE);
addskilldesc(SK_SPEECH, PR_EXPERT, "^gYou can now persuade people to join to as followers.^n", B_TRUE);
addskilldesc(SK_SPEECH, PR_MASTER, "^gYou can now choose which skills to learn from people.^n", B_TRUE);
addskill(SK_PERCEPTION, "Perception", "Your ability to notice hidden details, from simple footprints to sinister traps.", 50);
addskilldesc(SK_PERCEPTION, PR_INEPT, "- At higher levels this skill will also let you obscure your own tracks.", B_TRUE);
addskilldesc(SK_PERCEPTION, PR_NOVICE, "^gYou can now see footprints.^n", B_TRUE);

4
defs.h
View File

@ -1650,6 +1650,7 @@ enum OBTYPE {
// -- mental / psionic
OT_S_ANTICIPATE,
OT_S_BAFFLE,
OT_S_BOOSTCONFIDENCE,
OT_S_CHARM,
OT_S_DISORIENT,
OT_S_HUNGER,
@ -1745,8 +1746,9 @@ enum OBTYPE {
OT_S_TELEPORT,
OT_S_TRAVEL,
OT_S_TWIDDLE,
// -- wild
// -- wild magic
OT_S_ALARM,
OT_S_FIREWORKS,
OT_S_MANASPIKE,
OT_S_DETONATE,
OT_S_DETONATEDELAY,

3
io.c
View File

@ -759,8 +759,11 @@ cell_t *real_askcoords(char *prompt, char *subprompt, int targettype, lifeform_t
}
break;
case AL_PEACEFUL:
if ((getlorelevel(player, getraceclass(c->lf)) >= PR_NOVICE) ||
getskill(player, SK_SPEECH)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "peaceful");
}
break;
case AL_HOSTILE:
break;

9
lf.c
View File

@ -10062,6 +10062,7 @@ void givebehaviour(lifeform_t *lf, enum BEHAVIOUR bid) {
case BH_DRUGGED:
killflagsofid(lf->flags, F_FLEEONDAM);
killflagsofid(lf->flags, F_FLEEONHPPCT);
killflagsofid(lf->flags, F_FLEEFROM);
break;
case BH_DRUNK:
addflag(lf->flags, F_DRUNK, rnd(2,5), NA, NA, NULL);
@ -13071,6 +13072,14 @@ int ispeaceful(lifeform_t *lf) {
}
return B_TRUE;
}
int isknownpeaceful(lifeform_t *lf) {
if ((getlorelevel(player, getraceclass(lf)) >= PR_NOVICE) ||
(getskill(player, SK_SPEECH)) ) {
return B_FALSE;
}
return ispeaceful(lf);
}
int ispetof(lifeform_t *lf, lifeform_t *owner) {
if (!lf || !owner) return B_FALSE;

1
lf.h
View File

@ -342,6 +342,7 @@ int isspellskill(enum SKILL skid);
int ismadeofice(lifeform_t *lf);
int ismaxedskill(lifeform_t *lf, enum SKILL skid);
int ispeaceful(lifeform_t *lf);
int isknownpeaceful(lifeform_t *lf);
int ispetof(lifeform_t *lf, lifeform_t *owner);
flag_t *ispetortarget(lifeform_t *lf, lifeform_t *ownertarget);
int isplayer(lifeform_t *lf);

7
move.c
View File

@ -118,7 +118,6 @@ int canswapwith(lifeform_t *lf, lifeform_t *lf2) {
if (isplayer(lf2)) {
return B_FALSE;
}
// mosnters don't swap with people who have F_NOSWAP.
if (!isplayer(lf) && lfhasflag(lf2, F_NOSWAP)) {
return B_FALSE;
@ -139,12 +138,14 @@ int canswapwith(lifeform_t *lf, lifeform_t *lf2) {
return B_TRUE;
}
if (isplayer(lf) && !areenemies(lf, lf2)) {
if (isknownpeaceful(lf2)) {
// player can swap with peaceful lgs
// if they are a lot smaller
if (getlfsize(lf) - getlfsize(lf2) >= 2) {
return B_TRUE;
}
}
}
return B_FALSE;
}
@ -1519,8 +1520,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
//precalclos(l);
}
if (isplayer(l)) { // player saw someone move
if (areenemies(lf, l) && !isplayer(lf)) {
if (isplayer(l) && !isplayer(lf)) { // player saw someone move
if (areenemies(lf, l) || !isknownpeaceful(lf) ) {
if (!preseenbyplayer) {
// TODO: also check for isresting(l), if we have allies standing watch
getlfnamea(lf, lfname);

View File

@ -12335,8 +12335,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
}
adjustdamob(o, &howmuch, damtype);
assert(howmuch < 1000);
//assert(howmuch < 1000);
// effects which have to happen before damage is applied...
// explodes?

View File

@ -90,7 +90,7 @@ float applyshoppricemod(float origprice, lifeform_t *lf, object_t *shop, enum SH
int canafford(lifeform_t *lf, int amt) {
int goldamt = 0,gemamt = 0;
goldamt = countmoney(lf->pack);
if (getskill(lf, SK_SPEECH) >= PR_NOVICE) {
if (getskill(lf, SK_SPEECH) >= PR_BEGINNER) {
gemamt = applyshoppricemod(counthighestobflagvalue(lf->pack, F_GEM), lf, NULL, SA_BUY); // adjust using charisma etc
}
if ((goldamt >= amt ) || (gemamt >= amt) || hasob(lf->pack, OT_CREDITCARD)) {
@ -788,7 +788,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
// only list gold if you have enough
if (getobvalue(oo) >= value) valid = B_TRUE;
strcpy(fullname, moneyname);
} else if ((slev >= PR_NOVICE) && hasflag(oo->flags, F_GEM)) {
} else if ((slev >= PR_BEGINNER) && hasflag(oo->flags, F_GEM)) {
// only list gems which are worth enough
int thisval;
thisval = applyshoppricemod(getobvalue(oo), player, vm, SA_SELL);

60
spell.c
View File

@ -3675,6 +3675,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (totalmass > 0) {
float max;
int mptoheal;
// heal 1 mp per kilo
howmuch = floor(totalmass);
@ -3683,7 +3684,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (howmuch > max) howmuch = max;
mptoheal = getmaxmp(caster) - caster->mp;
gainmp(caster, howmuch);
// any left? heal hp with half the remaining amt now.
howmuch -= mptoheal;
howmuch /= 2;
if (howmuch > 0) {
gainhp(caster, howmuch);
}
} else {
fizzle(caster);
return B_TRUE;
@ -4283,6 +4293,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(caster->flags, F_SLOWMOVE, 5, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
}
} else if (spellid == OT_S_BOOSTCONFIDENCE) {
flag_t *f;
if (!target) {
target = targcell->lf;
}
if (!target) {
fizzle(caster);
return B_TRUE;
}
if (isplayer(target)){
msg("You suddenly feel supremely confident!");
} else if (cansee(player, target)) {
char targname[BUFLEN];
getlfname(target, targname);
msg("%s looks more confident!", targname);
}
killflagsofid(target->flags, F_FLEEONDAM);
killflagsofid(target->flags, F_FLEEONHPPCT);
killflagsofid(target->flags, F_FLEEFROM);
killflagsofid(target->flags, F_TIMID);
addflag(target->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
f = lfhasflag(target, F_MORALE); if (f) f->val[0] = 30;
} else if (spellid == OT_S_BURNINGFEET) {
char killertext[BUFLEN];
if (!target) {
@ -6137,6 +6170,33 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster);
return B_TRUE;
}
} else if (spellid == OT_S_FIREWORKS) {
lifeform_t *poss[MAXCANDIDATES];
int nposs = 0;
if (isplayer(caster)) {
msg("A burst of fireworks explodes around you!");
} else if (cansee(player, caster)) {
msg("A burst of fireworks explodes around %s!", castername);
}
for (target = caster->cell->map->lf ; target ; target = target->next) {
if (target == caster) continue;
if (haslos(target, caster->cell)) {
poss[nposs] = target;
nposs++;
if (nposs >= MAXCANDIDATES) break;
}
}
if (nposs) {
int i,n,idx;
for (i = 0; (i < power) && nposs; i++) {
idx = rnd(0,nposs-1);
stun(poss[idx], 2);
for (n = idx; n < nposs-1; n++) {
poss[n] = poss[n+1];
}
nposs--;
}
}
} else if (spellid == OT_S_FLASH) {
if (isplayer(caster) || cansee(player, caster)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;