about summary refs log tree commit diff
path: root/src/GameTick.cpp
diff options
context:
space:
mode:
authorNguyễn Gia Phong <cnx@loang.net>2023-11-19 04:11:46 +0900
committerNguyễn Gia Phong <cnx@loang.net>2023-11-19 04:11:46 +0900
commitdb730f01951231196cac36630d043c7a3676d446 (patch)
treef1f8cd2c2e2d8d24235a64fd5d9aa577ca73f4bc /src/GameTick.cpp
parentae0810b2d4cdd31cd05f5746c6411da9d458eead (diff)
downloadblackshades-db730f01951231196cac36630d043c7a3676d446.tar.gz
Finish porting model handling to Zig
Diffstat (limited to 'src/GameTick.cpp')
-rw-r--r--src/GameTick.cpp259
1 files changed, 84 insertions, 175 deletions
diff --git a/src/GameTick.cpp b/src/GameTick.cpp
index 2bfdda6..75bcc9d 100644
--- a/src/GameTick.cpp
+++ b/src/GameTick.cpp
@@ -527,7 +527,7 @@ void checkPersonCollisions(Game* game, int k)
 					move, city_rot, &collpoint);
 				if (whichtri == -1)
 					continue;
-				person.playercoords += rotate(game->blockwalls[city_type].normals[whichtri], 0, city_rot, 0);
+				person.playercoords += rotate(game->blockwalls[city_type].faces[whichtri][0].normal, 0, city_rot, 0);
 			}
 		}
 
@@ -608,15 +608,11 @@ void spawnNpc(Game* game)
 	default: break;
 	}
 
-	npc.pathnum = -1;
-	while (npc.pathnum < 0
-	       || npc.pathnum == 1
-	       || npc.pathnum >= game->path.vertexNum)
-		npc.pathnum = randUint(game->path.vertexNum);
 	npc.oldoldoldpathnum = npc.oldoldpathnum = npc.oldpathnum = -1;
+	npc.pathnum = randUint(8);
 
-	npc.pathtarget.x = game->path.vertex[npc.pathnum].x;
-	npc.pathtarget.z = game->path.vertex[npc.pathnum].z;
+	npc.pathtarget.x = DIRECTIONS[npc.pathnum].x;
+	npc.pathtarget.z = DIRECTIONS[npc.pathnum].z;
 	npc.pathtarget *= npc.pathsize;
 	npc.pathtarget.x += npc.whichblockx * block_spacing;
 	npc.pathtarget.z += npc.whichblocky * block_spacing;
