GetNearestObjectByTag - Won't Retrieve Object?
#1
Posté 05 juin 2014 - 04:12
I am in the process of trying to fix a lighting issue ...
and in the process I am checking to see if any "torches" are near to a creature by using this function: GetNearestObjectByTag
Now, when it does NOT find the object nearby, the creature has one created on them and they may or may not equip it. The item created has the same TAG as the function looks for. I have even confirmed the created item has the correct tag by debug feedback from the creature that carries it.
A few moments later, another NPC uses the same piece of code to check if anybody has a torch nearby ... and it fails to detect the object previously created for the earlier NPC. i.e The function returns OBJECT_INVALID, even though the earlier NPC confirmed the object TAG of the new torch created on them ... and continues to report the correct TAG on a heartbeat.
Any ideas anybody?
Cheers,
Lance.
#2
Posté 05 juin 2014 - 04:47
Not sure how to help unless you post the code that's causing problems. If I could hazard a guess it's because item objects don't have locations and area interaction like placeables or creatures, and you'll need to write your own code to check the equipped items of nearby NPCs.
#3
Posté 05 juin 2014 - 05:05
Not sure how to help unless you post the code that's causing problems. If I could hazard a guess it's because item objects don't have locations and area interaction like placeables or creatures, and you'll need to write your own code to check the equipped items of nearby NPCs.
OK, thanks for taking a look ... Here is an example of what I mean ... I had to take this from a larger function and edit it a bit, so I don't know if it works as it stands, but you get the gist, I hope.
EDIT: As you suggest, perhaps this function does not work with items. I thought I had used it this way in the past, but doing a quick search I didn't find anything when referring to an item.
It is called from a creatures heartbeart.
void CheckTorch()
{
object oNPC = OBJECT_SELF;
// OTHER RACES HAVE BETTER NIGHT VISION
if(GetRacialType(oNPC) == RACIAL_TYPE_HUMAN)
{
object oLightSource = GetItemPossessedBy(oNPC, "TorchHour");
if(oLightSource == OBJECT_INVALID){oLightSource = GetItemPossessedBy(oNPC, "LanternSixHour");}
// SCATTER LIGHT ACTIVATION RANDOMLY AMONG THOSE PRESENT
int iActivate = GetLocalInt(oNPC, "NPCLIGHTCHECK");
if(iActivate == 0)
{
iActivate = d10(2); SetLocalInt(oNPC, "NPCLIGHTCHECK", iActivate);
}
object oCarried = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oNPC);
string sLightTag = GetTag(oCarried);
if(oCarried == OBJECT_INVALID)
{
// TILE LIGHTING ISSUE (REDUCE CHANCE OF HAVING TORCH TO HELP PREVENT LIGHT ISSUE WHEN TOO MANY)
SetLocalInt(oNPC, "NPCLIGHTCHECK", iActivate - 1);
if(oLightSource == OBJECT_INVALID && iActivate == 1)
{
int iOption = d6();
// PREVENT TILE LIGHT ISSUE (ALSO NEED TO CONSIDER TORCHES AND LANTERNS)
object oNearestLight = GetNearestObject(OBJECT_TYPE_LIGHT);
object oNearestTorch = GetNearestObjectByTag("TorchHour", oNPC);
object oNearestLantern = GetNearestObjectByTag("LanternSixHour", oNPC);
if(oNearestTorch == OBJECT_INVALID){SendMessageToPC(GetFirstPC(), "<<< CANNOT FIND TORCH >>>");}
if(oNearestLantern == OBJECT_INVALID){SendMessageToPC(GetFirstPC(), "<<< CANNOT FIND LANTERN >>>");}
float fDisL = GetDistanceToObject(oNearestLight);
float fDisM = GetDistanceToObject(oNearestTorch);
float fDisN = GetDistanceToObject(oNearestLantern);
int iAllow = 1;
if(fDisL != -1.0 && fDisL < 20.0){iAllow = 0;}
if(fDisM != -1.0 && fDisM < 20.0){iAllow = 0;}
if(fDisN != -1.0 && fDisN < 20.0){iAllow = 0;}
SpeakString("LIGHT >>> " + GetTag(oNearestLight) + " AT " + FloatToString(fDisL), TALKVOLUME_SHOUT);
SpeakString("TORCH >>> " + GetTag(oNearestTorch) + " AT " + FloatToString(fDisM), TALKVOLUME_SHOUT);
SpeakString("LAMP >>> " + GetTag(oNearestLantern) + " AT " + FloatToString(fDisN), TALKVOLUME_SHOUT);
// LANTERN CHANCE
if(iOption == 6)
{
oLightSource = CreateItemOnObject("amr_it_brass_lantern");
SpeakString("MY LAMP TAG >>> " + GetTag(oLightSource), TALKVOLUME_SHOUT);
// GIVE MAXIMUM CHARGES
SetItemCharges(oLightSource, 50);
SetLocalInt(oLightSource, "BURNCOUNT", 50*18);
}
// CHANCE REDUCED FROM 100% TO HELP DECREASE "TILE LIGHT" ISSUE
else if(iAllow == 1)
{
oLightSource = CreateItemOnObject("torchhour");
SpeakString("MY TORCH TAG >>> " + GetTag(oLightSource), TALKVOLUME_SHOUT);
// GIVE MAXIMUM CHARGES
SetItemCharges(oLightSource, 50);
SetLocalInt(oLightSource, "BURNCOUNT", 50*3);
}
// FINISHED WHETHER HAVE A TORCH OR NOT
SetLocalInt(oNPC, "NPCLIGHTCHECK", -1);
}
// IF HAVE ONE, EQUIP IT
if(oLightSource != OBJECT_INVALID)
{
AssignCommand(oNPC, ClearAllActions(TRUE));
AssignCommand(oNPC, ActionEquipItem(oLightSource, INVENTORY_SLOT_LEFTHAND));
return; // SKIP FURTHER ACTIONS TO ENSURE FINISHES
}
}
}
}
#4
Posté 05 juin 2014 - 05:42
I'm fairly certain it won't work with items in inventories. You would have to scan inventories of all creatures in the area instead. On the ground.. not something ive ever tried with items.
There is another thing i once ran into though. The default number for instance in GetNearestObjectByTag is 0, and i seem to recall that it could have problems with that not finding anything. Changing it to 1 seemed to solve the problem, not sure why.
eg: GetNearestObjectByTag(itemtype, sourceobject, 1); or whatever.
#5
Posté 05 juin 2014 - 05:52
Yeah, as Loki said your code won't detect items. To avoid a giant heartbeat loop running on several NPCs it might be best to a single pass over an area (via area heartbeat) to determine which NPCs are eligible for carrying torches. Might be a bit of a complicated script but then your NPC heartbeat could just check whether or not the area determined that it was eligible for torch carrying.
#6
Posté 05 juin 2014 - 06:52
I'm fairly certain it won't work with items in inventories. You would have to scan inventories of all creatures in the area instead. On the ground.. not something ive ever tried with items.
There is another thing i once ran into though. The default number for instance in GetNearestObjectByTag is 0, and i seem to recall that it could have problems with that not finding anything. Changing it to 1 seemed to solve the problem, not sure why.
eg: GetNearestObjectByTag(itemtype, sourceobject, 1); or whatever.
Hi Loki_999,
Items in inventories is the most likely cause, as you say. I have run across the second issue before myself, and already checked that one ... but thanks for considering again.
Yeah, as Loki said your code won't detect items. To avoid a giant heartbeat loop running on several NPCs it might be best to a single pass over an area (via area heartbeat) to determine which NPCs are eligible for carrying torches. Might be a bit of a complicated script but then your NPC heartbeat could just check whether or not the area determined that it was eligible for torch carrying.
Hi P-E,
Yes, I reckon its the problem with inventory items ... I am looking at rewriting the script similar to how you say as well. All these "little issues" certainly slow down the process.
After much consideration, I will probably just check nearby NPCs left hand item using the cycle of GetFirstObjectInShape function.
Many thanks all,
Lance.
THIS BIT OF CODE WORKS FINE:-
// FIND POTENTIAL LIGHT CARRIERS
object oLightCarrier = GetFirstObjectInShape(SHAPE_SPHERE, 10.0, lNPC, FALSE, OBJECT_TYPE_CREATURE);
while(oLightCarrier != OBJECT_INVALID)
{
object oCheck = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oLightCarrier);
string sTagCheck = GetTag(oCheck);
if(sTagCheck == "TorchHour" || sTagCheck == "LanternSixHour")
{
iAllow = 0; break;
}
oLightCarrier = GetNextObjectInShape(SHAPE_SPHERE, 10.0, lNPC, FALSE, OBJECT_TYPE_CREATURE);
}
#7
Posté 05 juin 2014 - 10:40
Possibly you could do something with tag-based OnEquip/OnUnequip scripts for your torch that sets/unsets a variable on the associated creature.
#8
Posté 05 juin 2014 - 11:28
One method that might work would be to have an OnEquip script for the torch that applies a custom area-of-effect to the wielder (and an OnUnequip script that removes it again). The OnEnter script of the AOE could set a variable on other NPCs that prevents them from equipping torches of their own if they haven't already done so. The OnExit script for the AOE could delete that variable.
Each NPC could be running a heartbeat script that equips a torch if they don't have the variable set on them. Once they leave the 'aura' of another torch bearer, their HB script could re-evalute the situation and possibly equip a torch if needed (since the variable would have been deleted).
You would still have the situation where two torch bearers could come into close proximity though. I'm sure there'd be some way of determining which one of them should then unequip their torch, without both of them doing so and leaving everyone in the dark.
#9
Posté 06 juin 2014 - 11:25
Hi rjsahe and DannJ,
Thanks for the feedback.
As you can see from my edited post above, I found a solution using GetFirstObjectInShape and its accompanying "next" version. It's a quick solution, which (if you get the range about right) appears to work reasonably well enough.
A better solution may have been to keep checking if the NPC gets within another light source each heartbeat and un-equip if required (or re-equip if need be), but this would be too much of a resource hog and would probably not work that well, so I reckon the compromise I have above should do the trick .... It has so far. ![]()
Cheers,
Lance.





Retour en haut







