/* * Container.cpp * Classes to handle classes that can be containers or contained by a container * ____ _ * | _ \ ___ __ _| |_ __ ___ ___ * | |_) / _ \/ _` | | '_ ` _ \/ __| * | _ < __/ (_| | | | | | | \__ \ * |_| \_\___|\__,_|_|_| |_| |_|___/ * * 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" //################################################################################ //# Container //################################################################################ Container::Container() { // TODO Auto-generated constructor stub } bool Container::purge(bool includePets) { bool purgedAll = true; purgedAll &= purgeMonsters(includePets); purgedAll &= purgeObjects(); return(purgedAll); } bool Container::purgeMonsters(bool includePets) { bool purgedAll = true; MonsterSet::iterator mIt, prevIt; Monster *mons = 0; for(mIt = monsters.begin() ; mIt != monsters.end() ; ) { prevIt = mIt; mons = (*mIt++); if(includePets == false && mons->isPet()) { purgedAll = false; continue; } if(mons->flagIsSet(M_DM_FOLLOW)) { Player* master = mons->getPlayerMaster(); if(master) { master->clearFlag(P_ALIASING); master->setAlias(0); master->print("%1M's soul was purged.\n", mons); master->delPet(mons->getAsMonster()); } } monsters.erase(prevIt); free_crt(mons); } return(purgedAll); } bool Container::purgeObjects() { bool purgedAll = true; ObjectSet::iterator oIt, prevIt; Object* obj; for(oIt = objects.begin() ; oIt != objects.end() ; ) { prevIt = oIt; obj = (*oIt++); if(!obj->flagIsSet(O_TEMP_PERM)) { objects.erase(prevIt); delete obj; } else { purgedAll = false; } } return(purgedAll); } Container* Container::remove(Containable* toRemove) { if(!toRemove) return(NULL); Object* remObject = dynamic_cast<Object*>(toRemove); Player* remPlayer = dynamic_cast<Player*>(toRemove); Monster* remMonster = dynamic_cast<Monster*>(toRemove); bool toReturn = false; if(remObject) { objects.erase(remObject); toReturn = true; } else if(remPlayer) { players.erase(remPlayer); toReturn = true; } else if(remMonster) { monsters.erase(remMonster); toReturn = true; } else { std::cout << "Don't know how to remove " << toRemove << std::endl; toReturn = false; } //std::cout << "Removing " << toRemove->getName() << " from " << this->getName() << std::endl; if(toReturn) { Container* retVal = toRemove->getParent(); toRemove->setParent(NULL); return(retVal); } return(NULL); } bool Container::add(Containable* toAdd) { if(!toAdd) return(false); Object* addObject = dynamic_cast<Object*>(toAdd); Player* addPlayer = dynamic_cast<Player*>(toAdd); Monster* addMonster = dynamic_cast<Monster*>(toAdd); // If we're adding an object or a monster, we're registered and the item we're adding is not, // then register the item if((addObject || addMonster) && isRegistered() && !toAdd->isRegistered()) { toAdd->registerMo(); } bool toReturn = false; if(addObject) { std::pair<ObjectSet::iterator, bool> p = objects.insert(addObject); toReturn = p.second; } else if(addPlayer) { std::pair<PlayerSet::iterator, bool> p = players.insert(addPlayer); toReturn = p.second; } else if(addMonster) { std::pair<MonsterSet::iterator, bool> p = monsters.insert(addMonster); toReturn = p.second; } else { std::cout << "Don't know how to add " << toAdd << std::endl; toReturn = false; } if(toReturn) { toAdd->setParent(this); } //std::cout << "Adding " << toAdd->getName() << " to " << this->getName() << std::endl; return(toReturn); } void Container::registerContainedItems() { // Player registration is handled by the server MonsterSet::iterator mIt; for(mIt = monsters.begin() ; mIt != monsters.end() ; ) { Monster* mons = *mIt++; mons->registerMo(); } ObjectSet::iterator oIt; for(oIt = objects.begin() ; oIt != objects.end() ; ) { Object* obj = *oIt++; obj->registerMo(); } } void Container::unRegisterContainedItems() { // Player registration is handled by the server for(Monster* mons : monsters) { mons->unRegisterMo(); } for(Object* obj : objects) { obj->unRegisterMo(); } } //********************************************************************* // wake //********************************************************************* void Container::wake(bstring str, bool noise) const { for(Player* ply : players) { ply->wake(str, noise); } } bool Container::checkAntiMagic(Monster* ignore) { for(Monster* mons : monsters) { if(mons == ignore) continue; if(mons->flagIsSet(M_ANTI_MAGIC_AURA)) { broadcast(NULL, this, "^B%M glows bright blue.", mons); return(true); } } return(false); } MudObject* Container::findTarget(const Creature* searcher, const cmd* cmnd, int num) const { return(findTarget(searcher, cmnd->str[num], cmnd->val[num])); } MudObject* Container::findTarget(const Creature* searcher, const bstring& name, const int num, bool monFirst, bool firstAggro, bool exactMatch) const { int match=0; return(findTarget(searcher, name, num, monFirst, firstAggro, exactMatch, match)); } MudObject* Container::findTarget(const Creature* searcher, const bstring& name, const int num, bool monFirst, bool firstAggro, bool exactMatch, int& match) const { MudObject* toReturn = 0; if((toReturn = findCreature(searcher, name, num, monFirst, firstAggro, exactMatch, match))) { return(toReturn); } // TODO: Search the container's objects return(toReturn); } // Wrapper for the real findObject to support legacy callers Object* Container::findObject(const Creature *searcher, const cmd* cmnd, int val) const { return(findObject(searcher, cmnd->str[val], cmnd->val[val])); } Object* Container::findObject(const Creature* searcher, const bstring& name, const int num, bool exactMatch ) const { int match = 0; return(findObject(searcher, name, num,exactMatch, match)); } Object* Container::findObject(const Creature* searcher, const bstring& name, const int num, bool exactMatch, int& match) const { Object *target = 0; for(Object* obj : objects) { if(isMatch(searcher, obj, name, exactMatch)) { match++; if(match == num) { if(exactMatch) return(obj); else { target = obj; break; } } } } return(target); } // Wrapper for the real findCreature to support legacy callers Creature* Container::findCreature(const Creature* searcher, const cmd* cmnd, int num) const { return(findCreature(searcher, cmnd->str[num], cmnd->val[num])); } Creature* Container::findCreaturePython(Creature* searcher, const bstring& name, bool monFirst, bool firstAggro, bool exactMatch ) { int ignored=0; int num = 1; bstring newName = name; newName.trim(); unsigned int sLoc = newName.ReverseFind(" "); if(sLoc != bstring::npos) { num = newName.right(newName.length() - sLoc).toInt(); if(num != 0) { newName = newName.left(sLoc); } else { num = 1; } } std::cout << "Looking for '" << newName << "' #" << num << "\n"; return(findCreature(searcher, newName, num, monFirst, firstAggro, exactMatch, ignored)); } // Wrapper for the real findCreature for callers that don't care about the value of match Creature* Container::findCreature(const Creature* searcher, const bstring& name, const int num, bool monFirst, bool firstAggro, bool exactMatch ) const { int ignored=0; return(findCreature(searcher, name, num, monFirst, firstAggro, exactMatch, ignored)); } bool isMatch(const Creature* searcher, MudObject* target, const bstring& name, bool exactMatch, bool checkVisibility) { if(!target) return(false); if(checkVisibility && !searcher->canSee(target)) return(false); // ID match is exact, regardless of exactMatch option if(target->getId() == name) return(true); if(exactMatch) { if(target->getName() == name) { return(true); } } else { if(target->isCreature() && keyTxtEqual(target->getAsCreature(), name.c_str())) { return(true); } else if(target->isObject() && keyTxtEqual(target->getAsObject(), name.c_str())) { return(true); } } return(false); } // The real findCreature, will take and return the value of match as to allow for findTarget to find the 3rd thing named // gold with a monster name goldfish, player named goldmine, and some gold in the room! Creature* Container::findCreature(const Creature* searcher, const bstring& name, const int num, bool monFirst, bool firstAggro, bool exactMatch, int& match) const { if(!searcher || name.empty()) return(NULL); Creature* target=0; for(int i = 1 ; i <= 2 ; i++) { if( (monFirst && i == 1) || (!monFirst && i == 2) ) { target = findMonster(searcher, name, num, firstAggro, exactMatch, match); } else { target = findPlayer(searcher, name, num, exactMatch, match); } if(target) { return(target); } } return(target); } Monster* Container::findMonster(const Creature* searcher, const cmd* cmnd, int num) const { return(findMonster(searcher, cmnd->str[num], cmnd->val[num])); } Monster* Container::findMonster(const Creature* searcher, const bstring& name, const int num, bool firstAggro, bool exactMatch) const { int match = 0; return(findMonster(searcher, name, num, firstAggro, exactMatch, match)); } Monster* Container::findMonster(const Creature* searcher, const bstring& name, const int num, bool firstAggro, bool exactMatch, int& match) const { Monster* target = 0; for(Monster* mons : searcher->getParent()->monsters) { if(isMatch(searcher, mons, name, exactMatch)) { match++; if(match == num) { if(exactMatch) return(mons); else { target = mons; break; } } } } if(firstAggro && target) { if(num < 2 && searcher->pFlagIsSet(P_KILL_AGGROS)) return(getFirstAggro(target, searcher)); else return(target); } else { return(target); } } Player* Container::findPlayer(const Creature* searcher, const cmd* cmnd, int num) const { return(findPlayer(searcher, cmnd->str[num], cmnd->val[num])); } Player* Container::findPlayer(const Creature* searcher, const bstring& name, const int num, bool exactMatch) const { int match = 0; return(findPlayer(searcher, name, num, exactMatch, match)); } Player* Container::findPlayer(const Creature* searcher, const bstring& name, const int num, bool exactMatch, int& match) const { for(Player* ply : searcher->getParent()->players) { if(isMatch(searcher, ply, name, exactMatch)) { match++; if(match == num) { return(ply); } } } return(NULL); } //################################################################################ //# Containable //################################################################################ Containable::Containable() { parent = 0; lastParent = 0; } void Containable::removeFromSet() { lastParent = removeFrom(); } void Containable::addToSet() { addTo(lastParent); lastParent = 0; } bool Containable::addTo(Container* container) { if(this->parent != NULL && parent->getAsMudObject() != container->getAsMudObject()) { std::cout << "Non Null Parent" << std::endl; return(0); } if(container == NULL) return(removeFrom()); if(this->isCreature()) { if(container->isUniqueRoom()) { getAsCreature()->currentLocation.room = container->getAsUniqueRoom()->info; } else if (container->isAreaRoom()) { getAsCreature()->currentLocation.mapmarker = container->getAsAreaRoom()->mapmarker; } } return(container->add(this)); } Container* Containable::removeFrom() { if(!parent) { return(NULL); } if(isCreature()) { getAsCreature()->currentLocation.room.clear(); getAsCreature()->currentLocation.mapmarker.reset(); } return(parent->remove(this)); } void Containable::setParent(Container* container) { parent = container; } Container* Containable::getParent() const { return(parent); } bool Containable::inRoom() const { return(parent && parent->isRoom()); } bool Containable::inUniqueRoom() const { return(parent && parent->isUniqueRoom()); } bool Containable::inAreaRoom() const { return(parent && parent->isAreaRoom()); } bool Containable::inObject() const { return(parent && parent->isObject()); } bool Containable::inPlayer() const { return(parent && parent->isPlayer()); } bool Containable::inMonster() const { return(parent && parent->isMonster()); } bool Containable::inCreature() const { return(parent && parent->isCreature()); } BaseRoom* Containable::getRoomParent() { if(!parent) return(NULL); return(parent->getAsRoom()); } UniqueRoom* Containable::getUniqueRoomParent() { if(!parent) return(NULL); return(parent->getAsUniqueRoom()); } AreaRoom* Containable::getAreaRoomParent() { if(!parent) return(NULL); return(parent->getAsAreaRoom()); } Object* Containable::getObjectParent() { if(!parent) return(NULL); return(parent->getAsObject()); } Player* Containable::getPlayerParent() { if(!parent) return(NULL); return(parent->getAsPlayer()); } Monster* Containable::getMonsterParent() { if(!parent) return(NULL); return(parent->getAsMonster()); } Creature* Containable::getCreatureParent() { if(!parent) return(NULL); return(parent->getAsCreature()); } const BaseRoom* Containable::getConstRoomParent() const { if(!parent) return(NULL); return(parent->getAsConstRoom()); } const UniqueRoom* Containable::getConstUniqueRoomParent() const { if(!parent) return(NULL); return(parent->getAsConstUniqueRoom()); } const AreaRoom* Containable::getConstAreaRoomParent() const { if(!parent) return(NULL); return(parent->getAsConstAreaRoom()); } const Object* Containable::getConstObjectParent() const { if(!parent) return(NULL); return(parent->getAsConstObject()); } const Player* Containable::getConstPlayerParent() const { if(!parent) return(NULL); return(parent->getAsConstPlayer()); } const Monster* Containable::getConstMonsterParent() const { if(!parent) return(NULL); return(parent->getAsConstMonster()); } const Creature* Containable::getConstCreatureParent() const { if(!parent) return(NULL); return(parent->getAsConstCreature()); }