ArcEmu: Dynamic Doors - ArcEmu

Jump to content

Toggle shoutbox Lastest Announcements

dfighter  : (07 December 2014 - 12:06 PM) Arcemu is in hibernation mode, please read http://arcemu.org/fo...showtopic=26903
dfighter  : (01 January 2013 - 05:56 PM) Arcemu wishes you all a happy new year!
Hasbro  : (12 September 2012 - 10:01 AM) Please excuse our outage from the web! Our web host had a major malfunction!
dfighter  : (01 September 2012 - 04:05 PM) Since the spam bots just don't want to stop, I've enabled admin verification when registering.
dfighter  : (23 January 2012 - 09:56 PM) Please note that from now on you will need to confirm your email on the wiki in order to edit it!
Hasbro  : (31 December 2011 - 12:50 PM) Happy New Years all!
Navid  : (26 December 2011 - 04:09 AM) Merry Christmas !!!!!! Happy holidays all :)
WAmadeus  : (24 December 2011 - 03:54 PM) Merry Christmas to all!
dfighter  : (24 December 2011 - 11:05 AM) The Arcemu team wishes y'all a Merry Christmukkah!
Hasbro  : (05 October 2011 - 12:53 PM) Looking for web designers for upcoming web related project. If you're interested in designing user interfaces contact me
dfighter  : (02 September 2011 - 03:47 PM) So who here wants vehicles in Arcemu? :P http://arcemu.org/fo...showtopic=25440
Hasbro  : (14 August 2011 - 03:25 PM) Join us on irc, grab an irc client and connect to irc.freenode.net join channel #arcemu /server irc.freenode.net:6667 /join #arcemu
jackpoz  : (03 August 2011 - 05:33 AM) to all Lua Engine (old one) users: please check http://arcemu.org/fo...showtopic=25274
Hasbro  : (20 May 2011 - 05:27 PM) Looking for people experienced with CMake configuration and setup! Contact me asap
Hasbro  : (15 May 2011 - 05:03 PM) ArcEmu is recruiting C++ programmers, contact Hasbro if interested.
paroxysm  : (03 May 2011 - 06:26 PM) Updated luabridge gossip example to describe the whole gossip creation process rather than just how to create menu. Gossip tutorial
paroxysm  : (23 April 2011 - 11:35 AM) Lua writers can refer to the Luabridge Tutorials section in the Wiki to learn how to write gossip code correctly.
Hasbro  : (20 April 2011 - 05:22 PM) Thank you for your continuous contribution of bug reports, we are working on them.
Hasbro  : (17 April 2011 - 03:20 AM) Please consider donating to support our bills. Donations can be sent using PayPal to donations@arcemu.org - Thank you for your support.
paroxysm  : (10 April 2011 - 12:43 AM) Refer to the Luabridge Tutorials section in the Wiki to learn the new syntax of luabridge.
Resize Shouts Area

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Dynamic Doors Manipulate your Doors!

#1 User is offline   niru4l 

  • Member
  • Pip
  • Group: Members
  • Posts: 14
  • Joined: 09-December 10
  • Gender:Male

Posted 02 April 2012 - 02:56 AM

The first part of this tutorial is just a translation from this german forum : Click here

This workshop is about how to manipulate doors, for example that they just open if you have a specific item.
First we have to add a new function to the class GameObjectAIScript located in ScriptMgr.h:

class SERVER_DECL GameObjectAIScript
{
	public:
		GameObjectAIScript(GameObject* goinstance);
		virtual ~GameObjectAIScript() {}

		virtual bool OnOpenDoor(Player* pPlayer, bool open){return true;} // this one
		virtual void OnCreate() {}
		virtual void OnSpawn() {}
                [...]


Now, this function should be called when a player clicks on the door. When a player clicks on the door WorldSession::HandleGameObjectUse is called, so we have to implement our new function there.

The function is located in MiscHandler.cpp, we have to switch to the case GAMEOBJECT_TYPE_DOOR, it should look like this:
	case GAMEOBJECT_TYPE_DOOR:
		{
			// cebernic modified this state =0 org =1
			if((obj->GetByte(GAMEOBJECT_BYTES_1, 0) == 0) ) //&& (obj->GetUInt32Value(GAMEOBJECT_FLAGS) == 33) )
				obj->EventCloseDoor();
			else
			{
				obj->SetUInt32Value(GAMEOBJECT_FLAGS, obj->GetUInt32Value( GAMEOBJECT_FLAGS ) | 1); // lock door
				obj->SetByte(GAMEOBJECT_BYTES_1, 0, 0);
				sEventMgr.AddEvent(obj,&GameObject::EventCloseDoor,EVENT_GAMEOBJECT_DOOR_CLOSE,20000,1,0);
			}
		}break;


Now we have to check if the gameobject has a script and if it returns true (open door) or false (keep door locked).

This should look like this:

