Converti my purchase of 95-inch 96 and now the npc's (Vendor's) not respond to command sell (say).
Merchant.src
use npc;
use basic;
use cfgfile;
use os;
use uo;
include "include/dotempmods";
include "include/attributes";
include "include/eventid";
include "include/sysevent";
include "include/npcbackpacks";
include "include/randname";
include "include/utility";
include "include/mrcspawn";
include "include/speech";
include "include/myutil";
include "ai/setup/modsetup";
include "ai/main/sleepmode";
include "include/random";
include "include/factions";
const REACT_THRESHOLD := 3;
const RESPAWN_MINUTES := 30;
const MAXFRIENDS := 3;
const MAX_SKILLS := 48;
var me := Self();
var storage, inv_fs, inv_pb, inv_1c;
storage := FindStorageArea( "Merchant Storage" );
if (!storage)
exit;
endif
inv_fs := find_or_create_item( storage, me.serial + " FS", 0xe7c );
inv_pb := find_or_create_item( storage, me.serial + " PB", 0xe7c );
inv_1c := find_or_create_item( storage, me.serial + " 1C", 0xe7c );
if (!inv_fs || !inv_pb || !inv_1c)
exit;
endif
var speech;
var merchant_type;
var currentmoney;
SetSpeechAndType();
if( me.name["<random>"] )
SetMeUp();
endif
EnableEvents( REACT_THRESHOLD );
program merchantai()
me.title_suffix := "";
if ( me.graphic == 401 )
me.gender := 1;
endif
me.graphic := 400 + me.gender;
var next_restock := ReadGameClock() + RESPAWN_MINUTES*60;
WalkHome();
EnableMainEvents();
var mydestx := 0;
var mydesty := 0;
var steps := 0;
var wanders := 60;
var next_wander := ReadGameClock();
while (1)
var ev;
if (me.hidden)
me.hidden := 0;
endif
ev := os::wait_for_event( 120 );
if (ev)
case (ev.type)
SYSEVENT_ENGAGED:
say( ev.source.name + ", I'll call a guard, if you don't stop that!");
SYSEVENT_DAMAGED:
SetHp(me, me.maxhp);
if( me.poisoned ) CurePoison( me ); endif
// ev.source.hp := 0; hploss removed
say("Help guards!!! I'm being attacked!!");
SetObjProperty(me, "guardkill", 1);
start_script( ":areas:callguards", me );
sleep(5);
say("You scoundrel!!!");
foreach chr in EnumerateOnlineCharacters()
if (chr.cmdlevel>0)
SendSysMessage(chr, CStr(ev.source.name + " is attacking an invul NPC!!!"), 3, 130);
endif
endforeach
me.hidden := 1;
sleep(200);
me.hidden := 0;
SYSEVENT_ENTEREDAREA:
YellToFriend(ev.source);
SYSEVENT_SPEECH:
If( !IsOpposingFaction( me, ev.source ) )
TurnToward(ev.source);
if (ev.text["buy"])
var res;
res := SendBuyWindow( ev.source, inv_fs, me, inv_pb );
if (!res)
print( "SendBuyWindow failed: " + res.errortext );
endif
elseif (ev.text["sell all"])
BuyAll(ev.source);
elseif (ev.text["sell bag"])
BuyBag(ev.source);
elseif (ev.text["sell many"])
BuyMany(ev.source);
elseif (ev.text["sell"])
sell(me, ev.source );
/*
set_priority( 1 );
currentmoney:= CheckMoney(ev.source);
var res := SendSellWindow( ev.source, me, inv_fs, inv_pb, inv_1c );
if (res)
PrintTextAbovePrivate( me, "Can I help thee?", ev.source );
else
print( "SendSellWindow failed: " + res.errortext );
endif
set_priority( 50 );
*/
elseif ( ev.text["vendor train"] || ev.text["merchant train"] )
TurnToward( ev.source );
MerchantTrain( me, ev.source, ev.text );
else
check_speech(ev.text, ev.source);
endif
Endif
SYSEVENT_MERCHANT_BOUGHT:
TurnToward( ev.source );
PrintTextAbovePrivate( me, "The total of your sale is " + ev.amount, ev.source );
LogSold(ev.source);
set_priority( 50 );
SetObjProperty(me, "restock", 1);
var currentamount := CheckMoney(ev.source)-currentmoney;
var newamount := ev.amount - currentamount;
while( newamount > 60000 )
CreateItemInBackpack( ev.source, 0xeed, 60000 );
newamount := newamount - 60000;
endwhile
if( newamount > 0 ) CreateItemInBackpack( ev.source, 0xeed, newamount ); endif
newamount := 0;
SYSEVENT_MERCHANT_SOLD:
TurnToward( ev.source );
PrintTextAbovePrivate( me, "The total of your purchase is " + ev.amount, ev.source );
SetObjProperty(me, "restock", 1);
Var TotalSold := GetObjProperty( me, "MercTotalSold" );
If( !TotalSold )
TotalSold := 0;
Endif
SetObjProperty( me, "MercTotalSold", CInt( TotalSold ) + CInt( ev.amount ) );
TotalSold := GetObjProperty( me, "MercTotalSold" );
If( ev.source.cmdlevel )
PrintTextAbovePrivate( me, "I now have " + TotalSold + "gp to spend.", ev.source );
Endif
SYSEVENT_ITEM_GIVEN:
if( ev.item.objtype == 0xeed )
TrainSkill( me, ev.source, ev.item );
else
TakeItem(ev.source, ev.item);
endif
endcase
elseif (ReadGameClock() > next_restock)
if ( GetObjProperty(me, "restock") )
RestockInventory( merchant_type, inv_fs );
EraseObjProperty(me, "restock");
endif
next_restock := ReadGameClock() + RESPAWN_MINUTES*60;
endif
endwhile
endprogram
function BuyAll(you)
var itemdesc := ReadConfigFile("::itemdesc");
PrintTextAbovePrivate( me, "What would you like me to buy all of?", you );
var items := Target(you);
if ( (!items) || (not Accessible(you, items)) )
return;
endif
var elem := FindConfigElem(itemdesc, items.objtype);
if (!elem)
return;
endif
var itemprice := GetConfigInt(elem, "vendorbuysfor");
if( !itemprice )
return;
endif
Var MagicItemBonus := CInt( GetObjProperty( items, "uItemLevel" ) );
If( !MagicItemBonus )
MagicItemBonus := 1;
Endif
itemprice := itemprice * MagicItemBonus;
var theobjtype := items.objtype;
var thecolor := items.color;
var thecontainer := items.container.serial;
if (!itemprice)
return;
endif
Var GoldAvailable := CInt( GetObjProperty( me, "MercTotalSold" ) );
If( !GoldAvailable )
GoldAvailable := 0;
Endif
Var totalsale := 0;
Var itemamount := 0;
Foreach item in EnumerateItemsInContainer(you.backpack)
If( ( item.objtype == theobjtype ) &&
( item.color == thecolor ) &&
( !item.newbie ) &&
( item.container.serial == thecontainer ) &&
( !IsMagic( item ) ) && ( !IsContainer( item ) ) )
If( !GetObjProperty(item, "ownerserial") && ReserveItem( item ) )
itemamount := item.amount;
If( itemamount * itemprice < GoldAvailable )
If( DestroyItem( item ) )
totalsale := totalsale + ( itemprice * itemamount );
GoldAvailable := GoldAvailable - totalsale;
Sleepms( 100 );
Endif
Else
PrintTextAbovePrivate( me, "I can't afford that.", you );
ReleaseItem( item );
Return;
Endif
Else
PrintTextAbovePrivate( me, item.desc + " is marked!", you );
ReleaseItem( item );
Return;
Endif
Endif
Endforeach
If( GoldAvailable < 0 )
GoldAvailable := 0;
Endif
SetObjProperty( me, "MercTotalSold", GoldAvailable );
var amount := totalsale;
var stacksinbag := totalsale / 60000;
var putinbag;
for (putinbag := 1; putinbag <= stacksinbag; putinbag := putinbag + 1 )
CreateItemInContainer( you.backpack, 0xeed,60000);
endfor
var bagremainder := amount - (stacksinbag * 60000);
PrintTextAbovePrivate( me, "The total of your sale is " + totalsale, you );
CreateItemInContainer(you.backpack, "goldcoin", bagremainder );
Var TotalSold := GetObjProperty( me, "MercTotalSold" );
If( you.cmdlevel )
PrintTextAbovePrivate( me, "I now have " + TotalSold + "gp left to spend.", you );
Endif
LogSold(you);
Endfunction
function BuyBag(you)
var itemdesc := ReadConfigFile("::itemdesc");
PrintTextAbovePrivate( me, "What bag of stuff would you like to sell me?", you );
var bag := Target(you);
if (!bag)
return;
endif
if ( bag.serial != you.backpack.serial )
var inpack := 0;
foreach item in EnumerateItemsInContainer(you.backpack)
if (bag.serial == item.serial)
inpack := 1;
break;
endif
endforeach
if (!inpack)
say("That bag isn't in your inventory.");
return;
endif
else
say("You can't select your own backpack.");
return;
endif
If( !ReserveItem( bag ) )
say("That bag is being used.");
Return 0;
Endif
Var GoldAvailable := CInt( GetObjProperty( me, "MercTotalSold" ) );
If( !GoldAvailable )
GoldAvailable := 0;
Endif
Var elem;
Var itemprice;
Var itemamount;
Var totalsale := 0;
Foreach item in ListRootItemsInContainer(bag)
elem := FindConfigElem(itemdesc, item.objtype);
If(elem)
itemprice := GetConfigInt(elem, "vendorbuysfor");
Var MagicItemBonus := CInt( GetObjProperty( item, "ItemLevel" ) );
If( !MagicItemBonus )
MagicItemBonus := 1;
Endif
itemprice := itemprice * MagicItemBonus;
itemamount := item.amount;
If( ( itemprice ) && ( !item.newbie ) &&
( !IsContainer( item ) ) &&
( !IsMagic( item ) && ReserveItem( item ) ) )
If( !GetObjProperty( item, "ownerserial" ) )
Sleepms( 100 );
If( itemamount * itemprice < GoldAvailable )
If( DestroyItem( item ) )
totalsale := totalsale + ( itemprice * itemamount );
GoldAvailable := GoldAvailable - totalsale;
Else
ReleaseItem( item );
Say( item.desc + " is marked!");
Endif
Else
Say( "I can't afford all of that." );
ReleaseItem( bag );
ReleaseItem( item );
Break;
Endif
Else
ReleaseItem( item );
Say( item.desc + " is marked!" );
Endif
Endif
Endif
Endforeach
If( GoldAvailable < 0 )
GoldAvailable := 0;
Endif
SetObjProperty( me, "MercTotalSold", GoldAvailable );
Var amount := totalsale;
Var stacksinbag := totalsale / 60000;
Var putinbag;
For( putinbag := 1; putinbag <= stacksinbag; putinbag := putinbag + 1 )
CreateItemInContainer( you.backpack, 0xeed,60000);
Endfor
Var bagremainder := amount - (stacksinbag * 60000);
PrintTextAbovePrivate( me, "The total of your sale is " + totalsale, you );
CreateItemInContainer(you.backpack, "goldcoin", bagremainder );
Var TotalSold := GetObjProperty( me, "MercTotalSold" );
If( you.cmdlevel )
PrintTextAbovePrivate( me, "I now have " + TotalSold + "gp left to spend.", you );
Endif
ReleaseItem( bag );
endfunction
function BuyMany(you)
var itemdesc := ReadConfigFile("::itemdesc");
PrintTextAbovePrivate( me, "What would you like me to buy all of?", you );
var items := Target(you);
if ( (!items) || (not Accessible(you, items)) )
return;
endif
var elem := FindConfigElem(itemdesc, items.objtype);
if (!elem)
return;
endif
var itemprice := GetConfigInt(elem, "vendorbuysfor");
var theobjtype := items.objtype;
var thecolor := items.color;
var thecontainer := items.container.serial;
var thename;
if (items.name)
thename := items.name;
endif
if (!itemprice)
return;
endif
Var MagicItemBonus := CInt( GetObjProperty( items, "ItemLevel" ) );
If( !MagicItemBonus )
MagicItemBonus := 1;
Endif
itemprice := itemprice * MagicItemBonus;
Var GoldAvailable := CInt( GetObjProperty( me, "MercTotalSold" ) );
If( !GoldAvailable )
GoldAvailable := 0;
Endif
Var totalsale := 0;
Var itemamount := 0;
Foreach item in EnumerateItemsInContainer(you.backpack)
If( ( item.objtype == theobjtype ) &&
( item.color == thecolor ) &&
( !item.newbie ) &&
( item.container.serial == thecontainer ) &&
( !IsMagic( item ) ) && ( !IsContainer( item ) ) )
If( !GetObjProperty(item, "ownerserial") && ReserveItem( item ) )
itemamount := item.amount;
If( itemamount * itemprice < GoldAvailable )
If( DestroyItem( item ) )
totalsale := totalsale + ( itemprice * itemamount );
GoldAvailable := GoldAvailable - totalsale;
Sleepms( 100 );
Endif
Else
Say( "I can't afford that." );
ReleaseItem( item );
Return;
Endif
Else
Say( item.desc + " is marked!" );
ReleaseItem( item );
Return;
Endif
Endif
Endforeach
If( GoldAvailable < 0 )
GoldAvailable := 0;
Endif
SetObjProperty( me, "MercTotalSold", GoldAvailable );
var amount := totalsale;
var stacksinbag := totalsale / 60000;
var putinbag;
for (putinbag := 1; putinbag <= stacksinbag; putinbag := putinbag + 1 )
CreateItemInContainer( you.backpack, 0xeed,60000);
endfor
var bagremainder := amount - (stacksinbag * 60000);
PrintTextAbovePrivate( me, "The total of your sale is " + totalsale, you );
CreateItemInContainer(you.backpack, "goldcoin", bagremainder );
Var TotalSold := GetObjProperty( me, "MercTotalSold" );
If( you.cmdlevel )
PrintTextAbovePrivate( me, "I now have " + TotalSold + "gp left to spend.", you );
Endif
LogSold(you);
endfunction
function sell(me, you)
var itemdesc := ReadConfigFile("::itemdesc");
PrintTextAbovePrivate( me, "Can i help thee?", you);
var tgt := Target(you);
if ( (!tgt) || (not Accessible(you, tgt)) )
return;
endif
if ( tgt.container.serial != you.backpack.serial )
var inpack := 0;
foreach item in EnumerateItemsInContainer(you.backpack)
if (tgt.serial == item.serial)
inpack := 1;
break;
endif
endforeach
if (!inpack)
say("That item isn't in your inventory.");
return;
endif
endif
var elem := FindConfigElem(itemdesc, tgt.objtype);
if (!elem)
return;
endif
var itemprice := GetConfigInt(elem, "vendorbuysfor");
if(!itemprice)
return;
endif
Var MagicItemBonus := CInt( GetObjProperty( tgt, "ItemLevel" ) );
If( !MagicItemBonus )
MagicItemBonus := 1;
Endif
itemprice := itemprice * MagicItemBonus;
var amount := tgt.amount;
var sale;
if(tgt.movable==0)
return;
endif
if( !ReserveItem( tgt ) )
return;
endif
if(amount)
sale := itemprice * amount;
endif
Var GoldAvailable := CInt( GetObjProperty( me, "MercTotalSold" ) );
If( !GoldAvailable )
GoldAvailable := 0;
Endif
If( sale < GoldAvailable )
if( ( itemprice ) && ( !tgt.newbie ) && ( tgt.objtype != 0xeed ) && ( !IsMagic( tgt ) ) )
LogIt(you, tgt, sale);
var di := DestroyItem(tgt);
if(!di)
foreach chr in EnumerateOnlineCharacters();
if(chr.cmdlevel)
SendSysMessage(chr, "_POSSIBLE_ sell bug abuse detected for character " + you.name + " : " + di.errortext, 3, 130);
endif
endforeach
syslog("_POSSIBLE_ sell bug detected for chracter " + you.name + " : " + di.errotext + " for item : " + tgt + " " + tgt.serial);
return;
endif
GoldAvailable := GoldAvailable - sale;
SetObjProperty( me, "MercTotalSold", GoldAvailable );
var amount := sale;
var stacksinbag := sale / 60000;
var putinbag;
for (putinbag := 1; putinbag <= stacksinbag; putinbag := putinbag + 1 )
CreateItemInContainer( you.backpack, 0xeed,60000);
endfor
var bagremainder := amount - (stacksinbag * 60000);
PrintTextAbovePrivate( me, "The total of your sale is " + sale, you );
CreateItemInContainer(you.backpack, "goldcoin", bagremainder );
Var TotalSold := GetObjProperty( me, "MercTotalSold" );
If( you.cmdlevel )
PrintTextAbovePrivate( me, "I now have " + TotalSold + "gp left to spend.", you );
Endif
else
PrintTextAbovePrivate( me, "Sorry i can't buy this!", you );
endif
else
Say( "I can't afford that." );
ReleaseItem( tgt );
endif
endfunction
function LogSold(who)
var cfg;
var elemkey := who.name + "(" + who.acctname + ")";
var logfile := { };
var prop:= { };
prop .+ pname;
prop .+ pvalue;
foreach item in EnumerateItemsInContainer( inv_pb )
if ( (GetObjProperty(item, "ownerserial")) &&
(GetObjProperty(item, "ownerserial") != who.serial) )
prop.pname := "Owned by: "+ GetObjProperty(item, "ownername");
prop.pvalue := "item: " + item.name;
logfile.append( prop );
endif
DestroyItem( item );
endforeach
if ( len(logfile) )
AppendConfigFileElem( "itemssold", "SOLD BY", elemkey, logfile );
UnloadConfigFile("itemssold");
endif
endfunction
function WalkHome()
var myhome := {};
if (!GetObjProperty(me, "myhome"))
myhome[1] := me.x;
myhome[2] := me.y;
SetObjProperty(me, "myhome", myhome);
else
myhome := GetObjProperty(me, "myhome");
endif
if ( me.x == myhome[1] && me.y == myhome[2] )
SetAnchor( me.x, me.y, 3, 80 );
return;
endif
var i;
for (i := 1; i < 11; i := i + 1)
WalkTowardLocation(myhome[1], myhome[2]);
if (me.x == myhome[1] && me.y == myhome[2] )
break;
endif
endfor
if (me.x != myhome[1] && me.y != myhome[2] )
MoveCharacterToLocation(me, myhome[1], myhome[2],
GetMapInfo(myhome[1], myhome[2]).z, MOVECHAR_FORCELOCATION);
endif
SetAnchor( myhome[1], myhome[2], 3, 80 );
endfunction
function CheckMoney(who)
var totalmoney := 0, backpack := EnumerateItemsInContainer(who.backpack);
foreach item in backpack
if (item.objtype == UOBJ_GOLD_COIN)
totalmoney := totalmoney + GetAmount(item);
endif
endforeach
return totalmoney;
endfunction
function SetMeUp()
SetObjProperty(me, "serial", me.serial);
me.gender := Random(2);
me.graphic := 400+me.gender;
me.name := RandomName( me );
var style := "poor";
if ((lower(merchant_type) == "mage") || (lower(merchant_type) == "healer"))
style:="mage";
elseif ((lower(merchant_type) == "alchemist") || (lower(merchant_type) == "scribe"))
style:="mage";
elseif ((lower(merchant_type) == "weaponsmith") || (lower(merchant_type) == "armorer"))
style:="warrior";
elseif ((lower(merchant_type) == "tinker") || (lower(merchant_type) == "leatherworker"))
style:="warrior";
elseif ((lower(merchant_type) == "bowyer") || (lower(merchant_type) == "leatherworker"))
style:="warrior";
elseif ((lower(merchant_type) == "bard") || (lower(merchant_type) == "jeweler"))
style:="rich";
elseif ((lower(merchant_type) == "tailor") || (lower(merchant_type) == "architect"))
style:="rich";
else
style:="rich";
endif
var parms := {};
parms[1]:= me;
parms[2]:= style;
set_priority( 1 );
start_script("::/misc/dressme", parms);
if ( !me.title_suffix || me.title_suffix["error"] )
me.title_suffix := "";
endif
RestockInventory( merchant_type, inv_fs );
endfunction
function SetSpeechAndType()
var npccfg := ReadConfigFile("npcdesc");
var elem := npccfg[me.npctemplate];
speech := GetConfigString(elem, "speech");
merchant_type := GetObjProperty( Self(), "MerchantType" );
if( !merchant_type )
SetObjProperty( Self(), "MerchantType", "Mage" );
merchant_type := "Mage";
endif
endfunction
function EnableMainEvents()
EnableEvents( SYSEVENT_ITEM_GIVEN );
EnableEvents( SYSEVENT_ENGAGED);
EnableEvents( SYSEVENT_DAMAGED );
EnableEvents( SYSEVENT_ENTEREDAREA, 4 );
EnableEvents( SYSEVENT_SPEECH, 1 );
endfunction
function DisableMainEvents()
DisableEvents( SYSEVENT_ITEM_GIVEN );
DisableEvents( SYSEVENT_SPEECH );
endfunction
// Used to inform a player if and how much a NPC can train a player
function MerchantTrain( me, who, text )
var skillcfg := ReadConfigFile( "::skills" ); // Link to the skills cfg file 'pol\config\skills.cfg'
var elem; // used to contain the skill structure for the skill in question.
var i; // Counter for various operations
var totaltrain := 0; // How many skills the player can be trained in <Used as a flag>
// Get what the player says and divide it into words
var words := SplitWords( text );
// The third word is the skill we are looking for
var skill := words[3];
// Test to see if it exists, if not then player wants to know what NPC an train them
if( !skill )
var trainable := "";
// For each of the available skills
for( i := 0; i <= MAX_SKILLS; i := i+1 )
// acquire the skills attributes.
elem := FindConfigElem( skillcfg, i );
// if the NPC has the skill
if( GetEffectiveSkill(me, i) )
// if the NPC's skill is greater then the PC's
if ((GetEffectiveSkill(me, i)/3) > GetEffectiveSkill(who, i))
// Add the skill to the string, and increment total train.
trainable := trainable + GetConfigString( elem, "Name" ) + ", ";
totaltrain := totaltrain + 1;
endif
endif
endfor
// If there where skills that the PC can be trained in, list them, else say so.
if (totaltrain > 0)
say( "I can train thee in the following skills:" );
say(trainable);
else
say("I can not train thee.");
endif
else
// The player wishes to train in a skill
skill := lower(skill);
// for each of the available skills
for( i := 0; i <= MAX_SKILLS; i := i+1 )
// Acquire skill attributes
elem := FindConfigElem( skillcfg, i );
// Test to see if this skill is the one the player is referring to.
if( lower(GetConfigString( elem, "Name" )) == skill )
// Acquire the NPC's value at this skill.
var npc_level := (GetEffectiveSkill(me, i) / 3);
// Test to see if there is a skill value <Redundant check>
if( npc_level != 0 )
// Get PC's skill
var pc_level := GetEffectiveSkill( who, i );
// if the pc's skill is greater then the NPC's we can do nothing
if( pc_level > npc_level )
say("I cannot teach you anymore.");
return;
else
// Determine the cost for training the PC, and inform the PC of the cost
var skillid := i;
var trainmaxcost := GoldForSkillGain(npc_level, pc_level, skillid);
say( "I will train thee " + GetConfigString( elem, "Name" ) + " for " + trainmaxcost + " gold.");
// Mark the PC with the skill and The cost to train in the skill
SetObjProperty( who, "TrainMaxCost", trainmaxcost );
SetObjProperty( who, "TrainSkillID", skillid );
return;
endif
endif
endif
endfor
// All else, The player named an unknown skill.
say("I know not of that skill.");
endif
endfunction
// This handles the NPC's training of the PC or the PC's donation of gold to the NPC
// TODO: Reputation bonus if gold donation is greater then a specific amount.
function TrainSkill( me, who, item )
var skillcfg := ReadConfigFile( "::skills" ); // Link to master skills config file
var variance := 0; // The variance between the players skill and the npc's skill
var npc_level := 0; // The NPC's level at the skill
var pc_level := 0; // The PC's level at the skill
var goldreceived := 0; // The amount of gold the PC did give us.
var new_level := 0; // The PC's new skill level
var currentnpccost := 0; // The current NPC's cost for training the Player
// if the item handed to the NPC was gold and not zero <Integrity check>
if( (item.objtype == UOBJ_GOLD_COIN) && (item.amount != 0) )
// Acquire information on what skill the PC whishes to train in.
var trainmaxcost := GetObjProperty( who, "TrainMaxCost" );
var trainskillid := GetObjProperty( who, "TrainSkillID" );
// If the pc is not expecting training, then it was a donation.
if( (!trainmaxcost || !trainskillid) && trainskillid != 0)
say( "I don't know what this is for, but thanks!" );
DestroyItem( item );
// TODO: Reputation bonus
// TODO: OSI has a "Desires" property with all npc's. It's used to determine if an NPC gives out clues to a minor quest.
return;
endif
// If the NPC does have the skill
if( GetEffectiveSkill(me, trainskillid) )
npc_level := GetEffectiveSkill(me, trainskillid) / 3; // Acquire NPC's training level
pc_level := GetEffectiveSkill(who, trainskillid); // Acquire PC's level
goldreceived := item.amount; // How much gold was received
variance := npc_level - pc_level; // How many skill points are there between the npc and player.
currentnpccost := GoldForSkillGain(npc_level, pc_level, trainskillid);
// Double check to make sure that the pc's skill is lower then the NPC's
if (pc_level < npc_level)
// If what the NPC can train the player is different from what the player is expecting, adjust accordingly.
if (currentnpccost != trainmaxcost)
if (currentnpccost > trainmaxcost)
// The current NPC is better then the one we received an offer from.
npc_level := SkillGainForGold(npc_level, pc_level, trainskillid, trainmaxcost); // Adjust the NPC's level variable to the lower skill level
variance := npc_level - pc_level;
else
// The current NPC is worse then the one we received an offer from.
// Determine what the cost would be for this NPC
if (goldreceived > currentnpccost)
// The NPC can't help the player
say("I can not train thee to that level.");
MoveItemToContainer( who.backpack, item );
return;
else
// The NPC can help, but we need to adjust
trainmaxcost := currentnpccost;
endif
endif
endif
// Determine what level the player will be trained to
// if the PC gives the NPC the max cost or more. Train them to the fullest
if( trainmaxcost <= goldreceived )
new_level := (npc_level * 10);
EraseObjProperty( who, "TrainMaxCost" ); // Clear the trainmaxcost property on the PC.
EraseObjProperty( who, "TrainSkillID" ); // Clear the skill flag
// TODO: If the player gives a lot more then the training cost, grant a Reputation Bonus and/or a mini-quest clue.
else
// Train the PC to whatever percentage they can afford.
new_level := ((pc_level + CInt((CDbl(variance) * (CDbl(goldreceived) / CDbl(trainmaxcost))))) * 10);
SetObjProperty( who, "TrainMaxCost", trainmaxcost-goldreceived );
endif
say("Let me show you how it's done."); // NPC informs player training was successful
// Set the PC's skill
SetBaseSkillBaseValue( who, trainskillid, new_level);
DestroyItem( item ); // Destroy gold
SendSysMessage( who, "Your skill increases." ); // Note increase
else
// PC just paid NPC to be trained but NPC doesn't have the skill.
say("I'm not as good as thee. Please find another to train thee.");
MoveItemToContainer( who.backpack, item );
endif
else
// NPC does not have that skill to train the PC. Return gold
say("I don't know that skill. Why don't you ask me what i can train you in?");
MoveItemToContainer( who.backpack, item );
endif
else
// PC gave NPC something else other then gold. Return it.
say("Bah, I have no use for this. Be off with ye.");
MoveItemToContainer( who.backpack, item );
// TODO: OSI has a "Desires" property with all npc's. I think it's used to determine if an NPC
// gives out clues to a minor quest or reputation bonus, depending on the item donated <Type and value>
endif
endfunction
// Used to determine cost for raising the pc's skill to the level of the NPC.
// Note: This function is designed to handle different skills have different rates at different levels, etc.
function GoldForSkillGain( npc_skill, pc_skill, skillid )
var maxskill := npc_skill - pc_skill;
return maxskill*10; // Cost equals ten times the difference.
endfunction
// Used to determine what the skill level of the PC will be for the amount of gold they gave
// Note: This function is designed to handle different skills have different rates at different levels, etc.
function SkillGainForGold(npc_level, pc_level, trainskillid, goldreceived)
return (goldreceived/10) + pc_level;
endfunction
function IsMagic(item)
if ( item.desc["magic"] )
say("Ooh, "+item.desc);
return 1;
else
return 0;
endif
endfunction
function BuyContainers( you )
var itemdesc := ReadConfigFile("::itemdesc");
PrintTextAbovePrivate( me, "What containers would you like me to buy all of?", you );
var items := Target(you);
if ( (!items) || (not Accessible(you, items)) )
return;
endif
var elem := FindConfigElem(itemdesc, items.objtype);
if (!elem)
return;
endif
var itemprice := GetConfigInt(elem, "vendorbuysfor");
var theobjtype := items.objtype;
var thecolor := items.color;
var thecontainer := items.container.serial;
if (!itemprice)
return;
endif
//zeeber changed this bit same again
var totalsale := 0;
var itemamount := 0;
foreach item in EnumerateItemsInContainer(you.backpack)
if ( (item.objtype == theobjtype) &&
(item.color == thecolor) &&
(!item.newbie) &&
(item.container.serial == thecontainer) &&
(!IsMagic(item)) )
if (!GetObjProperty(item, "ownerserial") && ReserveItem( item ))
itemamount := item.amount;
if (totalsale + (itemprice * itemamount) < 50000)
if (DestroyItem(item))
totalsale := totalsale + (itemprice * itemamount);
sleepms(100);
if (totalsale > 50000)
break;
endif
endif
else
say("That's too much!");
break;
endif
else
say(item.desc + " is marked!");
endif
endif
endforeach
PrintTextAbovePrivate( me, "The total of your sale is " + totalsale, you );
CreateItemInContainer(you.backpack, "goldcoin", totalsale);
LogSold(you);
endfunction
function LogIt(me, item, sellprice)
var where := me;
var desc := "name: " + me.name + " / acct: " + me.acctname;
var elemkey := desc;
var props:= array;
var prop:= array;
prop .+ pname;
prop .+ pvalue;
prop.pname := "x y z: ";
prop.pvalue := where.x + " " + where.y + " " + where.z;
props[1] := prop;
prop.pname := "item: ";
prop.pvalue := item.name;
props[3] := prop;
prop.pname := "serial: ";
prop.pvalue := item.serial;
props[4] := prop;
prop.pname := "sell price:";
prop.pvalue := sellprice;
props[5] := prop;
AppendConfigFileElem( "sell-logger", "res", elemkey, props );
UnloadConfigFile("textcmd.res");
endfunction
Compiling: c:\pol2\scripts\ai\merchant.src
Expected an identifier, got User Function ListRootItemsInContainer instead.
Near: function ListRootItemsInContainer(container)
File: c:/pol2/scripts/include/containers.inc, Line 104
File: c:/pol2/scripts/include/containers.inc, Line 104
Error reading function
File: c:/pol2/scripts/include/containers.inc, Line 104
someone please help me .../*
* $Id: containers.inc 979 2007-01-19 04:22:30Z sroyalty $
*
*/
use uo;
use os;
/*
* AmountInContainer(container, properties)
*
* Purpose
* Finds the amount of items with a certain objtype and
* optional additional properties that are in a container.
*
* Parameters
* container: Container to search
* properties: Optional - dictionary ( dict[property] = value )
* Example: dict{"objtype"->0x1235}; // only objtype 0x1235
* Example: dict{"color"->0} // only count if uncolored
*
* Return value
* Returns an integer
*
*/
function AmountInContainer(container, properties)
if ( Lower(TypeOf(properties)) != "dictionary" )
return error{"errortext":="Property list must be a dictionary."};
endif
var amount := 0;
MAIN: foreach item in ( EnumerateItemsInContainer(container) )
foreach property in ( properties.Keys() )
if ( item.Get_Member(property) != properties[property] )
continue MAIN;
endif
SleepMS(2);
endforeach
// amount + = item.amount;
SleepMS(2);
endforeach
return amount;
endfunction
/*
* FindMatchesInContainer(container, params)
*
* Purpose
* Builds a list of items with properties matching 'params'
*
* Parameters
* container: Container to search
* properties: Optional - dictionary ( dict[property] = value )
* Examples: dict{"color"->0} // only count if uncolored
* dict{"objtype"->0x123A, "color"->45}
* dict{"container"->itemref}
*
* Return value
* Returns an array of item refs.
*
*/
function FindMatchesInContainer(container, properties)
if ( Lower(TypeOf(properties)) != "dictionary" )
return error{"errortext":="Property list must be a dictionary."};
endif
var item_list := array{};
MAIN: foreach item in ( EnumerateItemsInContainer(container) )
foreach property in ( properties.Keys() )
if ( item.Get_Member(property) != properties[property] )
continue MAIN;
endif
SleepMS(2);
endforeach
item_list.Append(item);
SleepMS(2);
endforeach
return item_list;
endfunction
/*
* ListRootItemsInContainer(container)
*
* Purpose
* Returns an array of all of the top level items in a container.
*
* Parameters
* container: Container to search
*
* Return value
* Returns an array of item refs.
*
*/
function ListRootItemsInContainer(container)
var item_list := array{};
foreach item in ( EnumerateItemsInContainer(container) )
if ( item.container == container )
item_list.Append(item);
endif
SleepMS(2);
endforeach
return item_list;
endfunction
/*
* CreateLockID()
*
* Purpose
* Returns a new unique lock id for a container or other lockable.
*
* Parameters
*
* Return value
* Returns a lock id.
*
*/
function CreateLockID()
var lock_id := GetGlobalProperty( "NextLockID" );
if (!lock_id || lock_id.errortext)
lock_id := 1;
endif
SetGlobalProperty( "NextLockID", lock_id+1 );
return lock_id;
endfunction