Moving between rooms

For all coding issues - MODers and programmers, HTML and more.

Moderators: Jeff250, fliptw

Post Reply
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Moving between rooms

Post by Foil »

Now I have another problem: one of the functions of my new gametype is a \"teleport\" function, which just moves the player to a different room by resetting the playerobject position-vector to the center of the destination room, and resetting the playerobject roomnumber.

It works perfectly! The player is suddenly in the destination room, just like I wanted. That is, until some point later (usually when flying normally from room to room) when D3 just locks up. No error message, it just dies.

I have been trying to debug this one for hours. Any ideas?
User avatar
DCrazy
DBB Alumni
DBB Alumni
Posts: 8826
Joined: Wed Mar 15, 2000 3:01 am
Location: Seattle

Post by DCrazy »

struct room has an \"objects\" member, which according to room_external.h is the objnum of the first object in the room. If you change the player's roomnum without checking to make sure that the old room's first object index doesn't still point at the player, the game will probably crash when firing On(Server|Client)PlayerChangeSegment.
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Post by Foil »

Ah... I was looking at it from the perspective of a player-object keeping track of which room it was in; I didn't even think to look at whether the room-object kept track of which objects were in it. That's probably the issue, thank you!
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Post by Foil »

Note:

Which of these do you think would be the likeliest to work?

A. Manually setting the object references in the room structs.

B. Manually calling the OnClientChangeSegment event, and passing it the old and new room references.

I figure B., since I figure it would take care of the changes to the room struct for me... but I'm not sure.

[Edit: this is all on the client side.]
User avatar
DCrazy
DBB Alumni
DBB Alumni
Posts: 8826
Joined: Wed Mar 15, 2000 3:01 am
Location: Seattle

Post by DCrazy »

B will not work because OnClientChangeSegment is a callback, not a mutator. And doing it on the client side only will cause an inconsistency between the client and server and probably lead to an assertion failure when the player next changes rooms.
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Re:

Post by Foil »

DCrazy wrote:B will not work because OnClientChangeSegment is a callback, not a mutator.
Yeah, I realized that after I got home today.

Thanks for the info, though! I'm still new at this; my coding background is mostly VB and web stuff, so I'm having to pick up the C/C++ as I go along. :roll:
User avatar
DCrazy
DBB Alumni
DBB Alumni
Posts: 8826
Joined: Wed Mar 15, 2000 3:01 am
Location: Seattle

Post by DCrazy »

No worries, man. I was still relatively green when I wrote Elimination. Working with DMFC finally gave me the courage to attempt to wrangle with COM.
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Post by Foil »

After about a weeks' vacation, I'm getting back to working on this.

I put in some HUD messages as a primitive debugging tool, to see what the room.objects values (and other values) are at different points. After some testing, I can't seem to find any relationship between the room.objects value and the player objnum, so it doesn't seem to be pointing at any player objects. In fact, most of the time, the room.objects value is -1 (which would make sense when there are no objects in the room). I also tried playing around with the player.oldroom value, but still got the crash.

Anyway, since that doesn't seem to be the issue, any more suggestions on where I might look? I think you're right that it's something about the ChangeSegment event when returning to the room I \"teleported\" from, but I'm not sure where to look anymore.
User avatar
SuperSheep
DBB Benefactor
DBB Benefactor
Posts: 935
Joined: Sun Jun 03, 2001 2:01 am
Location: Illinois

Post by SuperSheep »

Heya Foil!

When I wrote Asteroids, I had to create a teleport function for both the warping of the ship from one side of the level to the other and for the hyperspace jump drive. I didn't use Dallas to write the code, I compiled it as a DLL in MSVS however you might be able to glean some useful information from it.

Code: Select all

