Moving between rooms
- Foil
- DBB Material Defender
- Posts: 4900
- Joined: Tue Nov 23, 2004 3:31 pm
- Location: Denver, Colorado, USA
- Contact:
Moving between rooms
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?
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?
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.
- Foil
- DBB Material Defender
- Posts: 4900
- Joined: Tue Nov 23, 2004 3:31 pm
- Location: Denver, Colorado, USA
- Contact:
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.]
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.]
- Foil
- DBB Material Defender
- Posts: 4900
- Joined: Tue Nov 23, 2004 3:31 pm
- Location: Denver, Colorado, USA
- Contact:
Re:
Yeah, I realized that after I got home today.DCrazy wrote:B will not work because OnClientChangeSegment is a callback, not a mutator.
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.
- Foil
- DBB Material Defender
- Posts: 4900
- Joined: Tue Nov 23, 2004 3:31 pm
- Location: Denver, Colorado, USA
- Contact:
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.
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.
- SuperSheep
- DBB Benefactor
- Posts: 935
- Joined: Sun Jun 03, 2001 2:01 am
- Location: Illinois
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.
I never did get Multiplayer functioning properly but I do think it's possible.
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);
}
}
- Foil
- DBB Material Defender
- Posts: 4900
- Joined: Tue Nov 23, 2004 3:31 pm
- Location: Denver, Colorado, USA
- Contact:
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.
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.
- SuperSheep
- DBB Benefactor
- Posts: 935
- Joined: Sun Jun 03, 2001 2:01 am
- Location: Illinois
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?
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?
Re:
sup SheepSuperSheep wrote:I never did get Multiplayer functioning properly but I do think it's possible.
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
- Foil
- DBB Material Defender
- Posts: 4900
- Joined: Tue Nov 23, 2004 3:31 pm
- Location: Denver, Colorado, USA
- Contact:
Here's the function:
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.)
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);
}
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.)
- SuperSheep
- DBB Benefactor
- Posts: 935
- Joined: Sun Jun 03, 2001 2:01 am
- Location: Illinois
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.
I would write the code to be more usable for any player as well...
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.
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);
}
- Foil
- DBB Material Defender
- Posts: 4900
- Joined: Tue Nov 23, 2004 3:31 pm
- Location: Denver, Colorado, USA
- Contact:
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.
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);
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.
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);
- SuperSheep
- DBB Benefactor
- Posts: 935
- Joined: Sun Jun 03, 2001 2:01 am
- Location: Illinois