Log in

View Full Version : fake attackable objects


jdoran
10-31-2012, 05:51 PM
I'm trying to figure out if it would be possible to attack an object. I'm not talking about the destructible objects tied to zones, but something that looks like a static model and could be used in any zone. There would not need to be any animation.

There are some inanimate npc models, which would be my last choice.

An invisible frozen npc superimposed on a static object is one of the things I thought about, although I don't see how one could target the npc.

If I shrunk the size of the npc and buried it in the model, it might work. But smaller npcs are smaller targets, and pixel hunting would be frustrating. Burying the mob underground might work, but one would need to click on the ground to target.

The inanimate model might be implemented as a door, and when clicked could target the invisible npc. But I wouldn't want the npc becoming visible.

Does anyone have any clever ideas to fake this? I don't mind modifying the server to accomplish this. (However I'm not willing to try to make doors into mobs)

This is just a local proof of concept.

Caryatis
10-31-2012, 07:12 PM
You need to re-examine the reasons why you don't want to use destructible objects or inanimate npc models as you can't remove(ie kill) an object from the zone without shutting it down.

You need to remember you are working with a very constrained framework and if you don't want to mold that to suit your needs, you are going to have a bad time.

jdoran
10-31-2012, 07:35 PM
I have been led to believe that destructible objects are only available in certain of the later zones, in which case they would not be available to me in the older zones. If this is not the case, then I have a solution. I may go ahead and experiment with them in a newer zone anyway.

The only problem I have with inanimate models is the limited selection. In particular, no tents or structures. The races that look like banners would be my choice if I go this route.

The thing about constrained frameworks is there are often hacks/workarounds that people come up with. Invisible npcs to check proximities for example. I'm hoping that someone sees something that I don't. It would seem that this is close to doable: npcs can be attacked (but have the wrong models), static objects have the right models (but cannot be attacked). If I could come across a race that did not appear on the client, but could be targetted, then I would have a solution. There are a couple of races which do not display anything on the Underfoot client, however they cannot be targetted.

Randymarsh9
10-31-2012, 08:14 PM
Race 127 is invisible man. It's invisible and targetable as long as you do not have bodytype=11

Caryatis
10-31-2012, 08:38 PM
You can add any model(destructible or reg) to any zone, but you can not remove an object from a zone dynamically, so hack anyway you want with invis NPCs but its going to be very underwhelming to kill something only to have it remain in place.

jdoran
10-31-2012, 08:50 PM
I tried 127 earlier, but am not sure of the other npc attributes. I'll look into this some more. Thanks.

trevius
11-01-2012, 04:05 AM
You can actually remove objects from zones if they are ones you spawned dynamically at least. I have done basically the same thing you are wanting to do and it isn't too hard at all thanks to the object code added by Secrets (I think) last year. Here is an example default.pl I use in a zone I was working on for a bit. It does a few extra things in the script that you probably don't need, but the basic idea is there for you to play with:

Note that this is for the revamped version of Steamfont Mountains, so the objects used in this list most likely won't work for any other zone you try it in. You can just replace the list with objects available in the zone you are working on using the global model viewer tool.
sub EVENT_SPAWN {

# Prevent pets or charmed NPCs from loading the default.pl
if (!$npc || $npc->GetOwnerID() || $npc->GetSwarmOwner())
{
return;
}

my $NPCRace = $npc->GetRace();

# Races of the zone
$InvisibleRace = 127;
$TeleporterRace = 240;

if ($NPCRace == $InvisibleRace || $NPCRace == $TeleporterRace)
{
quest::settimer("SpawnObject", 35);
}


}


