Game not working with one more thing in struct?

I'm making a multiplayer shooter game, and for some reason whenever I add anything else to the bullet struct, the game crashes. If I add anything to any other struct its fine. Could it be that I am checking what weapon the player has too much or something? I have no idea why just adding one int to the struct makes it crash. Here is the bullet struct. Too long so I deleted some of the weapons.

1
2
3
4
5
6
7
struct Bullet
{
	float x, y, speed, dir, damage;
	int radius, playerID, life;
	int type, explosive, collidedPlayer;
	bool active;
};


And where bullets get added.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
else if (event.packet->data[0] == 'B') {

	char message[100];
	int messageCount = 0;
	int ID;

	for(unsigned int i = 0; i < event.packet->dataLength; ++i) {
		message[i] = event.packet->data[i];
	}
	string coords = message;

	istringstream ss(coords);
	string token;

	while(getline(ss, token, ',')) {
		ID = atoi(token.c_str());
	}

	if (players[ID].weapon == MACHINE_GUN) {
		Bullet newBullet;
		newBullet.dir = players[ID].dir + (rand() % 6 - 3) * .01;
		newBullet.x = players[ID].x + (players[ID].gunOffX * cos(players[ID].dir)) - (players[ID].gunOffY * sin(players[ID].dir)); 
		newBullet.y = players[ID].y + (players[ID].gunOffY * cos(players[ID].dir)) + (players[ID].gunOffX * sin(players[ID].dir));
		newBullet.speed = 10;
		newBullet.life = 70;
		newBullet.radius = 3;
		newBullet.active = true;
		newBullet.damage = .35;
		newBullet.type = 0;
		newBullet.playerID = ID;
		newBullet.explosive = 0;
		newBullet.knockback = 1;
		newBullet.collidedPlayer = 1000;
		newBullet.x += (newBullet.speed * 3) * cos(newBullet.dir);
		newBullet.y += (newBullet.speed * 3) * sin(newBullet.dir);
		bullets.push_back(newBullet);
		char packet[256];
		sprintf_s(packet, sizeof(packet), "B,%f,%f,%f,%f,%i,%i,%i,%i,%i", newBullet.x, newBullet.y, newBullet.dir, newBullet.speed, ID, newBullet.radius, newBullet.life, newBullet.type, newBullet.explosive);
		ENetPacket *p = enet_packet_create((char*)packet, strlen(packet)+1, NULL);
		//printf("Sent a packet to client containing %s\n", packet);
		enet_host_broadcast(server, 0, p);
	}
	else if (players[ID].weapon == SHOTGUN) {
		for (int i = 0; i < 5; i++) {
			Bullet newBullet;
			newBullet.dir = players[ID].dir + (rand() % 600 - 299) * .001;
			newBullet.x = players[ID].x + (players[ID].gunOffX * cos(players[ID].dir)) - (players[ID].gunOffY * sin(players[ID].dir)); 
			newBullet.y = players[ID].y + (players[ID].gunOffY * cos(players[ID].dir)) + (players[ID].gunOffX * sin(players[ID].dir));
			newBullet.speed = 10 + (rand() % 10) * .1;
			newBullet.life = 30;
			newBullet.radius = 3;
			newBullet.active = true;
			newBullet.damage = 1;
			newBullet.type = 0;
			newBullet.playerID = ID;
			newBullet.explosive = 0;
			newBullet.knockback = 1;
			newBullet.collidedPlayer = 1000;
			newBullet.x += (newBullet.speed * 3) * cos(newBullet.dir);
			newBullet.y += (newBullet.speed * 3) * sin(newBullet.dir);
			bullets.push_back(newBullet);
			char packet[256];
			sprintf_s(packet, sizeof(packet), "B,%f,%f,%f,%f,%i,%i,%i,%i,%i", newBullet.x, newBullet.y, newBullet.dir, newBullet.speed, ID, newBullet.radius, newBullet.life, newBullet.type, newBullet.explosive);
			ENetPacket *p = enet_packet_create((char*)packet, strlen(packet)+1, NULL);
			enet_host_broadcast(server, 0, p);
		}
	}
	else if (players[ID].weapon == FLAMETHROWER) {
		for (int i = 0; i < 10 + (rand() % 5 - 5); i++) {
			Bullet newBullet;
			newBullet.dir = players[ID].dir + (rand() % 1000 - 490) * .001;
			newBullet.x = players[ID].x + (players[ID].gunOffX * cos(players[ID].dir)) - (players[ID].gunOffY * sin(players[ID].dir)); 
			newBullet.y = players[ID].y + (players[ID].gunOffY * cos(players[ID].dir)) + (players[ID].gunOffX * sin(players[ID].dir));
			newBullet.speed = 10 + (rand() % 100 - 50) * .1;
			newBullet.life = 5 + (rand() % 10 - 5);
			newBullet.radius = 5;
			newBullet.active = true;
			newBullet.damage = .25;
			newBullet.type = 2;
			newBullet.playerID = ID;
			newBullet.explosive = 0;
			newBullet.knockback = 1;
			newBullet.collidedPlayer = 1000;
			newBullet.x += (newBullet.speed * 3) * cos(newBullet.dir);
			newBullet.y += (newBullet.speed * 3) * sin(newBullet.dir);
			bullets.push_back(newBullet);
			char packet[256];
			sprintf_s(packet, sizeof(packet), "B,%f,%f,%f,%f,%i,%i,%i,%i,%i", newBullet.x, newBullet.y, newBullet.dir, newBullet.speed, ID, newBullet.radius, newBullet.life, newBullet.type, newBullet.explosive);
			ENetPacket *p = enet_packet_create((char*)packet, strlen(packet)+1, NULL);
			enet_host_broadcast(server, 0, p);
		}
	}
	else if (players[ID].weapon == BAZOOKA) {
		Bullet newBullet;
		newBullet.dir = players[ID].dir;
		newBullet.x = players[ID].x + (players[ID].gunOffX * cos(players[ID].dir)) - (players[ID].gunOffY * sin(players[ID].dir)); 
		newBullet.y = players[ID].y + (players[ID].gunOffY * cos(players[ID].dir)) + (players[ID].gunOffX * sin(players[ID].dir));
		newBullet.speed = 15;
		newBullet.life = 25;
		newBullet.radius = 10;
		newBullet.active = true;
		newBullet.damage = 1.5;
		newBullet.type = 5;
		newBullet.playerID = ID;
		newBullet.explosive = 0;
		newBullet.knockback = 1;
		newBullet.collidedPlayer = 1000;
		newBullet.x += (newBullet.speed * 2) * cos(newBullet.dir);
		newBullet.y += (newBullet.speed * 2) * sin(newBullet.dir);
		bullets.push_back(newBullet);
		char packet[256];
		sprintf_s(packet, sizeof(packet), "B,%f,%f,%f,%f,%i,%i,%i,%i,%i", newBullet.x, newBullet.y, newBullet.dir, newBullet.speed, ID, newBullet.radius, newBullet.life, newBullet.type, newBullet.explosive);
		ENetPacket *p = enet_packet_create((char*)packet, strlen(packet)+1, NULL);
		enet_host_broadcast(server, 0, p);
	}
	if (players[ID].weapon == CHAIN_GUN) {
		for (float i = -.125; i <= .125; i += .125) {
			Bullet newBullet;
			newBullet.dir = players[ID].dir + i;
			newBullet.x = players[ID].x + (players[ID].gunOffX * cos(players[ID].dir)) - (players[ID].gunOffY * sin(players[ID].dir)); 
			newBullet.y = players[ID].y + (players[ID].gunOffY * cos(players[ID].dir)) + (players[ID].gunOffX * sin(players[ID].dir));
			newBullet.speed = 10;
			newBullet.life = 50;
			newBullet.radius = 4;
			newBullet.active = true;
			newBullet.damage = .35;
			newBullet.type = 0;
			newBullet.playerID = ID;
			newBullet.explosive = 0;
			newBullet.knockback = 1;
			newBullet.collidedPlayer = 1000;
			newBullet.x += (newBullet.speed) * 2 * cos(newBullet.dir);
			newBullet.y += (newBullet.speed) * 2 * sin(newBullet.dir);
			bullets.push_back(newBullet);
			char packet[256];
			sprintf_s(packet, sizeof(packet), "B,%f,%f,%f,%f,%i,%i,%i,%i,%i", newBullet.x, newBullet.y, newBullet.dir, newBullet.speed, ID, newBullet.radius, newBullet.life, newBullet.type, newBullet.explosive);
			ENetPacket *p = enet_packet_create((char*)packet, strlen(packet)+1, NULL);
			//printf("Sent a packet to client containing %s\n", packet);
			enet_host_broadcast(server, 0, p);
		}
	}
}
Well, what a mess. I would suggest that you add a constructor to your struct, or better still make it into a class. Then pass a player object in the argument list to the constructor. Then you can encapsulate all the initialisation of the Bullet instance within the struct/class of Bullet. Your code will suddenly be much cleaner and more manageable.
Would that fix the weird thing with the struct crashing the program with one more thing in it? Even if I don't do anything with whatever variable it is in the struct, it still crashes. Just adding int Test to the struct makes it not work. Even if I get rid of all that code, it still crashes.
Last edited on
You got a problem somewhere in your program, but I don't know if it is in the code that you have posted or not. It could be anywhere. That it crash when you add one more member variable to the struct is just a coincidence. The easiest way to find where things go wrong is probably to use a debugger.
Last edited on
Well I change it to debug mode instead of release mode, and all of the sudden it works with however many things I add to the struct. Is there some weird option for release mode that would mess that up?
It's undefined behaviour ;) Dereferencing invalid pointers, dividing by zero and writing to arrays out of bounds are some of the things that can result in undefined behaviour, which means there are no guarantees what will happen. It might crash, it might act buggy or it might just "work".
Last edited on
So it somehow works in debug mode but not in release mode?
Okay so I've been commenting out a lot of the code to try to find the problem, and I found it but don't really have any idea what is wrong. Here is whats wrong...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
else if (event.packet->data[0] == 'B') {
	char message[100];
	int messageCount = 0;
	int ID;

	for(unsigned int i = 0; i < event.packet->dataLength; ++i) {
		message[i] = event.packet->data[i];
	}
	string coords = message;

	istringstream ss(coords);
	string token;

	while(getline(ss, token, ',')) {
		if (messageCount == 1) {
			ID = atoi(token.c_str());
		}
		messageCount++;
	}
	cout << "ID: " << ID << endl;

	if (players[ID].weapon == MACHINE_GUN) {
		Bullet newBullet;
		newBullet.dir = players[ID].dir + (rand() % 6 - 3) * .01;
		newBullet.x = players[ID].x + (players[ID].gunOffX * cos(players[ID].dir)) - (players[ID].gunOffY * sin(players[ID].dir)); 
		newBullet.y = players[ID].y + (players[ID].gunOffY * cos(players[ID].dir)) + (players[ID].gunOffX * sin(players[ID].dir));
		newBullet.speed = 10;
		newBullet.life = 70;
		newBullet.radius = 3;
		newBullet.active = true;
		newBullet.damage = .35;
		newBullet.type = 0;
		newBullet.playerID = ID;
		newBullet.explosive = 0;
		newBullet.knockback = 1;
		newBullet.collidedPlayer = 1000;
		newBullet.x += (newBullet.speed * 3) * cos(newBullet.dir);
		newBullet.y += (newBullet.speed * 3) * sin(newBullet.dir);
		bullets.push_back(newBullet); //This is what is wrong for some reason and if i delete it the server doesn't know the bullet exists....
		char packet[256];
		sprintf_s(packet, sizeof(packet), "B,%f,%f,%f,%f,%i,%i,%i,%i,%i,%f", newBullet.x, newBullet.y, newBullet.dir, newBullet.speed, ID, newBullet.radius, newBullet.life, newBullet.type, newBullet.explosive, newBullet.knockback);
		ENetPacket *p = enet_packet_create((char*)packet, strlen(packet)+1, NULL);
		enet_host_broadcast(server, 0, p);
		// It still messes it up even if I move it down here so I don't know what's wrong
	}
}
Last edited on
We can't know for sure that the problem is in this code. It might just be where the symptoms show.

