- [+] wizard staff should deal 1 extra magic damage as long as you can
pay it - [+] use "enchanted" weapon mod? - [+] test - [+] why aren't obmods working on start obs? - [+] why isn't wizard starting with staff weilded - [+] because gamemode was GM_LOADING - [+] use something different during character gen. - [+] use different text for followup weapon hits (extradam) - [+] "you hit the xxx" (first one) - [+] "the xxx burns" (second) - [+] "magic blasts the xxx" - [+] "the xxx is chilled" - [+] move all of this into construct_hit_string(lf, victim, wep, damtype, dam, damnum) - [+] test - [+] move getkillvebr() and getattackverb() into text.c - [+] make attackob() use the same code - [+] spellbooks now contain multiple spells - [+] they have an associated SKILL (not spell) - [+] they have contents (a list of spells) - [+] hiddenname isn't getting assigned - [+] contents aren't getitng filled in - [+] when you read them, you learn all the spells (if you can)... OR prompt what to read - [+] DONT give wizards spells on levelup anymore? - [+] gods should say WHY they are angry. - [+] angergodmaybe, angergod need to take enum GODANGERREASON - [+] change definitions - [+] change calls - [+] add new godsay text into angergod()
This commit is contained in:
parent
168a3c49ff
commit
c79a0403c2
401
attack.c
401
attack.c
|
@ -446,34 +446,34 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
// god effects...
|
||||
if ((attacktype == AT_LF) && isplayer(lf)) {
|
||||
if (attackedfriend) {
|
||||
angergodmaybe(R_GODMERCY, 100);
|
||||
angergodmaybe(R_GODPURITY, 100);
|
||||
angergodmaybe(R_GODMERCY, 100, GA_ATTACKALLY);
|
||||
angergodmaybe(R_GODPURITY, 100, GA_ATTACKALLY);
|
||||
switch (getalignment(attacktarget)) {
|
||||
case AL_EVIL:
|
||||
angergodmaybe(R_GODDEATH, 20); // even more
|
||||
angergodmaybe(R_GODDEATH, 20, GA_ATTACKALLY); // even more
|
||||
break;
|
||||
case AL_GOOD:
|
||||
angergodmaybe(R_GODPURITY, 20); // even more
|
||||
angergodmaybe(R_GODPURITY, 20, GA_ATTACKALLY); // even more
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (attackedpeaceful) {
|
||||
angergodmaybe(R_GODMERCY, 50);
|
||||
angergodmaybe(R_GODPURITY, 50);
|
||||
angergodmaybe(R_GODMERCY, 50, GA_ASSAULT);
|
||||
angergodmaybe(R_GODPURITY, 50, GA_ASSAULT);
|
||||
switch (getalignment(attacktarget)) {
|
||||
case AL_EVIL:
|
||||
angergodmaybe(R_GODDEATH, 20); // even more
|
||||
angergodmaybe(R_GODDEATH, 20, GA_ASSAULT); // even more
|
||||
break;
|
||||
case AL_GOOD:
|
||||
angergodmaybe(R_GODPURITY, 20); // even more
|
||||
angergodmaybe(R_GODPURITY, 20, GA_ASSAULT); // even more
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (attackedhelpless) {
|
||||
angergodmaybe(R_GODMERCY, 100);
|
||||
angergodmaybe(R_GODPURITY, 100);
|
||||
angergodmaybe(R_GODMERCY, 100, GA_ATTACKHELPLESS);
|
||||
angergodmaybe(R_GODPURITY, 100, GA_ATTACKHELPLESS);
|
||||
if (getalignment(attacktarget) != AL_EVIL) {
|
||||
pleasegodmaybe(R_GODTHIEVES, 5);
|
||||
pleasegodmaybe(R_GODDEATH, 10);
|
||||
|
@ -481,8 +481,8 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
}
|
||||
if (lfhasflag(lf, F_USEDPOISON)) {
|
||||
killflagsofid(lf->flags, F_USEDPOISON);
|
||||
angergodmaybe(R_GODPURITY, 100);
|
||||
angergodmaybe(R_GODMERCY, 50);
|
||||
angergodmaybe(R_GODPURITY, 100, GA_POISON);
|
||||
angergodmaybe(R_GODMERCY, 50, GA_POISON);
|
||||
pleasegodmaybe(R_GODDEATH, 3);
|
||||
}
|
||||
}
|
||||
|
@ -882,96 +882,24 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
|
|||
|
||||
// announce it
|
||||
if (!feigneddeath) {
|
||||
int usecrittext = B_FALSE;
|
||||
|
||||
if ((i == 0) && critical && !fatal) usecrittext = B_TRUE;
|
||||
|
||||
if (isplayer(lf)) {
|
||||
char extradambuf[BUFLEN];
|
||||
char withwep[BUFLEN];
|
||||
char *verb;
|
||||
int needfree = B_FALSE;
|
||||
|
||||
strcpy(extradambuf, "");
|
||||
|
||||
if (wep && !ismeleeweapon(wep)) {
|
||||
snprintf(withwep, BUFLEN, " with %s", wepname);
|
||||
} else {
|
||||
strcpy(withwep, "");
|
||||
if (isplayer(lf) || isplayer(victim) || cansee(player, lf) || cansee(player, victim)) {
|
||||
construct_hit_string(lf, victim, attackername, victimname, victimbpname, wep, damtype[i], dam[i], victim->maxhp, i, backstab, critical, fatal, isunarmed, buf);
|
||||
if (strlen(buf)) {
|
||||
warn("%s", buf);
|
||||
}
|
||||
|
||||
strcpy(extradambuf, "");
|
||||
if (dam[i] == 0) {
|
||||
if (getlorelevel(lf, victim->race->raceclass->id)) {
|
||||
//strcpy(extradambuf, " but do no damage");
|
||||
strcpy(extradambuf, " ineffectually");
|
||||
}
|
||||
} else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
|
||||
snprintf(extradambuf, BUFLEN, " [%d dmg]",dam[i]);
|
||||
}
|
||||
|
||||
if (backstab && (i == 0)) {
|
||||
verb = strdup("backstab");
|
||||
needfree = B_TRUE;
|
||||
} else if (fatal) {
|
||||
verb = getkillverb(victim, wep, damtype[i], dam[i], victim->maxhp);
|
||||
} else {
|
||||
if ((getlorelevel(lf, victim->race->raceclass->id) >= PR_BEGINNER) ||
|
||||
!ismeleedam(damtype[i])) {
|
||||
verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp);
|
||||
} else {
|
||||
// always use verb for 10%
|
||||
verb = getattackverb(lf, wep, damtype[i], pctof(10, victim->maxhp), victim->maxhp);
|
||||
}
|
||||
}
|
||||
warn("^%cYou %s%s %s%s%s%s", fatal ? 'g' : 'n',
|
||||
usecrittext ? "critically " : "", verb,
|
||||
usecrittext ? victimbpname : victimname, withwep,extradambuf,
|
||||
(fatal || backstab) ? "!" : ".");
|
||||
|
||||
if (fatal && strstr(verb, "behead")) {
|
||||
}
|
||||
if (!isplayer(lf) && !isplayer(victim)) {
|
||||
noise(lf->cell, lf, NC_OTHER, 3, "sounds of fighting.", NULL);
|
||||
}
|
||||
if (fatal) {
|
||||
if (strstr(buf, "behead")) {
|
||||
// we'll need to place the severed head object
|
||||
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
|
||||
if (fatal && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
|
||||
if (!hasflag(victim->flags, F_NODEATHANNOUNCE)) {
|
||||
// don't also say "the xx dies"
|
||||
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
if (needfree) {
|
||||
free(verb);
|
||||
}
|
||||
} else { // ie. the attacker is a monster
|
||||
if (cansee(player, lf) || isplayer(victim)) {
|
||||
char withwep[BUFLEN];
|
||||
char attackverb[BUFLEN];
|
||||
char nodamstr[BUFLEN];
|
||||
int nodam = B_FALSE;
|
||||
|
||||
// capitalise first letter
|
||||
strcpy(buf, attackername);
|
||||
capitalise(buf);
|
||||
|
||||
if (wep && !isunarmed && (lf->race->id != R_DANCINGWEAPON) && cansee(player, lf)) {
|
||||
snprintf(withwep, BUFLEN, " with %s", wepname);
|
||||
} else {
|
||||
strcpy(withwep, "");
|
||||
}
|
||||
|
||||
strcpy(attackverb, getattackverb(lf, wep, damtype[i],dam[i],victim->maxhp));
|
||||
if ((dam[i] == 0) && (damtype[i] != DT_TOUCH)) {
|
||||
nodam = B_TRUE;
|
||||
strcpy(nodamstr, " ineffectually");
|
||||
} else {
|
||||
strcpy(nodamstr, "");
|
||||
}
|
||||
warn("^%c%s %s%s%s %s%s%s.", (isplayer(victim) && !nodam) ? 'b' : 'n', buf,
|
||||
usecrittext ? "critically " : "", attackverb,
|
||||
needses(attackverb) ? "es" : "s",
|
||||
usecrittext ? victimbpname : victimname,withwep, nodamstr);
|
||||
}
|
||||
if (!isplayer(victim)) {
|
||||
noise(lf->cell, lf, NC_OTHER, 3, "sounds of fighting.", NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1280,7 +1208,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
|
|||
flag_t *f;
|
||||
int isunarmed = B_FALSE;
|
||||
cell_t *obloc = NULL;
|
||||
char wepname[BUFLEN];
|
||||
char wepname[BUFLEN],buf[BUFLEN];
|
||||
int i;
|
||||
//int aidb = B_TRUE;
|
||||
int maxhp;
|
||||
|
@ -1329,6 +1257,10 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
|
|||
|
||||
for (i = 0; i < ndam; i++) {
|
||||
// announce the hit
|
||||
|
||||
construct_hit_string(lf, NULL, attackername, obname, NULL, wep, damtype[i], dam[i], maxhp, i, B_FALSE, B_FALSE, B_FALSE, isunarmed, buf);
|
||||
|
||||
/*
|
||||
if (isplayer(lf)) {
|
||||
char extradambuf[BUFLEN];
|
||||
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
|
||||
|
@ -1351,6 +1283,13 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
|
|||
} else {
|
||||
noise(lf->cell, NULL, NC_OTHER, 3, "sounds of fighting.", NULL);
|
||||
}
|
||||
*/
|
||||
if (strlen(buf)) {
|
||||
msg("%s", buf);
|
||||
}
|
||||
if (!isplayer(lf) && !cansee(player, lf)) {
|
||||
noise(lf->cell, lf, NC_OTHER, 3, "sounds of fighting.", NULL);
|
||||
}
|
||||
|
||||
if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(o->flags, F_HARDNESS)) {
|
||||
object_t *gloves;
|
||||
|
@ -1380,7 +1319,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
|
|||
// object loses hp
|
||||
takedamage(o, dam[i], damtype[i]);
|
||||
if (isplayer(lf) && hasflag(o->flags, F_LOCKED)) {
|
||||
angergodmaybe(R_GODTHIEVES, 25);
|
||||
angergodmaybe(R_GODTHIEVES, 25, GA_MONEY);
|
||||
}
|
||||
|
||||
} // end foreach damtype
|
||||
|
@ -1621,165 +1560,6 @@ void getarrange(int arating, int *min, int *max) {
|
|||
*max = pctof(60, arating);
|
||||
}
|
||||
|
||||
// returns a const char *
|
||||
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
enum LFSIZE ownersize = SZ_HUMAN;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
|
||||
if (lf) {
|
||||
ownersize = getlfsize(lf);
|
||||
}
|
||||
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
|
||||
if (wep) {
|
||||
int i;
|
||||
flag_t *f;
|
||||
getflags(wep->flags, retflag, &nretflags, F_ATTACKVERB, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
if ((f->val[0] == NA) && (f->val[1] == NA)) {
|
||||
return f->text;
|
||||
} else if (f->val[0]) {
|
||||
if (pct >= f->val[0]) {
|
||||
if (f->val[1] == NA) {
|
||||
return f->text;
|
||||
} else if (pct <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
} else if (f->val[1]) {
|
||||
if (pct <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (damtype == DT_ACID) {
|
||||
return "burn";
|
||||
} else if (damtype == DT_BASH) {
|
||||
if (pct <= 5) {
|
||||
return "whack";
|
||||
} else if (pct <= 15) {
|
||||
if (onein(2)) {
|
||||
return "hit";
|
||||
} else {
|
||||
return "bash";
|
||||
}
|
||||
} else if (pct <= 25) {
|
||||
return "pummel";
|
||||
} else if (pct <= 35) {
|
||||
return "slam";
|
||||
} else {
|
||||
return "clobber";
|
||||
}
|
||||
} else if (damtype == DT_BITE) {
|
||||
if (lf && (ownersize <= SZ_SMALL)) {
|
||||
if (pct <= 5) {
|
||||
return "nip";
|
||||
} else {
|
||||
return "bite";
|
||||
}
|
||||
} else {
|
||||
if (pct <= 5) {
|
||||
return "gnaw";
|
||||
} else if (pct <= 30) {
|
||||
return "bite";
|
||||
} else {
|
||||
return "savage";
|
||||
}
|
||||
}
|
||||
} else if (damtype == DT_CHOP) {
|
||||
if (pct <= 5) {
|
||||
return "hit";
|
||||
} else if (pct <= 15) {
|
||||
return "hack";
|
||||
} else {
|
||||
return "chop";
|
||||
}
|
||||
} else if (damtype == DT_COLD) {
|
||||
if (pct <= 10) {
|
||||
return "chill";
|
||||
} else {
|
||||
return "freeze";
|
||||
}
|
||||
} else if (damtype == DT_CRUSH) {
|
||||
return "crush";
|
||||
} else if (damtype == DT_ELECTRIC) {
|
||||
if (pct <= 5) {
|
||||
return "zap";
|
||||
} else if (pct <= 15) {
|
||||
return "jolt";
|
||||
} else if (pct <= 20) {
|
||||
return "shock";
|
||||
} else if (pct <= 30) {
|
||||
return "electrify";
|
||||
} else {
|
||||
return "electrocute";
|
||||
}
|
||||
} else if ((damtype == DT_FIRE) || (damtype == DT_HEAT)) {
|
||||
if (pct <= 5) {
|
||||
return "scorch";
|
||||
} else if (pct <= 20) {
|
||||
return "burn";
|
||||
} else if (pct <= 40) {
|
||||
return "scald";
|
||||
} else {
|
||||
return "incinerate";
|
||||
}
|
||||
} else if (damtype == DT_HOLY) {
|
||||
switch (rnd(1,3)) {
|
||||
case 1:
|
||||
return "smite";
|
||||
case 2:
|
||||
return "cleanse";
|
||||
case 3:
|
||||
return "purify";
|
||||
}
|
||||
} else if (damtype == DT_PIERCE) {
|
||||
if (pct <= 5) {
|
||||
return "poke";
|
||||
} else if (pct <= 15) {
|
||||
return "stab";
|
||||
} else if (pct <= 30) {
|
||||
return "pierce";
|
||||
} else if (pct <= 40) {
|
||||
return "spear";
|
||||
} else {
|
||||
return "deeply stab";
|
||||
}
|
||||
} else if (damtype == DT_POISONGAS) {
|
||||
return "poison";
|
||||
} else if (damtype == DT_PROJECTILE) {
|
||||
return "hit";
|
||||
} else if (damtype == DT_SLASH) {
|
||||
if (pct <= 5) {
|
||||
return "scratch";
|
||||
} else if (pct <= 15) {
|
||||
return "hit";
|
||||
} else if (pct <= 30) {
|
||||
return "slash";
|
||||
} else {
|
||||
return "slice";
|
||||
}
|
||||
} else if (damtype == DT_TOUCH) {
|
||||
return "touch";
|
||||
} else if (damtype == DT_WATER) {
|
||||
// for when water-vulnerable things go into water
|
||||
return "hurt";
|
||||
} else if (damtype == DT_UNARMED) {
|
||||
if (onein(2)) {
|
||||
return "punch";
|
||||
} else {
|
||||
return "hit";
|
||||
}
|
||||
}
|
||||
return "hit";
|
||||
}
|
||||
|
||||
/*
|
||||
object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag) {
|
||||
object_t *wep;
|
||||
|
@ -1867,6 +1647,22 @@ int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) {
|
|||
int i;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
lifeform_t *owner;
|
||||
owner = wep->pile->owner;
|
||||
|
||||
if (owner && owner->mp) {
|
||||
f = hasflag(wep->flags, F_ENCHANTED);
|
||||
if (f) {
|
||||
if (strlen(f->text)) {
|
||||
*(dam + *ndam) = roll(f->text);
|
||||
} else {
|
||||
*(dam + *ndam) = roll("1d2"); // default: 1d2 extra damage
|
||||
}
|
||||
*(damtype + *ndam) = DT_MAGIC;
|
||||
(*ndam)++;
|
||||
}
|
||||
}
|
||||
|
||||
getflags(wep->flags, retflag, &nretflags, F_FROZEN, F_ONFIRE, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
|
@ -1887,97 +1683,6 @@ int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) {
|
|||
return *dam;
|
||||
}
|
||||
|
||||
char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
|
||||
if (wep && hasflag(wep->flags, F_MERCIFUL)) {
|
||||
return "knock out";
|
||||
}
|
||||
|
||||
if (victim->race->id == R_DANCINGWEAPON) {
|
||||
return "defeat";
|
||||
}
|
||||
|
||||
if (getraceclass(victim) == RC_PLANT) {
|
||||
return "destroy";
|
||||
}
|
||||
|
||||
if (wep) {
|
||||
flag_t *f;
|
||||
int i;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
getflags(wep->flags, retflag, &nretflags, F_KILLVERB, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
if (f->id == F_KILLVERB) {
|
||||
if ((f->val[0] == NA) && (f->val[1] == NA)) {
|
||||
return f->text;
|
||||
} else if (f->val[0]) {
|
||||
if (pct >= f->val[0]) {
|
||||
if (f->val[1] == NA) {
|
||||
return f->text;
|
||||
} else if (pct <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
} else if (f->val[1]) {
|
||||
if (pct <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((damtype == DT_BASH) && ismadeofice(victim)) {
|
||||
return "shatter";
|
||||
}
|
||||
|
||||
if (damtype == DT_CRUSH) {
|
||||
return "crush";
|
||||
}
|
||||
|
||||
if (damtype == DT_HOLY) {
|
||||
return "smite";
|
||||
}
|
||||
|
||||
if (pct >= 70) {
|
||||
if (damtype == DT_PIERCE) return "impale";
|
||||
if (damtype == DT_BASH) {
|
||||
if (isunconscious(victim)) {
|
||||
return "kill";
|
||||
} else {
|
||||
return "flatten";
|
||||
}
|
||||
}
|
||||
if (damtype == DT_BITE) return "gore";
|
||||
if (damtype == DT_SLASH) {
|
||||
if (lfhasflagval(victim, F_NOBODYPART, BP_HEAD, NA, NA, NULL)) {
|
||||
return "bisect";
|
||||
} else {
|
||||
if ((getlfsize(victim) >= SZ_MEDIUM) && onein(3)) {
|
||||
return "behead";
|
||||
} else {
|
||||
return "bisect";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getraceclass(victim) == RC_UNDEAD) {
|
||||
// can't "kill" the undead
|
||||
return "destroy";
|
||||
}
|
||||
|
||||
// never use 'kill' for bashing since you might just knock them out
|
||||
if (damtype == DT_BASH) {
|
||||
return "clobber";
|
||||
}
|
||||
return "kill";
|
||||
}
|
||||
|
||||
void getdamrange(flag_t *f, int *min, int *max) {
|
||||
int mindam,maxdam;
|
||||
|
||||
|
|
2
attack.h
2
attack.h
|
@ -12,12 +12,10 @@ int damtypecausesbleed(enum DAMTYPE dt);
|
|||
int damtypecausescriteffects(enum DAMTYPE dt);
|
||||
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype);
|
||||
void getarrange(int arating, int *min, int *max);
|
||||
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
|
||||
//object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag);
|
||||
enum DAMTYPE getdamtype(object_t *wep);
|
||||
int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam);
|
||||
int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam);
|
||||
char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
|
||||
void getdamrange(flag_t *f, int *min, int *max);
|
||||
//void getdamrangeunarmed(flag_t *f, int *min, int *max);
|
||||
//float getdamreducepct(float armourrating);
|
||||
|
|
14
data.c
14
data.c
|
@ -621,7 +621,7 @@ void initjobs(void) {
|
|||
addflag(lastjob->flags, F_JOBATTRMOD, A_IQ, 4, NA, NULL);
|
||||
addflag(lastjob->flags, F_JOBATTRMOD, A_CON, -3, NA, NULL);
|
||||
// initial objects
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "wizard staff");
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "enchanted wizard staff");
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "wizard hat");
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "robe");
|
||||
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "2 potions of magic");
|
||||
|
@ -662,7 +662,7 @@ void initjobs(void) {
|
|||
addflag(lastjob->flags, F_LEVFLAG, 3, F_DETECTMAGIC, B_TRUE, NULL);
|
||||
addflag(lastjob->flags, F_LEVFLAG, 7, F_DETECTAURAS, B_TRUE, NULL);
|
||||
addflag(lastjob->flags, F_LEVFLAG, 10, F_CONTROL, B_TRUE, NULL);
|
||||
addflag(lastjob->flags, F_LEVSPELLSCHOOL, 101, SS_NONE, B_TRUE, NULL); // new spell every 1 level
|
||||
//addflag(lastjob->flags, F_LEVSPELLSCHOOL, 101, SS_NONE, B_TRUE, NULL); // new spell every 1 level
|
||||
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
|
||||
// monster job flags
|
||||
f = addflag(lastjob->flags, F_CANCAST, OT_S_FIREDART, NA, NA, NULL); addcondition(f, FC_IFMONSTER, 50);
|
||||
|
@ -775,6 +775,8 @@ void initobjects(void) {
|
|||
// object modifiers - flags can be either known or not, depending on if it's obvious
|
||||
addobmod(OM_BLOODSTAINED,"bloodstained");
|
||||
addflag_real(lastobmod->flags, F_SCARY, 2, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
||||
addobmod(OM_ENCHANTED, "enchanted");
|
||||
addflag_real(lastobmod->flags, F_ENCHANTED, NA, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
||||
addobmod(OM_FLAMING,"flaming");
|
||||
addflag_real(lastobmod->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
||||
addobmod(OM_FROZEN,"frozen");
|
||||
|
@ -1799,7 +1801,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEBURST, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
|
||||
|
||||
addot(OT_SCR_ENCHANT, "scroll of enchantment", "Magically enhances a weapon or piece of armour.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
|
||||
addot(OT_SCR_ENCHANT, "scroll of enhancement", "Magically enhances a weapon or piece of armour.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
|
||||
addflag(lastot->flags, F_LINKSPELL, OT_S_ENCHANT, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
|
||||
|
||||
|
@ -1891,7 +1893,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
||||
|
||||
///////////////////
|
||||
// death
|
||||
// death / ncromancy
|
||||
///////////////////
|
||||
// l1
|
||||
addot(OT_S_STENCH, "stench", "Nauseates the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
|
@ -2083,7 +2085,7 @@ void initobjects(void) {
|
|||
// enchantment
|
||||
///////////////////
|
||||
// l7
|
||||
addot(OT_S_ENCHANT, "enchantment", "Magically enhances a weapon or piece of armour.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addot(OT_S_ENCHANT, "enhancement", "Magically enhances a weapon or piece of armour.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
|
||||
|
@ -3178,7 +3180,7 @@ void initobjects(void) {
|
|||
// books
|
||||
addot(OT_MANUAL, "manual", "Teaches you one level of its subject matter.", MT_PAPER, 1.5, OC_BOOK, SZ_SMALL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
|
||||
addot(OT_SPELLBOOK, "spellbook", "Teaches you the spell contained within.", MT_PAPER, 1.5, OC_BOOK, SZ_SMALL);
|
||||
addot(OT_SPELLBOOK, "spellbook", "Teaches you the spells contained within.", MT_PAPER, 1.5, OC_BOOK, SZ_SMALL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
|
||||
|
||||
// wands
|
||||
|
|
21
defs.h
21
defs.h
|
@ -379,6 +379,21 @@ enum DRAINTYPE {
|
|||
DR_FROMWEP
|
||||
};
|
||||
|
||||
enum GODANGERREASON {
|
||||
GA_ATTACKALLY,
|
||||
GA_ATTACKHELPLESS, // attacked someone who was sleeping etc
|
||||
GA_ATTACKOBJECT, // attacked or broke an object
|
||||
GA_ASSAULT, // attacked someone peaceful
|
||||
GA_EAT, // ate something the god doesn't like
|
||||
GA_HERESY, // blessed or cursed an object
|
||||
GA_MERCY, // allowed something to flee
|
||||
GA_MONEY, // paid money to someone
|
||||
GA_MURDER, // killed someone peaceful
|
||||
GA_POISON, // used poison
|
||||
GA_PRAY, // pestering through constant prayer
|
||||
GA_SPELL, // cast a spell from the wrong school
|
||||
};
|
||||
|
||||
enum NOISECLASS {
|
||||
NC_NONE = 0,
|
||||
NC_MOVEMENT = 1,
|
||||
|
@ -502,6 +517,7 @@ enum GAMEMODE {
|
|||
GM_VALIDATION,
|
||||
GM_LOADING,
|
||||
GM_LOADED,
|
||||
GM_CHARGEN,
|
||||
GM_GAMESTARTED,
|
||||
GM_GAMEOVER,
|
||||
};
|
||||
|
@ -1971,6 +1987,7 @@ enum FLAG {
|
|||
// object mods/effects
|
||||
F_ONFIRE, // burning, also deals extra fire damage
|
||||
// option text = xdx amount of damage.
|
||||
F_ENCHANTED, // weapon also deals 'text' extra fire damage
|
||||
F_HEADLESS, // for corpses. can go on LFs too.
|
||||
F_MASTERWORK, // weps do higher damager, armour protects better
|
||||
F_SHODDY, // weps do less damage, armour protects less.
|
||||
|
@ -2044,7 +2061,8 @@ enum FLAG {
|
|||
F_LINKSPELL, // val0 = spell this scroll will cast when read
|
||||
// v1 = spell power
|
||||
// book flags
|
||||
F_MANUALOF, // val0 = spellschool this book trains
|
||||
F_MANUALOF, // val0 = skill this book trains
|
||||
F_LINKSCHOOL, // val0 = spellschool this book has spells from
|
||||
// ob identification flags
|
||||
F_HASHIDDENNAME, // whether this object class has a hidden name
|
||||
// text is the name if you don't know what it is
|
||||
|
@ -3263,6 +3281,7 @@ enum RUSTINESS {
|
|||
|
||||
enum OBMOD {
|
||||
OM_BLOODSTAINED,
|
||||
OM_ENCHANTED,
|
||||
OM_FLAMING,
|
||||
OM_FROZEN,
|
||||
OM_HEADLESS,
|
||||
|
|
40
god.c
40
god.c
|
@ -30,7 +30,7 @@ extern lifeform_t *player;
|
|||
lifeform_t *godlf[MAXGODS];
|
||||
int ngodlfs = 0;
|
||||
|
||||
void angergod(enum RACE rid, int amt) {
|
||||
void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
|
||||
lifeform_t *god;
|
||||
char lfname[BUFLEN];
|
||||
int piety;
|
||||
|
@ -48,6 +48,36 @@ void angergod(enum RACE rid, int amt) {
|
|||
|
||||
// if you HAVE prayed to this god before, something bad will probably happen.
|
||||
|
||||
switch (why) {
|
||||
case GA_ATTACKALLY:
|
||||
godsay(rid, "How dare you attack an ally!"); break;
|
||||
case GA_ATTACKHELPLESS:
|
||||
godsay(rid, "You would attack one who is helpless?"); break;
|
||||
case GA_ATTACKOBJECT:
|
||||
if (rid == R_GODTHIEVES) {
|
||||
godsay(rid, "What are you, a common thug?"); break;
|
||||
} else {
|
||||
godsay(rid, "You dare destroy my symbols?"); break;
|
||||
}
|
||||
case GA_ASSAULT:
|
||||
godsay(rid, "You dare attack one of my innocent servants?"); break;
|
||||
case GA_EAT:
|
||||
godsay(rid, "That is NOT acceptable for consumption!"); break;
|
||||
case GA_HERESY:
|
||||
godsay(rid, "Heresy!"); break;
|
||||
case GA_MERCY:
|
||||
godsay(rid, "You allowed your foe to escape!"); break;
|
||||
case GA_MONEY:
|
||||
godsay(rid, "Giving away money offends me..."); break;
|
||||
case GA_MURDER:
|
||||
godsay(rid, "You have taken a life!"); break;
|
||||
case GA_PRAY: break;
|
||||
case GA_POISON:
|
||||
godsay(rid, "I do not condone the use of poison!"); break;
|
||||
case GA_SPELL:
|
||||
godsay(rid, "Your magic offends me!"); break;
|
||||
}
|
||||
|
||||
// announce
|
||||
if (piety > 0) { // not angry yet.
|
||||
godsay(rid, "You are testing my patience, mortal!");
|
||||
|
@ -243,11 +273,11 @@ void angergod(enum RACE rid, int amt) {
|
|||
}
|
||||
|
||||
// anger the god if you are worshippin them.
|
||||
void angergodmaybe(enum RACE rid, int amt) {
|
||||
void angergodmaybe(enum RACE rid, int amt, enum GODANGERREASON why) {
|
||||
lifeform_t *god;
|
||||
god = findgod(rid);
|
||||
if (lfhasflag(god, F_PRAYEDTO)) {
|
||||
angergod(rid, amt);
|
||||
angergod(rid, amt, why);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,7 +784,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
|
||||
if (godisangry(god->race->id)) {
|
||||
// get even more angry
|
||||
angergod(god->race->id, PIETYPRAYLOSS);
|
||||
angergod(god->race->id, PIETYPRAYLOSS, GA_PRAY);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -781,7 +811,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
|
|||
if (piety <= 99) {
|
||||
// piety between 0 and 99 = ignored
|
||||
//godsay(god->race->id, "Stop pestering me!");
|
||||
angergod(god->race->id, 0);
|
||||
angergod(god->race->id, 0, GA_PRAY);
|
||||
modpiety(god->race->id, -30);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
|
4
god.h
4
god.h
|
@ -1,7 +1,7 @@
|
|||
#include "defs.h"
|
||||
|
||||
void angergod(enum RACE rid, int amt);
|
||||
void angergodmaybe(enum RACE rid, int amt);
|
||||
void angergod(enum RACE rid, int amt, enum GODANGERREASON why);
|
||||
void angergodmaybe(enum RACE rid, int amt, enum GODANGERREASON why);
|
||||
void dooffer(void);
|
||||
lifeform_t *findgod(enum RACE rid);
|
||||
int getpiety(enum RACE rid);
|
||||
|
|
49
io.c
49
io.c
|
@ -4591,11 +4591,17 @@ char *makedesc_ob(object_t *o, char *retbuf) {
|
|||
// other extra damage or effects?
|
||||
f = hasflag(o->flags, F_ONFIRE);
|
||||
if (f) {
|
||||
if (f->text) {
|
||||
sprintf(buf," It also inflicts %s extra burning damage.\n", f->text);
|
||||
} else {
|
||||
sprintf(buf," It also inflicts extra burning damage.\n");
|
||||
}
|
||||
sprintf(buf," It also inflicts %s extra burning damage.\n", strlen(f->text) ? f->text : "2-12");
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
f = hasflag(o->flags, F_FROZEN);
|
||||
if (f) {
|
||||
sprintf(buf," It also inflicts %s extra cold damage.\n", strlen(f->text) ? f->text : "1-4");
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
f = hasflag(o->flags, F_ENCHANTED);
|
||||
if (f) {
|
||||
sprintf(buf," It also inflicts %s extra magical damage if the user has spare mana.\n", strlen(f->text) ? f->text : "1-2");
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
} else {
|
||||
|
@ -5379,15 +5385,32 @@ char *makedesc_ob(object_t *o, char *retbuf) {
|
|||
|
||||
if (o->contents->first) {
|
||||
object_t *oo;
|
||||
int showcontents = B_TRUE;
|
||||
|
||||
sprintf(buf, "\n%s currently contain%s:\n", (o->amt == 1) ? "It" : "They", (o->amt == 1) ? "s" : "");
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
|
||||
for (oo = o->contents->first ;oo ; oo = oo->next) {
|
||||
char contentname[BUFLEN];
|
||||
getobname(oo, contentname, oo->amt);
|
||||
sprintf(buf, " - %s\n", contentname);
|
||||
if ((o->type->id == OT_SPELLBOOK) && !isknown(o)) {
|
||||
showcontents = B_FALSE;
|
||||
}
|
||||
|
||||
if (showcontents) {
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
sprintf(buf, "\n%s contain%s the following spells:\n", (o->amt == 1) ? "It" : "They", (o->amt == 1) ? "s" : "");
|
||||
} else {
|
||||
sprintf(buf, "\n%s currently contain%s:\n", (o->amt == 1) ? "It" : "They", (o->amt == 1) ? "s" : "");
|
||||
}
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
|
||||
for (oo = o->contents->first ;oo ; oo = oo->next) {
|
||||
char contentname[BUFLEN];
|
||||
getobname(oo, contentname, oo->amt);
|
||||
sprintf(buf, " - %s", contentname);
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
char lbuf[BUFLEN];
|
||||
sprintf(lbuf, " (Lv %d)", getspelllevel(oo->type->id));
|
||||
strcat(buf, lbuf);
|
||||
}
|
||||
strcat(buf, "\n");
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7379,7 +7402,7 @@ int getkey(int escseqok) {
|
|||
|
||||
if (key_code == CH_BREAK) { // ctrl-c
|
||||
cbreak();
|
||||
raise(SIGINT);
|
||||
raise(SIGINT); // break to debugger
|
||||
raw();
|
||||
}
|
||||
|
||||
|
|
14
lf.c
14
lf.c
|
@ -1502,11 +1502,11 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
switch (school) {
|
||||
case SS_DEATH:
|
||||
pleasegodmaybe(R_GODDEATH, getspelllevel(sid));
|
||||
angergodmaybe(R_GODPURITY, getspelllevel(sid)*5);
|
||||
angergodmaybe(R_GODPURITY, getspelllevel(sid)*5, GA_SPELL);
|
||||
break;
|
||||
case SS_LIFE:
|
||||
pleasegodmaybe(R_GODPURITY, getspelllevel(sid));
|
||||
angergodmaybe(R_GODDEATH, getspelllevel(sid)*5);
|
||||
angergodmaybe(R_GODDEATH, getspelllevel(sid)*5, GA_SPELL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2110,7 +2110,7 @@ void die(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
// mercy god doesn't like killing
|
||||
angergodmaybe(R_GODMERCY, 1);
|
||||
angergodmaybe(R_GODMERCY, 1, GA_MURDER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2936,7 +2936,7 @@ int eat(lifeform_t *lf, object_t *o) {
|
|||
|
||||
// eating your pet is very bad!
|
||||
if (isplayer(lf) && hasflagval(o->flags, F_PETOF, player->id, NA, NA, NULL)) {
|
||||
angergodmaybe(R_GODPURITY, 150);
|
||||
angergodmaybe(R_GODPURITY, 150, GA_EAT);
|
||||
stopeating = B_TRUE;
|
||||
}
|
||||
|
||||
|
@ -3776,7 +3776,7 @@ int flee(lifeform_t *lf) {
|
|||
// player let something flee?
|
||||
if (isplayer(thisone)) {
|
||||
pleasegodmaybe(R_GODMERCY, 5);
|
||||
angergodmaybe(R_GODDEATH, 25);
|
||||
angergodmaybe(R_GODDEATH, 25, GA_MERCY);
|
||||
}
|
||||
killflag(f);
|
||||
} else {
|
||||
|
@ -10979,7 +10979,7 @@ int makenauseated(lifeform_t *lf, int amt, int howlong) {
|
|||
|
||||
if (!hasbp(lf, BP_HEAD)) return B_TRUE; // can't smell with no head
|
||||
|
||||
if (!lfhasflag(lf, F_HUMANOID)) return B_TRUE;
|
||||
//if (!lfhasflag(lf, F_HUMANOID)) return B_TRUE;
|
||||
|
||||
f = lfhasflag(lf, F_NAUSEATED);
|
||||
if (f) {
|
||||
|
@ -13581,7 +13581,7 @@ void startlfturn(lifeform_t *lf) {
|
|||
int angeramt;
|
||||
angeramt = f->val[0];
|
||||
limit(&angeramt, 25, NA);
|
||||
angergodmaybe(R_GODTHIEVES, angeramt);
|
||||
angergodmaybe(R_GODTHIEVES, angeramt, GA_MONEY);
|
||||
killflag(f);
|
||||
}
|
||||
}
|
||||
|
|
2
map.c
2
map.c
|
@ -1,6 +1,7 @@
|
|||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -5157,6 +5158,7 @@ int linkstairs(object_t *o, object_t *o2) {
|
|||
msg("ERROR - stairs link to existing map %d('%s', depth %d), but it has no free stairs.",othermap->id,
|
||||
othermap->name, othermap->depth);
|
||||
more();
|
||||
raise(SIGINT); // debug
|
||||
}
|
||||
} // end if othermap
|
||||
} // end if !o2
|
||||
|
|
2
move.c
2
move.c
|
@ -2718,7 +2718,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
|
|||
|
||||
// purposely moving away fmor money?
|
||||
if (onpurpose && isplayer(lf) && srcmoney) {
|
||||
angergodmaybe(R_GODTHIEVES, srcmoney);
|
||||
angergodmaybe(R_GODTHIEVES, srcmoney, GA_MONEY);
|
||||
}
|
||||
|
||||
if (reason != E_OK) {
|
||||
|
|
16
nexus.c
16
nexus.c
|
@ -198,6 +198,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (!startrace) {
|
||||
race_t *r;
|
||||
gamemode = GM_CHARGEN;
|
||||
// ask for race
|
||||
initprompt(&prompt, "Select your race:");
|
||||
ch = 'a';
|
||||
|
@ -288,6 +289,7 @@ int main(int argc, char **argv) {
|
|||
addchoice(&prompt, 'a', getskillname(SK_SS_AIR), NULL, findskill(SK_SS_AIR), NULL);
|
||||
addchoice(&prompt, 'c', getskillname(SK_SS_COLD), NULL, findskill(SK_SS_COLD), NULL);
|
||||
addchoice(&prompt, 'f', getskillname(SK_SS_FIRE), NULL, findskill(SK_SS_FIRE), NULL);
|
||||
addchoice(&prompt, 'n', getskillname(SK_SS_DEATH), NULL, findskill(SK_SS_DEATH), NULL);
|
||||
addchoice(&prompt, 'w', getskillname(SK_SS_WILD), NULL, findskill(SK_SS_WILD), NULL);
|
||||
getchoice(&prompt);
|
||||
sk = (skill_t *) prompt.result;
|
||||
|
@ -296,19 +298,28 @@ int main(int argc, char **argv) {
|
|||
case SK_SS_AIR:
|
||||
addflag(player->flags, F_CANCAST, OT_S_MIST, NA, NA, NULL);
|
||||
addflag(player->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of air magic");
|
||||
break;
|
||||
case SK_SS_COLD:
|
||||
addflag(player->flags, F_CANCAST, OT_S_CHILL, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of cold magic");
|
||||
break;
|
||||
case SK_SS_FIRE:
|
||||
addflag(player->flags, F_CANCAST, OT_S_SPARK, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of fire magic");
|
||||
break;
|
||||
case SK_SS_DEATH:
|
||||
addflag(player->flags, F_CANCAST, OT_S_STENCH, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of necromancy");
|
||||
break;
|
||||
case SK_SS_WILD:
|
||||
addflag(player->flags, F_CANCAST, OT_S_MANASPIKE, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of wild magic");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
initprompt(&prompt, "Select your secondary spell school:");
|
||||
addchoice(&prompt, 'd', getskillname(SK_SS_DIVINATION), NULL, findskill(SK_SS_DIVINATION), NULL);
|
||||
addchoice(&prompt, 'g', getskillname(SK_SS_GRAVITY), NULL, findskill(SK_SS_GRAVITY), NULL);
|
||||
|
@ -321,18 +332,23 @@ int main(int argc, char **argv) {
|
|||
switch (sk->id) {
|
||||
case SK_SS_DIVINATION:
|
||||
addflag(player->flags, F_CANCAST, OT_S_SIXTHSENSE, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of divination magic");
|
||||
break;
|
||||
case SK_SS_GRAVITY:
|
||||
addflag(player->flags, F_CANCAST, OT_S_TRUESTRIKE, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of gravitation magic");
|
||||
break;
|
||||
case SK_SS_MODIFICATION:
|
||||
addflag(player->flags, F_CANCAST, OT_S_HOLDPORTAL, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of modification magic");
|
||||
break;
|
||||
case SK_SS_SUMMONING:
|
||||
addflag(player->flags, F_CANCAST, OT_S_FLOATINGDISC, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of summoning magic");
|
||||
break;
|
||||
case SK_SS_TRANSLOCATION:
|
||||
addflag(player->flags, F_CANCAST, OT_S_APPORTATION, NA, NA, NULL);
|
||||
addob(player->pack, "spellbook of translocation magic");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
185
objects.c
185
objects.c
|
@ -434,7 +434,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
int bonus = 0;
|
||||
int nom = 0;
|
||||
int n;
|
||||
int bookcontents = -1;
|
||||
int bookcontents = -1;// a skill for manuals, or a spellschool id for spellbooks
|
||||
enum DEPTH wantdepth = DP_MAX;
|
||||
int wantlit = B_FALSE;
|
||||
int wantrarity = RR_NONE;
|
||||
|
@ -778,10 +778,10 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
char *pp;
|
||||
pp = p + 13;
|
||||
if (*pp) {
|
||||
objecttype_t *spelltype = NULL;
|
||||
spelltype = findspelln(pp);
|
||||
if (spelltype) {
|
||||
bookcontents = spelltype->id;
|
||||
enum SPELLSCHOOL school;
|
||||
school = findspellschoolbyname(pp);
|
||||
if (school != SS_NONE) {
|
||||
bookcontents = school;
|
||||
}
|
||||
}
|
||||
ot = findot(OT_SPELLBOOK);
|
||||
|
@ -892,9 +892,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
}
|
||||
|
||||
if (ot->obclass->id == OC_SPELL) {
|
||||
if (db) dblog("DB: Cannot give a spell object! object name '%s'", p );
|
||||
nretobs = 0;
|
||||
return NULL;
|
||||
if (where->owner || where->where) {
|
||||
if (db) dblog("DB: Cannot give a spell object to a player, or a cell! object name '%s'", ot->name );
|
||||
nretobs = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// override canstack if required
|
||||
|
@ -1173,14 +1175,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
int numhiddennames;
|
||||
int n,sel;
|
||||
if (bookcontents == -1) {
|
||||
int maxlev;
|
||||
maxlev = getmapdifficulty(obloc->map) / 3;
|
||||
limit(&maxlev, 1, 9);
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
bookcontents = getrandomspell(maxlev);
|
||||
while (!schoolappearsinbooks(getspellschool(bookcontents))) {
|
||||
bookcontents = getrandomspell(maxlev);
|
||||
}
|
||||
// pick a random school
|
||||
bookcontents = getrandomspellschool();
|
||||
//bookcontents = getrandomspell(maxlev);
|
||||
//while (!schoolappearsinbooks(getspellschool(bookcontents))) {
|
||||
// bookcontents = getrandomspell(maxlev);
|
||||
// }
|
||||
} else { // ie. manual
|
||||
bookcontents = getrandomskill();
|
||||
}
|
||||
|
@ -1188,12 +1189,31 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
|
||||
// link
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
addflag(o->flags, F_LINKSPELL, bookcontents, NA, NA, NULL);
|
||||
int nspells,firstlev;
|
||||
// remember the book's school (used for description)
|
||||
addflag(o->flags, F_LINKSCHOOL, bookcontents, NA, NA, NULL);
|
||||
// add contents to the book
|
||||
if (where->owner) { // giving to a lifeform?
|
||||
nspells = 6;
|
||||
firstlev = 1;
|
||||
} else {
|
||||
nspells = rnd(2,5);
|
||||
firstlev = rnd(1,4);
|
||||
}
|
||||
for (i = 0; i < nspells; i++) {
|
||||
enum OBTYPE oid;
|
||||
int lev;
|
||||
lev = firstlev + i;
|
||||
if (lev > MAXSPELLLEV) break;
|
||||
oid = getrandomspellfromschool(bookcontents,lev);
|
||||
if (oid != OT_NONE) {
|
||||
assert(addobfast(o->contents, oid));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addflag(o->flags, F_MANUALOF, bookcontents, NA, NA, NULL);
|
||||
}
|
||||
|
||||
|
||||
// count hidden names
|
||||
numhiddennames = 0;
|
||||
for (hn = firsthiddenname ; hn ; hn = hn->next) {
|
||||
|
@ -1214,6 +1234,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
}
|
||||
}
|
||||
addflag(o->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, selhn->text);
|
||||
// don't call sethiddenname, because it acts on OBJECT TYPES not OBJECTS.
|
||||
// all books are unique
|
||||
}
|
||||
|
||||
|
||||
|
@ -3731,6 +3753,14 @@ char *gethiddenname(object_t *o) {
|
|||
if (hasflag(o->flags, F_IDENTIFIED)) {
|
||||
return o->type->name;
|
||||
}
|
||||
// otherwise special case for unidentified books...
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_HASHIDDENNAME);
|
||||
if (f) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
// otherwise check if it has a hidden name
|
||||
for (k = knowledge; k ; k = k->next) {
|
||||
if (k->id == o->type->id) {
|
||||
|
@ -3755,6 +3785,16 @@ char *gethiddennameot(enum OBTYPE otid) {
|
|||
knowledge_t *k;
|
||||
objecttype_t *ot;
|
||||
ot = findot(otid);
|
||||
|
||||
// otherwise special case for unidentified books...
|
||||
if (ot->id == OT_SPELLBOOK) {
|
||||
flag_t *f;
|
||||
f = hasflag(ot->flags, F_HASHIDDENNAME);
|
||||
if (f) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
|
||||
for (k = knowledge; k ; k = k->next) {
|
||||
if (k->id == ot->id) {
|
||||
// it DOES have a hidden name.
|
||||
|
@ -4322,14 +4362,12 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
|
|||
}
|
||||
|
||||
if (o->type->obclass->id == OC_BOOK) {
|
||||
if (!strcmp(basename, o->type->name)) {
|
||||
if (streq(basename, o->type->name)) {
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
f = hasflag(o->flags, F_LINKSPELL);
|
||||
f = hasflag(o->flags, F_LINKSCHOOL);
|
||||
if (f) {
|
||||
objecttype_t *st;
|
||||
st = findot(f->val[0]);
|
||||
strcat(basename, " of ");
|
||||
strcat(basename, st->name);
|
||||
strcat(basename, getschoolname(f->val[0]));
|
||||
}
|
||||
} else {
|
||||
f = hasflag(o->flags, F_MANUALOF);
|
||||
|
@ -4341,6 +4379,9 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (o->type->obclass->id == OC_SPELL) {
|
||||
strcpy(buf, o->type->name);
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (!showall) {
|
||||
|
@ -5209,17 +5250,16 @@ char *getschoolname(enum SPELLSCHOOL sch) {
|
|||
case SS_COLD: return "Cold Magic";
|
||||
case SS_MODIFICATION: return "Modification Magic";
|
||||
case SS_DEATH: return "Necromancy";
|
||||
case SS_NATURE: return "Nature";
|
||||
case SS_NATURE: return "Enviromancy";
|
||||
case SS_LIFE: return "Life Magic";
|
||||
case SS_DIVINATION: return "Divination Magic";
|
||||
case SS_TRANSLOCATION: return "Translocation Magic";
|
||||
case SS_SUMMONING: return "Summoning Magic";
|
||||
case SS_GRAVITY: return "Gravitation Magic";
|
||||
case SS_LAST: return "!invalid school!";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "unknown school";
|
||||
return "badschool";
|
||||
}
|
||||
|
||||
char *getschoolnameshort(enum SPELLSCHOOL sch) {
|
||||
|
@ -5878,6 +5918,11 @@ int isknown(object_t *o) {
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
// unidentified books are always unknown
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
return isknownot(o->type);
|
||||
}
|
||||
|
||||
|
@ -8181,7 +8226,7 @@ int pour(lifeform_t *lf, object_t *o) {
|
|||
// god effects
|
||||
if (isplayer(lf)) {
|
||||
pleasegodmaybe(R_GODPURITY, 3);
|
||||
angergodmaybe(R_GODDEATH, 15);
|
||||
angergodmaybe(R_GODDEATH, 15, GA_HERESY);
|
||||
}
|
||||
} else if ((o->type->id == OT_POT_WATER) && (o->blessed == B_CURSED)) { // unholy water
|
||||
if (isplayer(lf)) {
|
||||
|
@ -8190,12 +8235,12 @@ int pour(lifeform_t *lf, object_t *o) {
|
|||
o->blessknown = B_TRUE;
|
||||
// curse whatever we poured onto
|
||||
curseob(dst);
|
||||
// we now know that this is holy water
|
||||
// we now know that this is unholy water
|
||||
if (!isknown(o)) makeknown(o->type->id);
|
||||
// god effects
|
||||
if (isplayer(lf)) {
|
||||
pleasegodmaybe(R_GODDEATH, 3);
|
||||
angergodmaybe(R_GODPURITY, 25);
|
||||
angergodmaybe(R_GODPURITY, 25, GA_HERESY);
|
||||
}
|
||||
} else if (o->type->id == OT_POT_INVULN) {
|
||||
flag_t *f;
|
||||
|
@ -8909,6 +8954,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
|
|||
} else {
|
||||
readtime = SPEED_READ;
|
||||
}
|
||||
|
||||
taketime(lf, readtime);
|
||||
|
||||
if (isplayer(lf)) maketried(o->type->id);
|
||||
|
@ -8938,7 +8984,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
|
|||
if (playercansee) {
|
||||
if (o->type->obclass->id == OC_BOOK) {
|
||||
// is this a spellbook?
|
||||
if (linkspell) {
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
// if so, always id it.
|
||||
// note though that we can only actually LEARN
|
||||
// the spell if we are skilled in that school.
|
||||
|
@ -9303,35 +9349,66 @@ int readsomething(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
} else if (o->type->obclass->id == OC_BOOK) {
|
||||
// is this a spellbook?
|
||||
if (linkspell) {
|
||||
// if so, can we read it?
|
||||
if (o->type->id == OT_SPELLBOOK) {
|
||||
object_t *oo;
|
||||
char ch = 'a';
|
||||
enum SPELLSCHOOL school;
|
||||
enum SKILLLEVEL slev;
|
||||
f = hasflag(o->flags, F_LINKSCHOOL);
|
||||
school = f->val[0];
|
||||
slev = getskill(lf, getschoolskill(school));
|
||||
|
||||
if (!slev) {
|
||||
if (isplayer(lf)) msg("You cannot comprehend the contents of this book.");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// we are skilled in the right school. now ask which spell to learn.
|
||||
initprompt(&prompt, "Which spell will you try to learn?");
|
||||
for (oo = o->contents->first ;oo ; oo = oo->next) {
|
||||
if (!hasflagval(lf->flags, F_CANCAST, oo->type->id, NA, NA, NULL)) {
|
||||
char *longdesc;
|
||||
char spellname[BUFLEN];
|
||||
longdesc = malloc(HUGEBUFLEN * sizeof(char));
|
||||
sprintf(spellname, "%s (Lv %d)", oo->type->name, getspelllevel(oo->type->id));
|
||||
makedesc_spell(oo->type, longdesc);
|
||||
addchoice(&prompt, ch++, oo->type->name, NULL, oo->type, longdesc);
|
||||
free(longdesc);
|
||||
}
|
||||
}
|
||||
addchoice(&prompt, '-', "none", NULL, NULL, NULL);
|
||||
if (prompt.nchoices == 1) {
|
||||
msg("You already know all the spells in this book!");
|
||||
return B_FALSE;
|
||||
}
|
||||
prompt.maycancel = B_TRUE;
|
||||
ch = getchoicestr(&prompt, B_FALSE, B_TRUE);
|
||||
if ((ch == '\0') || (ch == '-')) {
|
||||
// not 'cancelled' because we still took time
|
||||
msg("You close the spellbook without reading it.");
|
||||
return B_FALSE;
|
||||
}
|
||||
linkspell = (objecttype_t *) prompt.result;
|
||||
|
||||
|
||||
// too hard?
|
||||
if (getspellpower(lf, linkspell->id) > 0) {
|
||||
if (lfhasflagval(lf, F_CANCAST, linkspell->id, NA, NA, NULL)) {
|
||||
if (isplayer(lf)) msg("You already know how to cast this spell!");
|
||||
} else {
|
||||
enum SPELLSCHOOL school;
|
||||
enum SKILLLEVEL slev;
|
||||
school = getspellschool(linkspell->id);
|
||||
slev = getspellskill(lf, linkspell->id);
|
||||
|
||||
// can we learn this?
|
||||
if (slev) {
|
||||
// try to learn it
|
||||
int difficulty, mod;
|
||||
difficulty = 15 + (getspelllevel(linkspell->id)*3);
|
||||
mod = slev * 2;
|
||||
if (skillcheck(lf, SC_LEARNMAGIC, difficulty, mod)) {
|
||||
// learn it
|
||||
addflag(lf->flags, F_CANCAST, linkspell->id, NA, NA, NULL);
|
||||
} else {
|
||||
msg("^bYou fail to learn %s.",linkspell->name);
|
||||
}
|
||||
// try to learn it
|
||||
int difficulty, mod;
|
||||
difficulty = 15 + (getspelllevel(linkspell->id)*3);
|
||||
mod = slev * 2;
|
||||
if (skillcheck(lf, SC_LEARNMAGIC, difficulty, mod)) {
|
||||
// learn it
|
||||
addflag(lf->flags, F_CANCAST, linkspell->id, NA, NA, NULL);
|
||||
} else {
|
||||
msg("You are not yet skilled in %s.",getschoolnameshort(school));
|
||||
msg("^bYou fail to learn %s.",linkspell->name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isplayer(lf)) msg("You cannot comprehend the contents of this book.");
|
||||
if (isplayer(lf)) msg("This spell is too hard for you to learn right now.");
|
||||
}
|
||||
} else {
|
||||
// manuals
|
||||
|
@ -9518,8 +9595,10 @@ int sethiddenname(objecttype_t *ot, char *text) {
|
|||
int n;
|
||||
int gotcolour = B_FALSE;
|
||||
|
||||
// add knowledge for it
|
||||
addknowledge(ot->id, text, B_UNKNOWN);
|
||||
// add knowledge for it (unless it's a book
|
||||
if (ot->obclass->id != OC_BOOK) {
|
||||
addknowledge(ot->id, text, B_UNKNOWN);
|
||||
}
|
||||
|
||||
// some descriptions confer other effecst too...
|
||||
if (strstr(text, "glowing")) {
|
||||
|
@ -9810,7 +9889,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
|
|||
case OT_POT_HEALINGMIN:
|
||||
case OT_POT_HEALINGMAJ:
|
||||
case OT_POT_AMBROSIA:
|
||||
angergodmaybe(R_GODMERCY, 25);
|
||||
angergodmaybe(R_GODMERCY, 25, GA_ATTACKOBJECT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
44
spell.c
44
spell.c
|
@ -5532,7 +5532,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (!frompot) {
|
||||
pleasegodmaybe(R_GODMERCY, 3);
|
||||
}
|
||||
angergodmaybe(R_GODDEATH, 20);
|
||||
angergodmaybe(R_GODDEATH, 20, GA_HERESY);
|
||||
}
|
||||
// hostile monsters might calm down
|
||||
if (!frompot && donesomething && isplayer(caster) && !isplayer(target) && (getallegiance(target) == AL_HOSTILE)) {
|
||||
|
@ -9195,6 +9195,14 @@ objecttype_t *findspelln(char *buf) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
enum SPELLSCHOOL findspellschoolbyname(char *buf) {
|
||||
enum SPELLSCHOOL ss;
|
||||
for (ss = SS_NONE; ss <= SS_LAST; ss++) {
|
||||
if (!strcasecmp(buf, getschoolname(ss))) return ss;
|
||||
}
|
||||
return SS_NONE;
|
||||
}
|
||||
|
||||
void fizzle(lifeform_t *caster) {
|
||||
if (!caster) return;
|
||||
if (isplayer(caster)) {
|
||||
|
@ -9299,6 +9307,40 @@ enum OBTYPE getrandomspell(int maxlev) {
|
|||
return ot->id;
|
||||
}
|
||||
|
||||
// wantlev = 0 means 'any level'
|
||||
enum OBTYPE getrandomspellfromschool(enum SPELLSCHOOL school, int wantlev) {
|
||||
objecttype_t *ot,*poss[MAXCANDIDATES];
|
||||
int nposs = 0;
|
||||
|
||||
// get list of all spells of this school
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if ((ot->obclass->id == OC_SPELL) && spellisfromschool(ot->id, school)) {
|
||||
if ((wantlev == 0) || (getspelllevel(ot->id) == wantlev)) {
|
||||
poss[nposs++] = ot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nposs <= 0) {
|
||||
return OT_NONE;
|
||||
}
|
||||
ot = poss[rnd(0,nposs-1)];
|
||||
return ot->id;
|
||||
}
|
||||
|
||||
enum SPELLSCHOOL getrandomspellschool(void) {
|
||||
enum SPELLSCHOOL poss[MAXCANDIDATES],ss;
|
||||
int nposs = 0;
|
||||
// count valid schools
|
||||
for (ss = SS_NONE; ss <= SS_LAST; ss++) {
|
||||
if (schoolappearsinbooks(ss) && !streq(getschoolname(ss), "badschool")) {
|
||||
poss[nposs++] = ss;
|
||||
}
|
||||
}
|
||||
// make
|
||||
return poss[rnd(0,nposs-1)];
|
||||
}
|
||||
|
||||
enum SKILL getschoolskill(enum SPELLSCHOOL ss) {
|
||||
switch (ss) {
|
||||
case SS_ALLOMANCY:
|
||||
|
|
3
spell.h
3
spell.h
|
@ -5,12 +5,15 @@
|
|||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target, flag_t *cwflag);
|
||||
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer, int frompot);
|
||||
objecttype_t *findspelln(char *buf);
|
||||
enum SPELLSCHOOL findspellschoolbyname(char *buf);
|
||||
void fizzle(lifeform_t *caster);
|
||||
//int getiqreq(enum OBTYPE oid);
|
||||
char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr);
|
||||
int getmpcost(lifeform_t *lf, enum OBTYPE oid);
|
||||
int getmrdiff(enum OBTYPE spellid, int power);
|
||||
enum OBTYPE getrandomspell(int maxlev);
|
||||
enum OBTYPE getrandomspellfromschool(enum SPELLSCHOOL school, int wantlev);
|
||||
enum SPELLSCHOOL getrandomspellschool(void);
|
||||
enum SKILL getschoolskill(enum SPELLSCHOOL ss);
|
||||
char *getspellcosttext(lifeform_t *lf, enum OBTYPE spellid, int power, char *buf);
|
||||
int getspellduration(int min,int max,int blessed);
|
||||
|
|
402
text.c
402
text.c
|
@ -4,7 +4,9 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "attack.h"
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "lf.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
|
@ -12,6 +14,8 @@
|
|||
|
||||
extern long curtime;
|
||||
|
||||
extern lifeform_t *player;
|
||||
|
||||
int needan(char *text) {
|
||||
if (isvowel(tolower(text[0]))) {
|
||||
return B_TRUE;
|
||||
|
@ -78,6 +82,150 @@ enum COLOUR chartocol(char ch) {
|
|||
return C_GREY;
|
||||
}
|
||||
|
||||
char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackername, char *victimname, char *victimbpname, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp, int idx, int backstab, int critical, int fatal, int isunarmed, char *retbuf) {
|
||||
int usecrittext = B_FALSE;
|
||||
char wepname[BUFLEN],buf[BUFLEN];
|
||||
|
||||
getobname(wep, wepname, 1);
|
||||
|
||||
// initial hit...
|
||||
if (idx == 0) {
|
||||
if (critical && !fatal) usecrittext = B_TRUE;
|
||||
|
||||
if (isplayer(lf)) {
|
||||
char extradambuf[BUFLEN];
|
||||
char withwep[BUFLEN];
|
||||
char *verb;
|
||||
int needfree = B_FALSE;
|
||||
|
||||
strcpy(extradambuf, "");
|
||||
|
||||
if (wep && !ismeleeweapon(wep)) {
|
||||
snprintf(withwep, BUFLEN, " with %s", wepname);
|
||||
} else {
|
||||
strcpy(withwep, "");
|
||||
}
|
||||
|
||||
strcpy(extradambuf, "");
|
||||
if (dam == 0) {
|
||||
if (!victim || getlorelevel(lf, victim->race->raceclass->id)) {
|
||||
//strcpy(extradambuf, " but do no damage");
|
||||
strcpy(extradambuf, " ineffectually");
|
||||
}
|
||||
} else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
|
||||
snprintf(extradambuf, BUFLEN, " [%d dmg]",dam);
|
||||
}
|
||||
|
||||
if (backstab && (idx == 0)) {
|
||||
verb = strdup("backstab");
|
||||
needfree = B_TRUE;
|
||||
} else if (fatal) {
|
||||
verb = getkillverb(victim, wep, damtype, dam, maxhp);
|
||||
} else {
|
||||
if (!victim || // atacking an object
|
||||
(getlorelevel(lf, victim->race->raceclass->id) >= PR_BEGINNER) || // know about the race
|
||||
!ismeleedam(damtype)) { // non-physical damage
|
||||
verb = getattackverb(lf, wep, damtype, dam, maxhp);
|
||||
} else {
|
||||
// always use verb for 10%
|
||||
verb = getattackverb(lf, wep, damtype, pctof(10, maxhp), maxhp);
|
||||
}
|
||||
}
|
||||
snprintf(retbuf, BUFLEN, "^%cYou %s%s %s%s%s%s", fatal ? 'g' : 'n',
|
||||
usecrittext ? "critically " : "", verb,
|
||||
usecrittext ? victimbpname : victimname, withwep,extradambuf,
|
||||
(fatal || backstab) ? "!" : ".");
|
||||
|
||||
if (needfree) {
|
||||
free(verb);
|
||||
}
|
||||
} else { // ie. the attacker is a monster
|
||||
if (cansee(player, lf) || (victim && isplayer(victim))) {
|
||||
char withwep[BUFLEN];
|
||||
char attackverb[BUFLEN];
|
||||
char nodamstr[BUFLEN];
|
||||
int nodam = B_FALSE;
|
||||
|
||||
// capitalise first letter
|
||||
strcpy(buf, attackername);
|
||||
capitalise(buf);
|
||||
|
||||
if (wep && !isunarmed && (lf->race->id != R_DANCINGWEAPON) && cansee(player, lf)) {
|
||||
snprintf(withwep, BUFLEN, " with %s", wepname);
|
||||
} else {
|
||||
strcpy(withwep, "");
|
||||
}
|
||||
|
||||
strcpy(attackverb, getattackverb(lf, wep, damtype,dam,maxhp));
|
||||
if ((dam == 0) && (damtype != DT_TOUCH)) {
|
||||
nodam = B_TRUE;
|
||||
strcpy(nodamstr, " ineffectually");
|
||||
} else {
|
||||
strcpy(nodamstr, "");
|
||||
}
|
||||
snprintf(retbuf, BUFLEN, "^%c%s %s%s%s %s%s%s.", (victim && isplayer(victim) && !nodam) ? 'b' : 'n', buf,
|
||||
usecrittext ? "critically " : "", attackverb,
|
||||
needses(attackverb) ? "es" : "s",
|
||||
usecrittext ? victimbpname : victimname,withwep, nodamstr);
|
||||
}
|
||||
}
|
||||
} else { // follow-up weapon damage (ie from a flaming sword etc)
|
||||
if (victim && cansee(player, victim)) {
|
||||
if (dam == 0) { // ineffectual
|
||||
switch (damtype) {
|
||||
case DT_COLD:
|
||||
snprintf(retbuf, BUFLEN, "^n%s %s cold.", victimname, isplayer(victim) ? "don't feel" : "doesn't look");
|
||||
break;
|
||||
case DT_HEAT:
|
||||
case DT_FIRE:
|
||||
snprintf(retbuf, BUFLEN, "^n%s %s hot.", victimname, isplayer(victim) ? "don't feel" : "doesn't look");
|
||||
break;
|
||||
case DT_MAGIC:
|
||||
strcpy(retbuf, "");
|
||||
break;
|
||||
default:
|
||||
snprintf(retbuf, BUFLEN, "^n%s shrug%s off the effects.", victimname, isplayer(victim) ? "" : "s");
|
||||
break;
|
||||
}
|
||||
} else if (fatal) { // fatal
|
||||
switch (damtype) {
|
||||
case DT_COLD:
|
||||
snprintf(retbuf, BUFLEN, "^%c%s %s chilled to the bone", getlfcol(victim, CC_BAD), victimname, is(victim));
|
||||
break;
|
||||
case DT_HEAT:
|
||||
case DT_FIRE:
|
||||
snprintf(retbuf, BUFLEN, "^%c%s %s incinerated!", getlfcol(victim, CC_BAD), victimname, is(victim));
|
||||
break;
|
||||
case DT_MAGIC:
|
||||
snprintf(retbuf, BUFLEN, "^%c%s %s blasted with magic!", getlfcol(victim, CC_BAD), victimname, is(victim));
|
||||
break;
|
||||
default:
|
||||
snprintf(retbuf, BUFLEN, "^%c%s %s killed!", getlfcol(victim, CC_BAD), victimname, is(victim));
|
||||
break;
|
||||
}
|
||||
} else { // normal
|
||||
switch (damtype) {
|
||||
case DT_COLD:
|
||||
snprintf(retbuf, BUFLEN, "^n%s %s chilled!", victimname, is(victim));
|
||||
break;
|
||||
case DT_HEAT:
|
||||
case DT_FIRE:
|
||||
snprintf(retbuf, BUFLEN, "^n%s %s burned!", victimname, is(victim));
|
||||
break;
|
||||
case DT_MAGIC:
|
||||
snprintf(retbuf, BUFLEN, "^nMagical energy sears %s!", victimname);
|
||||
break;
|
||||
default:
|
||||
snprintf(retbuf, BUFLEN, "^n%s %s hurt!", victimname, is(victim));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
capitalise(retbuf);
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf) {
|
||||
int localmin, localmax;
|
||||
|
||||
|
@ -188,6 +336,168 @@ int getaccuracynum(int accpct) {
|
|||
return num;
|
||||
}
|
||||
|
||||
// returns a const char *
|
||||
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
enum LFSIZE ownersize = SZ_HUMAN;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
|
||||
if (lf) {
|
||||
ownersize = getlfsize(lf);
|
||||
}
|
||||
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
|
||||
if (wep) {
|
||||
int i;
|
||||
flag_t *f;
|
||||
getflags(wep->flags, retflag, &nretflags, F_ATTACKVERB, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
if ((f->val[0] == NA) && (f->val[1] == NA)) {
|
||||
return f->text;
|
||||
} else if (f->val[0]) {
|
||||
if (pct >= f->val[0]) {
|
||||
if (f->val[1] == NA) {
|
||||
return f->text;
|
||||
} else if (pct <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
} else if (f->val[1]) {
|
||||
if (pct <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (damtype == DT_ACID) {
|
||||
return "burn";
|
||||
} else if (damtype == DT_BASH) {
|
||||
if (pct <= 5) {
|
||||
return "whack";
|
||||
} else if (pct <= 15) {
|
||||
if (onein(2)) {
|
||||
return "hit";
|
||||
} else {
|
||||
return "bash";
|
||||
}
|
||||
} else if (pct <= 25) {
|
||||
return "pummel";
|
||||
} else if (pct <= 35) {
|
||||
return "slam";
|
||||
} else {
|
||||
return "clobber";
|
||||
}
|
||||
} else if (damtype == DT_BITE) {
|
||||
if (lf && (ownersize <= SZ_SMALL)) {
|
||||
if (pct <= 5) {
|
||||
return "nip";
|
||||
} else {
|
||||
return "bite";
|
||||
}
|
||||
} else {
|
||||
if (pct <= 5) {
|
||||
return "gnaw";
|
||||
} else if (pct <= 30) {
|
||||
return "bite";
|
||||
} else {
|
||||
return "savage";
|
||||
}
|
||||
}
|
||||
} else if (damtype == DT_CHOP) {
|
||||
if (pct <= 5) {
|
||||
return "hit";
|
||||
} else if (pct <= 15) {
|
||||
return "hack";
|
||||
} else {
|
||||
return "chop";
|
||||
}
|
||||
} else if (damtype == DT_COLD) {
|
||||
if (pct <= 10) {
|
||||
return "chill";
|
||||
} else {
|
||||
return "freeze";
|
||||
}
|
||||
} else if (damtype == DT_CRUSH) {
|
||||
return "crush";
|
||||
} else if (damtype == DT_ELECTRIC) {
|
||||
if (pct <= 5) {
|
||||
return "zap";
|
||||
} else if (pct <= 15) {
|
||||
return "jolt";
|
||||
} else if (pct <= 20) {
|
||||
return "shock";
|
||||
} else if (pct <= 30) {
|
||||
return "electrify";
|
||||
} else {
|
||||
return "electrocute";
|
||||
}
|
||||
} else if ((damtype == DT_FIRE) || (damtype == DT_HEAT)) {
|
||||
if (pct <= 5) {
|
||||
return "scorch";
|
||||
} else if (pct <= 20) {
|
||||
return "burn";
|
||||
} else if (pct <= 40) {
|
||||
return "scald";
|
||||
} else {
|
||||
return "incinerate";
|
||||
}
|
||||
} else if (damtype == DT_HOLY) {
|
||||
switch (rnd(1,3)) {
|
||||
case 1:
|
||||
return "smite";
|
||||
case 2:
|
||||
return "cleanse";
|
||||
case 3:
|
||||
return "purify";
|
||||
}
|
||||
} else if (damtype == DT_MAGIC) {
|
||||
return "blast";
|
||||
} else if (damtype == DT_PIERCE) {
|
||||
if (pct <= 5) {
|
||||
return "poke";
|
||||
} else if (pct <= 15) {
|
||||
return "stab";
|
||||
} else if (pct <= 30) {
|
||||
return "pierce";
|
||||
} else if (pct <= 40) {
|
||||
return "spear";
|
||||
} else {
|
||||
return "deeply stab";
|
||||
}
|
||||
} else if (damtype == DT_POISONGAS) {
|
||||
return "poison";
|
||||
} else if (damtype == DT_PROJECTILE) {
|
||||
return "hit";
|
||||
} else if (damtype == DT_SLASH) {
|
||||
if (pct <= 5) {
|
||||
return "scratch";
|
||||
} else if (pct <= 15) {
|
||||
return "hit";
|
||||
} else if (pct <= 30) {
|
||||
return "slash";
|
||||
} else {
|
||||
return "slice";
|
||||
}
|
||||
} else if (damtype == DT_TOUCH) {
|
||||
return "touch";
|
||||
} else if (damtype == DT_WATER) {
|
||||
// for when water-vulnerable things go into water
|
||||
return "hurt";
|
||||
} else if (damtype == DT_UNARMED) {
|
||||
if (onein(2)) {
|
||||
return "punch";
|
||||
} else {
|
||||
return "hit";
|
||||
}
|
||||
}
|
||||
return "hit";
|
||||
}
|
||||
|
||||
|
||||
char *getattrabbrev(enum ATTRIB att) {
|
||||
switch (att) {
|
||||
case A_NONE:
|
||||
|
@ -336,6 +646,98 @@ int gethitconferlifetime(char *text, int *min, int *max) {
|
|||
return howlong;
|
||||
}
|
||||
|
||||
char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
|
||||
if (wep && hasflag(wep->flags, F_MERCIFUL)) {
|
||||
return "knock out";
|
||||
}
|
||||
|
||||
if (victim->race->id == R_DANCINGWEAPON) {
|
||||
return "defeat";
|
||||
}
|
||||
|
||||
if (getraceclass(victim) == RC_PLANT) {
|
||||
return "destroy";
|
||||
}
|
||||
|
||||
if (wep) {
|
||||
flag_t *f;
|
||||
int i;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
getflags(wep->flags, retflag, &nretflags, F_KILLVERB, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
if (f->id == F_KILLVERB) {
|
||||
if ((f->val[0] == NA) && (f->val[1] == NA)) {
|
||||
return f->text;
|
||||
} else if (f->val[0]) {
|
||||
if (pct >= f->val[0]) {
|
||||
if (f->val[1] == NA) {
|
||||
return f->text;
|
||||
} else if (pct <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
} else if (f->val[1]) {
|
||||
if (pct <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((damtype == DT_BASH) && ismadeofice(victim)) {
|
||||
return "shatter";
|
||||
}
|
||||
|
||||
if (damtype == DT_CRUSH) {
|
||||
return "crush";
|
||||
}
|
||||
|
||||
if (damtype == DT_HOLY) {
|
||||
return "smite";
|
||||
}
|
||||
|
||||
if (pct >= 70) {
|
||||
if (damtype == DT_PIERCE) return "impale";
|
||||
if (damtype == DT_BASH) {
|
||||
if (isunconscious(victim)) {
|
||||
return "kill";
|
||||
} else {
|
||||
return "flatten";
|
||||
}
|
||||
}
|
||||
if (damtype == DT_BITE) return "gore";
|
||||
if (damtype == DT_SLASH) {
|
||||
if (lfhasflagval(victim, F_NOBODYPART, BP_HEAD, NA, NA, NULL)) {
|
||||
return "bisect";
|
||||
} else {
|
||||
if ((getlfsize(victim) >= SZ_MEDIUM) && onein(3)) {
|
||||
return "behead";
|
||||
} else {
|
||||
return "bisect";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getraceclass(victim) == RC_UNDEAD) {
|
||||
// can't "kill" the undead
|
||||
return "destroy";
|
||||
}
|
||||
|
||||
// never use 'kill' for bashing since you might just knock them out
|
||||
if (damtype == DT_BASH) {
|
||||
return "clobber";
|
||||
}
|
||||
return "kill";
|
||||
}
|
||||
|
||||
|
||||
char *getpoisondamverb(enum POISONTYPE ptype) {
|
||||
switch (ptype) {
|
||||
case P_FOOD:
|
||||
|
|
3
text.h
3
text.h
|
@ -4,16 +4,19 @@ int needan(char *text);
|
|||
char *capitalise(char *text);
|
||||
char *capitaliseall(char *text);
|
||||
enum COLOUR chartocol(char ch);
|
||||
char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackername, char *victimname, char *victimbpname, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp, int damidx, int critical, int backstab, int fatal, int isunarmed, char *retbuf);
|
||||
char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf);
|
||||
int flip(int ch);
|
||||
char *getaccuracyname(int accpct);
|
||||
int getaccuracymodnum(int accmodpct);
|
||||
int getaccuracynum(int accpct);
|
||||
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
|
||||
char *getattrabbrev(enum ATTRIB att);
|
||||
char *getattrname(enum ATTRIB att);
|
||||
char *getdirname(int dir);
|
||||
char *getdirnameshort(int dir);
|
||||
int gethitconferlifetime(char *text, int *min, int *max);
|
||||
char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
|
||||
char *getpoisondamverb(enum POISONTYPE ptype);
|
||||
char *getpoisondesc(enum POISONTYPE ptype);
|
||||
char *getpoisonname(enum POISONTYPE ptype);
|
||||
|
|
Loading…
Reference in New Issue