- [+] bug: getobvlue price keeps going up
- [+] make food poisoning last longer! - [+] bug: pet starting in water - [+] ability to pay at shops using gems? but no change. - [+] implement - [+] require speech skill at a certain level (novice) - [+] reveal attack location for unseen attacks - [+] bug: poisonbolt spell shouldn't cause fire damage to objects! - [+] return to your original form after dying when polymorphed, but just retain SOME hp - [+] new spell: shapeshift - [+] like polymorph but only affects yourself and always controlled - [+] you have to pick something you can see - [+] spell power determiens hitdice you can copy - [+] purify food now works on all your objects, not just one - [+] Nature god(farming, creation) - [+] Ekrub - [+] doesn't like wyrms because they destroy things? - [+] objects - [+] has a pitchfork vs dragons - [+] longbow of xxx - [+] sun hat - [+] overalls - [+] gloves - [+] effects: - [+] canwill all nature spells - [+] likes - [+] killing animals (but only while hungry) - [+] killing dragons - [+] casting nature spells - [+] creating objects or lfs (wish, monsters, food) - [+] dislikes: - [+] destroying objects - [+] attackob() - [+] throwing a flask which shatters - [+] crush objects underfoot - [+] via non-nature spells...? - [+] poison - [+] attacking plants - [+] casting poison spells (same with other antipoison gods!) - [+] sacrifice: - [+] animal corpses - [+] dragon corpses - [+] pray: - [+] battle: - [+] will come to your aid against wyrms - [+] OTHERWISE: - [+] entangle enemies - [+] lightning - [+] summon plants to help you - [+] nonbattle: - [+] purify food on player - [+] THEN one of the following: - [+] cure poison - [+] fix hunger or give food - [+] heal - [+] give ammo (if ranged weapon equipped and out of ammo) - [+] give it. - [+] make it "of seeking" (ie. always hits) - [+] mend armour - [+] bless armour - [+] gifts - [+] ability: calm animals, power 10 - [+] can shapeshift into a bear - [+] resist poison - [+] resist cold - [+] ranged weapon - [+] magic ammo for ranged weapons - [+] angry (minor) - [+] no nature spells work while god is angry ? - [+] taint your food and any food you touch - [+] summons entangling vines around you - [+] angry (major) - [+] one of: - [+] cloudkill - [+] summon storm - [+] surround you with sawgrass
This commit is contained in:
parent
81d65d35d9
commit
5506fdcc86
6
ai.c
6
ai.c
|
@ -799,6 +799,12 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
|
|||
hateposs[nhateposs++] = who;
|
||||
}
|
||||
break;
|
||||
} else if (lfhasflagval(lf, F_HATESRACECLASS, who->race->raceclass->id, NA, NA, NULL) ) {
|
||||
if ((nhateposs < MAXCANDIDATES) && !areallies(lf, who)) {
|
||||
if (db) dblog(".oO { found a hated raceclass target - lfid %d (%s) ! }",who->id, who->race->name);
|
||||
hateposs[nhateposs++] = who;
|
||||
}
|
||||
break;
|
||||
} else if ( ((f = lfhasflag(lf, F_TERRITORIAL)) != NULL) &&
|
||||
(getcelldist(who->cell, lf->cell) <= f->val[0]) ) {
|
||||
if ((nhateposs < MAXCANDIDATES) && !areallies(lf, who)) {
|
||||
|
|
102
attack.c
102
attack.c
|
@ -19,7 +19,8 @@
|
|||
extern lifeform_t *player;
|
||||
|
||||
extern lifeform_t *godlf[];
|
||||
extern int ngodlfs;
|
||||
|
||||
extern int needredraw;
|
||||
|
||||
extern enum ERROR reason;
|
||||
|
||||
|
@ -478,59 +479,53 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
}
|
||||
|
||||
// god effects...
|
||||
if ((attacktype == AT_LF) && isplayer(lf) && attacktarget) {
|
||||
if (!isgod(attacktarget)) {
|
||||
if (attackedfriend) {
|
||||
angergodmaybe(R_GODMERCY, 100, GA_ATTACKALLY);
|
||||
angergodmaybe(R_GODPURITY, 100, GA_ATTACKALLY);
|
||||
switch (getalignment(attacktarget)) {
|
||||
case AL_EVIL:
|
||||
angergodmaybe(R_GODDEATH, 20, GA_ATTACKALLY); // even more
|
||||
break;
|
||||
case AL_GOOD:
|
||||
angergodmaybe(R_GODPURITY, 20, GA_ATTACKALLY); // even more
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (attackedpeaceful) {
|
||||
angergodmaybe(R_GODMERCY, 50, GA_ASSAULT);
|
||||
angergodmaybe(R_GODPURITY, 50, GA_ASSAULT);
|
||||
switch (getalignment(attacktarget)) {
|
||||
case AL_EVIL:
|
||||
angergodmaybe(R_GODDEATH, 20, GA_ASSAULT); // even more
|
||||
break;
|
||||
case AL_GOOD:
|
||||
angergodmaybe(R_GODPURITY, 20, GA_ASSAULT); // even more
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (attackedhelpless) {
|
||||
angergodmaybe(R_GODMERCY, 50, GA_ATTACKHELPLESS);
|
||||
angergodmaybe(R_GODPURITY, 50, GA_ATTACKHELPLESS);
|
||||
if (getalignment(attacktarget) != AL_EVIL) {
|
||||
pleasegodmaybe(R_GODTHIEVES, 5);
|
||||
pleasegodmaybe(R_GODDEATH, 10);
|
||||
}
|
||||
}
|
||||
if (lfhasflag(lf, F_USEDPOISON)) {
|
||||
int i;
|
||||
flag_t *f;
|
||||
killflagsofid(lf->flags, F_USEDPOISON);
|
||||
for (i = 0; i < ngodlfs; i++) {
|
||||
if (godlf[i]) {
|
||||
f = lfhasflag(godlf[i], F_GODPOISON);
|
||||
if (f) {
|
||||
if (f->val[0]) {
|
||||
pleasegodmaybe(godlf[i]->race->id, f->val[1]);
|
||||
} else {
|
||||
angergodmaybe(godlf[i]->race->id, f->val[1], GA_POISON);
|
||||
}
|
||||
}
|
||||
if (isplayer(lf) && attacktarget) {
|
||||
if (attacktype == AT_LF) {
|
||||
if (!isgod(attacktarget)) {
|
||||
if (attackedfriend) {
|
||||
angergodmaybe(R_GODMERCY, 100, GA_ATTACKALLY);
|
||||
angergodmaybe(R_GODPURITY, 100, GA_ATTACKALLY);
|
||||
switch (getalignment(attacktarget)) {
|
||||
case AL_EVIL:
|
||||
angergodmaybe(R_GODDEATH, 20, GA_ATTACKALLY); // even more
|
||||
break;
|
||||
case AL_GOOD:
|
||||
angergodmaybe(R_GODPURITY, 20, GA_ATTACKALLY); // even more
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (attackedpeaceful) {
|
||||
angergodmaybe(R_GODMERCY, 50, GA_ASSAULT);
|
||||
angergodmaybe(R_GODPURITY, 50, GA_ASSAULT);
|
||||
switch (getalignment(attacktarget)) {
|
||||
case AL_EVIL:
|
||||
angergodmaybe(R_GODDEATH, 20, GA_ASSAULT); // even more
|
||||
break;
|
||||
case AL_GOOD:
|
||||
angergodmaybe(R_GODPURITY, 20, GA_ASSAULT); // even more
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (attackedhelpless) {
|
||||
angergodmaybe(R_GODMERCY, 50, GA_ATTACKHELPLESS);
|
||||
angergodmaybe(R_GODPURITY, 50, GA_ATTACKHELPLESS);
|
||||
if (getalignment(attacktarget) != AL_EVIL) {
|
||||
pleasegodmaybe(R_GODTHIEVES, 5);
|
||||
pleasegodmaybe(R_GODDEATH, 10);
|
||||
}
|
||||
}
|
||||
if ( ((lifeform_t *)attacktarget)->race->raceclass->id == RC_PLANT) {
|
||||
angergodmaybe(R_GODNATURE, 25, GA_ATTACKOBJECT);
|
||||
}
|
||||
if (lfhasflag(lf, F_USEDPOISON)) {
|
||||
killflagsofid(lf->flags, F_USEDPOISON);
|
||||
if (isplayer(lf)) god_usepoison_response();
|
||||
}
|
||||
}
|
||||
} else if (attacktype == AT_OB) {
|
||||
angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -750,6 +745,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
|
|||
if (hit) {
|
||||
if (aidb) dblog(".oO { i hit! }");
|
||||
|
||||
if (!cansee(victim, lf)) {
|
||||
addflag(lf->flags, F_UNSEENATTACKER, victim->id, NA, NA, NULL);
|
||||
if (isplayer(victim) && !isplayer(lf)) needredraw = B_TRUE;
|
||||
}
|
||||
|
||||
// special case
|
||||
if (isplayer(lf) && (victim->race->id == R_GLOWBUG)) {
|
||||
if ((wep->type->id == OT_EMPTYFLASK) || (wep->type->id == OT_EMPTYVIAL)) {
|
||||
|
|
94
data.c
94
data.c
|
@ -988,9 +988,14 @@ void initobjects(void) {
|
|||
addflag_real(lastobmod->flags, F_RUSTED, R_TRUSTY, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
||||
|
||||
// brands modifiers - flags should be UNKNOWN!
|
||||
// also don't double up with names of scrolls etc.
|
||||
// also don't double up with names of scrolls,books etc.
|
||||
// ie. spellbook of flight, boots of flight.
|
||||
|
||||
// missile weapons
|
||||
addbrand(BR_HOMING, "of seeking", BP_NONE, B_UNCURSED, 0);
|
||||
addflag_real(lastbrand->flags, F_HOMING, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
||||
addflag_real(lastbrand->flags, F_ONLYFOROBCLASS, OC_MISSILE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
||||
|
||||
// weapons
|
||||
addbrand(BR_BALANCE, "of balance", BP_WEAPON, B_UNCURSED, 0);
|
||||
addflag_real(lastbrand->flags, F_BALANCE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
||||
|
@ -1088,6 +1093,7 @@ void initobjects(void) {
|
|||
addbrand(BR_HEALTH, "of health", BP_BODY, B_UNCURSED, 0);
|
||||
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_CON, 15, NULL, PERMENANT, B_UNKNOWN, -1);
|
||||
|
||||
|
||||
// materials
|
||||
addmaterial(MT_NOTHING, "nothing", 0);
|
||||
addmaterial(MT_MAGIC, "magical energy", 0);
|
||||
|
@ -3611,6 +3617,12 @@ void initobjects(void) {
|
|||
addot(OT_S_EXCAVATE, "excavate", "Creates a large open area surrounding the caster. No effect on living creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
||||
addot(OT_S_SHAPESHIFT, "shapeshift", "Causes the caster to take on the form of any creature within sight.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how powerful a creature you can become.");
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, 10, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
|
||||
// l5
|
||||
addot(OT_S_GASEOUSFORM, "gaseous form", "Changes the caster into a cloud of gas.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
||||
|
@ -3633,8 +3645,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
||||
addot(OT_S_POLYMORPH, "polymorph", "Transmutes the target into a new living race.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability.");
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power V, you can polymorph other creatures.");
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power VIII, you can choose what kind of creature to polymorph into.");
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power V, you can choose what kind of creature to polymorph into.");
|
||||
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
|
||||
|
@ -5275,7 +5286,7 @@ void initobjects(void) {
|
|||
|
||||
addot(OT_POISONPUFF, "puff of poison gas", "A small puff of poisonous gas.", MT_GAS, 0, OC_EFFECT, SZ_MEDIUM);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREEN, UNI_SHADELIGHT, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
||||
|
@ -6215,8 +6226,8 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
||||
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL);
|
||||
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 15, NA, NULL);
|
||||
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addot(OT_BOLT, "bolt", "A sharp metal spike, meant for firing from a crossbow.", MT_METAL, 0.25, OC_MISSILE, SZ_SMALL);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
||||
|
@ -6227,7 +6238,6 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL);
|
||||
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 20, NA, NULL);
|
||||
|
||||
|
||||
addot(OT_BULLET, "bullet", "A regular gun bullet.", MT_METAL, 0.1, OC_MISSILE, SZ_MINI);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
|
||||
|
@ -6581,6 +6591,16 @@ void initobjects(void) {
|
|||
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);
|
||||
addot(OT_PITCHFORK, "pitchfork", "A multi-pronged agricultural tool designed to lift loose material. Works as a makeshift weapon.", MT_METAL, 5, OC_WEAPON, SZ_HUMAN);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, RR_FREQUENT, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_FOREST, 85, RR_FREQUENT, NULL);
|
||||
addflag(lastot->flags, F_DAM, DT_SLASH, 3, NA, NULL);
|
||||
addflag(lastot->flags, F_ALTDAM, DT_BASH, 3, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTACKVERB, NA, 2, NA, "scratch");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 3, 6, NA, "scrape");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 7, NA, NA, "rake");
|
||||
addot(OT_RANSEUR, "ranseur", "A long spear and cross hilt, resembling a pole-mounted sai. Good for disarming.", MT_METAL, 12, OC_WEAPON, SZ_HUMAN);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_CAVE, 67, NA, NULL);
|
||||
|
@ -7703,6 +7723,59 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_SACRIFICEOBWITHFLAG, F_BATTLESPOILS, NA, 3, "OB explode#S into a shower of blood!");
|
||||
addflag(lastrace->flags, F_SACRIFICEOB, OT_SPELLBOOK, NA, 10, "OB explode#S into a shower of blood!");
|
||||
|
||||
addrace(R_GODNATURE, "Ekrub", 200, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Ekrub is god of nature and creation. She appears as a female figure dressed in farming clothes. Ekrub has a burning hatred of all dragonkind, who she views as abhorrent due to their destructive nature.");
|
||||
setbodytype(lastrace, BT_HUMANOID);
|
||||
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_FLEEONHPPCT, 95, NA, NA, "");
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "80");
|
||||
addflag(lastrace->flags, F_STARTATT, A_AGI, NA, NA, "80");
|
||||
addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "85");
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "65");
|
||||
addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "90");
|
||||
addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "60");
|
||||
addflag(lastrace->flags, F_STARTASLEEPPCT, 0, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "50d4");
|
||||
addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 6, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed +5 pitchfork of dragonslaying");
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed +5 longbow");
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "100 arrows of seeking");
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed +2 overalls");
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed sun hat");
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed leather gloves");
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed rubber boots");
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_POLEARMS, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_EXPERT, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_COOKING, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_LISTEN, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_RANGED, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_LORE_NATURE, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_LORE_DRAGONS, PR_ADEPT, NA, NULL); // ekrub hates dragons
|
||||
// god abilities
|
||||
addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Nature");
|
||||
// may cast all nature spells
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if ((ot->obclass->id == OC_SPELL) && (getspellschool(ot->id) == SS_NATURE)) {
|
||||
addflag(lastrace->flags, F_CANWILL, ot->id, NA, NA, "pw:10;");
|
||||
}
|
||||
}
|
||||
addflag(lastrace->flags, F_GODPOISON, B_FALSE, 25, NA, NULL);
|
||||
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing animals when hungry");
|
||||
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing dragons");
|
||||
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "cooking");
|
||||
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "creating objects");
|
||||
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting nature spells");
|
||||
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "damaging or destroying objects");
|
||||
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison");
|
||||
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_DRAGON, 25, "Writhing vines sprout up and tear OB to pieces!");
|
||||
|
||||
|
||||
addrace(R_GODTHIEVES, "Felix", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Felix is the god of Thieves, Greed and Trickery. He generally appears as an overweight glutton carrying his contraband loot around in huge sacks. Despite this, he is amazingly agile and is said to be able to steal one's soul right out of their body.");
|
||||
|
@ -7889,7 +7962,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "allowing fleeing creatures to escape");
|
||||
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "acts of charity");
|
||||
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "natural healing");
|
||||
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking the innocent");
|
||||
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking the innocent or helpless");
|
||||
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "sneak attacks");
|
||||
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison");
|
||||
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the destruction of healing potions");
|
||||
|
@ -11642,7 +11715,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_CANWILL, OT_S_CHARM, 3, 3, "pw:6;");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:3;");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_STUN, 5, 5, "pw:1;");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_POLYMORPH, 3, 3, "pw:1;race:vampire bat;");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_SHAPESHIFT, 3, 3, "pw:1;race:vampire bat;");
|
||||
addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_DETECTOBS, 10, OT_COFFIN, NA, NULL);
|
||||
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pile of ash");
|
||||
|
@ -11966,8 +12039,9 @@ void initskills(void) {
|
|||
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);
|
||||
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 items on the current level.", B_TRUE);
|
||||
addskilldesc(SK_SPEECH, PR_BEGINNER, "^gYou can now question people about nearby traps or monsters.", 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 trade knowledge and spells with other people.", B_TRUE);
|
||||
addskilldesc(SK_SPEECH, PR_SKILLED, "^gYou can now persuade people to join to as followers.", B_TRUE);
|
||||
addskilldesc(SK_SPEECH, PR_EXPERT, "^gYou can now choose which skills to learn from people.", B_TRUE);
|
||||
|
|
16
defs.h
16
defs.h
|
@ -445,6 +445,7 @@ enum GODANGERREASON {
|
|||
GA_MURDER, // killed someone peaceful
|
||||
GA_POISON, // used poison
|
||||
GA_PRAY, // pestering through constant prayer
|
||||
GA_RACE, // prayed while a hated race.
|
||||
GA_SPELL, // cast a spell from the wrong school
|
||||
};
|
||||
|
||||
|
@ -877,7 +878,7 @@ enum RACECLASS {
|
|||
};
|
||||
|
||||
#define R_GODFIRST R_GODPURITY
|
||||
#define MAXGODS 6
|
||||
#define MAXGODS 7
|
||||
|
||||
enum RACE {
|
||||
R_NONE = 0,
|
||||
|
@ -904,6 +905,7 @@ enum RACE {
|
|||
R_GODTHIEVES, // felix
|
||||
R_GODDEATH, // hecta
|
||||
R_GODMERCY, // yumi
|
||||
R_GODNATURE, // ekrub
|
||||
R_GODBATTLE, // bjorn
|
||||
R_GODMAGIC, // lumara
|
||||
// monsters
|
||||
|
@ -1440,6 +1442,7 @@ enum OBTYPE {
|
|||
OT_S_POLYMORPH,
|
||||
OT_S_POLYMORPHRND,
|
||||
OT_S_QUICKENSTONE,
|
||||
OT_S_SHAPESHIFT,
|
||||
OT_S_SIZEUP,
|
||||
OT_S_SIZEDOWN,
|
||||
// nature / enviromancy
|
||||
|
@ -1867,6 +1870,7 @@ enum OBTYPE {
|
|||
OT_GUISARME,
|
||||
OT_HALBERD,
|
||||
OT_LANCE,
|
||||
OT_PITCHFORK,
|
||||
OT_RANSEUR,
|
||||
OT_SCYTHE,
|
||||
OT_SPEAR,
|
||||
|
@ -2098,6 +2102,7 @@ enum FLAG {
|
|||
// monetary value)
|
||||
// for object brands
|
||||
F_ONLYFOROBTYPE, // brand can only go on obtype v0
|
||||
F_ONLYFOROBCLASS, // brand can only go on obclass v0
|
||||
F_ONLYFOROBWITHFLAG, // brand can only go on obs with flag v0
|
||||
F_ONLYFORDAMTYPE, // brand can only go on obs with damtype v0
|
||||
F_ONLYFORWEPSKILL, // brand can only go on obclass v0
|
||||
|
@ -2108,6 +2113,7 @@ enum FLAG {
|
|||
// equipped on _ONE OF_ the.
|
||||
F_BONUS, // val0=bonus/penalty to damage+accuracy/armour. ie. +1 sword
|
||||
F_THROWMISSILE, // weapon would make a good thrown missle - used by AI
|
||||
F_CANHOME, // this object can have the 'homing' flag
|
||||
F_UNIQUE, // only one may appear
|
||||
F_GLYPH, // override the glyph with the first char of text.
|
||||
// v0 is either NA (white) or colourid (C_xxx).
|
||||
|
@ -2406,6 +2412,7 @@ enum FLAG {
|
|||
// end gun flags
|
||||
F_FLAMESTRIKE, // causes fires where you hit
|
||||
F_BALANCE, // heals target if their maxhp < your maxhp
|
||||
F_HOMING, // missile always hits
|
||||
F_MERCIFUL, // puts to sleep instead of killing.
|
||||
F_REVENGE, // causes damage based on your hp
|
||||
//
|
||||
|
@ -2555,6 +2562,9 @@ enum FLAG {
|
|||
F_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18
|
||||
F_SIZE, // val0 = lf size (enum LFSIZE)
|
||||
F_SIZETIMER, // lf weill resize to LFSIZE val0 in val1 turns.
|
||||
F_UNSEENATTACKER, // this lf attacked lfid v0 while lfid v0 couldn't
|
||||
// see them. used to mark 'X' on the player's map
|
||||
// for unseen attackers.
|
||||
F_USEDPOISON, // this lf used a poisoned weapon to attack
|
||||
F_RANDOMTALKPCT, // v0 = chance of randomly saying something each turn
|
||||
F_RANDOMTALK, // EITHER:
|
||||
|
@ -2715,6 +2725,7 @@ enum FLAG {
|
|||
F_HATESALL, // lf will attack ALL other lfs on sight
|
||||
F_HATESRACE, // lf will attack lfs with race=v0 or baseid=v0 on
|
||||
// sight
|
||||
F_HATESRACECLASS, // lf will attack lfs with raceclass->id=v0
|
||||
F_HATESRACEWITHFLAG, // lf will attack lfs with flag v0 on sight
|
||||
F_TERRITORIAL, // lf will attack ALL other visible lfs within range v0
|
||||
F_HARMLESS, // it is safe to rest around this lf
|
||||
|
@ -2798,6 +2809,8 @@ enum FLAG {
|
|||
// OB is replace with object name
|
||||
F_SACRIFICEOBWITHFLAG, // v0 = can sacrifice obs with flag v0 to this go
|
||||
F_SACRIFICEOB, // v0 = can sacrifice obtype v0 to this god
|
||||
// if v1 is set, object must be the
|
||||
// corpse of something with raceclass v1.
|
||||
F_SACRIFICEOBCLASS, // v0 = can sacrifice obclass v0 to this god
|
||||
F_SACRIFICEOBBLESSED, // v0 = can sacrifice obs with ->blessed=v0
|
||||
|
||||
|
@ -3939,6 +3952,7 @@ enum BRAND {
|
|||
BR_FLIGHT,
|
||||
BR_GIANTSTRENGTH,
|
||||
BR_HEALTH,
|
||||
BR_HOMING,
|
||||
BR_IMPACT,
|
||||
BR_THINKING,
|
||||
BR_KNOWLEDGE,
|
||||
|
|
286
god.c
286
god.c
|
@ -57,6 +57,8 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
|
|||
case GA_ATTACKOBJECT:
|
||||
if (rid == R_GODTHIEVES) {
|
||||
godsay(rid, B_TRUE, "What are you, a common thug?"); break;
|
||||
} else if (rid == R_GODNATURE) {
|
||||
godsay(rid, B_TRUE, "You dare destroy my creations?"); break;
|
||||
} else {
|
||||
godsay(rid, B_TRUE, "You dare destroy my symbols?"); break;
|
||||
}
|
||||
|
@ -77,6 +79,8 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
|
|||
case GA_PRAY: dosay = B_TRUE; break;
|
||||
case GA_POISON:
|
||||
godsay(rid, B_TRUE, "I do not condone the use of poison!"); break;
|
||||
case GA_RACE:
|
||||
godsay(rid, B_TRUE, "Your form offends me!"); break;
|
||||
case GA_SPELL:
|
||||
godsay(rid, B_TRUE, "Your magic offends me!"); break;
|
||||
}
|
||||
|
@ -182,6 +186,12 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
|
|||
killflag(f);
|
||||
}
|
||||
break;
|
||||
case R_GODNATURE:
|
||||
msg("\"You have transgressed against nature!\"");
|
||||
dospelleffects(NULL, OT_S_ENTANGLE, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE);
|
||||
// note: you will also rot food on touch until god is appeased.
|
||||
// see touch().
|
||||
break;
|
||||
case R_GODMERCY:
|
||||
// lower one attribute
|
||||
msg("\"Be glad that I am feeling merciful, mortal!\"");
|
||||
|
@ -344,6 +354,22 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
|
|||
modattr(player, a, -1);
|
||||
}
|
||||
|
||||
break;
|
||||
case R_GODNATURE:
|
||||
msg("\"You have violated the cardinal laws of nature!\"");
|
||||
dospelleffects(NULL, OT_S_ENTANGLE, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE);
|
||||
switch (rnd(1,3)) {
|
||||
case 1:
|
||||
dospelleffects(NULL, OT_S_CLOUDKILL, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE);
|
||||
break;
|
||||
case 2:
|
||||
dospelleffects(NULL, OT_S_HAILSTORM, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE);
|
||||
break;
|
||||
case 3:
|
||||
msg("\"Destroy him, my pets!\"");
|
||||
summonlfs(god, player->cell, R_SAWGRASS, RC_ANY, SZ_ANY, AL_GOOD, 8, PERMENANT, B_FALSE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case R_GODPURITY:
|
||||
switch (rnd(1,2)) {
|
||||
|
@ -424,8 +450,24 @@ void dooffer(void) {
|
|||
flag_t *f;
|
||||
f = retflag[i];
|
||||
if ((f->id == F_SACRIFICEOB) && (f->val[0] == o->type->id)) {
|
||||
ok = B_TRUE;
|
||||
thispiety = f->val[2];
|
||||
int validcorpse = B_FALSE;
|
||||
if (f->val[1] == NA) {
|
||||
validcorpse = B_TRUE;
|
||||
} else {
|
||||
flag_t *ff;
|
||||
ff = hasflag(o->flags, F_CORPSEOF);
|
||||
if (ff) {
|
||||
race_t *r;
|
||||
r = findrace(ff->val[0]);
|
||||
if (r->raceclass->id == f->val[1]) {
|
||||
validcorpse = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (validcorpse) {
|
||||
ok = B_TRUE;
|
||||
thispiety = f->val[2];
|
||||
}
|
||||
} else if ((f->id == F_SACRIFICEOBCLASS) && (f->val[0] == o->type->obclass->id)) {
|
||||
ok = B_TRUE;
|
||||
thispiety = f->val[2];
|
||||
|
@ -508,6 +550,7 @@ enum RACE getopposinggod(enum RACE rid) {
|
|||
case R_GODMERCY: return R_GODDEATH;
|
||||
case R_GODBATTLE: return R_GODMAGIC;
|
||||
case R_GODMAGIC: return R_GODBATTLE;
|
||||
// TODO: nature/destruction
|
||||
default: break;
|
||||
}
|
||||
return R_NONE;
|
||||
|
@ -639,6 +682,23 @@ lifeform_t *godappears(enum RACE rid, cell_t *where) {
|
|||
return god;
|
||||
}
|
||||
|
||||
void god_usepoison_response(void) {
|
||||
int i;
|
||||
flag_t *f;
|
||||
for (i = 0; i < ngodlfs; i++) {
|
||||
if (godlf[i]) {
|
||||
f = lfhasflag(godlf[i], F_GODPOISON);
|
||||
if (f) {
|
||||
if (f->val[0]) {
|
||||
pleasegodmaybe(godlf[i]->race->id, f->val[1]);
|
||||
} else {
|
||||
angergodmaybe(godlf[i]->race->id, f->val[1], GA_POISON);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int godblocked(enum RACE rid) {
|
||||
lifeform_t *opposegod;
|
||||
enum RACE opposeid;
|
||||
|
@ -813,6 +873,81 @@ int godgiftmaybe(enum RACE rid, int fromtemple) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case R_GODNATURE:
|
||||
while (rollagain) {
|
||||
flag_t *f;
|
||||
object_t *o;
|
||||
objecttype_t *ot;
|
||||
rollagain = B_FALSE;
|
||||
switch (rnd(1,6)) {
|
||||
case 1: // resist/immune poison
|
||||
if (lfhasflag(player, F_DISEASEIMMUNE)) {
|
||||
if (lfhasflagval(player, F_DTIMMUNE, DT_POISON, NA, NA, NULL)) {
|
||||
rollagain = B_TRUE;
|
||||
} else {
|
||||
f = addtempflag(player->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL, FROMGODGIFT);
|
||||
f->obfrom = god->race->id;
|
||||
}
|
||||
} else {
|
||||
f = addtempflag(player->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL, FROMGODGIFT);
|
||||
f->obfrom = god->race->id;
|
||||
}
|
||||
break;
|
||||
case 2: // resist/immune cold
|
||||
if (lfhasflagval(player, F_DTRESIST, DT_COLD, NA, NA, NULL)) {
|
||||
if (lfhasflagval(player, F_DTIMMUNE, DT_COLD, NA, NA, NULL)) {
|
||||
rollagain = B_TRUE;
|
||||
} else {
|
||||
f = addtempflag(player->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL, FROMGODGIFT);
|
||||
f->obfrom = god->race->id;
|
||||
}
|
||||
} else {
|
||||
f = addtempflag(player->flags, F_DTRESIST, DT_COLD, NA, NA, NULL, FROMGODGIFT);
|
||||
f->obfrom = god->race->id;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// good ranged weapon
|
||||
if (getskill(player, SK_RANGED)) {
|
||||
char obname[BUFLEN];
|
||||
if (real_getrandomob(NULL, obname, 25, NA, getlfsize(player),
|
||||
SK_RANGED, B_TRUE, OC_WEAPON, OC_NONE, DT_NONE)) {
|
||||
snprintf(obtogive, BUFLEN, "excellent %s", obname);
|
||||
} else {
|
||||
rollagain = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
rollagain = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case 4: // ammo
|
||||
o = getfirearm(player);
|
||||
if (o) {
|
||||
ot = getrandomammofor(o);
|
||||
snprintf(obtogive, BUFLEN, "%d excellent %s", rnd(20,30), ot->name);
|
||||
} else {
|
||||
rollagain = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case 5: // calm animals ability
|
||||
if (lfhasflagval(player, F_CANWILL, OT_S_CALMANIMALS, NA, NA, NULL)) {
|
||||
rollagain = B_TRUE;
|
||||
} else {
|
||||
f = addtempflag(player->flags, F_CANWILL, OT_S_CALMANIMALS, NA, NA, "pw:10;", FROMGODGIFT);
|
||||
f->obfrom = god->race->id;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (lfhasflagval(player, F_CANWILL, OT_S_SHAPESHIFT, NA, NA, "pw:1;race:hawk;")) {
|
||||
rollagain = B_TRUE;
|
||||
} else {
|
||||
f = addtempflag(player->flags, F_CANWILL, OT_S_SHAPESHIFT, 50, 50, "pw:1;race:hawk;", FROMGODGIFT);
|
||||
f->obfrom = god->race->id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_GODPURITY:
|
||||
while (rollagain) {
|
||||
int n,nposs,i;
|
||||
|
@ -939,6 +1074,15 @@ int godisangry(enum RACE rid) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int godprayedto(enum RACE rid) {
|
||||
lifeform_t *god;
|
||||
god = findgod(rid);
|
||||
if (hasflag(god->flags, F_PRAYEDTO)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
void godsay(enum RACE rid, int says, char *format, ...) {
|
||||
lifeform_t *god;
|
||||
char godname[BUFLEN], buf[BUFLEN];
|
||||
|
@ -968,6 +1112,13 @@ void godsay(enum RACE rid, int says, char *format, ...) {
|
|||
case R_GODMERCY:
|
||||
strcpy(voiceverb, "washes over you");
|
||||
break;
|
||||
case R_GODNATURE:
|
||||
if (godisangry(rid)) {
|
||||
strcpy(voiceverb, "arrives with a buffeting wind");
|
||||
} else {
|
||||
strcpy(voiceverb, "arrives with a gentle breeze");
|
||||
}
|
||||
break;
|
||||
case R_GODPURITY:
|
||||
default:
|
||||
strcpy(voiceverb, "booms out from the heavens");
|
||||
|
@ -1016,6 +1167,9 @@ void pleasegod(enum RACE rid, int amt) {
|
|||
case R_GODMAGIC:
|
||||
msg("You feel Lumara's presense nearby.");
|
||||
break;
|
||||
case R_GODNATURE:
|
||||
msg("You feel in tune with nature.");
|
||||
break;
|
||||
case R_GODMERCY:
|
||||
msg("You feel a sense of serenity.");
|
||||
break;
|
||||
|
@ -1063,6 +1217,12 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (lfhasflagval(god, F_HATESRACECLASS, lf->race->raceclass->id, NA, NA, NULL) ||
|
||||
lfhasflagval(god, F_HATESRACE, lf->race->id, NA, NA, NULL)) {
|
||||
angergod(god->race->id, 50, GA_RACE);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// this will return 100 if we haven't prayed to this
|
||||
// god before
|
||||
piety = getpiety(god->race->id);
|
||||
|
@ -1103,6 +1263,9 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
case R_GODMERCY:
|
||||
strcpy(assisttext, "I hear your prayer, child.");
|
||||
break;
|
||||
case R_GODNATURE:
|
||||
strcpy(assisttext, "Nature hears your call!");
|
||||
break;
|
||||
case R_GODMAGIC:
|
||||
strcpy(assisttext, "One calls upon the eldritch powers...");
|
||||
break;
|
||||
|
@ -1288,7 +1451,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
case 1:
|
||||
// steal from your enemies
|
||||
for (l = lf->cell->map->lf ; l ; l = l->next) {
|
||||
if ((l != lf) && lfhasflagval(l, F_TARGETLF, lf->id, NA, NA, NULL)) {
|
||||
if ((l != lf) && areenemies(l, lf)) {
|
||||
object_t *wep;
|
||||
// confiscate their weapon
|
||||
wep = getweapon(l);
|
||||
|
@ -1436,7 +1599,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
castspell(god, OT_S_SATEHUNGER, player, NULL, player->cell, NULL, NULL);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
if (islowhp(lf) || !donesomething) {
|
||||
if (islowhp(lf)) {
|
||||
msg("\"Let thy wounds be healed.\"");
|
||||
castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL);
|
||||
donesomething = B_TRUE;
|
||||
|
@ -1445,6 +1608,121 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
// uncurse one equipped ob
|
||||
uncurse_one_equipped(lf, "\"Let thy curse be ended!\"");
|
||||
break;
|
||||
case R_GODNATURE:
|
||||
if (isinbattle(lf, B_TRUE)) {
|
||||
lifeform_t *l;
|
||||
int donesomething = B_FALSE;
|
||||
int redo = B_TRUE;
|
||||
while (redo) {
|
||||
redo = B_FALSE;
|
||||
switch (rnd(1,3)) {
|
||||
case 1:
|
||||
msg("\"My children will bind your enemies!\"");
|
||||
// entangle your enemies
|
||||
for (l = lf->cell->map->lf ; l ; l = l->next) {
|
||||
if ((l != lf) && areenemies(l, lf)) {
|
||||
dospelleffects(NULL, OT_S_ENTANGLE, 10, NULL, NULL, l->cell, B_BLESSED, NULL, B_TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: // summon plants
|
||||
msg("\"My children will aid you!\"");
|
||||
summonlfs(player, player->cell, R_NONE, RC_PLANT, SZ_ANY, AL_NONE, 5, PERMENANT, B_TRUE);
|
||||
break;
|
||||
case 3: // lightning
|
||||
msg("\"The powers of the sky will smite your foes!\"");
|
||||
for (l = lf->cell->map->lf ; l ; l = l->next) {
|
||||
if ((l != lf) && areenemies(l, lf)) {
|
||||
dospelleffects(god, OT_S_CALLLIGHTNING, 10, NULL, NULL, l->cell, B_BLESSED, NULL, B_TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fighting a dragon?
|
||||
for (i = 0; i < lf->nlos; i++) {
|
||||
if (lf->los[i]->lf && (getraceclass(lf->los[i]->lf) == RC_DRAGON)) {
|
||||
godappears(god->race->id, NULL);
|
||||
aiattack(god, lf->los[i]->lf, PERMENANT);
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {// not in battle
|
||||
int donesomething = B_FALSE;
|
||||
flag_t *f;
|
||||
|
||||
// fix any poison potions
|
||||
dospelleffects(god, OT_S_PURIFYFOOD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
|
||||
|
||||
if (ispoisoned(lf)) {
|
||||
msg("\"I will cure your poison...\"");
|
||||
castspell(god, OT_S_CUREPOISON, player, NULL, player->cell, NULL, NULL);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
if (!donesomething && (gethungerlevel(gethungerval(player)) >= H_PECKISH)) {
|
||||
msg("\"I will cure your hunger...\"");
|
||||
castspell(god, OT_S_SATEHUNGER, player, NULL, player->cell, NULL, NULL);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
if (!donesomething && islowhp(lf)) {
|
||||
msg("\"I will heal your injuries...\"");
|
||||
castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
if (!donesomething) { // out of ammo?
|
||||
object_t *gun;
|
||||
gun = getfirearm(lf);
|
||||
if (gun && !getammo(gun) && !getrandomammo(lf)) {
|
||||
objecttype_t *ot;
|
||||
ot = getrandomammofor(gun);
|
||||
if (ot) {
|
||||
char obtogive[BUFLEN],ammoname[BUFLEN];
|
||||
char gunname[BUFLEN];
|
||||
object_t *ammo;
|
||||
f = hasflag(gun->flags, F_AMMOCAPACITY);
|
||||
snprintf(obtogive, BUFLEN, "%d %s of seeking", f->val[0], ot->name);
|
||||
ammo = addob(gun->contents, obtogive);
|
||||
identify(ammo);
|
||||
getobname(ammo, ammoname, ammo->amt);
|
||||
getobname(gun, gunname, 1);
|
||||
msg("%s appear%s in your %s!", ammoname, OBS1(ammo), noprefix(gunname));
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!donesomething) { // mend one random armour
|
||||
object_t *poss[MAXCANDIDATES];
|
||||
int nposs = 0;
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
if (isequipped(o) && isarmour(o) && isdamaged(o)) {
|
||||
poss[nposs++] = o;
|
||||
}
|
||||
}
|
||||
if (nposs) {
|
||||
o = poss[rnd(0,nposs-1)];
|
||||
dospelleffects(lf, OT_S_MENDING, 10, NULL, o, NULL, B_BLESSED, NULL, B_FALSE);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
if (!donesomething) { // bless armour
|
||||
object_t *poss[MAXCANDIDATES];
|
||||
int nposs = 0;
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
if (isequipped(o) && isarmour(o) && (o->blessed == B_UNCURSED)) {
|
||||
poss[nposs++] = o;
|
||||
}
|
||||
}
|
||||
if (nposs) {
|
||||
o = poss[rnd(0,nposs-1)];
|
||||
msg("\"Nature's power will protect you...\"");
|
||||
blessob(o);
|
||||
}
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
2
god.h
2
god.h
|
@ -11,9 +11,11 @@ int getprayedgods(lifeform_t **retgod, int *nretgods);
|
|||
lifeform_t *getrandomgod(void);
|
||||
lifeform_t *getrandomprayedgod(void);
|
||||
lifeform_t *godappears(enum RACE rid, cell_t *where);
|
||||
void god_usepoison_response(void);
|
||||
int godblocked(enum RACE rid);
|
||||
int godgiftmaybe(enum RACE rid, int fromtemple);
|
||||
int godisangry(enum RACE rid);
|
||||
int godprayedto(enum RACE rid);
|
||||
void godsay(enum RACE rid, int says, char *format, ...);
|
||||
void modpiety(enum RACE rid, int amt);
|
||||
void pleasegod(enum RACE rid, int amt);
|
||||
|
|
20
io.c
20
io.c
|
@ -3790,10 +3790,10 @@ void docomms(lifeform_t *lf) {
|
|||
enum SKILLLEVEL slev;
|
||||
slev = getskill(player, SK_SPEECH);
|
||||
if (slev >= PR_NOVICE) {
|
||||
addchoice(&prompt, 'i', "What can you tell me about this area?", NULL, NULL, NULL);
|
||||
addchoice(&prompt, 'x', "Any dangers nearby that I should look out for?", NULL, NULL, NULL);
|
||||
}
|
||||
if (slev >= PR_BEGINNER) {
|
||||
addchoice(&prompt, 'x', "Any dangers nearby that I should look out for?", NULL, NULL, NULL);
|
||||
addchoice(&prompt, 'i', "What can you tell me about this area?", NULL, NULL, NULL);
|
||||
}
|
||||
if (!areallies(player, lf)) {
|
||||
if (slev >= PR_ADEPT) {
|
||||
|
@ -4841,14 +4841,22 @@ char *makedesc_god(lifeform_t *god, char *retbuf) {
|
|||
}
|
||||
getflags(god->flags, retflag, &nretflags, F_SACRIFICEOB, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
objecttype_t *ot;
|
||||
if (i == 0) {
|
||||
sprintf(thisline, "%s accepts the sacrifice of:\n", godname);
|
||||
strncat(retbuf, thisline, HUGEBUFLEN);
|
||||
}
|
||||
ot = findot(retflag[i]->val[0]);
|
||||
sprintf(thisline, "- %s\n", ot->name);
|
||||
strncat(retbuf, thisline, HUGEBUFLEN);
|
||||
|
||||
if (retflag[i]->val[1] == NA) {
|
||||
objecttype_t *ot;
|
||||
ot = findot(retflag[i]->val[0]);
|
||||
sprintf(thisline, "- %s\n", ot->name);
|
||||
strncat(retbuf, thisline, HUGEBUFLEN);
|
||||
} else {
|
||||
raceclass_t *rc;
|
||||
rc = findraceclass(retflag[i]->val[1]);
|
||||
sprintf(thisline, "- %s corpses\n", rc->name);
|
||||
strncat(retbuf, thisline, HUGEBUFLEN);
|
||||
}
|
||||
}
|
||||
getflags(god->flags, retflag, &nretflags, F_SACRIFICEOBBLESSED, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
|
|
58
lf.c
58
lf.c
|
@ -1662,6 +1662,13 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
// casting a nature spell while nature god is angry at you?
|
||||
if (isplayer(lf) && godprayedto(R_GODNATURE) && godisangry(R_GODNATURE) && !willflag) {
|
||||
if (hasflagval(sp->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL)) {
|
||||
msg("You seem to be cut off from the powers of nature magic.");
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust power?
|
||||
if (hasjob(lf, J_DRUID)) {
|
||||
|
@ -1814,6 +1821,9 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
pleasegodmaybe(R_GODPURITY, getspelllevel(sid));
|
||||
angergodmaybe(R_GODDEATH, getspelllevel(sid)*5, GA_SPELL);
|
||||
break;
|
||||
case SS_NATURE:
|
||||
pleasegodmaybe(R_GODNATURE, getspelllevel(sid)*2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2401,9 +2411,22 @@ void die(lifeform_t *lf) {
|
|||
// revert to your original form first.
|
||||
if (lfhasflag(lf, F_POLYMORPHED)) {
|
||||
if (lfhasflag(lf, F_ORIGRACE)) {
|
||||
int premaxhp;
|
||||
premaxhp = lf->maxhp;
|
||||
abilityeffects(lf, OT_A_POLYREVERT, lf->cell, lf, NULL);
|
||||
// but you stay at lower hp.
|
||||
if (premaxhp < lf->maxhp) {
|
||||
float ratio;
|
||||
ratio = (float)premaxhp / (float) lf->maxhp;
|
||||
lf->maxhp = ratio * lf->maxhp;
|
||||
limit(&(lf->hp), 1, lf->maxhp);
|
||||
}
|
||||
if (isplayer(lf)) statdirty = B_TRUE;
|
||||
/*
|
||||
// ... but you're still dead
|
||||
lf->hp = 0;
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2527,6 +2550,19 @@ void die(lifeform_t *lf) {
|
|||
pleasegodmaybe(R_GODDEATH, 1);
|
||||
}
|
||||
|
||||
switch (lf->race->raceclass->id) {
|
||||
case RC_ANIMAL:
|
||||
if (gethungerlevel(gethungerval(player)) > H_NONE) {
|
||||
pleasegodmaybe(R_GODNATURE, 3);
|
||||
}
|
||||
break;
|
||||
case RC_DRAGON:
|
||||
pleasegodmaybe(R_GODNATURE, 50);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// mercy god doesn't like killing
|
||||
//angergodmaybe(R_GODMERCY, 1, GA_MURDER);
|
||||
}
|
||||
|
@ -3446,7 +3482,7 @@ int eat(lifeform_t *lf, object_t *o) {
|
|||
} else {
|
||||
snprintf(dambuf, BUFLEN, "a bad %s",noprefix(obname));
|
||||
}
|
||||
poison(lf, 20, P_FOOD, 1, dambuf);
|
||||
poison(lf, rnd(20,40), P_FOOD, 1, dambuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12839,7 +12875,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
|
|||
} else if (damtype == DT_POISONGAS) {
|
||||
if (amt > 0) {
|
||||
if (!skillcheck(lf, SC_POISON, 35, 0)) { // HARD.
|
||||
poison(lf, rnd(5,10), P_GAS, 2, "poison gas");
|
||||
poison(lf, rnd(20,40), P_GAS, 2, "poison gas");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15520,14 +15556,14 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
|
|||
// announce
|
||||
if (reverting) {
|
||||
// reverting to original form....
|
||||
if (!isdead(lf)) {
|
||||
//if (!isdead(lf)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("^wYou revert to your original form!");
|
||||
} else if (cansee(player, lf)) {
|
||||
getlfname(lf, buf);
|
||||
msg("^wThe %s transforms back to its original form!", newrace->name);
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
if ((lf->race->id == R_GASCLOUD) && (origrace->id == R_VAMPIRE)) {
|
||||
if (!isplayer(lf)) {
|
||||
|
@ -16444,6 +16480,7 @@ void startlfturn(lifeform_t *lf) {
|
|||
if (isplayer(lf) && lfhasflag(lf, F_DRUNK)) statdirty = B_TRUE;
|
||||
|
||||
// clear one-turn-only flags
|
||||
killflagsofid(lf->flags, F_UNSEENATTACKER);
|
||||
killflagsofid(lf->flags, F_DONELISTEN);
|
||||
killflagsofid(lf->flags, F_NOSWAP);
|
||||
movedlastturn = 0;
|
||||
|
@ -18137,6 +18174,19 @@ int touch(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
|
||||
|
||||
if (isplayer(lf)) {
|
||||
if (godprayedto(R_GODNATURE) && godisangry(R_GODNATURE) && isedible(o)) {
|
||||
char obname[BUFLEN];
|
||||
getobname(o, obname, o->amt);
|
||||
msg("A green miasma surrounds %s as you touch %s.", obname,
|
||||
(o->amt == 1) ? "it" : "them");
|
||||
if (!hasflag(o->flags, F_TAINTED)) {
|
||||
addflag(o->flags, F_TAINTED, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
f = hasflag(o->flags, F_SHARP);
|
||||
if (f) {
|
||||
object_t *gloves;
|
||||
|
|
23
map.c
23
map.c
|
@ -2852,7 +2852,7 @@ void createheaven(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
|
|||
godlf[ngodlfs++] = lf;
|
||||
if (ngodlfs > MAXGODS) {
|
||||
dblog("Error - number of gods(%d) exceeds MAXGODS.",ngodlfs);
|
||||
msg("Error - number of gods(%d) exceeds MAXGODS.",ngodlfs);
|
||||
msg("Error - number of gods(%d) exceeds MAXGODS.",ngodlfs); more();
|
||||
exit(1);
|
||||
}
|
||||
roomid++;
|
||||
|
@ -6245,6 +6245,9 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
|
|||
if (!f) {
|
||||
f = lfhasflagval(c->lf, F_ATTACHEDTO, player->id, NA, NA, NULL);
|
||||
}
|
||||
if (!f) {
|
||||
f = lfhasflagval(c->lf, F_UNSEENATTACKER, player->id, NA, NA, NULL);
|
||||
}
|
||||
if (f) {
|
||||
if (glyph) {
|
||||
glyph->ch = 'X';
|
||||
|
@ -6253,10 +6256,20 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
|
|||
*thing = c->lf;
|
||||
if (desc) {
|
||||
getlfname(c->lf, desc);
|
||||
if (f->id == F_GRABBEDBY) {
|
||||
strcat(desc, " (holding you)");
|
||||
} else {
|
||||
strcat(desc, " (attached to you)");
|
||||
switch (f->id) {
|
||||
case F_GRABBEDBY:
|
||||
strcat(desc, " (holding you)");
|
||||
break;
|
||||
case F_ATTACHEDTO:
|
||||
strcat(desc, " (attached to you)");
|
||||
break;
|
||||
case F_UNSEENATTACKER:
|
||||
strcat(desc, " (unseen attacker)");
|
||||
break;
|
||||
default:
|
||||
// should never happen
|
||||
strcat(desc, " (detected)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TT_MONSTER;
|
||||
|
|
3
move.c
3
move.c
|
@ -1342,6 +1342,9 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
}
|
||||
// kill object which is being crushed.
|
||||
removeob(o, o->amt);
|
||||
if (isplayer(lf)) {
|
||||
angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} // end if crushable
|
||||
|
|
10
nexus.c
10
nexus.c
|
@ -11,6 +11,7 @@
|
|||
#include "data.h"
|
||||
#include "io.h"
|
||||
#include "flag.h"
|
||||
#include "god.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "move.h"
|
||||
|
@ -330,6 +331,7 @@ int main(int argc, char **argv) {
|
|||
if (j->id == J_DRUID) {
|
||||
enum OBTYPE spell;
|
||||
int i;
|
||||
lifeform_t *god;
|
||||
for (i = 0;i < 3; i++) {
|
||||
// pick a spell which you don't already have...
|
||||
spell = getrandomspellfromschool(SS_NATURE, 1);
|
||||
|
@ -339,6 +341,9 @@ int main(int argc, char **argv) {
|
|||
// you can now cast it.
|
||||
addflag(player->flags, F_CANCAST, spell, NA, NA, NULL);
|
||||
}
|
||||
// druids always worship ekrub
|
||||
god = findgod(R_GODNATURE);
|
||||
addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL);
|
||||
} else if (j->id == J_WIZARD) {
|
||||
skill_t *sk;
|
||||
object_t *sb1,*sb2;
|
||||
|
@ -443,13 +448,14 @@ int main(int argc, char **argv) {
|
|||
cell_t *c;
|
||||
race_t *r;
|
||||
lifeform_t *pet;
|
||||
enum OBTYPE avoidob = OT_WATERDEEP;
|
||||
|
||||
f = retflag[i];
|
||||
r = findracebyname(f->text);
|
||||
assert(r);
|
||||
|
||||
// create it
|
||||
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
// create pet, in view of player if possible.
|
||||
c = real_getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, &avoidob, player);
|
||||
assert(c);
|
||||
pet = addlf(c, r->id, 1);
|
||||
// mark us as its master
|
||||
|
|
133
objects.c
133
objects.c
|
@ -2833,6 +2833,23 @@ int countnames(char **list) {
|
|||
return count;
|
||||
}
|
||||
|
||||
// returns the value of the most valuable object with flag 'fid'
|
||||
// if fid is F_NONE, just returns the most valuable object
|
||||
int counthighestobflagvalue(obpile_t *op, enum FLAG fid) {
|
||||
object_t *o;
|
||||
int maxval = -1;
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if ((fid == F_NONE) || hasflag(o->flags, fid)) {
|
||||
int thisval;
|
||||
thisval = getobvalue(o);
|
||||
if (thisval > maxval) {
|
||||
maxval = thisval;
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxval;
|
||||
}
|
||||
|
||||
int countobs(obpile_t *op, int onlyifknown) {
|
||||
object_t *o;
|
||||
|
||||
|
@ -3741,33 +3758,40 @@ int getobspellpower(object_t *o, lifeform_t *lf) {
|
|||
return power;
|
||||
}
|
||||
|
||||
// returns value of obejcts, in gold
|
||||
int getobvalue(object_t *o) {
|
||||
float price;
|
||||
return real_getobvalue(o, o->amt);
|
||||
}
|
||||
|
||||
// returns value of obejcts, in gold
|
||||
int real_getobvalue(object_t *o, int amt) {
|
||||
float price = 1;
|
||||
flag_t *f;
|
||||
int rarity = 0,i;
|
||||
int i;
|
||||
enum RARITY rr = RR_FREQUENT;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
|
||||
if (o->type->id == OT_GOLD) {
|
||||
return o->amt;
|
||||
return amt;
|
||||
}
|
||||
|
||||
if (o->type->id == OT_CREDITCARD) {
|
||||
return getcharges(o);
|
||||
}
|
||||
|
||||
|
||||
// base value: weight * material value
|
||||
price = (float)getobweight(o) * (float)getmaterialvalue(o->material->id);
|
||||
// rarity
|
||||
getobrarity(o, &rr);
|
||||
|
||||
//adjustprice(o->type, &price);
|
||||
|
||||
// fixed prices
|
||||
f = hasflag(o->flags, F_VALUE);
|
||||
if (f) {
|
||||
price += f->val[0];
|
||||
}
|
||||
price = f->val[0];
|
||||
} else {
|
||||
// base value: weight * material value
|
||||
price = (float)getobweight(o) * (float)getmaterialvalue(o->material->id);
|
||||
}
|
||||
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
price += (89*countobs(o->contents, B_FALSE));
|
||||
|
@ -3822,9 +3846,6 @@ int getobvalue(object_t *o) {
|
|||
price += 1000;
|
||||
}
|
||||
|
||||
// rarity
|
||||
rarity = getobrarity(o, &rr);
|
||||
|
||||
// TODO: conferred intrinsics - depends on which one
|
||||
|
||||
// TODO: conferred spells - use spell price * multiplier
|
||||
|
@ -3838,27 +3859,30 @@ int getobvalue(object_t *o) {
|
|||
}
|
||||
|
||||
// scarcity...
|
||||
switch (rr) {
|
||||
case RR_UNIQUE:
|
||||
price *= 5;
|
||||
break;
|
||||
case RR_VERYRARE:
|
||||
price *= 3;
|
||||
break;
|
||||
case RR_RARE:
|
||||
price *= 2;
|
||||
break;
|
||||
case RR_UNCOMMON:
|
||||
break;
|
||||
case RR_COMMON:
|
||||
price *= 0.75;
|
||||
break;
|
||||
case RR_FREQUENT:
|
||||
price *= 0.5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (!hasflag(o->flags, F_VALUE)) {
|
||||
switch (rr) {
|
||||
case RR_UNIQUE:
|
||||
price *= 5;
|
||||
break;
|
||||
case RR_VERYRARE:
|
||||
price *= 3;
|
||||
break;
|
||||
case RR_RARE:
|
||||
price *= 2;
|
||||
break;
|
||||
case RR_UNCOMMON:
|
||||
break;
|
||||
case RR_COMMON:
|
||||
price *= 0.75;
|
||||
break;
|
||||
case RR_FREQUENT:
|
||||
price *= 0.5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// blessed/cursed
|
||||
if (o->type->id == OT_POT_WATER) {
|
||||
if (isblessed(o) || iscursed(o)) price *= 29.25;
|
||||
|
@ -3869,7 +3893,8 @@ int getobvalue(object_t *o) {
|
|||
// minimum
|
||||
limitf(&price, 1, NA);
|
||||
|
||||
price = ((int)price * o->amt);
|
||||
price = ((int)price * amt);
|
||||
dblog("price for %s is %d", o->type->name, (int)price);
|
||||
return (int) price;
|
||||
}
|
||||
|
||||
|
@ -8146,20 +8171,28 @@ int brandappliesto(brand_t *br, objecttype_t *ot) {
|
|||
flag_t *retflag[MAXCANDIDATES];
|
||||
int i,nretflags = 0;
|
||||
|
||||
if (br->bp == BP_WEAPON) {
|
||||
if (ot->obclass->id != OC_WEAPON) {
|
||||
return B_FALSE;
|
||||
if (br->bp != BP_NONE) {
|
||||
if (br->bp == BP_WEAPON) {
|
||||
if (ot->obclass->id != OC_WEAPON) {
|
||||
return B_FALSE;
|
||||
}
|
||||
} else {
|
||||
// differentiate shields from guns using f_onlywithwepskill below.
|
||||
if (!hasflagval(ot->flags, F_GOESON, br->bp, NA, NA, NULL)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: how do we differentiate shields from guns?
|
||||
if (!hasflagval(ot->flags, F_GOESON, br->bp, NA, NA, NULL)) {
|
||||
}
|
||||
|
||||
// other restrictions?
|
||||
if (hasflag(br->flags, F_ONLYFOROBTYPE)) {
|
||||
if (!hasflagval(br->flags, F_ONLYFOROBTYPE, ot->id, NA, NA, NULL)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
// other restrictions?
|
||||
|
||||
if (hasflag(br->flags, F_ONLYFOROBTYPE)) {
|
||||
if (!hasflagval(br->flags, F_ONLYFOROBTYPE, ot->id, NA, NA, NULL)) {
|
||||
if (hasflag(br->flags, F_ONLYFOROBCLASS)) {
|
||||
if (!hasflagval(br->flags, F_ONLYFOROBCLASS, ot->obclass->id, NA, NA, NULL)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -10937,15 +10970,18 @@ object_t *relinkob(object_t *src, obpile_t *dst) {
|
|||
return src;
|
||||
}
|
||||
|
||||
void removedeadobs(obpile_t *op) {
|
||||
int removedeadobs(obpile_t *op) {
|
||||
object_t *o, *nexto;
|
||||
int nremoved = 0;
|
||||
for (o = op->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
if (hasflag(o->flags, F_DEAD)) {
|
||||
checkflagpile(o->flags);
|
||||
obdie(o);
|
||||
nremoved++;
|
||||
}
|
||||
}
|
||||
return nremoved;
|
||||
}
|
||||
|
||||
// returns the amount left
|
||||
|
@ -11240,6 +11276,9 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
|
|||
makeknown(o->type->id);
|
||||
}
|
||||
potioneffects(target, o->type->id, o, o->blessed, &observed);
|
||||
if (fromlf && isplayer(fromlf) && (o->type->id == OT_POT_POISON)) {
|
||||
god_usepoison_response();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OT_POT_HEALING:
|
||||
|
@ -12163,6 +12202,11 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
|
|||
myroll -= 20;
|
||||
}
|
||||
|
||||
// "of homing" missiles always hit.
|
||||
if (hasflag(o->flags, F_HOMING)) {
|
||||
myroll = acc;
|
||||
}
|
||||
|
||||
// metal projectile versus magnetic shield?
|
||||
if (target && lfhasflag(target, F_MAGSHIELD) && ismetal(o->material->id)) {
|
||||
// announce
|
||||
|
@ -12457,6 +12501,9 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
|
|||
char dambuf[BUFLEN];
|
||||
snprintf(dambuf, BUFLEN, "%s (%s by %s)",obname,throwverbpast, realthrowernamea);
|
||||
shatter(newob, youhit, dambuf, thrower);
|
||||
if (thrower && isplayer(thrower)) {
|
||||
angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT);
|
||||
}
|
||||
} else {
|
||||
// object only gets damaged if it hit someone/something
|
||||
if (missiledam) {
|
||||
|
|
|
@ -42,6 +42,7 @@ void copyobprops(object_t *dst, object_t *src);
|
|||
int counthiddennames(enum OBCLASS ocid, char *text);
|
||||
int countmoney(obpile_t *op);
|
||||
int countnames(char **list);
|
||||
int counthighestobflagvalue(obpile_t *op, enum FLAG fid);
|
||||
int countobs(obpile_t *op, int onlyifknown);
|
||||
int countobsoftype(obpile_t *op, enum OBTYPE oid);
|
||||
int countobswithflag(obpile_t *op, enum FLAG flagid);
|
||||
|
@ -87,6 +88,7 @@ skill_t *getobskill(flagpile_t *fp);
|
|||
enum LFSIZE getobsize(object_t *o);
|
||||
int getobspellpower(object_t *o, lifeform_t *lf);
|
||||
int getobvalue(object_t *o);
|
||||
int real_getobvalue(object_t *o, int amt);
|
||||
char *getoperateverb(object_t *o);
|
||||
object_t *getoutercontainer(object_t *o);
|
||||
object_t *getoutercontainerop(obpile_t *op);
|
||||
|
@ -253,7 +255,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
|
|||
int pour(lifeform_t *lf, object_t *o);
|
||||
void quaff(lifeform_t *lf, object_t *o);
|
||||
int readsomething(lifeform_t *lf, object_t *o);
|
||||
void removedeadobs(obpile_t *op);
|
||||
int removedeadobs(obpile_t *op);
|
||||
int removeob(object_t *o, int howmany);
|
||||
object_t *relinkob(object_t *src, obpile_t *dst);
|
||||
void resizeobject(object_t *o, enum LFSIZE wantsize);
|
||||
|
|
201
shops.c
201
shops.c
|
@ -32,17 +32,18 @@ extern WINDOW *mainwin;
|
|||
float applyshoppricemod(float origprice, lifeform_t *lf) {
|
||||
float newprice;
|
||||
if (lf) {
|
||||
float pricepctmod = 0;
|
||||
float pricepct = 100;
|
||||
enum SKILLLEVEL slev;
|
||||
// price goes up/down for charisma (+/- 25%)
|
||||
pricepctmod -= getstatmod(lf, A_CHA)/2;
|
||||
// high bonus = lower price.
|
||||
pricepct -= (getstatmod(lf, A_CHA)/2);
|
||||
|
||||
// modify for speech (up to -30%);
|
||||
// reduce based on speech (up to -30%);
|
||||
slev = getskill(lf, SK_SPEECH);
|
||||
if (slev) {
|
||||
pricepctmod -= (slev*5);
|
||||
pricepct -= (slev*5);
|
||||
}
|
||||
newprice = pctof(origprice, 100 + pricepctmod);
|
||||
newprice = pctof(pricepct, origprice);
|
||||
} else {
|
||||
newprice = origprice;
|
||||
}
|
||||
|
@ -52,6 +53,18 @@ float applyshoppricemod(float origprice, lifeform_t *lf) {
|
|||
return newprice;
|
||||
}
|
||||
|
||||
int canafford(lifeform_t *lf, int amt) {
|
||||
int goldamt = 0,gemamt = 0;
|
||||
goldamt = countmoney(lf->pack);
|
||||
if (getskill(lf, SK_SPEECH) >= PR_NOVICE) {
|
||||
gemamt = applyshoppricemod(counthighestobflagvalue(lf->pack, F_GEM), lf); // adjust using charisma etc
|
||||
}
|
||||
if ((goldamt >= amt ) || (gemamt >= amt) || hasob(lf->pack, OT_CREDITCARD)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int getshopblessprice(object_t *o) {
|
||||
int cost = 0;
|
||||
int remcursecost, blesscost,surcharge;
|
||||
|
@ -616,7 +629,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
|
|||
|
||||
snprintf(buf, BUFLEN, "%c - %s", o->letter, obname);
|
||||
if (shopmode == BUY) {
|
||||
if (countmoney(player->pack) >= thisprice) {
|
||||
if (canafford(player, thisprice)) {
|
||||
col = C_GREY;
|
||||
} else {
|
||||
col = C_RED;
|
||||
|
@ -676,80 +689,140 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
|
|||
}
|
||||
answer = askchar(buf, validchars,"n", B_TRUE, B_FALSE);
|
||||
if (answer == 'y') {
|
||||
// prompt to use a card
|
||||
if (hasob(player->pack, OT_CREDITCARD)) {
|
||||
char ch2;
|
||||
ch2 = askchar("Charge this purchase to your credit card?","yn","n", B_TRUE, B_FALSE);
|
||||
if (ch2 == 'y') {
|
||||
object_t *cc;
|
||||
// ask which one
|
||||
initprompt(&prompt, "Which credit card will you use?");
|
||||
for (cc = player->pack->first ; cc ; cc = cc->next) {
|
||||
if (cc->type->id == OT_CREDITCARD) {
|
||||
char cardname[BUFLEN];
|
||||
getobname(cc, cardname, 1);
|
||||
addchoice(&prompt, cc->letter, cardname, cardname, cc, NULL);
|
||||
char ques[BUFLEN];
|
||||
object_t *oo;
|
||||
|
||||
// do you have enough money (or a credit card)?
|
||||
if (canafford(player, value)) {
|
||||
object_t *money = NULL;
|
||||
enum SKILLLEVEL slev;
|
||||
slev = getskill(lf, SK_SPEECH);
|
||||
// determine payment method
|
||||
sprintf(ques, "How will you pay for %s?", obname);
|
||||
initprompt(&prompt, ques);
|
||||
for (oo = player->pack->first ; oo ; oo = oo->next) {
|
||||
if ((oo->type->id == OT_GOLD) || (oo->type->id == OT_CREDITCARD) || hasflag(oo->flags, F_GEM)) {
|
||||
char moneyname[BUFLEN];
|
||||
char fullname[BUFLEN];
|
||||
int valid = B_FALSE;
|
||||
|
||||
getobname(oo, moneyname, oo->amt);
|
||||
|
||||
if (oo->type->id == OT_GOLD) {
|
||||
// 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)) {
|
||||
// only list gems which are worth enough
|
||||
int thisval;
|
||||
thisval = applyshoppricemod(getobvalue(oo), player);
|
||||
if (thisval >= value) {
|
||||
valid = B_TRUE;
|
||||
sprintf(fullname, "%s (worth $%d)", moneyname, thisval);
|
||||
}
|
||||
} else {
|
||||
// always list cards
|
||||
valid = B_TRUE;
|
||||
strcpy(fullname, moneyname);
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
addchoice(&prompt, oo->letter, fullname, fullname, oo, NULL);
|
||||
}
|
||||
}
|
||||
if (prompt.nchoices == 1) {
|
||||
// only one card?
|
||||
cc = (object_t *)prompt.choice[0].data;
|
||||
} else {
|
||||
addchoice(&prompt, '-', "(cancel)", "(cancel)", NULL, NULL);
|
||||
prompt.maycancel = B_TRUE;
|
||||
getchoice(&prompt);
|
||||
cc = (object_t *)prompt.result;
|
||||
}
|
||||
money = NULL;
|
||||
if (prompt.nchoices == 1) {
|
||||
// only one possibility.
|
||||
// is it gold?
|
||||
money = (object_t *)prompt.choice[0].data;
|
||||
if (money->type->id != OT_GOLD) {
|
||||
// if not gold, still confirm it.
|
||||
money = NULL;
|
||||
}
|
||||
if (cc) {
|
||||
if (getcharges(cc) >= getobvalue(o)) {
|
||||
int shopamt;
|
||||
}
|
||||
if (!money) {
|
||||
addchoice(&prompt, '-', "(cancel)", "(cancel)", NULL, NULL);
|
||||
prompt.maycancel = B_TRUE;
|
||||
getchoice(&prompt);
|
||||
money = (object_t *)prompt.result;
|
||||
}
|
||||
if (money) {
|
||||
int buyit = B_FALSE;
|
||||
char buytext[BUFLEN];
|
||||
enum {
|
||||
PM_GOLD,
|
||||
PM_GEM,
|
||||
PM_CARD,
|
||||
} purchasemethod;
|
||||
if (money->type->id == OT_CREDITCARD) {
|
||||
purchasemethod = PM_CARD;
|
||||
if (getcharges(money) >= value) {
|
||||
// you got it!
|
||||
usecharges(cc, getobvalue(o));
|
||||
o->letter = '\0';
|
||||
shopamt = o->amt; // avoid "purchased: 2 apples" when you only bought 1 but were holding 1
|
||||
o = moveob(o, player->pack, ALL);
|
||||
identify(o);
|
||||
getobname(o, obname, shopamt);
|
||||
snprintf(toptext, BUFLEN, "Charged to card: %c - %s", o->letter, obname);
|
||||
buyit = B_TRUE;
|
||||
usecharges(money, value);
|
||||
strcpy(buytext, "Charged to card:");
|
||||
if (npurchased) (*npurchased)++;
|
||||
// god of thieves likes credit cards...
|
||||
pleasegodmaybe(R_GODTHIEVES, (value/75));
|
||||
return SR_CONTINUE;
|
||||
} else {
|
||||
// maxed!
|
||||
usecharges(cc, getcharges(o)); // use up all remaining charges
|
||||
usecharges(money, getcharges(o)); // use up all remaining charges
|
||||
// get kicked out
|
||||
msg("^B\"Trying to use a maxed out card, eh? Get out of here, thief!\""); more();
|
||||
// shop closes
|
||||
addflag(vm->flags, F_BANNEDLF, player->id, NA, NA, NULL);
|
||||
return SR_QUIT;
|
||||
}
|
||||
} else { // ie gold or gem;
|
||||
if (getobvalue(money) >= value) {
|
||||
buyit = B_TRUE;
|
||||
// lose money (do this first to avoid potential weight issues)
|
||||
if (hasflag(money->flags, F_GEM)) {
|
||||
int gemsneeded;
|
||||
char gemname[BUFLEN];
|
||||
int valpergem;
|
||||
valpergem = applyshoppricemod(real_getobvalue(money, 1), player);
|
||||
gemsneeded = value / valpergem;
|
||||
limit(&gemsneeded, 1, NA); // (in case gem is worth more than object)
|
||||
getobname(money, gemname, gemsneeded);
|
||||
// remove enough to pay...
|
||||
removeob(money, gemsneeded);
|
||||
purchasemethod = PM_GEM;
|
||||
|
||||
// announce that we're using a gem
|
||||
msg("You hand over %s.", gemname); more();
|
||||
} else {
|
||||
givemoney(player, NULL, value);
|
||||
purchasemethod = PM_GOLD;
|
||||
}
|
||||
strcpy(buytext, "Purchased");
|
||||
if (npurchased) (*npurchased)++;
|
||||
} else {
|
||||
msg("I'm afraid that won't cover it..."); more();
|
||||
o = NULL;
|
||||
}
|
||||
}
|
||||
if (buyit) {
|
||||
int shopamt;
|
||||
// clear o->letter
|
||||
o->letter = '\0';
|
||||
// give object
|
||||
shopamt = o->amt; // avoid "purchased: 2 apples" when you only bought 1 but were holding 1
|
||||
o = moveob(o, player->pack, ALL);
|
||||
identify(o);
|
||||
getobname(o, obname, shopamt);
|
||||
snprintf(toptext, BUFLEN, "%s: %c - %s", buytext, o->letter, obname);
|
||||
if (npurchased) (*npurchased)++;
|
||||
if (purchasemethod == PM_CARD) {
|
||||
// god of thieves likes credit cards...
|
||||
pleasegodmaybe(R_GODTHIEVES, (value/75));
|
||||
} else {
|
||||
practice(player, SK_SPEECH, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// do you have enough money?
|
||||
if (countmoney(player->pack) >= getobvalue(o) ) {
|
||||
int shopamt;
|
||||
object_t *gold;
|
||||
gold = hasob(player->pack, OT_GOLD);
|
||||
if (gold) {
|
||||
// if so, buy it
|
||||
// lose money (do this first to avoid potential weight issues)
|
||||
givemoney(player, NULL, value);
|
||||
// clear o->letter
|
||||
o->letter = '\0';
|
||||
// give object
|
||||
shopamt = o->amt; // avoid "purchased: 2 apples" when you only bought 1 but were holding 1
|
||||
o = moveob(o, player->pack, ALL);
|
||||
identify(o);
|
||||
getobname(o, obname, shopamt);
|
||||
snprintf(toptext, BUFLEN, "Purchased: %c - %s", o->letter, obname);
|
||||
if (npurchased) (*npurchased)++;
|
||||
practice(player, SK_SPEECH, 1);
|
||||
} else {
|
||||
msg("You don't seem to have any money..."); more();
|
||||
msg("Cancelled."); more();
|
||||
o = NULL;
|
||||
}
|
||||
} // end if money
|
||||
} else {
|
||||
msg("You can't afford that!"); more();
|
||||
o = NULL;
|
||||
|
|
1
shops.h
1
shops.h
|
@ -1,6 +1,7 @@
|
|||
#include "defs.h"
|
||||
|
||||
float applyshoppricemod(float origprice, lifeform_t *lf);
|
||||
int canafford(lifeform_t *lf, int amt);
|
||||
int getshopblessprice(object_t *o);
|
||||
void shop(lifeform_t *lf, object_t *vm);
|
||||
enum SHOPRETURN shopabsolve(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated);
|
||||
|
|
268
spell.c
268
spell.c
|
@ -698,6 +698,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
// take some time
|
||||
taketime(user, getactspeed(user));
|
||||
practice(user, SK_COOKING, 1);
|
||||
if (isplayer(user)) pleasegodmaybe(R_GODNATURE, 5);
|
||||
} else {
|
||||
// pack full?
|
||||
msg("You have no space to cook!");
|
||||
|
@ -3778,6 +3779,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
// no corpse after death (so you can't keep reanimating it)
|
||||
addflag(lf->flags, F_NOCORPSE, NA, NA, NA, NULL);
|
||||
if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 25);
|
||||
} else {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
|
@ -4167,7 +4169,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
|
||||
// outdoors?
|
||||
if (isoutdoors(target->cell->map)) {
|
||||
if (caster && (getraceclass(caster) == RC_GOD)) {
|
||||
losehp(target, rolldie(5,6), DT_ELECTRIC, caster, "a heavenly bolt of lightning");
|
||||
} else if (isoutdoors(target->cell->map)) {
|
||||
losehp(target, rolldie(4,6), DT_ELECTRIC, caster, "a bolt of lightning");
|
||||
} else {
|
||||
losehp(target, rolldie(3,6), DT_ELECTRIC, caster, "a bolt of lightning");
|
||||
|
@ -4413,7 +4417,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
addobburst(targcell, radius, DT_COMPASS, "puff of poison gas", caster, LOF_WALLSTOP);
|
||||
|
||||
if (haslos(player, targcell)) {
|
||||
msg("A puff of poison gas appears!");
|
||||
msg("A cloud of poison gas appears!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_CHARM) {
|
||||
|
@ -4729,6 +4733,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 5);
|
||||
} else if (spellid == OT_S_CREATEMONSTER) {
|
||||
lifeform_t *newlf;
|
||||
race_t *r = NULL;
|
||||
|
@ -5081,7 +5086,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (cansee(player, c2->lf)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(c2->lf, lfname);
|
||||
msg("%s %s showed with debris!", lfname, isplayer(c2->lf) ? "are" : "is");
|
||||
msg("%s %s showered with debris!", lfname, isplayer(c2->lf) ? "are" : "is");
|
||||
}
|
||||
losehp(c2->lf, rnd(2,6), DT_PROJECTILE, NULL, "flying debris");
|
||||
}
|
||||
|
@ -5381,7 +5386,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
}
|
||||
// destroy objects right away
|
||||
removedeadobs(targcell->obpile);
|
||||
if (removedeadobs(targcell->obpile)) {
|
||||
if (isplayer(caster)) angergodmaybe(R_GODNATURE, 20, GA_ATTACKOBJECT);
|
||||
}
|
||||
|
||||
// explosion, based on size...
|
||||
if (totalmass > 0) {
|
||||
|
@ -5702,6 +5709,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
msg("A huge pool of water appears!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 5);
|
||||
} else {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
|
@ -6102,13 +6110,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
f->val[0] = 30 + (power/2);
|
||||
f->val[1] = B_FALSE; // struggling doesn't damage the vine
|
||||
}
|
||||
/// remmeber creator. if they don't have los to us, spell
|
||||
// is broken and vines will vanish.
|
||||
setobcreatedby(o, caster);
|
||||
|
||||
if (caster) {
|
||||
/// remmeber creator. if they don't have los to us, spell
|
||||
// is broken and vines will vanish.
|
||||
setobcreatedby(o, caster);
|
||||
}
|
||||
} else if (spellid == OT_S_EXCAVATE) {
|
||||
cell_t *retcell[MAXRETCELLS],*c;
|
||||
int nretcells,i,radius,seenwalls = 0, seenobs = 0;
|
||||
int killedobs = 0;
|
||||
radius = power;
|
||||
limit(&radius, 3, NA);
|
||||
getradiuscells(caster->cell, radius, DT_ORTH, B_FALSE, LOF_DONTNEED, B_FALSE, retcell, &nretcells, 0);
|
||||
|
@ -6127,6 +6137,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
killob(o);
|
||||
addobfast(c->obpile, OT_ASH);
|
||||
if (haslos(player, c)) seenobs++;
|
||||
killedobs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6134,6 +6145,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
msg("A shockwave of destructive force rips through the air!");
|
||||
setlosdirty(player);
|
||||
}
|
||||
if (isplayer(caster) && killedobs) {
|
||||
angergodmaybe(R_GODNATURE, 10*killedobs, GA_ATTACKOBJECT);
|
||||
}
|
||||
} else if (spellid == OT_S_FLIGHT) {
|
||||
flag_t *f;
|
||||
// always targetted at caster
|
||||
|
@ -6354,7 +6368,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else if (spellid == OT_S_HAILSTORM) {
|
||||
int failed = B_FALSE;
|
||||
if (isoutdoors(caster->cell->map)) {
|
||||
if (caster && isoutdoors(caster->cell->map)) {
|
||||
power += 3;
|
||||
limit(&power, NA, 10);
|
||||
}
|
||||
|
@ -7439,9 +7453,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
poison(target, power*3, P_VENOM, (power/4)+1, "a glob of venom");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
damageallobs(NULL, targcell->obpile, 0, DT_FIRE);
|
||||
}
|
||||
if (isplayer(caster)) god_usepoison_response();
|
||||
} else if (spellid == OT_S_POSSESSION) {
|
||||
char targname[BUFLEN];
|
||||
|
||||
|
@ -8461,12 +8474,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
f->obfrom = OT_S_PASSWALL;
|
||||
|
||||
breakgrabs(target, B_TRUE, B_TRUE);
|
||||
} else if (spellid == OT_S_POLYMORPH) {
|
||||
} else if ((spellid == OT_S_POLYMORPH) || (spellid == OT_S_SHAPESHIFT)) {
|
||||
race_t *r = NULL;
|
||||
target = targcell->lf;
|
||||
|
||||
if (frompot) {
|
||||
caster = target;
|
||||
if (frompot || (spellid == OT_S_SHAPESHIFT)) {
|
||||
target = caster;
|
||||
} else {
|
||||
target = targcell->lf;
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
|
@ -8474,63 +8488,109 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
if ((target != caster) && spellresisted(target, caster, spellid, power, seenbyplayer, B_FALSE)) {
|
||||
if (isplayer(target)) {
|
||||
msg("You feel momentarily different.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, target->cell)) {
|
||||
getlfname(target, buf);
|
||||
msg("%s looks momentarily different.", buf);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
if (spellid != OT_S_SHAPESHIFT) {
|
||||
if ((target != caster) && spellresisted(target, caster, spellid, power, seenbyplayer, B_FALSE)) {
|
||||
if (isplayer(target)) {
|
||||
msg("You feel momentarily different.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, target->cell)) {
|
||||
getlfname(target, buf);
|
||||
msg("%s looks momentarily different.", buf);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
if ((caster == target) && getforcedspellrace(caster, spellid, buf)) {
|
||||
//if ((caster == target) && getforcedspellrace(caster, spellid, buf)) {
|
||||
if (caster && getforcedspellrace(caster, spellid, buf)) {
|
||||
r = findracebyname(buf);
|
||||
} else {
|
||||
if (lfhasflag(caster, F_CONTROL)) {
|
||||
if (power < 5) {
|
||||
power = 5;
|
||||
if (spellid == OT_S_POLYMORPH) {
|
||||
if (lfhasflag(caster, F_CONTROL)) {
|
||||
if (power < 5) {
|
||||
power = 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (isplayer(caster) && (power >= 5)) {
|
||||
if (isplayer(target)) { // ie. polymorphing yourself
|
||||
askstring("What will you become", '?', buf, BUFLEN, NULL);
|
||||
} else {
|
||||
char buf2[BUFLEN];
|
||||
char targname[BUFLEN];
|
||||
getlfname(target, targname);
|
||||
snprintf(buf2, BUFLEN, "What will you transform %s into", targname);
|
||||
askstring(buf2, '?', buf, BUFLEN, NULL);
|
||||
}
|
||||
r = findracebyname(buf);
|
||||
} else { // random
|
||||
if (isplayer(target) && lfhasflag(target, F_CONTROL)) {
|
||||
askstring("What will you become", '?', buf, BUFLEN, NULL);
|
||||
r = findracebyname(buf);
|
||||
|
||||
// make sure race is valid:
|
||||
if (r && !canpolymorphto(r->id)) r = NULL;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
// random race, but not the same!
|
||||
r = target->race;
|
||||
while ((r == target->race) || !canpolymorphto(r->id)) {
|
||||
r = getrandomrace(NULL, NA);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_SHAPESHIFT) {
|
||||
int i,ch = 'a';
|
||||
// get list of all lfs in sight
|
||||
initprompt(&prompt, "What will you become?");
|
||||
for (i = 0; i < target->nlos; i++) {
|
||||
if (target->los[i]->lf && cansee(target, target->los[i]->lf)) {
|
||||
race_t *potrace;
|
||||
int n;
|
||||
potrace = target->los[i]->lf->race;
|
||||
// same race?
|
||||
if (potrace == target->race) continue;
|
||||
// too powerful?
|
||||
if (gethitdicerace(potrace) > power) {
|
||||
continue;
|
||||
}
|
||||
// already in the list?
|
||||
for (n = 0; n < prompt.nchoices; n++) {
|
||||
if (prompt.choice[n].data == potrace) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
addchoice(&prompt, ch++, potrace->name, NULL, potrace, NULL);
|
||||
}
|
||||
}
|
||||
addchoice(&prompt, '-', "(cancel)", NULL, NULL, NULL);
|
||||
prompt.maycancel = B_TRUE;
|
||||
if (prompt.nchoices == 1) {
|
||||
if (isplayer(caster)) {
|
||||
msg("You cannot see any forms to copy!");
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
return B_TRUE;
|
||||
} else {
|
||||
if (isplayer(caster)) {
|
||||
getchoice(&prompt);
|
||||
r = (race_t *)prompt.result;
|
||||
} else {
|
||||
r = (race_t *)prompt.choice[rnd(0,prompt.nchoices-1)].data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isplayer(caster) && (power >= 5)) {
|
||||
if (isplayer(target)) { // ie. polymorphing yourself
|
||||
askstring("What will you become", '?', buf, BUFLEN, NULL);
|
||||
} else {
|
||||
char buf2[BUFLEN];
|
||||
char targname[BUFLEN];
|
||||
getlfname(target, targname);
|
||||
snprintf(buf2, BUFLEN, "What will you transform %s into", targname);
|
||||
askstring(buf2, '?', buf, BUFLEN, NULL);
|
||||
}
|
||||
r = findracebyname(buf);
|
||||
|
||||
// make sure race is valid:
|
||||
// - can't turn into monsters which aren't randomly generated.
|
||||
// - can't turn into unique monsters
|
||||
// - can't turn into undead monsters
|
||||
if (r && !canpolymorphto(r->id) && !hasjob(caster, J_GOD)) {
|
||||
if (isplayer(caster)) msg("As you think of a %s, magic energy dampens around you.", r->name);
|
||||
r = NULL;
|
||||
}
|
||||
} else { // random
|
||||
if (isplayer(target) && lfhasflag(target, F_CONTROL)) {
|
||||
askstring("What will you become", '?', buf, BUFLEN, NULL);
|
||||
r = findracebyname(buf);
|
||||
|
||||
// make sure race is valid:
|
||||
if (r && !canpolymorphto(r->id)) r = NULL;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
// random race, but not the same!
|
||||
r = target->race;
|
||||
while ((r == target->race) || !canpolymorphto(r->id)) {
|
||||
r = getrandomrace(NULL, NA);
|
||||
}
|
||||
}
|
||||
// make sure race is valid:
|
||||
// - can't turn into monsters which aren't randomly generated.
|
||||
// - can't turn into unique monsters
|
||||
// - can't turn into undead monsters
|
||||
if (r && !canpolymorphto(r->id) && !hasjob(caster, J_GOD)) {
|
||||
if (isplayer(caster)) msg("As you think of a %s, magic energy dampens around you.", r->name);
|
||||
r = NULL;
|
||||
}
|
||||
} // end if forcepoly
|
||||
|
||||
|
@ -8564,8 +8624,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
setrace(target, r->id, B_TRUE);
|
||||
|
||||
// if someone cast the spell at themself and it's controlled, they can change back at will.
|
||||
if ((target == caster) && (power >= 5)) {
|
||||
addflag(target->flags, F_CANWILL, OT_A_POLYREVERT, NA, NA, NULL);
|
||||
if (target == caster) {
|
||||
int canrevert = B_FALSE;
|
||||
if ((spellid == OT_S_POLYMORPH) && (power >= 5)) {
|
||||
canrevert = B_TRUE;
|
||||
} else if (spellid == OT_S_SHAPESHIFT) {
|
||||
canrevert = B_TRUE;
|
||||
}
|
||||
if (canrevert) {
|
||||
addflag(target->flags, F_CANWILL, OT_A_POLYREVERT, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (haslos(player, target->cell)) {
|
||||
|
@ -8577,59 +8645,69 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
return B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_PURIFYFOOD) {
|
||||
object_t *o;
|
||||
object_t *o,*nexto;
|
||||
int ndone = 0;
|
||||
|
||||
if (targob) {
|
||||
o = targob;
|
||||
} else {
|
||||
// ask for an object
|
||||
o = askobject(caster->pack, "Purify what?", NULL, '\0', AO_EDIBLE | AO_DRINKABLE);
|
||||
if (!target) {
|
||||
target = caster;
|
||||
}
|
||||
if (!o) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (isplayer(caster)) {
|
||||
for (o = target->pack->first ; o ; o = nexto) {
|
||||
char obname[BUFLEN];
|
||||
flag_t *f;
|
||||
int donesomething = B_FALSE;
|
||||
flag_t *f;
|
||||
nexto = o->next;
|
||||
|
||||
getobname(o, obname, o->amt);
|
||||
|
||||
if (o->type->id == OT_POT_POISON) {
|
||||
msg("Your %s sparkles for a while.", noprefix(obname));
|
||||
makeknown(o->type->id); // you now know that it was poison.
|
||||
if (isplayer(target)) {
|
||||
msg("Your %s sparkles for a while.", noprefix(obname));
|
||||
makeknown(o->type->id); // you now know that it was poison.
|
||||
}
|
||||
o->type = findot(OT_POT_WATER);
|
||||
makeknown(o->type->id); // you now know what water is too.
|
||||
if (isplayer(target)) {
|
||||
makeknown(o->type->id); // you now know what water is too.
|
||||
}
|
||||
donesomething = B_TRUE;
|
||||
ndone++;
|
||||
} else {
|
||||
f = hasflag(o->flags, F_OBHP);
|
||||
if (f) {
|
||||
f->val[0] = f->val[1];
|
||||
f = hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL);
|
||||
if (f) killflag(f);
|
||||
donesomething = B_TRUE;
|
||||
if (f) {
|
||||
killflag(f);
|
||||
donesomething = B_TRUE;
|
||||
ndone++;
|
||||
}
|
||||
}
|
||||
|
||||
if (killflagsofid(o->flags, F_TAINTED)) {
|
||||
donesomething = B_TRUE;
|
||||
ndone++;
|
||||
}
|
||||
}
|
||||
|
||||
if (donesomething) {
|
||||
if (isdrinkable(o)) {
|
||||
msg("Your %s looks more clean now.", noprefix(obname));
|
||||
} else {
|
||||
msg("Your %s looks more fresh now.", noprefix(obname));
|
||||
if (isplayer(target)) {
|
||||
if (isdrinkable(o)) {
|
||||
msg("Your %s looks more clean now.", noprefix(obname));
|
||||
} else {
|
||||
msg("Your %s looks more fresh now.", noprefix(obname));
|
||||
}
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else {
|
||||
nothinghappens();
|
||||
return B_TRUE;
|
||||
}
|
||||
} else {
|
||||
// monsters can't purify things!
|
||||
}
|
||||
|
||||
if (!ndone) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_PYROMANIA) {
|
||||
int i,donesomething = B_FALSE;
|
||||
|
@ -10308,8 +10386,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
msg("A wall of ice appears!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 5);
|
||||
} else if (spellid == OT_S_WATERJET) {
|
||||
char lfname[BUFLEN];
|
||||
cell_t *retcell[MAXRETCELLS];
|
||||
|
@ -10517,7 +10594,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
f = addtempflag(caster->flags, F_WINDSHIELD, power, NA, NA, NULL, FROMSPELL);
|
||||
f->obfrom = spellid;
|
||||
} else if (spellid == OT_S_WISHLIMITED) {
|
||||
object_t *o;
|
||||
object_t *o = NULL;
|
||||
char obname[BUFLEN];
|
||||
char ch;
|
||||
if (!target) target = caster;
|
||||
|
@ -10707,6 +10784,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (isplayer(target)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
if (o && isplayer(caster)) pleasegodmaybe(R_GODNATURE, 5);
|
||||
} else if ((spellid == OT_S_WISH) || (spellid == OT_S_GIFT)) {
|
||||
object_t *o;
|
||||
if (isplayer(caster)) {
|
||||
|
@ -10732,6 +10810,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
askstring(question, '?', buf, BUFLEN, NULL);
|
||||
addob(target->cell->obpile, buf);
|
||||
if (nretobs) {
|
||||
int ncreated = 0;
|
||||
for (i = 0; i < nretobs; i++) {
|
||||
char obname[BUFLEN];
|
||||
o = retobs[i];
|
||||
|
@ -10744,6 +10823,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else {
|
||||
msg("%s is gifted with %s.", lfname, obname);
|
||||
}
|
||||
ncreated++;
|
||||
} else {
|
||||
// can't pick this up...
|
||||
|
||||
|
@ -10759,6 +10839,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (!isblind(caster)) {
|
||||
msg("%s appear%s on the ground!", obname, OBS1(o));
|
||||
}
|
||||
ncreated++;
|
||||
} else {
|
||||
// ob exists but couldn't make it appear
|
||||
msg("The air in front of %s seems to ripple for a moment.", lfname);
|
||||
|
@ -10766,6 +10847,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
}
|
||||
}
|
||||
if (ncreated) {
|
||||
if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 10);
|
||||
}
|
||||
} else {
|
||||
// couldn't make it appear - ob doesn't exist
|
||||
msg("The air in front of %s seems to ripple for a while.", lfname);
|
||||
|
|
Loading…
Reference in New Issue