Ancordia_PRC8/_module/nss/pacifico_trash.nss
Jaysyn904 102ba7dab6 Initial Commit
Initial Commit
2023-09-21 19:51:32 -04:00

292 lines
8.7 KiB
Plaintext

/*
pacifico_trash - Garbage Collector and Lost & Found script
By: Mike Knowles aka pacifico
Email: mknowles@ilovescience.com
Garbage collector NPC who will wander around and pick up dropped
objects, either disposing of them, or putting the objects in a
"lost and found" chest.
Feel free to use/modify/whatever. I'd love credit if you change it,
but would love more an email if you use it and your thoughts (good and bad)
about it.
Version 1.2
*/
/*
The first few tags are easy ways to customize
the garbage collector. Hopefully most are obvious.
To use, just place him in your module and he'll start
cleaning up. He can be lazy sometimes, so don't expect
him to pick things up immediately. He'll get to it
eventually, though.
Also, if you create a placeable obect that's a container
(a chest is a good choice) with a tag of "pac_lost_found"
then the collector will put anything he finds into that chest
instead of getting rid of it.
ISSUES AND SUCH:
He's not terribly tolerant of full lost and founds, and of
non-destroyable things if there's no lost and found. Also,
he's even takes gold to the lost and found, which will be changed,
soon (as well as emptying out the lost and found periodically).
*/
string P_TAG_LOSTFOUND = "pac_lost_found"; // tag of the lost & found container. If this box exists, the collector
// will put the trash here, instead of destroying it (assuming there's room
// in the box).
float P_TRASH_DISTANCE = 15.0; // number of meters that the garbage collector will look for local trash.
int P_FLAG_EFFICIENT = 0; // if 1, then the NPC picks up things as soon as they're dropped and doesn't take breaks.
// this flag is good for small areas where a roving collector isn't as appropriate.
// For instance, this script could be applied to a barmaid who is a normal maid, but
// also has floor sweeping duties when people drop things.
int P_FLAG_WHINER = 1; // if 1, then the collector says what he's about to collect. 0 turns this off.
int P_FLAG_WHISTLE = 1; // Sometimes whistles while on break.
int P_VALUE_LAZY = 4; // Indicates how lazy the garbage collector is. P_FLAG_EFFICIENT overides this value.
// Values between 1-9 work. 9 = super lazy, 1 = hardly any breaks.
int P_VALUE_MAXBREAKLEN = 15; // The max number of rounds a break will last.
/*******************************************************/
/********* END FLAGS AND STUFF**************************/
int P_STATUS_NOTHING = 0;
int P_STATUS_WALKING = 1;
int P_STATUS_REMOVEITEM = 3;
int P_STATUS_LOSTFOUND = 4;
int P_STATUS_ONBREAK = -1;
int P_STATUS_WORKING = -2;
int DoCollection();
int DecideWhatToDo();
int WalkSomewhere();
int LostAndFound();
int StillOnBreak();
void main()
{
switch(GetLocalInt(OBJECT_SELF, "iStatus"))
{
case -1: //P_STATUS_ONBREAK:
SetLocalInt(OBJECT_SELF, "iStatus", StillOnBreak());
break;
case 3: //P_STATUS_REMOVEITEM:
SetLocalInt(OBJECT_SELF, "iStatus", DoCollection());
break;
case 4: //P_STATUS_LOSTFOUND:
SetLocalInt(OBJECT_SELF, "iStatus", LostAndFound());
break;
case 1: //P_STATUS_WALKING:
SetLocalInt(OBJECT_SELF, "iStatus", WalkSomewhere());
break;
case 0: //P_STATUS_NOTHING:
SetLocalInt(OBJECT_SELF, "iStatus", DecideWhatToDo());
break;
case -2: //P_STATUS_WORKING:
default:
break;
}
}
int DecideWhatToDo()
{
// reset our internal data.
SetLocalInt(OBJECT_SELF, "iBreakTime", 0);
SetLocalObject(OBJECT_SELF,"oThing", OBJECT_INVALID);
ClearAllActions();
// if we have something in our hands, we should deal with it before getting more garbage
if (GetIsObjectValid(GetFirstItemInInventory()))
{
// there's something in our inventory, so we should do something with it.
// Someday, we should support picking up more than one item at a time...
ClearAllActions();
return P_STATUS_LOSTFOUND;
}
// see if there is garbage nearby. If not, decide to move to another area or take a break.
object oThing = GetNearestObject(OBJECT_TYPE_ITEM);
if (GetIsObjectValid(oThing))
{
float fDist = GetDistanceToObject(oThing);
if (fDist<P_TRASH_DISTANCE)
{
// object is close - should go get it.
return P_STATUS_REMOVEITEM;
}
// there's something out there, so a break is less likely
if (Random(10)<P_VALUE_LAZY) { return P_STATUS_ONBREAK; }
return P_STATUS_WALKING;
}
// nothing around, anyway. Better time for a break.
if (Random(5)<(P_VALUE_LAZY)) { return P_STATUS_ONBREAK; }
return P_STATUS_WALKING;
}
int WalkSomewhere()
{
// right now, the garbage collector doesn't do any rounds, and just walks towards the next
// item. I want him to do rounds, instead, until he comes across items. Will take longer to
// pick things up, but would seem more 'real'.
object oThing = GetNearestObject(OBJECT_TYPE_ITEM);
if (GetIsObjectValid(oThing))
{
ActionMoveToObject(oThing,FALSE, IntToFloat(Random(15)+1));
} else {
ActionRandomWalk();
}
return P_STATUS_NOTHING;
}
int StillOnBreak()
{
if (P_FLAG_EFFICIENT)
{
ActionRandomWalk();
return P_STATUS_NOTHING;
}
int iBreakTime = GetLocalInt(OBJECT_SELF,"iBreakTime");
if (iBreakTime==0 && P_FLAG_WHINER) { ActionSpeakString("What a tough job. Time for a break."); }
iBreakTime++;
SetLocalInt(OBJECT_SELF, "iBreakTime", iBreakTime);
int iBreak = P_VALUE_MAXBREAKLEN - iBreakTime;
if ((Random(P_VALUE_MAXBREAKLEN)-iBreakTime)<0) { ClearAllActions(); return P_STATUS_NOTHING; }
if (Random(3)==0 && P_FLAG_WHISTLE) { ActionSpeakString("*whistles*"); }
ActionRandomWalk();
return P_STATUS_ONBREAK;
}
int LostAndFound()
{
object oThing = GetFirstItemInInventory();
if (!GetIsObjectValid(oThing))
{
ClearAllActions();
return P_STATUS_NOTHING;
}
object oBox = GetNearestObjectByTag(P_TAG_LOSTFOUND);
if (!GetIsObjectValid(oBox) && (GetObjectType(oBox)==OBJECT_TYPE_PLACEABLE))
{ //No lost and found found. Just destroy the object.
DestroyObject(oThing);
return P_STATUS_NOTHING;
}
if (GetDistanceToObject(oBox)>2.0)
{
ActionMoveToObject(oBox,FALSE,1.0);
return P_STATUS_LOSTFOUND;
}
ClearAllActions();
ActionGiveItem(oThing,oBox);
ActionSpeakString("Well, that's done. Off to find more trash");
return P_STATUS_LOSTFOUND;
}
int DoCollection()
{
object oSavedThing = GetLocalObject(OBJECT_SELF,"oThing");
if (GetIsObjectValid(oSavedThing)) // we have trash targeted already
{
object oThing = GetNearestObject(OBJECT_TYPE_ITEM);
if (!GetIsObjectValid(oThing))
{
// someone beat us to the item.
ClearAllActions();
return P_STATUS_NOTHING;
}
if (oThing != oSavedThing)
{ // Something happened... either someone picked up the item,
// or someone dropped something closer to us.
// Note: originally this did a separate check for another item, but
// it seemed better to have the DecideWhatToDo() function should
// handle that. Now, this could be combined with the IsValid check,
// above.
ClearAllActions();
return P_STATUS_NOTHING;
}
// Still moving to oThing [ActionPickUpItem(oThing);] from below
return P_STATUS_REMOVEITEM;
} else {
// find new trash
object oThing = GetNearestObject(OBJECT_TYPE_ITEM);
SetLocalObject(OBJECT_SELF, "oThing", oThing);
if (!GetIsObjectValid(oThing)) { ClearAllActions(); return P_STATUS_NOTHING; }
if (P_FLAG_WHINER)
{
string sMessage = "When will someone enforce those litter laws?";
ActionSpeakString(sMessage);
}
ActionMoveToObject(oThing,FALSE,1.0); // I want to walk there instead of run. Looks more natural to me for this job.
ActionPickUpItem(oThing);
}
return P_STATUS_REMOVEITEM; // want to return here
}