If your program contains multiple files have you tried recompile everything? If for some reason some other source file that includes the header is not recompiled after you changed the header you could get weird problems like this. It has happened to me when I was using a not-so-perfect build script. If you use an IDE this would normally not happen but it doesn't hurt to recompile everything just to rule it out.

So if we assume this code really is the root of the problem then I would recommend to check so that no array accesses are out of bounds. You could use a debugger or add a couple of print statements to verify that event.packet->dataLength is not greater than 100, that getline or atoi doesn't fail and leaves ID with an erroneous value. Also make sure that ID is less than the length of the players array.
Well I've tried commenting out almost everything except stuff that it NEEDS to test it, and nothing else gets rid of the error except commenting out bullets.push_back(newBullet), so I have no idea what's wrong. Is there some kinda of program that can check for things that can cause undefined behavior? The atoi and event.packet->dataLength are all ok.
Last edited on
Is there some kinda of program that can check for things that can cause undefined behavior?

A debugger like valgrind usually helps a lot.

I have windows. Any other programs that can find undefined behavior code? Also would it work with libraries like Allegro and ENet?
I don't know which tools to use on Windows, sorry.
So it somehow works in debug mode but not in release mode?


Issues like this are usually attributed to uninitialised variables. Most debuggers will initialise your variables to zero for you (for POD types at least). Go through all of your code again and look for any variables that you use but don't initialise first.
Okay I found the problem! I guess I accidentally did this
1
2
3
for(unsigned int i = 1; i < event.packet->dataLength; ++i) {
		message[i] = event.packet->data[i];
	}


instead of this
1
2
3
for(unsigned int i = 0; i < event.packet->dataLength; ++i) {
		message[i] = event.packet->data[i];
	}


For some reason starting with 1 messes it up... thanks for the help.
Topic archived. No new replies allowed.