	case GAMEOBJECT_TYPE_DOOR:
		{
			// cebernic modified this state =0 org =1
			if((obj->GetByte(GAMEOBJECT_BYTES_1, 0) == 0)) //&& (obj->GetUInt32Value(GAMEOBJECT_FLAGS) == 33) )
			{
				if(!obj->GetScript())
					obj->EventCloseDoor();
				else if(obj->GetScript()->OnDoorOpen(m_player, false))
					obj->EventCloseDoor();
			}
			else
			{
				if(obj->GetScript() && !obj->GetScript()->OnDoorOpen(_player, true))
					break;
				obj->SetUInt32Value(GAMEOBJECT_FLAGS, obj->GetUInt32Value( GAMEOBJECT_FLAGS ) | 1); // lock door
				obj->SetByte(GAMEOBJECT_BYTES_1, 0, 0);
				sEventMgr.AddEvent(obj,&GameObject::EventCloseDoor,EVENT_GAMEOBJECT_DOOR_CLOSE,20000,1,0);
			}
		}break;


Now you can make your first test, create a new GameObjectAIScript and implement the function OnDoorOpen(Player * plr, bool open)!

Heres an easy example:
class Opener : public GameObjectAIScript
{
public:
	static GameObjectAIScript* Create(GameObject* pObj) { return new Opener(pObj); }
	Opener(GameObject* pObj) : GameObjectAIScript(pObj) { }
	bool OnDoorOpen(Player* plr, bool open)
	{
		if(!open)
			return true;
		if(plr->GetItemInterface()->GetItemCount(60000) == 0)
		{
			char msg[255];
			sprintf(msg, "Requires '%s'", ItemPrototypeStorage.LookupEntry(60000)->Name1);
			plr->GetSession()->SendNotification(msg);
			return false;
		}
		plr->GetItemInterface()->RemoveItemAmt(60000, 1);
		return true;
	}
};



And now my part of the tutorial

My idea was it to create a door which you can just open if you stand in front of it, else it won't open, look at this layout:
Posted Image
The door should just open of the player is located in the red area. (Props to my drawing skills!)

For beeing able to check this we need the coordinates of the blue marked points. This is just a little bit mathematics and can be easily calculated with the equation of a circle (dont know if its the correct translation you know circle sinus cosinus and ....)

Ok now lets calculate the points:
bool CheckPosition(Player* pPlayer)
	{
		float x_coord[4];
		float y_coord[4];
		float player_x = pPlayer->GetPositionX();
		float player_y = pPlayer->GetPositionY();
		float player_z = pPlayer->GetPositionZ();
		float go_x = _gameobject->GetPositionX();
		float go_y = _gameobject->GetPositionY();
		float radius = 2.5;
		float radian;

		// point 1 easy going
		radian = 90*3.14/180;
		x_coord[0] = go_x - radius * cosf(radian + _gameobject->GetOrientation());
		y_coord[0] =  go_y - radius * sinf(radian + _gameobject->GetOrientation());

		// point 2 easy going
		radian = 270*3.14/180;
		x_coord[1] = go_x - radius * cosf(radian + _gameobject->GetOrientation());
		y_coord[1] =  go_y - radius * sinf(radian + _gameobject->GetOrientation());

		// point 3 use coordinates from point 1
		radian = 0;
		x_coord[2]  = x_coord[0]  - radius * cosf(_gameobject->GetOrientation());
		y_coord[2] =  y_coord[0] - radius * sinf(_gameobject->GetOrientation());

		// point 4 use coordinates from point 2
		x_coord[3]  = x_coord[1]  - radius * cosf(_gameobject->GetOrientation());
		y_coord[3] =  y_coord[1] - radius * sinf(_gameobject->GetOrientation());


Another layout which could maybe help you (punkt = point):
Posted Image
blue ones are point 1 and 2 red ones 3 and 4.

Now we have to get the smallest & biggest x coordinate and the smallest & biggest y coordinate (for checking if the player is located in that area), this is easy going with the bubblesort concept. Should look like this:
float t;
		int count = 4;
		int a;
		int b;
                // X PART
		for(a = 1; a < count; ++a)
		{
			for(b = count-1; b >= a; --:) 
			{
				if(x_coord[ b - 1] > x_coord[ b ]) 
				{
					t = x_coord[ b - 1];
					x_coord[ b - 1] = x_coord[ b ];
					x_coord[ b ] = t;
				}
			}
		}
                // Y PART
		for(a = 1; a < count; ++a)
		{
			for(b = count-1; b >= a; --B) 
			{
				if(y_coord[ b - 1] > y_coord[ b ]) 
				{
					t = y_coord[ b - 1];
					y_coord[ b - 1] = y_coord[ b ];
					y_coord[ b ] = t;
				}
			}
		}


Now at least we have to check if the player is in that area:

if(x_coord[0] < player_x &&
			x_coord[3] > player_x &&
			y_coord[0] < player_y &&
			y_coord[3] > player_y)
			return true; // open door
		else
			return false; // close door
	}


At the End the Script should look like this:
class HouseDoor : public GameObjectAIScript
{
public:
	HouseDoor(GameObject*  goinstance) : GameObjectAIScript(goinstance) {}
	static GameObjectAIScript* Create(GameObject* GO) { return new HouseDoor(GO); }