// Warp player using Hyper Space Jump Drive
void WarpPlayer(int player_handle)
{
	float mult = 800.0f/RAND_HALF;
	msafe_struct mstruct;

	// Determine if player should be killed
	bool bKill=((float)rand()>(RAND_MAX*0.8f));

	// Play appropriate warp sound
	mstruct.objhandle = player_handle;
	mstruct.state     = 1;
	mstruct.index     = (bKill)?Sound_indexes[4]:Sound_indexes[5];
	mstruct.volume    = 1.0f;
	MSafe_CallFunction(MSAFE_SOUND_2D,&mstruct);

	// Set players new position
	MSafe_GetValue(MSAFE_OBJECT_WORLD_POSITION, &mstruct);
	mstruct.pos.x=2000 + mult*((float)rand()-RAND_HALF);
	mstruct.pos.y=mult * ((float)rand()-RAND_HALF);
	mstruct.pos.z=2000 + mult*((float)rand()-RAND_HALF);
	MSafe_CallFunction(MSAFE_OBJECT_WORLD_POSITION, &mstruct);

	// Deform the player
	mstruct.amount   = 0.2f;
	mstruct.lifetime = (bKill)?2.0f:1.0f;
	MSafe_CallFunction(MSAFE_OBJECT_DEFORM,&mstruct);

	// Kill player if dead or shake viewer if player not dead
	if(bKill)
		Obj_Kill(player_handle,OBJECT_HANDLE_NONE,0.0f,-1,0.0f,0.0f);
	else
	{
		mstruct.amount = 40.0f;
		mstruct.scalar = 10.0f;
		MSafe_CallFunction(MSAFE_OBJECT_SHAKE_AREA,&mstruct);
	}
}
I never did get Multiplayer functioning properly but I do think it's possible.
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Post by Foil »

Looks like the relevant part of what you're doing is essentially what I'm doing, as well.

My function does the following:

- Uses the ComputeRoomCenter function to get the center of the \"destination\" room
- Resets the player.pos to that spot (it currently leaves the orientation and velocity matrices alone)
- Resets the player.roomnum to that room handle (otherwise you get the \"hall of mirrors\" effect)
- Resets the playerobject.oldroom to the \"source\" room (the one the player was in before the move)

It's in a .dll, MSVS 2005, packaged into a .d3m.

The problem is that the functions works perfectly, once!... but when the player flies back to the \"source\" room, D3 crashes.
User avatar
SuperSheep
DBB Benefactor
DBB Benefactor
Posts: 935
Joined: Sun Jun 03, 2001 2:01 am
Location: Illinois

Post by SuperSheep »

Are you using the same function to set the players position?
Are you initializing the mstruct structure properly?

How about posting a snippet of your code for comparison.

And, this code only transports within the same room so that could be causing the problem. Have you tried teleporting within the same room to see if that crashes as well?
User avatar
Floyd
DBB Captain
DBB Captain
Posts: 561
Joined: Sat Apr 26, 2003 2:01 am
Location: Germany
Contact:

Re:

Post by Floyd »

SuperSheep wrote:I never did get Multiplayer functioning properly but I do think it's possible.
sup Sheep :)
it seems to be worked out in the Duel MOD.

Foil, you could also monitor what D3 changes itself when you fly trough a portal. I'd check both the player and both rooms structs. maybe there's something in room structs that keeps record of which objects are inside, which i'm too lazy to look up now ;)
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Post by Foil »

Here's the function:

Code: Select all

//Will move player to an entry room
void DoClientTeleport(void)
{
	vector vPosition;
	int CurrentRoomNumber;
	int NewRoomNumber;

	CurrentRoomNumber = dObjects[dPlayers[DMFCBase->GetPlayerNum()].objnum].roomnum;

	//Get player team
	int team;
	team = DMFCBase->GetMyTeam();

	//Choose a random entry room from the array
	if(team==RED_TEAM){
		//use red entry rooms
		int randomroomindex = rand() % NumberOfRedEntryRooms; //will be an integer in the range [0,NumberOfRedEntryRooms)
		NewRoomNumber = RedEntryRoomNumber[randomroomindex];
	}
	if(team==BLUE_TEAM){
		//use blue entry rooms
		int randomroomindex = rand() % NumberOfBlueEntryRooms; //will be an integer in the range [0,NumberOfBlueEntryRooms)
		NewRoomNumber = BlueEntryRoomNumber[randomroomindex];
	}

	//Get the coordinates for the center of the room
	DLLComputeRoomCenter(&vPosition,&dRooms[NewRoomNumber]);

	//Set the player's coordinates to that point
	memcpy(&dObjects[dPlayers[DMFCBase->GetPlayerNum()].objnum].pos,&vPosition,sizeof(vector));

	//Set the player's room to that room
	dPlayers[DMFCBase->GetPlayerNum()].oldroom = CurrentRoomNumber;
	dObjects[dPlayers[DMFCBase->GetPlayerNum()].objnum].roomnum = NewRoomNumber;
	
	//Display a HUD message
	DLLAddHUDMessage(TXT_ENTRY);
}
It's called only for clients, when certain conditions are met.