@@ -1078,16 +1074,14 @@ void Game::Tick()
 					    && !person[i].running) {
 						person[i].killtargetvisible = 0;
 						leastdistance = 2000000;
-						for (int j = 0; j < path.vertexNum; j++) {
-							person[i].pathtarget.x = path.vertex[j].x;
-							person[i].pathtarget.z = path.vertex[j].z;
-							person[i].pathtarget.y = path.vertex[j].y;
+						for (unsigned char j = 0; j < 8; j++) {
+							person[i].pathtarget = DIRECTIONS[j];
 							person[i].pathtarget *= person[i].pathsize;
 							person[i].pathtarget.x += person[i].whichblockx*block_spacing;
 							person[i].pathtarget.z += person[i].whichblocky*block_spacing;
 
 							if (sqrlen(person[i].playercoords - person[i].pathtarget) < leastdistance
-							    && j != 1 && j != person[i].oldpathnum
+							    && j != person[i].oldpathnum
 							    && j != person[i].oldoldpathnum
 							    && j != person[i].oldoldoldpathnum){
 								leastdistance = sqrlen(person[i].playercoords - person[i].pathtarget);
@@ -1095,13 +1089,12 @@ void Game::Tick()
 							}
 						}
 
-						if (closesttarget >= 0 && closesttarget < path.vertexNum) {
+						if (closesttarget >= 0 && closesttarget < 8) {
 							person[i].oldoldoldpathnum = person[i].oldoldpathnum;
 							person[i].oldoldpathnum = person[i].oldpathnum;
 							person[i].oldpathnum = person[i].pathnum;
 							person[i].pathnum = closesttarget;
-							person[i].pathtarget.x = path.vertex[person[i].pathnum].x;
-							person[i].pathtarget.z = path.vertex[person[i].pathnum].z;
+							person[i].pathtarget = DIRECTIONS[closesttarget];
 							person[i].pathtarget *= person[i].pathsize;
 							person[i].pathtarget.x += person[i].whichblockx*block_spacing;
 							person[i].pathtarget.z += person[i].whichblocky*block_spacing;
@@ -1141,17 +1134,14 @@ void Game::Tick()
 
 							for (int l = beginx; l <= endx; l++) {
 								for (int m = beginx; m <= endx; m++) {
-									for (int j = 0; j < path.vertexNum; j++){
-										person[i].pathtarget.x = path.vertex[j].x;
-										person[i].pathtarget.y = path.vertex[j].y;
-										person[i].pathtarget.z = path.vertex[j].z;
+									for (unsigned char j = 0; j < 8; ++j) {
+										person[i].pathtarget = DIRECTIONS[j];
 										person[i].pathtarget*=person[i].pathsize;
 										person[i].pathtarget.x+=l*block_spacing;
 										person[i].pathtarget.z+=m*block_spacing;
 
-										if (j != 1
-										    && (sqrlen(person[i].playercoords - person[i].pathtarget)
-										        < leastdistance)
+										if ((sqrlen(person[i].playercoords - person[i].pathtarget)
+										     < leastdistance)
 										    && (sqrlen(person[i].pathtarget - person[person[i].killtarget].playercoords)
 										        < sqrlen(person[i].playercoords - person[person[i].killtarget].playercoords))
 										    && (segCrossModelTrans(person[i].playercoords, person[i].pathtarget, &blocksimple,
@@ -1222,18 +1212,15 @@ void Game::Tick()
 						person[i].lastdistancevictim=2000000;
 						closesttarget=-1;
 
-						//Check best path
-						for(int j=0;j<path.vertexNum;j++){
-							person[i].pathtarget.x=path.vertex[j].x;
-							person[i].pathtarget.z=path.vertex[j].z;
-							person[i].pathtarget.y=path.vertex[j].y;
+						// Check best path
+						for (unsigned char j = 0; j < 8; ++j) {
+							person[i].pathtarget = DIRECTIONS[j];
 							person[i].pathtarget*=person[i].pathsize;
 							person[i].pathtarget.x+=person[i].whichblockx*block_spacing;
 							person[i].pathtarget.z+=person[i].whichblocky*block_spacing;
 
-							if (j != 1
-							    && (sqrlen(person[i].playercoords - person[i].pathtarget)
-							        < leastdistance)
+							if ((sqrlen(person[i].playercoords - person[i].pathtarget)
+							     < leastdistance)
 							    && (sqrlen(person[i].pathtarget - person[person[i].killtarget].playercoords)
 							        < person[i].lastdistancevictim)
 							    && (segCrossModelTrans(person[i].playercoords, person[i].pathtarget, &blocksimple,
@@ -1262,17 +1249,14 @@ void Game::Tick()
 								for(int m=beginx;m<=endx;m++){
 									if(l!=person[i].whichblockx||m!=person[i].whichblocky){
 
-									for(int j=0;j<path.vertexNum;j++){
-										person[i].pathtarget.x=path.vertex[j].x;
-										person[i].pathtarget.y=path.vertex[j].y;
-										person[i].pathtarget.z=path.vertex[j].z;
+									for (unsigned char j = 0; j < 8; ++j){
+										person[i].pathtarget = DIRECTIONS[j];
 										person[i].pathtarget*=person[i].pathsize;
 										person[i].pathtarget.x+=l*block_spacing;
 										person[i].pathtarget.z+=m*block_spacing;
 
-										if (j != 1
-										    && (sqrlen(person[i].playercoords - person[i].pathtarget)
-										        < leastdistance)
+										if ((sqrlen(person[i].playercoords - person[i].pathtarget)
+										     < leastdistance)
 										    && (sqrlen(person[i].pathtarget - person[person[i].killtarget].playercoords)
 										        < sqrlen(person[i].playercoords - person[person[i].killtarget].playercoords))
 										    && (segCrossModelTrans(person[i].playercoords, person[i].pathtarget, &blocksimple,
@@ -1576,13 +1560,7 @@ void Game::Tick()
 
 	XYZ wallhit;
 	XYZ start;
-	XYZ finalwallhit;
 	int numshots;
-	XYZ hitnorm;
-	XYZ hitmove;
-	int hitpoly = 0;
-	float hitrotation = 0.0f;
-	Model* model = NULL;
 
 	for (int j = 0; j < numpeople; j++) {
 		if (j && person[j].type != eviltype)
@@ -1733,17 +1711,11 @@ void Game::Tick()
 			int firstpass=-1;
 
 			for(int m=0;m<bulletstrength;m++){
-
 				//People
-
 				whichhit=-1;
-
 				for(int i=0;i<numpeople;i++){
-
 					if(i!=j&&i!=firstpass&&person[i].existing){
-
 						temphitstruct=person[i].BulletCollideWithPlayer(i, start, end);
-
 						if(temphitstruct.collision){
 							distance = sqrlen(start - temphitstruct.hitlocation);
 							if(distance<olddistance||whichhit==-1){
@@ -1756,124 +1728,89 @@ void Game::Tick()
 					}
 				}
 
-				// Blocks
-				wallhit = {};
-				beginx=(person[j].playercoords.x+block_spacing/2)/block_spacing-3;
-
-				if(beginx<0)beginx=0;
-
-				beginz=(person[j].playercoords.z+block_spacing/2)/block_spacing-3;
-
-				if(beginz<0)beginz=0;
-
-				endx=(person[j].playercoords.x+block_spacing/2)/block_spacing+3;
-
-				if(endx>num_blocks-1)endx=num_blocks-1;
-
-				endz=(person[j].playercoords.z+block_spacing/2)/block_spacing+3;
-
-				if(endz>num_blocks-1)endz=num_blocks-1;
-
-				if(beginx<endx&&beginz<endz)
-
-				finalwallhit = {};
-				for(int i=beginx;i<=endx;i++)
-					for(int j=beginz;j<=endz;j++){
+				// Terrain damage
+				XYZ hitNorm;
+				Model* model;
+				GLfloat hitRot;
+				whichtri = -1;
+				beginx = std::max(0,
+					(int) (person[j].playercoords.x + block_spacing / 2) / block_spacing - 3);
+				beginz = std::max(0,
+					(int) (person[j].playercoords.z + block_spacing / 2) / block_spacing - 3);
+				endx = std::min(num_blocks - 1,
+					(int) (person[j].playercoords.x + block_spacing / 2) / block_spacing + 3);
+				endz = std::min(num_blocks - 1,
+					(int) (person[j].playercoords.z + block_spacing / 2) / block_spacing + 3);
+				for (auto i = beginx; i <= endx; ++i)
+					for (auto j = beginz; j <= endz; ++j) {
+						model = blocks + citytype[i][j];
 						move = {(float) i * block_spacing, 0.0f, (float) j * block_spacing};
+						hitRot = cityrotation[i][j] * 90;
 						whichtri = segCrossModelTrans(start, end,
-							blocks + citytype[i][j],
-							move, cityrotation[i][j] * 90,
-							&wallhit);
+							model, move, hitRot, &wallhit);
 						if (whichtri > -1) {
-							whichhit = -1;
-							end = finalwallhit = wallhit;
-							hitnorm = rotate(blocks[citytype[i][j]].normals[whichtri],
-								0, cityrotation[i][j]*90, 0);
-							hitmove = move;
-							hitrotation = cityrotation[i][j]*90;
-							hitpoly = whichtri;
-							model = &blocks[citytype[i][j]];
-							if (j == 0
-							    && blocks[citytype[i][j]].normals[whichtri].y > 0.9)
-								bulletstrength = 2;
+							hitNorm = rotate(model->faces[whichtri][0].normal,
+								0, hitRot, 0);
+							goto hit_terrain;
 						}
 					}
-				whichtri = segCrossModelTrans(start, end, &Bigstreet,
-					{camera.position.x, 0.0f, camera.position.z}, 0,
-					&wallhit);
+				model = &this->Bigstreet;
+				move = {camera.position.x, 0.0f, camera.position.z};
+				hitRot = 0.0f;
+				whichtri = segCrossModelTrans(start, end,
+					model, move, hitRot, &wallhit);
 				if (whichtri > -1) {
-					end.y-=.5;
-					end=wallhit;
-					finalwallhit=wallhit;
-					bulletstrength=2;
-					hitnorm = {0.0f, 1.0f, 0.0f};
-					hitmove = {};
-					hitrotation=0;
-				}
-
-				if(m==0){
-
-					if(j==0&&slomo==2){
-						alSourceStop(gSourceID[whichsong]);
-
-						alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
-
-						alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
-
-						if(person[0].whichgun==knife)whichsong=knifesong;
-
-						if(person[0].whichgun!=knife)whichsong=shootsong;
-
-						if(type==zombie_type)whichsong=zombiesong;
-
-						alSourcef(gSourceID[whichsong], AL_PITCH, 1);
-
-						alSourcePlay(gSourceID[whichsong]);
-
-						alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
-
-						alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
-
-						slomo=0;
-
-						if(whichhit==-1)alSourcePlay(gSourceID[disguisekillsound]);
-
-						flashamount=.5;
-
-						flashr=1;flashg=1;flashb=1;
-
+					hitNorm = {0.0f, 1.0f, 0.0f};
+hit_terrain:
+					whichhit = -1;
+					addDecal(&decals, BULLET_HOLE, wallhit, 0.7f,
+						hitNorm, whichtri, model, move, hitRot);
+					const auto& velocity = hitNorm * 3;
+					switch (person[j].whichgun) {
+					case sniperrifle:
+						sprites.MakeSprite(smokesprite, .4, 1, 1, 1, wallhit, velocity, 10);
+						sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, wallhit, velocity, 2);
+						break;
+					case shotgun:
+						sprites.MakeSprite(smokesprite, .4, 1, 1, 1, wallhit, velocity, 5);
+						sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, wallhit, velocity, .8);
+						break;
+					case assaultrifle:
+					case handgun1:
+					case handgun2:
+						sprites.MakeSprite(smokesprite, .4, 1, 1, 1, wallhit, velocity, 6);
+						sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, wallhit, velocity, 1);
+						break;
 					}
 
+					auto soundpos = wallhit - camera.position;
+					playSound(gSourceID[wallhitsound],
+						soundpos.x, soundpos.y, soundpos.z);
 				}
 
-				//Impact
-
-				XYZ oldend {end};
-
-				//with person
+				if (m == 0 && j == 0 && slomo == 2){
+					if (whichhit == -1)
+						alSourcePlay(gSourceID[disguisekillsound]);
+					alSourcef(gSourceID[whichsong], AL_PITCH, 1);
+					slomo = 0;
+					flashamount = 0.5f;
+					flashr = flashg = flashb = 1.0f;
+				}
 
+				// Impact with person
 				if(whichhit!=-1&&whichhit!=firstpass){
-
 					if(j==0)person[whichhit].dead=1;
-
 					if(whichhit==1){
-
 						murderer=j;
-
 					}
 
 					if(person[whichhit].health==100&&j==0){
-
 						if(person[whichhit].type==civiliantype)civkills++;
-
 						if(person[whichhit].type==eviltype)goodkills++;
-
 					}
 
 					if(person[whichhit].health==100&&j!=0){
-
 						badkills++;
-
 					}
 
 					bool penetrate = (numshots > 1) ? 0 : !randUint(3);
@@ -2085,37 +2022,8 @@ void Game::Tick()
 					playSound(hitsound, hitpos.x, hitpos.y, hitpos.z);
 				}
 
-				// with wall
-				if (oldend == finalwallhit) {
-					addDecal(&decals, BULLET_HOLE, finalwallhit, 0.7f,
-						hitnorm, hitpoly, model, hitmove, hitrotation);
-					// FIXME: WTF?
-					XYZ velocity = aim * -4.0f;
-					velocity = hitnorm * 3;
-					switch (person[j].whichgun) {
-					case sniperrifle:
-						sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 10);
-						sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 2);
-						break;
-					case shotgun:
-						sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 5);
-						sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, .8);
-						break;
-					case assaultrifle:
-					case handgun1:
-					case handgun2:
-						sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 6);
-						sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 1);
-						break;
-					}
-
-					auto soundpos = finalwallhit - camera.position;
-					playSound(gSourceID[wallhitsound],
-						soundpos.x, soundpos.y, soundpos.z);
-				}
-
 				lastshot[0]=start;
-				lastshot[1]=oldend;
+				lastshot[1]=end;
 				auto velocity = aim * 8;
 
 				if(person[j].whichgun!=sniperrifle&&person[j].whichgun!=shotgun&&p==numshots-1)sprites.MakeSprite(smokesprite, .3, 1, 1, 1, start+aim*1.5, velocity, 3);
@@ -2209,7 +2117,8 @@ void Game::Tick()
 
 			if (whichtri != -1) {
 				impact = true;
-				auto normalrotated = rotate(blocks[citytype[wherex][wherey]].normals[whichtri], 0, cityrotation[wherex][wherey] * 90, 0);
+				const auto& normalrotated = rotate(blocks[citytype[wherex][wherey]].faces[whichtri][0].normal,
+					0, cityrotation[wherex][wherey] * 90, 0);
 				if (sprites.size[i] > 1)
 					addDecal(&decals, CRATER, wallhit, 9.0f,
 						normalrotated, whichtri,