        bool CheckPosition(Player* pPlayer)
	{
		float x_coord[4];
		float y_coord[4];
		float player_x = pPlayer->GetPositionX();
		float player_y = pPlayer->GetPositionY();
		float player_z = pPlayer->GetPositionZ();
		float go_x = _gameobject->GetPositionX();
		float go_y = _gameobject->GetPositionY();
		float radius = 2.5;
		float radian;

		//Calculate points
		radian = 90*3.14/180;
		x_coord[0] = go_x - radius * cosf(radian + _gameobject->GetOrientation());
		y_coord[0] =  go_y - radius * sinf(radian + _gameobject->GetOrientation());


		radian = 270*3.14/180;
		x_coord[1] = go_x - radius * cosf(radian + _gameobject->GetOrientation());
		y_coord[1] =  go_y - radius * sinf(radian + _gameobject->GetOrientation());


		radian = 0;
		x_coord[2]  = x_coord[0]  - radius * cosf(_gameobject->GetOrientation());
		y_coord[2] =  y_coord[0] - radius * sinf(_gameobject->GetOrientation());


		x_coord[3]  = x_coord[1]  - radius * cosf(_gameobject->GetOrientation());
		y_coord[3] =  y_coord[1] - radius * sinf(_gameobject->GetOrientation());



		//Sort coordinates
		float t;
		int count = 4;
		int a;
		int b;
		for(a = 1; a < count; ++a)
		{
			for(b = count-1; b >= a; --B) 
			{
				if(x_coord[ b - 1] > x_coord[ b ]) 
				{
					t = x_coord[ b - 1];
					x_coord[ b - 1] = x_coord[ b ];
					x_coord[ b ] = t;
				}
			}
		}

		for(a = 1; a < count; ++a)
		{
			for(b = count-1; b >= a; --B) 
			{
				if(y_coord[ b - 1] > y_coord[ b ]) 
				{
					t = y_coord[ b - 1];
					y_coord[ b - 1] = y_coord[ b ];
					y_coord[ b ] = t;
				}
			}
		}

		//Check if player is in the selected area
		if(x_coord[0] < player_x &&
			x_coord[3] > player_x &&
			y_coord[0] < player_y &&
			y_coord[3] > player_y)
			return true; // open door
		else
			return false; // close door
	}

        bool OnOpenDoor(Player* pPlayer, bool open)
	{
            if(CheckPosition(pPlayer)
            {
               sChatHandler.BlueSystemMessageToPlr(pPlayer,"Youre welcome!");
               return true;
             }
            else
             {
               sChatHandler.RedSystemMessageToPlr(pPlayer,"No entry!");
               return false;
             }
        }
};


Good Luck to all which are going to use this and greets from germany :), I hope you enjoy this little workshop!
2

#2 User is offline   dfighter 

  • Titles are overrated
  • PipPipPipPipPipPipPipPipPipPip
  • Group: Administrator
  • Posts: 5,189
  • Joined: 14-June 08
  • IRC:dfighter
  • Gender:Male
  • Server OS:Linux

Posted 02 April 2012 - 10:55 PM

Can't you just check if the player faces the door using the orientation + distance somehow?
Also instead of writing some homebrew bubblesort you could just use http://www.cplusplus...algorithm/sort/ that's why it's in the STL :)
"The demand for free goods is infinite."
0

#3 User is offline   niru4l 

  • Member
  • Pip
  • Group: Members
  • Posts: 14
  • Joined: 09-December 10
  • Gender:Male

Posted 04 April 2012 - 03:52 AM

First i tried to work on a version which should just use distance and orientation from the player to the gameobject, but it bugged a lot.. depending on the orientation of the doors some work correct some open always and some won't open

Here's the code would be cool if someone could check it, because i donnot get what's wrong there..

bool CheckPosition(Player* pPlayer)
	{
		float radius = sqrt(pPlayer->GetDistance2dSq(_gameobject));


		//calculate the radian of the player to the gameobject 
		float b = pPlayer->GetPositionX() - _gameobject->GetPositionX();
		float radian = acosf(b/radius);

		float angle1; 
		float angle2 = 270*3.14/180 + _gameobject->GetOrientation();

		//orientation cannott be over 6.28
		if(angle2 > 2*3.14)
			angle2 = angle2 - 2*3.14;

		// 180 degrees
		if(angle2 > 3.14) 
			angle1 = angle2 - 3.14;
		else
			angle1 = angle2 + 3.14;

		if(angle1 < angle2)
		{
			if(radian > angle2 || radian < angle1)
				return true;
		}
		
		if(angle1 > angle2)
		{
			if(radian < angle1 && radian > angle2)
				return true;
		}

		return false;
	}

0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users