FYI, dPlayers and dObjects are exactly as in the Entropy code, NumberOfRedEntryRooms is the number of possible rooms to teleport to, and RedEntryRooms[] is a 0-based array with room handles - that part works fine, it picks a random \"destination\" room correctly.

In fact, the whole function works correctly the first time.


Floyd, I have done a little experimenting with seeing what the room.objects and player-object.room does when going through a portal... there's nothing useful I've seen so far. Of course, I could be missing something obvious.

(P.S. I know, there are easier ways to handle a couple of those variables... I just want to get this working before I start tweaking it.)
User avatar
SuperSheep
DBB Benefactor
DBB Benefactor
Posts: 935
Joined: Sun Jun 03, 2001 2:01 am
Location: Illinois

Post by SuperSheep »

Now I see why your function is failing. You can not simply set the room number and position in the players structure as D3 does not know that it has changed. You need to move the player using one of the built in functions.

In gamedll_header.h, you will find a huge number of functions. In particular you want the functions for moving an object.

Code: Select all


typedef void( *ObjSetPosNoMark_fp ) (object *objp,vector *newpos,int roomnum,matrix *orient,bool f_update_attached_children);
DMFCDLLOUT(ObjSetPosNoMark_fp DLLObjSetPosNoMark;)

// ObjSetPos, that automatically sets the OF_MOVED_THIS_FRAME
typedef void (*ObjSetPos_fp)(object *obj,vector *pos,int roomnum,matrix *orient,bool f_update_attached_children);
DMFCDLLOUT(ObjSetPos_fp DLLObjSetPos;)

I would write the code to be more usable for any player as well...

Code: Select all

//Will move player to an entry room
void DoClientTeleport(int pnum)
{
  object* obj     = &dObjects[dPlayers[pnum].objnum];
  matrix* orient  = &obj->orient;
  int     newroom = obj->roomnum;
  vector  newpos  = obj->pos;
  int     team    = DMFCBase->GetPlayerTeam(pnum);

  //Choose a random entry room from the array
  if(team == RED_TEAM)
  {
    //use red entry rooms
    newroom = RedEntryRoomNumber[rand() % NumberOfRedEntryRooms];
    DLLComputeRoomCenter(&newpos, &dRooms[newroom]);
  }
  else if(team==BLUE_TEAM)
  {
    //use blue entry rooms
    newroom = BlueEntryRoomNumber(rand() % NumberOfBlueEntryRooms);
    DLLComputeRoomCenter(&newpos, &dRooms[newroom]);
  }

  // Teleport Player
  DLLObjSetPos(obj, &newpos, newroom, &obj->orient, true);
}
This function sets newroom and newpos to the players current room and current position in case they aren't on red or blue team. Simply to protect the function call to setpos.
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Post by Foil »

Ah... thanks, SS!

I figured there had to be something not getting moved/re-set properly, I just didn't know what, or how else to move the player. Heck, I had even tried to implement the DALLAS \"FadeAndMovePlayer\" cinematic. :roll:

How I missed the possibility of using that function, I don't know. It should have been obvious:
typedef void (*ObjSetPos_fp)(object *obj,vector *pos,int roomnum,matrix *orient,bool f_update_attached_children);
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Post by Foil »

BTW, that works perfectly. :D

Now to round up a teammate or three, and do some more thorough testing!
User avatar
SuperSheep
DBB Benefactor
DBB Benefactor
Posts: 935
Joined: Sun Jun 03, 2001 2:01 am
Location: Illinois

Post by SuperSheep »

Glad to hear it. :P

You know, Anticheat is still looking for coders willing to take over. :D
User avatar
Foil
DBB Material Defender
DBB Material Defender
Posts: 4900
Joined: Tue Nov 23, 2004 3:31 pm
Location: Denver, Colorado, USA
Contact:

Post by Foil »

So I've heard. :wink:

Seriously, lemme finish this first. I'm also dabbling in D3Edit now, gotta make some levels for this new mod of mine.
Post Reply