not sure you're going to want to hear this, Morbane
of course go with what you want, I'm just going to bring up some issues i encountered and ideas.
Issues:
a) if the PC drops more than one item, can lead to a problem.
B) if GetRandomLocation() returns a location outside the walkable area, no beggar spawn.
- so i put CalcSafeLocation() in and that seems to clear things up.
c) I wasn't getting good results with GetExit(), so I went with GetNearestObject(oDoor)
- the timeout for ActionForceMoveToObject() was kicking in
- the timeout was also kicking in for Doors that can be opened, but ironically *not* for doors that are static.
- so i decreased the timeout to 7.5 seconds.
d) if the beggar hangs on something (say the PC tries to talk to it enroute), the whole thing hangs.
- so I lined all actions up for the beggar with ActionDoCommand(), then SetCommandable(FALSE)
- note that SetCommandable() has to be done via AssignCommand() or else it executes before the other AssignCommands and therefore prevents any actions from queueing.
I agree with Lance, that significant parts of your code are redundant. But if it works good for you it works good for me (i can just zap the critter with my insta-kill..)
// 'morbs_beggar'
// 2014 mar 24, fixed localObjects.
// 2014 mar 25, fixed CopyAndStoreItem(), stop retaining bPlot var during iterations.
// see GetRandomLocation() in 'x0_i0_position' condensed w/ CalcSafeLocation()
// oItem: denotes the Area
// fDist: distance from oItem
// oActor: size of walkable space needed
location GetRandomSafeLocation(object oItem, float fDist, object oActor)
{
//SendMessageToPC(GetFirstPC(FALSE), "run GetRandomSafeLocation()");
object oArea = GetArea(oItem);
float fFace = IntToFloat(Random(360));
location lItem = GetLocation(oItem);
vector vItem = GetPositionFromLocation(lItem);
vector vOut = Vector(0.f, 0.f, vItem.z);
float fDir = 0.f;
int i = 7;
do
{
//SendMessageToPC(GetFirstPC(FALSE), ". iterate");
// I want to do this because otherwise CalcSafeLocation() tends to
// cramp out-of-bounds spawns into a corner ... So, make several
// attempts to get a 'true' random location first.
fDir = IntToFloat(Random(360));
vOut.x = vItem.x + fDist * cos(fDir);
vOut.y = vItem.y + fDist * sin(fDir);
if (vOut.x < 0.f) vOut.x = -vOut.x;
if (vOut.y < 0.f) vOut.y = -vOut.y;
lItem = Location(oArea, vOut, fFace);
--i;
}
while (!GetIsLocationValid(lItem) && i > -1);
//SendMessageToPC(GetFirstPC(FALSE), "EXIT GetRandomSafeLocation()");
// This ought ensure that a path from the input position to the output
// location is valid.
return CalcSafeLocation(oActor, lItem, 50.f, TRUE, FALSE);
}
// Copies individual item to store then destroys it.
void CopyAndDestroyItem(object oItem, object oStore)
{
//SendMessageToPC(GetFirstPC(FALSE), "run CopyAndDestroyItem()");
int bPlot = FALSE;
if (GetPlotFlag(oItem))
{
bPlot = TRUE;
SetPlotFlag(oItem, FALSE);
}
object oCopy = CopyItem(oItem, oStore, TRUE);
DestroyObject(oItem);
if (bPlot)
SetPlotFlag(oCopy, TRUE);
}
// Copies bag contents to store then destroys source items.
void CopyAndStoreItem(object oItem, object oStore)
{
//SendMessageToPC(GetFirstPC(FALSE), "run CopyAndStoreItem()");
if (GetIsObjectValid(oItem)
&& GetIsObjectValid(oStore))
{
//SendMessageToPC(GetFirstPC(FALSE), ". . item & store VALID");
object oCopy = OBJECT_INVALID;
int bPlot = FALSE;
object oContent = GetFirstItemInInventory(oItem);
while (GetIsObjectValid(oContent))
{
//SendMessageToPC(GetFirstPC(FALSE), ". . . is in Bag: iterate contents");
if (GetPlotFlag(oContent))
{
bPlot = TRUE;
SetPlotFlag(oContent, FALSE);
}
else
bPlot = FALSE;
oCopy = CopyItem(oContent, oStore, TRUE);
DestroyObject(oContent);
if (bPlot)
SetPlotFlag(oCopy, TRUE);
oContent = GetNextItemInInventory(oItem);
}
//SendMessageToPC(GetFirstPC(FALSE), ". . call Copy & Destroy");
AssignCommand(GetModule(), DelayCommand(0.1f, CopyAndDestroyItem(oItem, oStore)));
}
}
// Checks localObject variables on Module.
int GetIsContent(object oItem)
{
//SendMessageToPC(GetFirstPC(FALSE), "run GetIsContent()");
int i = 0;
string sVar = "DroppedContent";
object oContent = GetLocalObject(OBJECT_SELF, sVar + IntToString(++i));
while (GetIsObjectValid(oContent))
{
//SendMessageToPC(GetFirstPC(FALSE), ". content " + IntToString(i) + " : " + GetName(oContent));
if (oContent == oItem)
{
//SendMessageToPC(GetFirstPC(FALSE), ". . return TRUE");
return TRUE;
}
oContent = GetLocalObject(OBJECT_SELF, sVar + IntToString(++i));
}
//SendMessageToPC(GetFirstPC(FALSE), ". . return FALSE");
return FALSE;
}
// Deletes localObject variables on Module.
void DeleteIsContent()
{
//SendMessageToPC(GetFirstPC(FALSE), "run DeleteIsContent()");
int i;
int iVars = GetVariableCount(OBJECT_SELF);
for (i = 0; i < iVars; ++i)
{
string sVar = GetVariableName(OBJECT_SELF, i);
if (GetStringLeft(sVar, 14) == "DroppedContent")
{
DeleteLocalObject(OBJECT_SELF, sVar);
--i;
}
}
}
// Make the beggar destucktible & destroy it.
// & close the door
void DestroyBeggar(object oBeggar, object oDoor)
{
//SendMessageToPC(GetFirstPC(FALSE), "run DestroyBeggar()");
SetPlotFlag(oBeggar, FALSE);
SetImmortal(oBeggar, FALSE);
AssignCommand(oBeggar, SetIsDestroyable(TRUE, FALSE));
DestroyObject(oBeggar);
if (GetIsObjectValid(oDoor)
&& GetIsOpen(oDoor))
{
AssignCommand(oDoor, DelayCommand(3.1f, ActionCloseDoor(oDoor)));
}
//SendMessageToPC(GetFirstPC(FALSE), "DestroyBeggar() EXIT");
}
// __________
// * MAIN ***
// ----------
void main()
{
SendMessageToPC(GetFirstPC(FALSE), "\nRun ( morbs_beggar ) " + GetName(OBJECT_SELF));
object oItem = GetModuleItemLost();
if (!GetIsObjectValid(oItem)
|| GetIsObjectValid(GetItemPossessor(oItem)))
{
return;
}
if (GetIsContent(oItem)) // in a Bag. Items in bags are handled by the bag itself.
return;
// this is also used as a placeholder for the beggar in GetRandomSafeLocation()
object oActor = GetModuleItemLostBy();
// don't want disarm to trigger this. Really.
if (GetIsInCombat(oActor))
return;
//SendMessageToPC(GetFirstPC(FALSE), ". dropped : " + GetName(oItem));
DeleteIsContent(); // Clean up vars on Module, ready for another run
DelayCommand(30.f, DeleteIsContent()); // keep the Vars clean. should do onExit area...
// Checks if item dropped is a container w/ Content. If so, write the
// contents as localObjects to the Module so they can be checked (see
// GetIsContent()) and bypassed (above), since each one would otherwise
// trigger this script. Items in bags are handled along with the bag --
// via CopyAndStoreItem() (fortunately the engine always drops the
// container first, so this actually works as intended).
int i = 0;
string sVar = "DroppedContent";
object oContent = GetFirstItemInInventory(oItem);
while (GetIsObjectValid(oContent))
{
SetLocalObject(OBJECT_SELF, sVar + IntToString(++i), oContent);
//SendMessageToPC(GetFirstPC(FALSE), ". . setLocal " + IntToString(i));
oContent = GetNextItemInInventory(oItem);
}
float fDist = IntToFloat(10 + d10());
location lSpawn = GetRandomSafeLocation(oItem, fDist, oActor);
object oBeggar = CreateObject(OBJECT_TYPE_CREATURE, "dexc_bombbunny", lSpawn, TRUE);
if (GetIsObjectValid(oBeggar))
{
//SendMessageToPC(GetFirstPC(FALSE), ". bunny created");
SetPlotFlag(oBeggar, TRUE);
SetCreatureScriptsToSet(oBeggar, SCRIPTSET_NOAI);
AssignCommand(oBeggar, ActionPickUpItem(oItem));
object oDoor = GetNearestObject(OBJECT_TYPE_DOOR, oBeggar);
AssignCommand(oBeggar, ActionForceMoveToObject(oDoor, TRUE, 2.35f, 7.65f));
AssignCommand(oBeggar, ActionOpenDoor(oDoor));
object oStore = GetObjectByTag("kg_st_flayer");
AssignCommand(oBeggar, ActionDoCommand(CopyAndStoreItem(oItem, oStore)));
AssignCommand(oBeggar, ActionDoCommand(DestroyBeggar(oBeggar, oDoor)));
AssignCommand(oBeggar, SetCommandable(FALSE, oBeggar));
}
}ps. I was using dex's BombBunny for oBeggar - it was pretty funny dropping 4 items and watching them all buzz around! (it's a bunny on flames, which somehow i think Lance could appreciate :)
whether you find something interesting or push on with your own that's great,
Modifié par kevL, 25 mars 2014 - 08:42 .