Loading...   

[Show Table of Contents]


§What is an Entity?

* Manipulating entity lists is EXTREMELY powerful and if you were smart you would read this article.

This article also assumes you have read other articles and have a relatively basic understanding of the quest/scripting engine.

To start off, an entity could be any of the following:

  • NPC ($npc)
  • Mob ($mob Almost the same thing as NPC, can be used interchangeably) 
  • Client ($client)
  • Door ($door - not implied)
  • Object ($object - not implied)
  • Corpse ($corpse - not implied)

Now, to differentiate implied and not implied, when we trigger events in Perl the EQEmu server software will push variables that are implied such as $client and $npc.

In this simple example below you can always assume that the $client is the player who 'triggered' the script to occur, and the NPC who is bound to the script that has triggered:

sub EVENT_SAY{
	if($text=~/hail/i){
		$client->Message(15, "This is a client message");
		$npc->Say("Hello there " . $name);
	}
}

Some of you may already know this as common knowledge, but in order for this to cover everyone's knowledge levels I will preamble with the basics a bit.

§What are Entity Objects?

Entity objects are used most commonly as a way encorporate the simple example above, I have one $client that triggered the script and a $npc that was triggered when I hailed​ the npc, but what they were really intended for is so you can flexibly 'select' any NPC in the zone when trying to perform any specific function.

We can essentially use a Controller NPC or any NPC for that matter to control any other NPC in the zone using entity objects, you just need to know how to select them and use them to your extreme advantage.

§Crushbone

I am going to use Crushbone as a simple example here.

This zone by default has 119 NPC's approximately. Most if not all of them are Orc's and some prisoners and such.

  • Below is a list of NPC's in the zone, we're simply using this as a reference of what kind of NPC's are in the zone. There are other ways to get this information using plugins and handy tools but for now simply for illustration purposes we want to take a quick survery of what we have in the zone and how many NPC's of certain name types we have.
  • Below is simpy the spawn data, it does not mean that all of these NPC's are what is spawned at all times in the database, these are the unique entries that are in the database. Once again there are about 119 NPC's with the zone fully popped.
mysql> SELECT
npc_types.id,
COUNT(npc_types.id) AS `npc_count`,
npc_types.`name`,
npc_types.lastname,
npc_types.`level`
FROM
(spawn2 ,
npc_types)
INNER JOIN spawnentry ON npc_types.id = spawnentry.npcID AND spawnentry.spawngroupID = spawn2.spawngroupID
WHERE spawn2.zone = 'crushbone' GROUP BY `npc_types`.`name`;
+-------+-----------+-----------------------------+----------+-------+
| id    | npc_count | name                        | lastname | level |
+-------+-----------+-----------------------------+----------+-------+
| 58059 |         1 | Ambassador_DVinn            |          |    20 |
| 58019 |         1 | an_elven_priest             |          |     5 |
| 58007 |         9 | an_elven_slave              |          |     3 |
| 58043 |         1 | an_orc_thaumaturgist        |          |    12 |
| 58020 |         9 | a_dwarven_slave             |          |     2 |
| 58018 |         3 | a_dwarven_smith             |          |     3 |
| 58032 |         1 | Emperor_Crush               |          |    18 |
| 58056 |         1 | Kelynn                      |          |     9 |
| 58028 |         1 | Lord_Darish                 |          |    14 |
| 58015 |       114 | orc_centurion               |          |     9 |
| 58025 |         6 | orc_emissary                |          |    15 |
| 58008 |        33 | orc_legionnaire             |          |    12 |
| 58024 |         9 | orc_oracle                  |          |    13 |
| 58001 |        25 | orc_pawn                    |          |     1 |
| 58042 |         1 | Orc_Scoutsman               |          |    12 |
| 58016 |        15 | orc_slaver                  |          |     5 |
| 58040 |         1 | orc_taskmaster              |          |    14 |
| 58035 |         1 | orc_trainer                 |          |    13 |
| 58047 |         1 | Orc_Warden                  |          |    14 |
| 58002 |         1 | orc_warlord                 |          |    16 |
| 58017 |         1 | Retlon_Brenclog             |          |    16 |
| 58010 |         1 | Rondo_Dunfire               |          |     9 |
| 58030 |         1 | royal_guard                 |          |    15 |
| 58058 |         1 | The_Fabled_Ambassador_Dvinn |          |    25 |
| 58057 |         1 | The_Fabled_Emperor_Crush    |          |    25 |
| 58031 |         1 | The_Prophet                 |          |    17 |
+-------+-----------+-----------------------------+----------+-------+
26 rows in set