sub EVENT_TIMER {

# Prevent pets or charmed NPCs from loading the default.pl
if (!$npc || $npc->GetOwnerID() || $npc->GetSwarmOwner())
{
return;
}

my $NPCName = $npc->GetCleanName();
my $NPCID = $npc->GetID();

if ($timer eq "SpawnObject")
{
quest::stoptimer("SpawnObject");
$npc->SetEntityVariable(1, $NPCID);
# OBJ_AKHUTA_EXT_ACTORDEF
# OBJ_AKHUTA_INT_ACTORDEF
# OBJ_AKHUTB_EXT_ACTORDEF
# OBJ_AKHUTB_INT_ACTORDEF
# OBJ_TENT_KOBOLDA_ACTORDEF
# OBJ_TENT_KOBOLDB_ACTORDEF
# OBJ_FUEL_ORB_WPIPES_ACTORDEF
# OBJ_ROOF_METAL_ACTORDEF
# OBJ_DRAGONBONES_ACTORDEF
my $ObjectID = 0;
my $ObjectID2 = 0;
my $RandomNum = plugin::RandomRange(0, 1);
my $Degrees = plugin::ConvertHeadingToDegrees($h);
if ($NPCName =~ /Gnome House/i)
{
if ($RandomNum)
{
$ObjectID = quest::creategroundobjectfrommodel("OBJ_AKHUTA_EXT_ACTORDEF", $x, $y, $z, $Degrees);
$ObjectID2 = quest::creategroundobjectfrommodel("OBJ_AKHUTA_INT_ACTORDEF", $x, $y, $z, $Degrees);
}
else
{
$ObjectID = quest::creategroundobjectfrommodel("OBJ_AKHUTB_EXT_ACTORDEF", $x, $y, $z, $Degrees);
$ObjectID2 = quest::creategroundobjectfrommodel("OBJ_AKHUTB_INT_ACTORDEF", $x, $y, $z, $Degrees);
}
}
if ($NPCName =~ /Peasant Tent/i)
{
if ($RandomNum)
{
$ObjectID = quest::creategroundobjectfrommodel("OBJ_TENT_KOBOLDA_ACTORDEF", $x, $y, $z, $Degrees);
}
else
{
$ObjectID = quest::creategroundobjectfrommodel("OBJ_TENT_KOBOLDB_ACTORDEF", $x, $y, $z, $Degrees);
}
# Spawn a peasant to random roam outside near the tent
#quest::spawn2(42100003, 0, 0, $x, $y, $z, $h);
}
if ($NPCName =~ /Fuel Tank/i)
{
$ObjectID = quest::creategroundobjectfrommodel("OBJ_FUEL_ORB_WPIPES_ACTORDEF", $x, $y, $z, $Degrees);
}
if ($NPCName =~ /Dragon Bones/i)
{
$ObjectID = quest::creategroundobjectfrommodel("OBJ_DRAGONBONES_ACTORDEF", $x, $y, $z, $Degrees);
}

if ($ObjectID)
{
my $obj = $entity_list->GetObjectByID($ObjectID);
if ($obj)
{
$obj->SetEntityVariable(1, $NPCID);
}
}
if ($ObjectID2)
{
my $obj = $entity_list->GetObjectByID($ObjectID2);
if ($obj)
{
$obj->SetEntityVariable(1, $NPCID);
}
}
}

}


sub EVENT_DEATH {

# Prevent pets or charmed NPCs from loading the default.pl
if (!$npc || $npc->GetOwnerID() || $npc->GetSwarmOwner())
{
return;
}

my $NPCRace = $npc->GetRace();
my $NPCName = $npc->GetCleanName();

if ($NPCRace == $InvisibleRace || $NPCRace == $TeleporterRace)
{
my $NPCID = 0;
if ($npc->EntityVariableExists(1))
{
$NPCID = $npc->GetEntityVariable(1);
}
my @ObjList = $entity_list->GetObjectList();
foreach $ent (@ObjList)
{
if ($ent->EntityVariableExists(1) && $ent->GetEntityVariable(1) == $NPCID)
{
$ent->Depop();
#plugin::Debug("Object Depopped");
}
}
}

}


The above script should work, but I am not 100% sure if I ever submitted my ConvertHeadingToDegrees plugin, so you may need to add this to one of your plugin files if you don't have it already:

#Usage: my $Degrees = plugin::ConvertHeadingToDegrees(Heading);
# Converts 0-256 headings into 0 to 360 degrees

sub ConvertHeadingToDegrees {

my $Heading = $_[0];

my $ReverseHeading = 256 - $Heading;
my $ConvertAngle = $ReverseHeading * 1.40625;
if ($ConvertAngle <= 270)
{
$ConvertAngle = $ConvertAngle + 90;
}
else
{
$ConvertAngle = $ConvertAngle - 270;
}

return $ConvertAngle;
}

jdoran
11-01-2012, 02:54 PM
Thanks. Race 127 worked fine. And I appreciate the scripts to look at. I was thinking that I would need to use a door that turns invisible for the building.