void Forge::CreateWeapon(CHAR_DATA & ch, const char * argument) { // Perform basic skill check int skill(get_skill(&ch, gsn_forgeweapon)); if (skill <= 0) { send_to_char("Huh?\n", &ch); return; } // Check for cooldown for (AFFECT_DATA * paf(get_affect(&ch, gsn_forgeweapon)); paf != NULL; paf = get_affect(&ch, gsn_forgeweapon, paf)) { if (paf->point == NULL && paf->location == APPLY_NONE) { send_to_char("You are not ready for the trying process of forging another weapon just yet.\n", &ch); return; } } // Check for naming AFFECT_DATA * nameAff(FindNameEffect(ch)); if (nameAff != NULL) { OBJ_DATA * nameObj(FindNameableObject(ch, *nameAff)); if (nameObj != NULL) { act("You must first confer a true Name upon $p.", &ch, nameObj, NULL, TO_CHAR); return; } // No longer has the obj, so just clean up the effect and move on affect_remove(&ch, nameAff); } // Get the weapon type name char arg[MAX_INPUT_LENGTH]; argument = one_argument(argument, arg); if (arg[0] == '\0') { send_to_char("Which type of weapon did you wish to forge?\n", &ch); return; } // Begin building the context, starting with the weapon type std::auto_ptr<ForgeContext> context(new ForgeContext); context->skill = skill; context->weaponInfo = LookupWeapon(arg); if (context->weaponInfo == NULL) { send_to_char("You do not know how to make weapons of that type.\n", &ch); return; } // Check for mana int manaCost(skill_table[gsn_forgeweapon].min_mana); if (ch.mana < manaCost) { send_to_char("You are too weary to forge a weapon right now.\n", &ch); return; } // Get the first object std::vector<OBJ_DATA*> baseObjects; if (!ObtainBaseObject(*context, baseObjects, ch, argument)) return; // Check for an alloy argument = one_argument(argument, arg); if (arg[0] != '\0' && !str_prefix(arg, "alloy")) { if (!ObtainBaseObject(*context, baseObjects, ch, argument)) return; argument = one_argument(argument, arg); } // Check for name if (arg[0] != '\0' && !str_prefix(arg, "name")) { // Verify max mana if (ch.max_mana < NamingManaCost) { send_to_char("You lack the will to speak a true Name.\n", &ch); return; } // Verify lava forge if (ch.in_room == NULL || !room_is_affected(ch.in_room, gsn_lavaforge)) { send_to_char("You may only confer a true Name from the heat of the earth itself, at a lava forge.\n", &ch); return; } context->named = true; argument = one_argument(argument, arg); } // Check for superfluous arguments if (arg[0] != '\0') { send_to_char("Syntax: forgeweapon <type> <base_object> [alloy <base_object>] [name]\n", &ch); return; } // Check for sufficient weight if (context->weight < context->weaponInfo->minWeight) { std::ostringstream mess; mess << "Forging a " << context->weaponInfo->name << " requires more raw material than that!\n"; send_to_char(mess.str().c_str(), &ch); return; } // Build object list to help with echoes std::ostringstream objMess; objMess << baseObjects[0]->short_descr; for (size_t i(1); (i + 1) < baseObjects.size(); ++i) objMess << ", " << baseObjects[i]->short_descr; if (baseObjects.size() > 1) objMess << " and " << baseObjects[baseObjects.size() - 1]->short_descr; std::string objList(objMess.str()); // Perform initial echoes std::ostringstream mess; mess << "With a blast of heat and flame, you render down " << objList << " into a liquid mass of metal."; act(mess.str().c_str(), &ch, NULL, NULL, TO_CHAR); mess.str(""); mess << "With a blast of heat and flame, $n renders down " << objList << " into a liquid mass of metal."; act(mess.str().c_str(), &ch, NULL, NULL, TO_ROOM); // Destroy the objects for (size_t i(0); i < baseObjects.size(); ++i) extract_obj(baseObjects[i]); // Set up the echo affect callbacks struct CallbackHandler { static bool HandleMove(CHAR_DATA * ch, ROOM_INDEX_DATA *, EchoAffect *, void * tag) { HandleCancel(ch, tag); return true; } static bool HandlePositionChange(CHAR_DATA * ch, int newPos, EchoAffect *, void * tag) { HandleCancel(ch, tag); return true; } static bool HandleCast(CHAR_DATA * ch, int, int, void *, int, EchoAffect *, void * tag) { HandleCancel(ch, tag); return true; } static bool CheckFailure(CHAR_DATA * ch, EchoAffect *, void * tag) { // Check for skill ForgeContext * context(static_cast<ForgeContext*>(tag)); if (number_percent() <= context->skill) { check_improve(ch, NULL, gsn_forgeweapon, true, 6); return false; } // Failed; increase the flaw count ++context->flaws; if (number_percent() <= context->flaws * 25) { // Fatal error act("You lose focus on your work, destroying it completely!", ch, NULL, NULL, TO_CHAR); act("$n loses focus on $s work, destroying it completely!", ch, NULL, NULL, TO_ROOM); check_improve(ch, NULL, gsn_forgeweapon, false, 6); delete context; return true; } // Non-fatal error act("You make a small error while folding the metal, introducing a slight flaw into the weapon.", ch, NULL, NULL, TO_CHAR); check_improve(ch, NULL, gsn_forgeweapon, false, 6); return false; } static bool Finish(CHAR_DATA * ch, EchoAffect *, void * tag) { std::auto_ptr<ForgeContext> context(static_cast<ForgeContext*>(tag)); CompleteWeapon(*ch, *context); return false; } private: static void HandleCancel(CHAR_DATA * ch, void * tag) { std::auto_ptr<ForgeContext> context(static_cast<ForgeContext*>(tag)); send_to_char("You abandon your efforts at the forge, letting the partially-worked metal run away to uselessness.\n", ch); act("$n abandons $s efforts at the forge, allowing the partially-worked metal to run away uselessly.", ch, NULL, NULL, TO_ROOM); } }; // Prepare the echoAffect EchoAffect * echoAff(new EchoAffect(1)); echoAff->SetPositionCallback(&CallbackHandler::HandlePositionChange); echoAff->SetMoveCallback(&CallbackHandler::HandleMove); echoAff->SetCastCallback(&CallbackHandler::HandleCast); // Add in lines echoAff->AddLine(&CallbackHandler::CheckFailure, "Working the mass carefully, you begin to shape the metal.", "Working the mass carefully, $n begins to shape the metal."); mess.str(""); mess << "As you fold the metal over itself time and again, it starts to take on the distinctive shape of a "; mess << context->weaponInfo->name << "."; std::ostringstream omess; omess << "As $n folds the metal over itself time and again, it starts to take on the distinctive shape of a "; omess << context->weaponInfo->name << "."; echoAff->AddLine(&CallbackHandler::CheckFailure, mess.str().c_str(), omess.str().c_str()); echoAff->AddLine(&CallbackHandler::CheckFailure, "Molding the weapon with magic and skill, you bring your work near completion.", "Molding the weapon with magic and skill, $n brings $s work near completion."); echoAff->AddLine(&CallbackHandler::Finish, ""); // Finish applying the effect echoAff->SetTag(context.release()); EchoAffect::ApplyToChar(&ch, echoAff); // Apply a cooldown AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = gsn_forgeweapon; af.location = APPLY_NONE; af.duration = 60; af.level = ch.level; affect_to_char(&ch, &af); // Charge mana and lag expend_mana(&ch, manaCost); WAIT_STATE(&ch, skill_table[gsn_forgeweapon].beats); }
ULONGLONG GetPerfData(LPCWSTR objectName, LPCWSTR instanceName, LPCWSTR counterName) { BYTE data[256]; WCHAR name[256]; ULONGLONG value = 0; CPerfSnapshot snapshot(&g_TitleCounter); CPerfObjectList objList(&snapshot, &g_TitleCounter); if (snapshot.TakeSnapshot(objectName)) { CPerfObject* pPerfObj = objList.GetPerfObject(objectName); if (pPerfObj) { for (CPerfObjectInstance* pObjInst = pPerfObj->GetFirstObjectInstance(); pObjInst != nullptr; pObjInst = pPerfObj->GetNextObjectInstance()) { if (*instanceName) { if (pObjInst->GetObjectInstanceName(name, 256)) { if (_wcsicmp(instanceName, name) != 0) { delete pObjInst; continue; } } else { delete pObjInst; continue; } } CPerfCounter* pPerfCntr = pObjInst->GetCounterByName(counterName); if (pPerfCntr != nullptr) { pPerfCntr->GetData(data, 256, nullptr); if (pPerfCntr->GetSize() == 1) { value = *(BYTE*)data; } else if (pPerfCntr->GetSize() == 2) { value = *(WORD*)data; } else if (pPerfCntr->GetSize() == 4) { value = *(DWORD*)data; } else if (pPerfCntr->GetSize() == 8) { value = *(ULONGLONG*)data; } delete pPerfCntr; delete pObjInst; break; // No need to continue } delete pObjInst; } delete pPerfObj; } } return value; }