Index: Distro/pkg/mobiles/merchants/config/npcdesc.cfg =================================================================== --- Distro/pkg/mobiles/merchants/config/npcdesc.cfg (revision 1090) +++ Distro/pkg/mobiles/merchants/config/npcdesc.cfg (working copy) @@ -66,4 +66,71 @@ EquipTemplate Villager_1 // CProps (eww!) -} \ No newline at end of file +} + +NPCTemplate BlacksmithMerchant +{ + // Primary NPC information + Name - the blacksmith + Script :brainAI:brain + ObjType 0x190 + Color 0 + TrueColor 0 + Gender 0 + AR 25 + RunSpeed 200 + Alignment neutral + Privs invul + Settings invul + Category Merchant + + // Attributes + Strength 2000 + Intelligence 2000 + Dexterity 2000 + + Wrestling 2000 + Tactics 2000 + + // Vitals + HITS 2000 + MANA 2000 + STAM 2000 + + // Intrinsic Weapon + AttackSpeed 1 + AttackDamage 100d100 + AttackAttribute Wrestling + AttackHitScript :combat:mainHitScript + + // Sounds + AttackHitSound 312 + AttackMissSound 569 + DeathSound 347 + DamagedSound 346 + IdleSound 1346 + + // Brain AI Settings + AISetting CycleWait i3600 + AISetting HearSpeech i1 + AISetting ListenRange i2 + AISetting NoSleep i1 + + // Brain AI Nerves + AIScript Combat :merchants:generic/combat + AIScript Init :merchants:generic/init + AIScript ItemGiven :merchants:generic/itemGiven + AIScript Listen :merchants:generic/listen + AIScript Merchant :merchants:generic/merchant + AIScript Restart :merchants:generic/restart + + // Skinning Info + // Skinning ItemName Amount + + // Settings other scripts use... + NameTemplate Human_Male + EquipTemplate Villager_1 + MerchantType Blacksmith + + // CProps (eww!) +} Index: Distro/pkg/mobiles/merchants/generic/init.src =================================================================== --- Distro/pkg/mobiles/merchants/generic/init.src (revision 1090) +++ Distro/pkg/mobiles/merchants/generic/init.src (working copy) @@ -10,6 +10,8 @@ include ":brainAI:npcInit"; include ":brainAI:npcCommands"; include ":dyes:dyes"; +include ":merchants:merchant"; +include ":merchants:storage"; program BrainCriticalScript(params) var npc := params[1]; @@ -42,5 +44,9 @@ SleepMS(2); endforeach + var merchant_type := CPM_GetMerchantType(npc); + var forsale := CPM_GetMerchantContainer(npc, CPM_FORSALE, CP_CREATE); + RestockInventory (merchant_type, forsale); + return 1; endprogram Index: Distro/pkg/mobiles/merchants/generic/listen.src =================================================================== --- Distro/pkg/mobiles/merchants/generic/listen.src (revision 1090) +++ Distro/pkg/mobiles/merchants/generic/listen.src (working copy) @@ -4,10 +4,13 @@ use uo; use os; +use util; +use cfgfile; include ":brainAI:eventid"; include ":brainAI:npcNerves"; include ":brainAI:npcCommands"; +include ":brainAI:npcUtil"; include ":merchants:merchant"; include ":merchants:storage"; @@ -18,12 +21,17 @@ //var settings := params[4]; //var scripts := params[5]; params := 0; // Not needed anymore. + + + var forsale := CPM_GetMerchantContainer(npc, CPM_FORSALE, CP_CREATE); + var buyable := CPM_GetMerchantContainer(npc, CPM_BUYING, CP_CREATE); + var shopping_cart := CPM_GetMerchantContainer(npc, CPM_SHOPPINGCART, CP_CREATE); while ( npc ) if ( event ) case ( event.type ) SYSEVENT_SPEECH: - SpeechEvent(npc, event); + SpeechEvent(npc, event, forsale, buyable, shopping_cart); break; default: break; @@ -37,21 +45,19 @@ endwhile endprogram -function SpeechEvent(npc, byref event) +function SpeechEvent(npc, byref event, forsale, buyable, shopping_cart) if ( event.text["buy"] ) - BuyStuff(npc, event.source); + BuyStuff(npc, event.source, forsale, shopping_cart); return 1; elseif ( event.text["sell"] ) - SellStuff(npc, event.source); + SellStuff(npc, event.source, forsale, buyable, shopping_cart); return 1; endif return 1; endfunction -function BuyStuff(npc, mobile) - var forsale := CPM_GetMerchantContainer(npc, CPM_FORSALE, CP_CREATE); - var shopping_cart := CPM_GetMerchantContainer(npc, CPM_SHOPPINGCART, CP_CREATE); +function BuyStuff(npc, mobile, forsale, shopping_cart) AI_Turn(npc, mobile, NETURN_TOWARD); var result := SendBuyWindow(mobile, forsale, npc, shopping_cart, 1); @@ -62,18 +68,16 @@ return 1; endfunction -function SellStuff(npc, mobile) - var forsale := CPM_GetMerchantContainer(npc, CPM_FORSALE, CP_CREATE); - var shopping_cart := CPM_GetMerchantContainer(npc, CPM_SHOPPINGCART, CP_CREATE); - var buyable := CPM_GetMerchantContainer(npc, CPM_BUYING, CP_CREATE); +function SellStuff(npc, mobile, forsale, buyable, shopping_cart) + var merchant_type := CPM_GetMerchantType(npc); + AI_Turn(npc, mobile, NETURN_TOWARD); - - if ( !HasSellableItems(buyable, mobile.backpack) ) + if ( !HasSellableItems(merchant_type, mobile.backpack) ) AI_Speak(npc, "You don't have anything that I am interested in buying."); return 1; endif - + var result := SendSellWindow(mobile, npc, forsale, shopping_cart, buyable); if ( result.errortext ) PrintTextAbove(npc, "SendSellWindow() error - "+result.errortext); Index: Distro/pkg/mobiles/merchants/include/merchant.inc =================================================================== --- Distro/pkg/mobiles/merchants/include/merchant.inc (revision 1090) +++ Distro/pkg/mobiles/merchants/include/merchant.inc (working copy) @@ -23,20 +23,171 @@ * */ -function HasSellableItems(container, backpack) - foreach item in ( EnumerateItemsInContainer(container) ) - if ( item.container != container ) - continue; - endif +var buySell_cfg := ReadConfigFile(":merchants:buySell"); + +function HasSellableItems(merchanttype, backpack) + var backpack_items := ListRootItemsInContainer(backpack); + var prodgroups := FindConfigElem(buySell_cfg, merchanttype); + var buys := GetConfigStringArray(prodgroups, "Buys"); + var normcost, normsell, percentage; + + // If not buying lets call the whole thing off. + if ( buys.size() < 1 ) + return 0; + endif - var props := dictionary{"objtype"->item.objtype, "container"->backpack}; - var plr_has := AmountInContainer(backpack, props); - if ( plr_has > 0 ) - return 1; - break; + var iteminit := 0; + var item_mark := -1; + + // set buy price for each item to be 0 to start. This means it won't be sellable. + foreach item in backpack_items + item.buyprice := iteminit; + SleepMS(2); + endforeach + + var buynobuyable := { }; + var objtype; + var counter := 0; + + // Populate the array of items the vendor will buy. + foreach prodgroup in buys + foreach itemstr in GetConfigStringArray(FindConfigElem(buySell_cfg, prodgroup), "Item") + itemstr := SplitWords(itemstr); + objtype := itemstr[1]; + if ( CInt(objtype) ) + objtype := CInt(objtype); + else + objtype := GetObjtypeByName(objtype); + endif + buynobuyable.append(objtype); + SleepMS(2); + endforeach + SleepMS(2); + endforeach + + // compare all the items in the top level of the backpack to things the vendor can buy and set the price. + if ( buynobuyable.size() ) + foreach item in backpack_items + if ( (item.objtype in buynobuyable) && (!item.newbie) ) + counter := counter + 1; + if ( !item.quality ) + item.quality := 1; + endif + var itemconfig := ReadConfigFile(":*:itemdesc"); + normcost := itemconfig[item.objtype].VendorBuysFor; + normsell := itemconfig[item.objtype].VendorSellsFor; + normcost := normcost * item.quality; + normsell := normsell * item.quality; + percentage := ( ( item.hp * 10 ) / item.maxhp ); + if(percentage) + normcost := CInt( ( normcost * percentage ) / 10 ); + normsell := CInt( ( normsell * percentage ) / 10 ); + item.buyprice := normcost; + item.sellprice := normsell; + else + item.buyprice := item_mark; + endif + endif + SleepMS(2); + endforeach + endif + return counter; +endfunction + +function CPM_GetMerchantType(npc) + var npc_cfg := NPC_GetNPCConfig(npc); + var type := npc_cfg.MerchantType; + return type; +endfunction + +function RestockInventory(merchanttype, byref inventory) + UnloadConfigFile (":merchants:buySell"); + foreach item in ListRootItemsInContainer (inventory) + DestroyItem (item); + SleepMS(2); + endforeach + + foreach productgroup in ProductGroups (buySell_cfg, merchanttype) + Restock (buySell_cfg, inventory, productgroup); + SleepMS(2); + endforeach + + foreach item in ListRootItemsInContainer ( inventory ) + if ( item.quality ) + item.quality := randomint (50) + 50; + item.hp := item.maxhp; endif SleepMS(2); endforeach +endfunction - return 0; +function ProductGroups (byref buySell_cfg, mtype) + var mtype_elem := FindConfigElem ( buySell_cfg, mtype ); + if (!mtype_elem) + return 0; + endif + + return GetConfigStringArray (mtype_elem, "Sells"); endfunction + +function Restock(byref buySell_cfg, byref inventory, byref productgroup) + var pg_elem := FindConfigElem (buySell_cfg, productgroup); + foreach itemstr in GetConfigStringArray (pg_elem, "Item") + SpawnItem (inventory, itemstr); + SleepMS(2); + endforeach + foreach itemstr in GetConfigStringArray( pg_elem, "Multibag" ) + var baglist := SplitWords(itemstr); + var spawnelem := FindConfigElem(buySell_cfg, baglist[1] ); + var desc := spawnelem.desc; + var stuffarray := GetConfigStringArray( spawnelem, "Item" ); + SpawnMultiBag( inventory, desc, stuffarray, cint(baglist[2]) ); + SleepMS(2); + endforeach +endfunction + +function SpawnMultiBag(byref inventory, desc, stuffarray, number) + var itemdesc := ReadConfigFile (":*:itemdesc"); + if (!itemdesc) + return 0; + endif + for i := 1 to number + var reg_bag := CreateItemInContainer (inventory, 0x0E76, 1); + if (!reg_bag) + return 0; + endif + reg_bag.name := desc; + reg_bag.sellprice := 10; + foreach item in stuffarray + var parms := SplitWords(item); + var elem := FindConfigElem(itemdesc, CInt(parms[1])); + if ( !elem ) + return 0; + endif + var item_price := GetConfigInt(elem, "VendorSellsFor"); + if ( !item_price ) + return 0; + endif + var it := CreateItemInContainer(reg_bag, CInt(parms[1]), CInt(parms[2])); + if ( !it ) + return 0; + endif + reg_bag.sellprice := reg_bag.sellprice + ( item_price * it.amount ); + SleepMS(2); + endforeach + endfor +endfunction + +function SpawnItem(byref inventory, itemstr) + var ii := SplitWords( itemstr ); + var objtype := ii[1]; + if (cint(objtype)) + objtype := cint(objtype); + else + objtype := GetObjtypeByName(objtype); + endif + var count := CInt(ii[2]); + CreateItemInInventory(inventory, objtype, count); +endfunction + + Index: Distro/pkg/skills/inscription/config/InscMenu.cfg =================================================================== --- Distro/pkg/skills/inscription/config/InscMenu.cfg (revision 1090) +++ Distro/pkg/skills/inscription/config/InscMenu.cfg (working copy) @@ -34,6 +34,7 @@ Group Circle 6 Group Circle 7 Group Circle 8 + Group Others } Craftitem Circle 1 @@ -156,3 +157,10 @@ Item summonwaterelemscroll } + +Craftitem Other +{ + //Sub Selections + Item Spellbook + Item runebook +} Index: Distro/pkg/skills/inscription/config/inscription.cfg =================================================================== --- Distro/pkg/skills/inscription/config/inscription.cfg (revision 1090) +++ Distro/pkg/skills/inscription/config/inscription.cfg (working copy) @@ -1501,3 +1501,45 @@ Retain 0 Assemble 0 } + +Element 0xEFA +{ + //Main Stuff + Name Spellbook + //Skill System + Skill 50.0 + Difficulty 65.0 + Points 50.0 + + //Material Related + Material 10 + Type Scroll + ManaUsage 50 + + //Booleans + Exceptional 1 + Mark 0 + Retain 0 + Assemble 0 +} + +Element 0x6100 +{ + //Main Stuff + Name Runebook + //Skill System + Skill 45.0 + Difficulty 65.0 + Points 50.0 + + //Material Related + Material 10 + Type Scroll + ManaUsage 50 + + //Booleans + Exceptional 1 + Mark 0 + Retain 0 + Assemble 0 +}