/*
* alignment.cpp
* Alignment-related functions
* ____ _
* | _ \ ___ __ _| |_ __ ___ ___
* | |_) / _ \/ _` | | '_ ` _ \/ __|
* | _ < __/ (_| | | | | | | \__ \
* |_| \_\___|\__,_|_|_| |_| |_|___/
*
* Permission to use, modify and distribute is granted via the
* Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License
* http://creativecommons.org/licenses/by-nc-sa/3.0/
*
* Copyright (C) 2007-2012 Jason Mitchell, Randi Mitchell
* Contributions by Tim Callahan, Jonathan Hseu
* Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
*
*/
#include "mud.h"
//***********************************************************************
// getAlignDiff
//***********************************************************************
// This function returns the distance on the alignment scale between
// any two different creatures. If either creature is neutral, or if
// both creatures are of the same moral character (i.e. both good or
// both evil) it will return 0. It is to be used for when opposing
// ethos has an effect on anything.
int getAlignDiff(Creature *crt1, Creature *crt2) {
int alignDiff = 0;
if( (crt1->getAdjustedAlignment() < NEUTRAL && crt2->getAdjustedAlignment() > NEUTRAL) ||
(crt2->getAdjustedAlignment() < NEUTRAL && crt1->getAdjustedAlignment() > NEUTRAL)
) {
alignDiff = abs(crt1->getAdjustedAlignment()) + abs(crt2->getAdjustedAlignment());
}
return(alignDiff);
}
//***********************************************************************
// getAdjustedAlignment
//***********************************************************************
int Monster::getAdjustedAlignment() const {
if(alignment <= -200)
return(BLOODRED);
else if(alignment > -200 && alignment < -50)
return(REDDISH);
else if(alignment >= -50 && alignment < 0)
return(PINKISH);
else if(alignment == 0)
return(NEUTRAL);
else if(alignment > 0 && alignment < 50)
return(LIGHTBLUE);
else if(alignment >= 50 && alignment < 200)
return(BLUISH);
else if(alignment >= 200)
return(ROYALBLUE);
return(NEUTRAL);
}
int Player::getAdjustedAlignment() const {
if(alignment <= -400)
return(BLOODRED);
else if(alignment <= -200 && alignment > -400)
return(REDDISH);
else if(alignment <= -100 && alignment > -200)
return(PINKISH);
else if(alignment > -100 && alignment < 100)
return(NEUTRAL);
else if(alignment >= 100 && alignment < 200)
return(LIGHTBLUE);
else if(alignment >= 200 && alignment < 400)
return(BLUISH);
else if(alignment >= 400)
return(ROYALBLUE);
return(NEUTRAL);
}
//***********************************************************************
// alignColor
//***********************************************************************
bstring Creature::alignColor() const {
if(getAdjustedAlignment() < NEUTRAL)
return("^r");
else if(getAdjustedAlignment() > NEUTRAL)
return("^c");
else
return("^x");
}
//********************************************************************
// cmdChooseAlignment
//********************************************************************
int cmdChooseAlignment(Player* player, cmd* cmnd) {
char syntax[] = "Syntax: alignment lawful\n"
" alignment chaotic\n"
"Note: Tieflings must be chaotic.\n\n";
if(player->isStaff() && !player->isCt())
return(0);
if(!player->ableToDoCommand())
return(0);
if(player->flagIsSet(P_CHOSEN_ALIGNMENT)) {
player->print("You have already chosen your alignment.\n");
if(player->flagIsSet(P_CHAOTIC))
player->print("In order to convert to lawful, use the 'convert' command. HELP CONVERT.\n");
return(0);
} else if(player->getLevel() < ALIGNMENT_LEVEL) {
player->print("You cannot choose your alignment until level %d.\n", ALIGNMENT_LEVEL);
return(0);
} else if(player->getLevel() > ALIGNMENT_LEVEL) {
player->print("Your alignment has already been chosen.\n");
return(0);
}
if(cmnd->num < 2) {
player->print(syntax);
return(0);
}
if(!strcasecmp(cmnd->str[1], "lawful")) {
if(player->getRace() == TIEFLING) {
player->print("Tieflings are required to be chaotic.\n\n");
} else {
broadcast("^B### %s chooses to adhere to the order of LAW!", player->getCName());
player->setFlag(P_CHOSEN_ALIGNMENT);
}
} else if(!strcasecmp(cmnd->str[1], "chaotic")) {
broadcast("^R### %s chooses to embrace the whims of CHAOS!", player->getCName());
player->setFlag(P_CHAOTIC);
player->setFlag(P_CHOSEN_ALIGNMENT);
} else {
player->print(syntax);
return(0);
}
return(0);
}
//*********************************************************************
// alignAdjustAcThaco
//*********************************************************************
// This function will be called whenever alignment changes,
// primarily in combat after killing a mob. It is initially
// designed to be only for monks and werewolves, but it can
// be applied to any class by altering the function. -TC
void Player::alignAdjustAcThaco() {
if(cClass != MONK && cClass != WEREWOLF)
return;
computeAC();
computeAttackPower();
}
//*********************************************************************
// alignmentString
//*********************************************************************
// Get alignment string
char *alignmentString(Creature* player) {
static char returnStr[1024];
strcpy(returnStr, "");
if(player->flagIsSet(P_OUTLAW))
strcat(returnStr, "Outlawed");
if( (player->flagIsSet(P_NO_PKILL) ||
player->flagIsSet(P_DIED_IN_DUEL) ||
player->getRoomParent()->isPkSafe()) && (player->flagIsSet(P_CHAOTIC) ||
player->getClan())
)
strcat(returnStr, "Neutral");
else if(player->flagIsSet(P_CHAOTIC))
strcat(returnStr, "Chaotic");
else
strcat(returnStr, "Lawful");
return (returnStr);
}
//*********************************************************************
// alignInOrder
//*********************************************************************
// basic alignment settings for races
// some extra checks may be need (ie, hands when royal blue)
// not set up for all clerics yet
bool Player::alignInOrder() const {
switch(deity) {
case GRADIUS:
return(getAdjustedAlignment() == NEUTRAL || getAdjustedAlignment() == LIGHTBLUE);
case LINOTHAN:
case ENOCH:
case KAMIRA:
return(getAdjustedAlignment() >= BLUISH);
case ARAMON:
case ARACHNUS:
return(getAdjustedAlignment() <= PINKISH);
default:
break;
}
return(true);
}
//*********************************************************************
// isAntiGradius
//*********************************************************************
bool Creature::isAntiGradius() const {
return(antiGradius(race));
}
//*********************************************************************
// antiGradius
//*********************************************************************
bool antiGradius(int race) {
return( race == ORC ||
race == OGRE ||
race == GOBLIN ||
race == TROLL ||
race == KOBOLD );
}
//********************************************************************
// adjustAlignment
//********************************************************************
void Player::adjustAlignment(Monster *victim) {
int adjust = victim->getAlignment() / 8;
if(victim->getAlignment() < 0 && victim->getAlignment() > -8)
adjust = -1;
if(victim->getAlignment() > 0 && victim->getAlignment() < 8)
adjust = 1;
bool toGood = adjust < 0;
bool toEvil = adjust > 0;
bool toNeutral = ((alignment > 0 && toEvil) ||
(alignment < 0 && toGood) );
// handle all the move-away-from-neutral cases
if(!toNeutral) {
// if they're gradius, an anti-gradius race can only help their alignment.
// same goes with the paly/dk war.
if(deity == GRADIUS) {
if(victim->isAntiGradius())
adjust = 0;
if(cClass == PALADIN && victim->getClass() == DEATHKNIGHT)
adjust = 0;
}
// werewolves and vampires can always kill each other
if(isEffected("vampirism") && victim->isEffected("lycanthropy"))
adjust = 0;
if(isEffected("lycanthropy") && victim->isEffected("vampirism"))
adjust = 0;
if(deity == CERIS && victim->isUndead())
adjust /= 2;
}
// paladin / deathknight war
// gradius paladins are taken care of above
if(deity != GRADIUS) {
if(cClass == PALADIN && victim->getClass() == DEATHKNIGHT && toEvil)
adjust = 0;
if(cClass == DEATHKNIGHT && victim->getClass() == PALADIN && toGood)
adjust = 0;
}
alignment -= adjust;
alignment = MAX(-1000, MIN(1000, alignment));
}
//*********************************************************************
// cmdConvert
//*********************************************************************
// This function allows a player to convert from chaotic to lawful alignment.
int cmdConvert(Player* player, cmd* cmnd) {
if(!player->ableToDoCommand())
return(0);
if(!player->flagIsSet(P_CHAOTIC)) {
player->print("You cannot convert. You're lawful.\n");
return(0);
} else if(player->getRace() == TIEFLING) {
player->print("Tieflings are required to be chaotic.\n");
return(0);
} else if(player->isNewVampire()) {
player->print("Vampires are required to be chaotic.\n");
return(0);
}
if(cmnd->num < 2 || strcasecmp(cmnd->str[1], "yes")) {
player->print("To prevent accidental conversion you must confirm you want to convert,\n");
player->print("to do so type 'convert yes'\n");
player->print("Remember, you will NEVER be able to be chaotic again.\n");
return(0);
}
if(player->getClass() == BUILDER) {
broadcast(isStaff, "^G### %s just converted to lawful alignment.", player->getCName());
logn("log.convert","%s converted to lawful.", player->getCName());
} else
broadcast("^G### %s just converted to lawful alignment.", player->getCName());
player->clearFlag(P_CHAOTIC);
if(player->getClass() == CLERIC)
player->clearFlag(P_PLEDGED);
return(0);
}