// *************************************************************************** static DECLARE_INTERFACE_USER_FCT(getBotChatItemSheetForItemType) { if(args.size()!=1) { nlwarning("<getBotChatItemSheetForItemType> requires 1 arg"); return false; } // get arg uint a0= (uint)args[0].getInteger(); clamp(a0,(uint)0,uint(ITEM_TYPE::UNDEFINED)); // get sheet name string name= CBotChatPageTrade::getItemSheetNameForItemType((ITEM_TYPE::TItemType)a0); // result CSheetId sheetId; sheetId.buildSheetId(name); result.setInteger(sheetId.asInt()); return true; }
void CPrimitivePlugin::drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &ctx) { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); static const float POINT_ARROW_LINE_SIZE = 20.f; static const float POINT_ARROW_HEAD_SIZE = 8.f; static const float POINT_DOT_SIZE = 3.f; static const uint CIRCLE_SEGMENT_SIZE = 20; static const uint CIRCLE_MIN_SEGMENT_COUNT = 8; std::string *sheetName; primitive->getPropertyByName("sheet_client", sheetName); TCreatureInfo *info = NULL; if (!sheetName->empty()) { // two step init of id to remove a flooding NeL warning CSheetId id; id.buildSheetId(*sheetName+".creature"); std::map<NLMISC::CSheetId, TCreatureInfo>::iterator it(_CreatureInfos.find(id)); if (it != _CreatureInfos.end()) { info = &(it->second); } } const CPrimPoint *point = dynamic_cast<const CPrimPoint *>(primitive); if (point) { // Clip ? if (!ctx.Display->isClipped (&point->Point, 1)) { // Position in world CVector center = point->Point; ctx.Display->worldToPixel (center); // Dot CVector dot0, dot1, dot2, dot3; dot0 = center; dot0.x += POINT_DOT_SIZE; dot0.y += POINT_DOT_SIZE; dot1 = center; dot1.x -= POINT_DOT_SIZE; dot1.y += POINT_DOT_SIZE; dot2 = center; dot2.x -= POINT_DOT_SIZE; dot2.y -= POINT_DOT_SIZE; dot3 = center; dot3.x += POINT_DOT_SIZE; dot3.y -= POINT_DOT_SIZE; // Transform primitive transformVector (dot0, point->Angle, center); transformVector (dot1, point->Angle, center); transformVector (dot2, point->Angle, center); transformVector (dot3, point->Angle, center); // In world space ctx.Display->pixelToWorld (center); ctx.Display->pixelToWorld (dot0); ctx.Display->pixelToWorld (dot1); ctx.Display->pixelToWorld (dot2); ctx.Display->pixelToWorld (dot3); // Draw it ctx.Display->triRenderProxy (ctx.MainColor, dot0, dot1, dot2, ctx.Selected?2:0); ctx.Display->triRenderProxy (ctx.MainColor, dot2, dot3, dot0, ctx.Selected?2:0); // Need detail? if (ctx.ShowDetail) { // Prim class available ? const CPrimitiveClass *primClass = ctx.PrimitiveClass; if (primClass != NULL) { // Draw an arraow ? if (primClass->ShowArrow) { // Position in world center = point->Point; ctx.Display->worldToPixel (center); CVector arrow = center; CVector arrow0 = center; arrow.x += POINT_ARROW_LINE_SIZE; CVector arrow1 = arrow; CVector arrow2 = arrow; arrow0.x += POINT_ARROW_LINE_SIZE + POINT_ARROW_HEAD_SIZE; arrow1.y += POINT_ARROW_HEAD_SIZE; arrow2.y -= POINT_ARROW_HEAD_SIZE; // Transform primitive transformVector (arrow, point->Angle, center); transformVector (arrow0, point->Angle, center); transformVector (arrow1, point->Angle, center); transformVector (arrow2, point->Angle, center); // In world space ctx.Display->pixelToWorld (center); ctx.Display->pixelToWorld (arrow); ctx.Display->pixelToWorld (arrow0); ctx.Display->pixelToWorld (arrow1); ctx.Display->pixelToWorld (arrow2); // Draw it ctx.Display->lineRenderProxy (ctx.MainColor, center, arrow, ctx.Selected?2:0); ctx.Display->triRenderProxy (ctx.ArrowColor, arrow0, arrow1, arrow2, ctx.Selected?2:0); } } // Have bounding info ? if (info != NULL) { if (info->HaveRadius) { // Get it float fRadius = info->Radius; // Get the perimeter float perimeter = 2.f*(float)Pi*fRadius; // Get the perimeter on the screen perimeter *= (float)ctx.Display->getWidth() / (ctx.Display->_CurViewMax.x - ctx.Display->_CurViewMin.x); // Get the segement count perimeter /= (float)CIRCLE_SEGMENT_SIZE; // Clamp if (perimeter < CIRCLE_MIN_SEGMENT_COUNT) perimeter = CIRCLE_MIN_SEGMENT_COUNT; // Segment count uint segmentCount = (uint)perimeter; // Draw a circle CVector posInit = center; posInit.x += fRadius; CVector posPrevious = posInit; for (uint i=1; i<segmentCount+1; i++) { CVector pos = posInit; transformVector (pos, (float)i*2.f*(float)Pi/(float)segmentCount, center); ctx.Display->lineRenderProxy (ctx.MainColor, pos, posPrevious, ctx.Selected?2:0); posPrevious = pos; } } if (info->HaveBox) { CVector center = point->Point; // ctx.Display->worldToPixel (center); // Dot CVector dot0, dot1, dot2, dot3; dot0 = center; dot0.x += info->Length/2; dot0.y += info->Width/2; dot1 = center; dot1.x -= info->Length/2; dot1.y += info->Width/2; dot2 = center; dot2.x -= info->Length/2; dot2.y -= info->Width/2; dot3 = center; dot3.x += info->Length/2; dot3.y -= info->Width/2; // Transform primitive transformVector (dot0, point->Angle, center); transformVector (dot1, point->Angle, center); transformVector (dot2, point->Angle, center); transformVector (dot3, point->Angle, center); // In world space /* ctx.Display->pixelToWorld (center); ctx.Display->pixelToWorld (dot0); ctx.Display->pixelToWorld (dot1); ctx.Display->pixelToWorld (dot2); ctx.Display->pixelToWorld (dot3); */ // Draw it ctx.Display->lineRenderProxy (ctx.MainColor, dot0, dot1, ctx.Selected?2:0); ctx.Display->lineRenderProxy (ctx.MainColor, dot1, dot2, ctx.Selected?2:0); ctx.Display->lineRenderProxy (ctx.MainColor, dot2, dot3, ctx.Selected?2:0); ctx.Display->lineRenderProxy (ctx.MainColor, dot3, dot0, ctx.Selected?2:0); } } } } } }
// *************************************************************************** void CSBrickSheet::build (const NLGEORGES::UFormElm &root) { string sTmp; uint i; // read the array of skills string skillUseStr; TRANSLATE_VAL(skillUseStr, "Basics.Skill"); while(strFindReplace(skillUseStr, ":", " ")); std::vector<string> listSkill; splitString(skillUseStr," ",listSkill); // build the req skill array UsedSkills.clear(); UsedSkills.reserve(listSkill.size()); for(i=0;i<listSkill.size();i++) { SKILLS::ESkills skill= SKILLS::toSkill(listSkill[i]); // Yoyo: patch to read auto generated bricks if(skill==SKILLS::unknown) { skill = (SKILLS::ESkills)SKILLS::toSkill("S" + listSkill[i]); } // keep only whats work if(skill!=SKILLS::unknown) { UsedSkills.push_back(skill); } } // if empty, fill at least with unknown if(UsedSkills.empty()) UsedSkills.push_back(SKILLS::unknown); // get family id root.getValueByName (sTmp, "Basics.FamilyId" ); BrickFamily = BRICK_FAMILIES::toSBrickFamily (sTmp); if(BrickFamily==BRICK_FAMILIES::Unknown) nlwarning("CSBrickSheet:build: BrickFamily Unknown '%s'.", sTmp.c_str()); /* // Yoyo: patch to read auto generated bricks if(BrickFamily==BRICK_FAMILIES::Unknown) { string sheetName= Id.toString(); std::string::size_type end= sheetName.find(".sbrick")-2; BrickFamily = BRICK_FAMILIES::toSBrickFamily ( NLMISC::toUpper(sheetName.substr(0,end)) ); if(BrickFamily==BRICK_FAMILIES::Unknown) nlwarning("Unknown Family for SBrick: %s", sheetName.c_str()); } */ root.getValueByName (IndexInFamily, "Basics.IndexInFamily" ); root.getValueByName (Level, "Basics.Level" ); // read icons string Icon; root.getValueByName (Icon, "Client.Icon" ); Icon = strlwr(Icon); IdIcon = ClientSheetsStrings.add(Icon); string IconBack; root.getValueByName (IconBack, "Client.IconBack" ); IconBack = strlwr(IconBack); IdIconBack = ClientSheetsStrings.add(IconBack); string IconOver; root.getValueByName (IconOver, "Client.IconOver" ); IconOver = strlwr(IconOver); IdIconOver = ClientSheetsStrings.add(IconOver); string IconOver2; root.getValueByName (IconOver2, "Client.IconOver2" ); IconOver2 = strlwr(IconOver2); IdIconOver2 = ClientSheetsStrings.add(IconOver2); root.getValueByName (IconColor, "Client.IconColor" ); root.getValueByName (IconBackColor, "Client.IconBackColor"); root.getValueByName (IconOverColor, "Client.IconOverColor"); root.getValueByName (IconOver2Color, "Client.IconOver2Color"); root.getValueByName (SabrinaCost, "Basics.SabrinaCost" ); root.getValueByName (SabrinaRelativeCost, "Basics.SabrinaRelativeValue" ); // mandatory families MandatoryFamilies.clear(); char tmp[256]; for(i=0;i<SBRICK_MAX_MANDATORY;i++) { sprintf(tmp, "Mandatory.f%d", i); root.getValueByName (sTmp, tmp); if (!sTmp.empty()) { BRICK_FAMILIES::TBrickFamily bf= BRICK_FAMILIES::toSBrickFamily(sTmp); if(bf != BRICK_FAMILIES::Unknown) MandatoryFamilies.push_back( bf ); else nlwarning("Unknown Mandatory family %s",sTmp.c_str()); } } // Optional families OptionalFamilies.clear(); for(i=0;i<SBRICK_MAX_OPTIONAL;i++) { sprintf(tmp, "Optional.f%d", i); root.getValueByName (sTmp, tmp); if (!sTmp.empty()) { BRICK_FAMILIES::TBrickFamily bf= BRICK_FAMILIES::toSBrickFamily(sTmp); if(bf != BRICK_FAMILIES::Unknown) OptionalFamilies.push_back( bf ); else nlwarning("Unknown optional family %s",sTmp.c_str()); } } // Parameter families ParameterFamilies.clear(); for(i=0;i<SBRICK_MAX_PARAMETER;i++) { sprintf(tmp, "Parameter.f%d", i); root.getValueByName (sTmp, tmp); if (!sTmp.empty()) { BRICK_FAMILIES::TBrickFamily bf= BRICK_FAMILIES::toSBrickFamily(sTmp); if(bf != BRICK_FAMILIES::Unknown) ParameterFamilies.push_back( bf ); else nlwarning("Unknown Parameter family %s",sTmp.c_str()); } } // Credit families CreditFamilies.clear(); for(i=0;i<SBRICK_MAX_CREDIT;i++) { sprintf(tmp, "Credit.f%d", i); root.getValueByName (sTmp, tmp); BRICK_FAMILIES::TBrickFamily bf= BRICK_FAMILIES::toSBrickFamily(sTmp); if(bf != BRICK_FAMILIES::Unknown) CreditFamilies.push_back( bf ); } string ForbiddenDef; root.getValueByName (ForbiddenDef, "Basics.ForbiddenDef" ); IdForbiddenDef = ClientSheetsStrings.add(ForbiddenDef); string ForbiddenExclude; root.getValueByName (ForbiddenExclude, "Basics.ForbiddenExclude" ); IdForbiddenExclude = ClientSheetsStrings.add(ForbiddenExclude); // **** Properties Properties.clear(); for(i=0;i<MaxProperties;i++) { string val; root.getValueByName(val, toString("Basics.Property %d", i).c_str() ); if(!val.empty() && val!="NULL") { CProperty prop; prop.Text= val; Properties.push_back(prop); } } // **** Faber // The FaberPlan are stored in Mandatory only, but the tool filter is in root if( isFaber() && (isMandatory() || isRoot()) ) { string val; FaberPlan.ItemPartMps.clear(); FaberPlan.FormulaMps.clear(); // Get Item Built TRANSLATE_VAL(val, "faber.Create.Crafted Item"); FaberPlan.ItemBuilt.buildSheetId(val); // Get Skill Filters TRANSLATE_ENUM ( FaberPlan.ToolType, TOOL_TYPE::Unknown, TOOL_TYPE::toToolType, "faber.Tool type"); // Get NB item built (for ammo) TRANSLATE_VAL( FaberPlan.NbItemBuilt, "faber.Create.Nb built items"); // MPs. Try all MP1 .. 5 slots. Stop when not valid for (uint k=0; k< MAX_FABER_REQ_MP; ++k) { sint32 mpQuantity= 0; root.getValueByName(mpQuantity, toString("faber.Create.Quantity %d", k+1).c_str() ); // if the req quantity is not 0 if ( mpQuantity>0 ) { CFaberPlan::CItemPartMP mpVal; mpVal.Quantity= mpQuantity; // No error if unknown: filter not used (all MPs match) TRANSLATE_ENUM_NODB( mpVal.FaberTypeFilter, RM_FABER_TYPE::Unknown, RM_FABER_TYPE::toFaberType, toString("faber.Create.MP %d", k+1).c_str() ); // Add this req MP. FaberPlan.ItemPartMps.push_back(mpVal); } // else subsequents MP slots are not used else break; } // Formula MPs. Try all MP1 .. 5 slots. Stop when not valid for (uint k=0; k< MAX_FABER_REQ_MP; ++k) { sint32 mpQuantity= 0; root.getValueByName(mpQuantity, toString("faber.Create.Quantity formula %d", k+1).c_str() ); // if the req quantity is not 0 if ( mpQuantity>0 ) { CFaberPlan::CFormulaMP mpVal; mpVal.Quantity= mpQuantity; // No error if unknown: filter not used (all MPs match) TRANSLATE_VAL(val, toString("faber.Create.MP formula %d", k+1).c_str()); mpVal.ItemRequired.buildSheetId(val); // Add this req MP. FaberPlan.FormulaMps.push_back(mpVal); } // else subsequents MP slots are not used else break; } } // read minmax range/cast time when guigui ready TRANSLATE_VAL(MinCastTime, "Basics.MinCastTime"); TRANSLATE_VAL(MaxCastTime, "Basics.MaxCastTime"); TRANSLATE_VAL(MinRange, "Basics.MinRange"); TRANSLATE_VAL(MaxRange, "Basics.MaxRange"); // Read SPCost TRANSLATE_VAL(SPCost, "Basics.SPCost"); // Read AvoidCyclic TRANSLATE_VAL(AvoidCyclic, "Basics.AvoidCyclic"); // Read UsableWithEmptyHands TRANSLATE_VAL(UsableWithEmptyHands, "Basics.UsableWithEmptyHands"); // Read Action Nature string val; TRANSLATE_ENUM(ActionNature, ACTNATURE::UNKNOWN, ACTNATURE::toActionNature, "Basics.Action Nature"); // Read CivRestriction TRANSLATE_ENUM(CivRestriction, EGSPD::CPeople::Common, EGSPD::CPeople::fromString, "Basics.CivRestriction"); // **** parse properties, to precompute the Bricks Flags. BrickRequiredFlags= 0; for(i=0;i<Properties.size();i++) { string text= NLMISC::toLower(Properties[i].Text); // If the property is an opening property const string openingProp[]= { "opening_1:", "opening_2:", "opening_3:" }; // or if the property is a general brick flag const string neededBrickFlag= "needed_brick_flag"; const uint nOpeningProp= sizeof(openingProp) / sizeof(openingProp[0]); for(uint j=0;j<nOpeningProp;j++) { const string &prop= openingProp[j]; // if found this property if( text.compare(0, prop.size(), prop)==0 || (j==0 && text.compare(0, neededBrickFlag.size(), neededBrickFlag)==0) ) { // get all the opening requirement vector<string> strList; strList.reserve(10); splitString(text, ":", strList); for(uint k=1;k<strList.size();k++) { // remove empty space, and convert to a bit strRemoveChar(strList[k], ' '); BRICK_FLAGS::TBrickFlag evFlag; evFlag= BRICK_FLAGS::toBrickFlag(strList[k]); if(evFlag!=BRICK_FLAGS::UnknownFlag) BrickRequiredFlags|= (uint64(1)<<(uint)evFlag); } break; } } } // **** parse required skills // parse the sheet str string skillReqStr; TRANSLATE_VAL(skillReqStr, "Basics.LearnRequiresOneOfSkills"); while(strFindReplace(skillReqStr, ":", " ")); listSkill.clear(); splitString(skillReqStr," ",listSkill); // build the req skill array RequiredSkills.clear(); RequiredSkills.reserve(listSkill.size()/2); for(i=0;i<listSkill.size()/2;i++) { CSkillValue sv; sv.Skill= SKILLS::toSkill(listSkill[i*2]); fromString(listSkill[i*2+1], sv.Value); // keep only whats work if(sv.Skill!=SKILLS::unknown) { RequiredSkills.push_back(sv); } } // **** parse required bricks // parse the sheet str string brickReqStr; TRANSLATE_VAL(brickReqStr, "Basics.LearnRequiresBricks"); while(strFindReplace(brickReqStr, ":", " ")); std::vector<string> listBrick; listBrick.clear(); splitString(brickReqStr," ",listBrick); // build the req skill array RequiredBricks.clear(); RequiredBricks.reserve(listBrick.size()); for(i=0;i<listBrick.size();i++) { CSheetId sheetId; string str= listBrick[i]; strlwr(str); if(str.find(".sbrick")==string::npos) str+= ".sbrick"; sheetId.buildSheetId(str); if(sheetId!=CSheetId::Unknown) { RequiredBricks.push_back(sheetId); } } // faction index string faction; root.getValueByName (faction, "Basics.Faction" ); FactionIndex = CStaticFames::getInstance().getFactionIndex( faction ); // min fame value TRANSLATE_VAL(MinFameValue, "Basics.Minimum fame"); // **** Magic only: try to get a ResistType against this brick for(i=0;i<Properties.size();i++) { string text= toLower(Properties[i].Text); // *** If the property is a DamageType const string dmgTypeProp= "ma_dmg_type:"; if( text.compare(0, dmgTypeProp.size(), dmgTypeProp)==0 ) { // extract the dmg type string dtStr= text.substr(dmgTypeProp.size()); strRemoveChar(dtStr, ' '); DMGTYPE::EDamageType dt= DMGTYPE::stringToDamageType(dtStr); if(dt!=DMGTYPE::UNDEFINED) { // Convert to a resist type RESISTANCE_TYPE::TResistanceType rt= DMGTYPE::getAssociatedResistanceType(dt); if(rt!=RESISTANCE_TYPE::None) MagicResistType= rt; } } // *** Do the same if the property is an effect family (affliction spells) const string effectFamProp= "ma_effect:"; if( text.compare(0, effectFamProp.size(), effectFamProp)==0 ) { // extract the effect family string efStr= text.substr(effectFamProp.size()); strRemoveChar(efStr, ' '); EFFECT_FAMILIES::TEffectFamily ef= EFFECT_FAMILIES::toEffectFamily(efStr); if(ef!=EFFECT_FAMILIES::Unknown) { // Convert to a resist type RESISTANCE_TYPE::TResistanceType rt= EFFECT_FAMILIES::getAssociatedResistanceType(ef); if(rt!=RESISTANCE_TYPE::None) MagicResistType= rt; } } } }