void parse(int c) { printf("\x1b[01;31m%c:%c[%.*s]\x1b[00m",state,c,(int)(stack-b_stack),b_stack); switch(state) { case 'C': if(c=='I') { out1("arg"); } if(c=='{') { *stack++='('; state='X'; } break; case 'F': state='X'; if(c=='=' && stack>b_stack && stack[-1]=='v') { out1("local"); } out1(c=='=' ? "ident" : "get"); case 'P': if(c=='(') { *stack++='f'; *stack++='('; outo('('); break; } case 'X': if(c=='N') { out1("num"); } else if(c=='I') { int l=ident-b_ident; if(l==8&&memcmp("function",b_ident,ident-b_ident)==0) { state='C'; outn("def",closuren); outn("args",closuren); *fstack++=closuren++; } else if(l==3&&memcmp("var",b_ident,ident-b_ident)==0) { *stack++='v'; } else if(l==6&&memcmp("return",b_ident,ident-b_ident)==0) { *stack++='r'; } else { state='F'; } } else if(c==';') { unstack(0); outo(';'); } else if(c=='(') { *stack++='('; out1("com ("); } else if(c==')') { unstack(0); stack--; state='P'; } else if(c=='}') { unstack(0); stack--; outn("end",*(--fstack)); } else { unstack(c); *stack++=c; } break; default: goto abort; } return; abort: printf("\n Parse abort: char '%c' state '%c'\n",c,state); abort(); }
MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipItemQuantity(const Ptr& item, const Ptr& actor, int count) { if (!isEquipped(item)) throw std::runtime_error ("attempt to unequip an item that is not currently equipped"); if (count <= 0) throw std::runtime_error ("attempt to unequip nothing (count <= 0)"); if (count > item.getRefData().getCount()) throw std::runtime_error ("attempt to unequip more items than equipped"); if (count == item.getRefData().getCount()) return unequipItem(item, actor); // Move items to an existing stack if possible, otherwise split count items out into a new stack. // Moving counts manually here, since ContainerStore's restack can't target unequipped stacks. for (MWWorld::ContainerStoreIterator iter (begin()); iter != end(); ++iter) { if (stacks(*iter, item) && !isEquipped(*iter)) { iter->getRefData().setCount(iter->getRefData().getCount() + count); item.getRefData().setCount(item.getRefData().getCount() - count); return iter; } } return unstack(item, actor, item.getRefData().getCount() - count); }
void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& iterator, const Ptr& actor) { if (iterator == end()) throw std::runtime_error ("can't equip end() iterator, use unequip function instead"); if (slot<0 || slot>=static_cast<int> (mSlots.size())) throw std::runtime_error ("slot number out of range"); if (iterator.getContainerStore()!=this) throw std::runtime_error ("attempt to equip an item that is not in the inventory"); std::pair<std::vector<int>, bool> slots_; slots_ = iterator->getClass().getEquipmentSlots (*iterator); if (std::find (slots_.first.begin(), slots_.first.end(), slot)==slots_.first.end()) throw std::runtime_error ("invalid slot"); if (mSlots[slot] != end()) unequipSlot(slot, actor); // unstack item pointed to by iterator if required if (iterator!=end() && !slots_.second && iterator->getRefData().getCount() > 1) // if slots.second is true, item can stay stacked when equipped { unstack(*iterator, actor); } mSlots[slot] = iterator; flagAsModified(); fireEquipmentChangedEvent(actor); updateMagicEffects(actor); }
void intr(int s __unused) { noreset = 0; if (!inithdr) sawcom++; inithdr = 0; while (sourcing) unstack(); close_all_files(); if (image >= 0) { (void)close(image); image = -1; } fprintf(stderr, "Interrupt\n"); reset(0); }
void Turtle::build(const std::string &str, Alg* alg) { unsigned int i; char c; initState(); for(i=0; i<str.size(); i++) { c = str[i]; switch(c) { // allowed letters case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': stepLine(alg); break; // other symbols case '+': rotate(true); break; case '-': rotate(false); break; case '[': stack(); break; case ']': unstack(); break; // ignore other default: break; } } }
void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) { TSlots slots_; initSlots (slots_); // Disable model update during auto-equip mUpdatesEnabled = false; for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter) { Ptr test = *iter; // Don't autoEquip lights. Handled in Actors::updateEquippedLight based on environment light. if (test.getTypeName() == typeid(ESM::Light).name()) { continue; } // Only autoEquip if we are the original owner of the item. // This stops merchants from auto equipping anything you sell to them. // ...unless this is a companion, he should always equip items given to him. if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) && (actor.getClass().getScript(actor).empty() || !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion")) && !actor.getClass().getCreatureStats(actor).isDead() // Corpses can be dressed up by the player as desired ) { continue; } int testSkill = test.getClass().getEquipmentSkill (test); std::pair<std::vector<int>, bool> itemsSlots = iter->getClass().getEquipmentSlots (*iter); for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin()); iter2!=itemsSlots.first.end(); ++iter2) { if (*iter2 == Slot_CarriedRight) // Items in right hand are situational use, so don't equip them. // Equipping weapons is handled by AiCombat. Anything else (lockpicks, probes) can't be used by NPCs anyway (yet) continue; if (iter.getType() == MWWorld::ContainerStore::Type_Weapon) continue; if (slots_.at (*iter2)!=end()) { Ptr old = *slots_.at (*iter2); // check skill int oldSkill = old.getClass().getEquipmentSkill (old); bool use = false; if (testSkill!=-1 && oldSkill==-1) use = true; else if (testSkill!=-1 && oldSkill!=-1 && testSkill!=oldSkill) { if (actor.getClass().getSkill(actor, oldSkill) > actor.getClass().getSkill (actor, testSkill)) continue; // rejected, because old item better matched the NPC's skills. if (actor.getClass().getSkill(actor, oldSkill) < actor.getClass().getSkill (actor, testSkill)) use = true; } if (!use) { // check value if (old.getClass().getValue (old)>= test.getClass().getValue (test)) { continue; } } } switch(test.getClass().canBeEquipped (test, actor).first) { case 0: continue; default: break; } if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped { // unstack item pointed to by iterator if required if (iter->getRefData().getCount() > 1) { unstack(*iter, actor); } } slots_[*iter2] = iter; break; } } bool changed = false; for (std::size_t i=0; i<slots_.size(); ++i) { if (slots_[i] != mSlots[i]) { changed = true; break; } } mUpdatesEnabled = true; if (changed) { mSlots.swap (slots_); fireEquipmentChangedEvent(actor); updateMagicEffects(actor); flagAsModified(); } }
void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) { TSlots slots_; initSlots (slots_); // Disable model update during auto-equip mUpdatesEnabled = false; for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter) { Ptr test = *iter; // Don't autoEquip lights. Handled in Actors::updateEquippedLight based on environment light. if (test.getTypeName() == typeid(ESM::Light).name()) { continue; } // Don't auto-equip probes or lockpicks. NPCs can't use them (yet). And AiCombat would attempt to "attack" with them. // NOTE: In the future AiCombat should handle equipping appropriate weapons if (test.getTypeName() == typeid(ESM::Lockpick).name() || test.getTypeName() == typeid(ESM::Probe).name()) continue; // Only autoEquip if we are the original owner of the item. // This stops merchants from auto equipping anything you sell to them. // ...unless this is a companion, he should always equip items given to him. if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) && (actor.getClass().getScript(actor).empty() || !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))) continue; int testSkill = test.getClass().getEquipmentSkill (test); std::pair<std::vector<int>, bool> itemsSlots = iter->getClass().getEquipmentSlots (*iter); for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin()); iter2!=itemsSlots.first.end(); ++iter2) { bool use = false; if (slots_.at (*iter2)==end()) use = true; // slot was empty before -> skip all further checks else { Ptr old = *slots_.at (*iter2); if (!use) { // check skill int oldSkill = old.getClass().getEquipmentSkill (old); if (testSkill!=-1 && oldSkill==-1) use = true; else if (testSkill!=-1 && oldSkill!=-1 && testSkill!=oldSkill) { if (actor.getClass().getSkill(actor, oldSkill) > actor.getClass().getSkill (actor, testSkill)) continue; // rejected, because old item better matched the NPC's skills. if (actor.getClass().getSkill(actor, oldSkill) < actor.getClass().getSkill (actor, testSkill)) use = true; } } if (!use) { // check value if (old.getClass().getValue (old)>= test.getClass().getValue (test)) { continue; } use = true; } } switch(test.getClass().canBeEquipped (test, actor).first) { case 0: continue; case 2: slots_[MWWorld::InventoryStore::Slot_CarriedLeft] = end(); break; case 3: // Prefer keeping twohanded weapon break; } if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped { // unstack item pointed to by iterator if required if (iter->getRefData().getCount() > 1) { unstack(*iter, actor); } } slots_[*iter2] = iter; break; } } bool changed = false; for (std::size_t i=0; i<slots_.size(); ++i) if (slots_[i]!=mSlots[i]) { changed = true; } mUpdatesEnabled = true; if (changed) { mSlots.swap (slots_); fireEquipmentChangedEvent(); updateMagicEffects(actor); flagAsModified(); } }
/* * Execute a single command. * Command functions return 0 for success, 1 for error, and -1 * for abort. A 1 or -1 aborts a load or source. A -1 aborts * the interactive command loop. * Contxt is non-zero if called while composing mail. */ int execute(char linebuf[], int contxt) { char word[LINESIZE]; char *arglist[MAXARGC]; const struct cmd *com; char *cp, *cp2; int c, muvec[2]; int e = 1; /* * Strip the white space away from the beginning * of the command, then scan out a word, which * consists of anything except digits and white space. * * Handle ! escapes differently to get the correct * lexical conventions. */ for (cp = linebuf; isspace((unsigned char)*cp); cp++) ; if (*cp == '!') { if (sourcing) { printf("Can't \"!\" while sourcing\n"); goto out; } shell(cp+1); return (0); } cp2 = word; while (*cp != '\0' && strchr(" \t0123456789$^.:/-+*'\"", *cp) == NULL) *cp2++ = *cp++; *cp2 = '\0'; /* * Look up the command; if not found, bitch. * Normally, a blank command would map to the * first command in the table; while sourcing, * however, we ignore blank lines to eliminate * confusion. */ if (sourcing && *word == '\0') return (0); com = lex(word); if (com == NULL) { printf("Unknown command: \"%s\"\n", word); goto out; } /* * See if we should execute the command -- if a conditional * we always execute it, otherwise, check the state of cond. */ if ((com->c_argtype & F) == 0) if ((cond == CRCV && !rcvmode) || (cond == CSEND && rcvmode)) return (0); /* * Process the arguments to the command, depending * on the type he expects. Default to an error. * If we are sourcing an interactive command, it's * an error. */ if (!rcvmode && (com->c_argtype & M) == 0) { printf("May not execute \"%s\" while sending\n", com->c_name); goto out; } if (sourcing && com->c_argtype & I) { printf("May not execute \"%s\" while sourcing\n", com->c_name); goto out; } if (readonly && com->c_argtype & W) { printf("May not execute \"%s\" -- message file is read only\n", com->c_name); goto out; } if (contxt && com->c_argtype & R) { printf("Cannot recursively invoke \"%s\"\n", com->c_name); goto out; } switch (com->c_argtype & ~(F|P|I|M|T|W|R)) { case MSGLIST: /* * A message list defaulting to nearest forward * legal message. */ if (msgvec == 0) { printf("Illegal use of \"message list\"\n"); break; } if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0) break; if (c == 0) { *msgvec = first(com->c_msgflag, com->c_msgmask); msgvec[1] = 0; } if (*msgvec == 0) { printf("No applicable messages\n"); break; } e = (*com->c_func)(msgvec); break; case NDMLIST: /* * A message list with no defaults, but no error * if none exist. */ if (msgvec == 0) { printf("Illegal use of \"message list\"\n"); break; } if (getmsglist(cp, msgvec, com->c_msgflag) < 0) break; e = (*com->c_func)(msgvec); break; case STRLIST: /* * Just the straight string, with * leading blanks removed. */ while (isspace((unsigned char)*cp)) cp++; e = (*com->c_func)(cp); break; case RAWLIST: /* * A vector of strings, in shell style. */ if ((c = getrawlist(cp, arglist, sizeof(arglist) / sizeof(*arglist))) < 0) break; if (c < com->c_minargs) { printf("%s requires at least %d arg(s)\n", com->c_name, com->c_minargs); break; } if (c > com->c_maxargs) { printf("%s takes no more than %d arg(s)\n", com->c_name, com->c_maxargs); break; } e = (*com->c_func)(arglist); break; case NOLIST: /* * Just the constant zero, for exiting, * eg. */ e = (*com->c_func)(0); break; default: errx(1, "Unknown argtype"); } out: /* * Exit the current source file on * error. */ if (e) { if (e < 0) return (1); if (loading) return (1); if (sourcing) unstack(); return (0); } if (com == NULL) return (0); if (value("autoprint") != NULL && com->c_argtype & P) if ((dot->m_flag & MDELETED) == 0) { muvec[0] = dot - &message[0] + 1; muvec[1] = 0; type(muvec); } if (!sourcing && (com->c_argtype & T) == 0) sawcom = 1; return (0); }
/* * Interpret user commands one by one. If standard input is not a tty, * print no prompt. */ void commands(void) { int n, eofloop = 0; char linebuf[LINESIZE]; if (!sourcing) { if (signal(SIGINT, SIG_IGN) != SIG_IGN) (void)signal(SIGINT, intr); if (signal(SIGHUP, SIG_IGN) != SIG_IGN) (void)signal(SIGHUP, hangup); (void)signal(SIGTSTP, stop); (void)signal(SIGTTOU, stop); (void)signal(SIGTTIN, stop); } setexit(); for (;;) { /* * Print the prompt, if needed. Clear out * string space, and flush the output. */ if (!sourcing && value("interactive") != NULL) { if ((value("autoinc") != NULL) && (incfile() > 0)) printf("New mail has arrived.\n"); reset_on_stop = 1; printf("%s", prompt); } (void)fflush(stdout); sreset(); /* * Read a line of commands from the current input * and handle end of file specially. */ n = 0; for (;;) { if (readline(input, &linebuf[n], LINESIZE - n) < 0) { if (n == 0) n = -1; break; } if ((n = strlen(linebuf)) == 0) break; n--; if (linebuf[n] != '\\') break; linebuf[n++] = ' '; } reset_on_stop = 0; if (n < 0) { /* eof */ if (loading) break; if (sourcing) { unstack(); continue; } if (value("interactive") != NULL && value("ignoreeof") != NULL && ++eofloop < 25) { printf("Use \"quit\" to quit.\n"); continue; } break; } eofloop = 0; if (execute(linebuf, 0)) break; } }
void MWWorld::InventoryStore::autoEquipArmor (const MWWorld::Ptr& actor, TSlots& slots_) { // Only NPCs can wear armor for now. // For creatures we equip only shields. if (!actor.getClass().isNpc()) { autoEquipShield(actor, slots_); return; } const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>(); static float fUnarmoredBase1 = store.find("fUnarmoredBase1")->mValue.getFloat(); static float fUnarmoredBase2 = store.find("fUnarmoredBase2")->mValue.getFloat(); int unarmoredSkill = actor.getClass().getSkill(actor, ESM::Skill::Unarmored); float unarmoredRating = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill); for (ContainerStoreIterator iter (begin(ContainerStore::Type_Clothing | ContainerStore::Type_Armor)); iter!=end(); ++iter) { Ptr test = *iter; if (!canActorAutoEquip(actor, test)) continue; switch(test.getClass().canBeEquipped (test, actor).first) { case 0: continue; default: break; } if (iter.getType() == ContainerStore::Type_Armor && test.getClass().getEffectiveArmorRating(test, actor) <= std::max(unarmoredRating, 0.f)) { continue; } std::pair<std::vector<int>, bool> itemsSlots = iter->getClass().getEquipmentSlots (*iter); // checking if current item pointed by iter can be equipped for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin()); iter2!=itemsSlots.first.end(); ++iter2) { // if true then it means slot is equipped already // check if slot may require swapping if current item is more valuable if (slots_.at (*iter2)!=end()) { Ptr old = *slots_.at (*iter2); if (iter.getType() == ContainerStore::Type_Armor) { if (old.getTypeName() == typeid(ESM::Armor).name()) { if (old.get<ESM::Armor>()->mBase->mData.mType < test.get<ESM::Armor>()->mBase->mData.mType) continue; if (old.get<ESM::Armor>()->mBase->mData.mType == test.get<ESM::Armor>()->mBase->mData.mType) { if (old.getClass().getEffectiveArmorRating(old, actor) >= test.getClass().getEffectiveArmorRating(test, actor)) // old armor had better armor rating continue; } } // suitable armor should replace already equipped clothing } else if (iter.getType() == ContainerStore::Type_Clothing) { // if left ring is equipped if (*iter2 == Slot_LeftRing) { // if there is a place for right ring dont swap it if (slots_.at(Slot_RightRing) == end()) { continue; } else // if right ring is equipped too { Ptr rightRing = *slots_.at(Slot_RightRing); // we want to swap cheaper ring only if both are equipped if (old.getClass().getValue (old) >= rightRing.getClass().getValue (rightRing)) continue; } } if (old.getTypeName() == typeid(ESM::Clothing).name()) { // check value if (old.getClass().getValue (old) >= test.getClass().getValue (test)) // old clothing was more valuable continue; } else // suitable clothing should NOT replace already equipped armor continue; } } if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped { // unstack item pointed to by iterator if required if (iter->getRefData().getCount() > 1) { unstack(*iter, actor); } } // if we are here it means item can be equipped or swapped slots_[*iter2] = iter; break; } } }
void MWWorld::InventoryStore::autoEquipWeapon (const MWWorld::Ptr& actor, TSlots& slots_) { if (!actor.getClass().isNpc()) { // In original game creatures do not autoequip weapon, but we need it for weapon sheathing. // The only case when the difference is noticable - when this creature sells weapon. // So just disable weapon autoequipping for creatures which sells weapon. int services = actor.getClass().getServices(actor); bool sellsWeapon = services & (ESM::NPC::Weapon|ESM::NPC::MagicItems); if (sellsWeapon) return; } static const ESM::Skill::SkillEnum weaponSkills[] = { ESM::Skill::LongBlade, ESM::Skill::Axe, ESM::Skill::Spear, ESM::Skill::ShortBlade, ESM::Skill::Marksman, ESM::Skill::BluntWeapon }; const size_t weaponSkillsLength = sizeof(weaponSkills) / sizeof(weaponSkills[0]); bool weaponSkillVisited[weaponSkillsLength] = { false }; // give arrows/bolt with max damage by default int arrowMax = 0; int boltMax = 0; ContainerStoreIterator arrow(end()); ContainerStoreIterator bolt(end()); // rate ammo for (ContainerStoreIterator iter(begin(ContainerStore::Type_Weapon)); iter!=end(); ++iter) { const ESM::Weapon* esmWeapon = iter->get<ESM::Weapon>()->mBase; if (esmWeapon->mData.mType == ESM::Weapon::Arrow) { if (esmWeapon->mData.mChop[1] >= arrowMax) { arrowMax = esmWeapon->mData.mChop[1]; arrow = iter; } } else if (esmWeapon->mData.mType == ESM::Weapon::Bolt) { if (esmWeapon->mData.mChop[1] >= boltMax) { boltMax = esmWeapon->mData.mChop[1]; bolt = iter; } } } // rate weapon for (int i = 0; i < static_cast<int>(weaponSkillsLength); ++i) { int max = 0; int maxWeaponSkill = -1; for (int j = 0; j < static_cast<int>(weaponSkillsLength); ++j) { int skillValue = actor.getClass().getSkill(actor, static_cast<int>(weaponSkills[j])); if (skillValue > max && !weaponSkillVisited[j]) { max = skillValue; maxWeaponSkill = j; } } if (maxWeaponSkill == -1) break; max = 0; ContainerStoreIterator weapon(end()); for (ContainerStoreIterator iter(begin(ContainerStore::Type_Weapon)); iter!=end(); ++iter) { if (!canActorAutoEquip(actor, *iter)) continue; const ESM::Weapon* esmWeapon = iter->get<ESM::Weapon>()->mBase; if (esmWeapon->mData.mType == ESM::Weapon::Arrow || esmWeapon->mData.mType == ESM::Weapon::Bolt) continue; if (iter->getClass().getEquipmentSkill(*iter) == weaponSkills[maxWeaponSkill]) { if (esmWeapon->mData.mChop[1] >= max) { max = esmWeapon->mData.mChop[1]; weapon = iter; } if (esmWeapon->mData.mSlash[1] >= max) { max = esmWeapon->mData.mSlash[1]; weapon = iter; } if (esmWeapon->mData.mThrust[1] >= max) { max = esmWeapon->mData.mThrust[1]; weapon = iter; } } } bool isBow = false; bool isCrossbow = false; if (weapon != end()) { const MWWorld::LiveCellRef<ESM::Weapon> *ref = weapon->get<ESM::Weapon>(); ESM::Weapon::Type type = (ESM::Weapon::Type)ref->mBase->mData.mType; if (type == ESM::Weapon::MarksmanBow) isBow = true; else if (type == ESM::Weapon::MarksmanCrossbow) isCrossbow = true; } if (weapon != end() && weapon->getClass().canBeEquipped(*weapon, actor).first) { // Do not equip ranged weapons, if there is no suitable ammo bool hasAmmo = true; if (isBow == true) { if (arrow == end()) hasAmmo = false; else slots_[Slot_Ammunition] = arrow; } if (isCrossbow == true) { if (bolt == end()) hasAmmo = false; else slots_[Slot_Ammunition] = bolt; } if (hasAmmo) { std::pair<std::vector<int>, bool> itemsSlots = weapon->getClass().getEquipmentSlots (*weapon); if (!itemsSlots.first.empty()) { if (!itemsSlots.second) { if (weapon->getRefData().getCount() > 1) { unstack(*weapon, actor); } } int slot = itemsSlots.first.front(); slots_[slot] = weapon; if (!isBow && !isCrossbow) slots_[Slot_Ammunition] = end(); } break; } } weaponSkillVisited[maxWeaponSkill] = true; } }
void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) { const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>(); MWMechanics::NpcStats& stats = actor.getClass().getNpcStats(actor); static float fUnarmoredBase1 = store.find("fUnarmoredBase1")->mValue.getFloat(); static float fUnarmoredBase2 = store.find("fUnarmoredBase2")->mValue.getFloat(); int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified(); float unarmoredRating = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill); TSlots slots_; initSlots (slots_); // Disable model update during auto-equip mUpdatesEnabled = false; // Autoequip clothing, armor and weapons. // Equipping lights is handled in Actors::updateEquippedLight based on environment light. for (ContainerStoreIterator iter (begin(ContainerStore::Type_Clothing | ContainerStore::Type_Armor)); iter!=end(); ++iter) { Ptr test = *iter; if (!canActorAutoEquip(actor, test)) continue; switch(test.getClass().canBeEquipped (test, actor).first) { case 0: continue; default: break; } if (iter.getType() == ContainerStore::Type_Armor && test.getClass().getEffectiveArmorRating(test, actor) <= std::max(unarmoredRating, 0.f)) { continue; } std::pair<std::vector<int>, bool> itemsSlots = iter->getClass().getEquipmentSlots (*iter); // checking if current item poited by iter can be equipped for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin()); iter2!=itemsSlots.first.end(); ++iter2) { // if true then it means slot is equipped already // check if slot may require swapping if current item is more valueable if (slots_.at (*iter2)!=end()) { Ptr old = *slots_.at (*iter2); if (iter.getType() == ContainerStore::Type_Armor) { if (old.getTypeName() == typeid(ESM::Armor).name()) { if (old.get<ESM::Armor>()->mBase->mData.mType < test.get<ESM::Armor>()->mBase->mData.mType) continue; if (old.get<ESM::Armor>()->mBase->mData.mType == test.get<ESM::Armor>()->mBase->mData.mType) { if (old.getClass().getEffectiveArmorRating(old, actor) >= test.getClass().getEffectiveArmorRating(test, actor)) // old armor had better armor rating continue; } } // suitable armor should replace already equipped clothing } else if (iter.getType() == ContainerStore::Type_Clothing) { // if left ring is equipped if (*iter2 == Slot_LeftRing) { // if there is a place for right ring dont swap it if (slots_.at(Slot_RightRing) == end()) { continue; } else // if right ring is equipped too { Ptr rightRing = *slots_.at(Slot_RightRing); // we want to swap cheaper ring only if both are equipped if (old.getClass().getValue (old) >= rightRing.getClass().getValue (rightRing)) continue; } } if (old.getTypeName() == typeid(ESM::Clothing).name()) { // check value if (old.getClass().getValue (old) >= test.getClass().getValue (test)) // old clothing was more valuable continue; } else // suitable clothing should NOT replace already equipped armor continue; } } if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped { // unstack item pointed to by iterator if required if (iter->getRefData().getCount() > 1) { unstack(*iter, actor); } } // if we are here it means item can be equipped or swapped slots_[*iter2] = iter; break; } } static const ESM::Skill::SkillEnum weaponSkills[] = { ESM::Skill::LongBlade, ESM::Skill::Axe, ESM::Skill::Spear, ESM::Skill::ShortBlade, ESM::Skill::Marksman, ESM::Skill::BluntWeapon }; const size_t weaponSkillsLength = sizeof(weaponSkills) / sizeof(weaponSkills[0]); bool weaponSkillVisited[weaponSkillsLength] = { false }; for (int i = 0; i < static_cast<int>(weaponSkillsLength); ++i) { int max = 0; int maxWeaponSkill = -1; for (int j = 0; j < static_cast<int>(weaponSkillsLength); ++j) { int skillValue = stats.getSkill(static_cast<int>(weaponSkills[j])).getModified(); if (skillValue > max && !weaponSkillVisited[j]) { max = skillValue; maxWeaponSkill = j; } } if (maxWeaponSkill == -1) break; max = 0; ContainerStoreIterator weapon(end()); for (ContainerStoreIterator iter(begin(ContainerStore::Type_Weapon)); iter!=end(); ++iter) { if (!canActorAutoEquip(actor, *iter)) continue; const ESM::Weapon* esmWeapon = iter->get<ESM::Weapon>()->mBase; if (esmWeapon->mData.mType == ESM::Weapon::Arrow || esmWeapon->mData.mType == ESM::Weapon::Bolt) continue; if (iter->getClass().getEquipmentSkill(*iter) == weaponSkills[maxWeaponSkill]) { if (esmWeapon->mData.mChop[1] >= max) { max = esmWeapon->mData.mChop[1]; weapon = iter; } if (esmWeapon->mData.mSlash[1] >= max) { max = esmWeapon->mData.mSlash[1]; weapon = iter; } if (esmWeapon->mData.mThrust[1] >= max) { max = esmWeapon->mData.mThrust[1]; weapon = iter; } } } if (weapon != end() && weapon->getClass().canBeEquipped(*weapon, actor).first) { std::pair<std::vector<int>, bool> itemsSlots = weapon->getClass().getEquipmentSlots (*weapon); if (!itemsSlots.first.empty()) { if (!itemsSlots.second) { if (weapon->getRefData().getCount() > 1) { unstack(*weapon, actor); } } int slot = itemsSlots.first.front(); slots_[slot] = weapon; } break; } weaponSkillVisited[maxWeaponSkill] = true; } bool changed = false; for (std::size_t i=0; i<slots_.size(); ++i) { if (slots_[i] != mSlots[i]) { changed = true; break; } } mUpdatesEnabled = true; if (changed) { mSlots.swap (slots_); fireEquipmentChangedEvent(actor); updateMagicEffects(actor); flagAsModified(); } }