§Manipulating the Entity List

Now, we can start getting to the real nuts and bolts of practical application here. Let's say I'm on a mission to liven up a custom version of my zone, and whenever Emperor Crush spawns, I want all of my Orc's in the zone to howl and beat their chest or swing their arm or do something provocative as well as make an emote we would use an example such as below.

quests/crushbone/Emperor_Crush.pl

sub EVENT_SPAWN{
	quest::shout("Graghhhh! Who goes there!"); #::: Ruh roh, Emperor is pissed I think!
	quest::settimer("get_zone_wriled_up", 3); #::: Use a timer so that if we #repop the zone, we give everything a little bit of time to pop before trying to manipulate the rest of the NPC's
}

sub EVENT_TIMER{
	if($timer eq "get_zone_wriled_up"){ #::: Triggering timer event
		quest::shout("lol"); #::: Some test thing message I left in apparently.
		my @nlist = $entity_list->GetNPCList(); #::: Use Entity List Object to get this
		foreach my $n (@nlist){ #::: Iterate through each NPC in the @nlist array
			if($n->GetCleanName()=~/orc/i){ #::: We are doing a simple string comparison, GetCleanName should be getting the name of the NPC, we want to match if it has the name 'orc' in it
				$n->Say("Yargghhh"); #::: Have each NPC say 'Yargghhh' that matches the name 'orc'
				$n->DoAnim(8); #::: Have each NPC do an attack aniamtion
			}
		}
		quest::stoptimer($timer); #::: Stop the timer, $timer is an exported object from the source as this event is triggered
	}
}
  • In this very quick example you can see that I used a timer as a delay to spawn the NPC's, and then I used a simply entity list iteration to have NPC's do what I want them to do

As you can see they Orc's are all performing animation 8 which is a simple attack animation, for animtions see Animation_Reference_(DoAnim)

You also see orcs nearby you are saying 'Yargghh''

§Iteration Example #2

  • Now, lets say I want to use the same iteration loop to do stuff to other NPC's. Let's say I want to have the slaves shout 'HLEP!' - this is getting a bit ridiculous isn't it? Who cares!
  • sub EVENT_SPAWN{
    	quest::shout("Graghhhh! Who goes there!");
    	quest::settimer("get_zone_wriled_up", 3);
    }
    
    sub EVENT_TIMER{
    	if($timer eq "get_zone_wriled_up"){
    		quest::shout("lol");
    		my @nlist = $entity_list->GetNPCList();
    		foreach my $n (@nlist){
    			if($n->GetCleanName()=~/orc/i){
    				$n->Say("Yargghhh");
    				$n->DoAnim(8);
    			}
    			if($n->GetCleanName()=~/slave/i){
    				$n->Shout("HLEPPP!");
    			}
    		}
    		quest::stoptimer($timer);
    	}
    }
  •  Now, I see exactly what we would expect, the slaves shouting for help, of course you could just have the elven scripts shout in their script but we're using this simply as an example

  • The same exact thing applies for clients, you can use any $client object listed in the Ultimate Perl Reference as manipulate the entity list and trigger any action in any event that you want. It is a less frequent thing to want to use a full list of clients to do something, but you can use it for a variety of things depending on the cool ideas that you come up with. But for examples sake I want to use an example where maybe I want to freeze all of the clients in a zone in a boss fight with Emperor Crushbone for many a few seconds at a time

§Client Example

quests/crushbone/Emperor_Crush.pl

sub EVENT_COMBAT{
	if($combat_state == 1){ #::: Attack state is on for NPC
		my @clist = $entity_list->GetClientList();
		foreach my $c (@clist){
			$c->Message(15, "You are frozen!");
			$c->Freeze();
		}
	}
}
  • And you can see below that when I attack Emperor Crush, I and every single other $client in the zone would be frozen until I did something to unfreeze the client. I literally had to force exit my game client because I lost complete control of my client and I could not do anything at this point. So it would be a good idea to set a timer for 5 seconds to also have all clients $client->UnFreeze(); once again to gain control.You may not want to actually use this example in your quests as there are spells that can achieve the same effect, this is simply for demonstrational purposes only.