Bug Tracker – Attachment #445: BlockThings Iterators for bug #976

View | Details | Raw Unified | Return to bug 976
Collapse All | Expand All

(-)common/p_local.h (-1 / +37 lines)
Lines 187-194 Link Here
187
void P_LineOpening (const line_t *linedef, fixed_t x, fixed_t y, fixed_t refx=MINFIXED, fixed_t refy=0);
187
void P_LineOpening (const line_t *linedef, fixed_t x, fixed_t y, fixed_t refx=MINFIXED, fixed_t refy=0);
188
188
189
BOOL P_BlockLinesIterator (int x, int y, BOOL(*func)(line_t*) );
189
BOOL P_BlockLinesIterator (int x, int y, BOOL(*func)(line_t*) );
190
BOOL P_BlockThingsIterator (int x, int y, BOOL(*func)(AActor*), AActor *start=NULL);
191
190
191
class BlockThingsIterator
192
{
193
public:
194
	BlockThingsIterator(int _bx1, int _by1, int _bx2, int _by2, BOOL(*_func)(AActor*));
195
	virtual AActor* nextThing() = 0;
196
197
protected:
198
	AActor* nextThing(int x, int y);
199
200
	int bx1;
201
	int by1;
202
	int bx2;
203
	int by2;
204
	BOOL (*func)(AActor*);
205
	AActor *mo;
206
207
	int x;
208
	int y;
209
210
	std::set<AActor*> checked;
211
};
212
213
class BlockThingsIteratorColumnMajor : public BlockThingsIterator
214
{
215
public:
216
	BlockThingsIteratorColumnMajor(int _bx1, int _by1, int _bx2, int _by2, BOOL(*_func)(AActor*));
217
	AActor* nextThing();
218
};
219
220
221
class BlockThingsIteratorRowMajor : public BlockThingsIterator
222
{
223
public:
224
	BlockThingsIteratorRowMajor(int _bx1, int _by1, int _bx2, int _by2, BOOL(*_func)(AActor*));
225
	AActor* nextThing();
226
};
227
192
#define PT_ADDLINES 	1
228
#define PT_ADDLINES 	1
193
#define PT_ADDTHINGS	2
229
#define PT_ADDTHINGS	2
194
#define PT_EARLYOUT 	4
230
#define PT_EARLYOUT 	4
(-)common/p_spec.cpp (-8 / +7 lines)
Lines 2679-2685 Link Here
2679
	AActor *thing;
2679
	AActor *thing;
2680
	msecnode_t *node;
2680
	msecnode_t *node;
2681
	int xspeed,yspeed;
2681
	int xspeed,yspeed;
2682
	int xl,xh,yl,yh,bx,by;
2683
	int radius;
2682
	int radius;
2684
	int ht = 0;
2683
	int ht = 0;
2685
2684
Lines 2721-2733 Link Here
2721
		tmbbox[BOXRIGHT]  = m_X + radius;
2720
		tmbbox[BOXRIGHT]  = m_X + radius;
2722
		tmbbox[BOXLEFT]   = m_X - radius;
2721
		tmbbox[BOXLEFT]   = m_X - radius;
2723
2722
2724
		xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
2723
		int xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
2725
		xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
2724
		int xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
2726
		yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
2725
		int yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
2727
		yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
2726
		int yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
2728
		for (bx=xl ; bx<=xh ; bx++)
2727
		BlockThingsIteratorColumnMajor bit(xl, yl, xh, yh, PIT_PushThing);
2729
			for (by=yl ; by<=yh ; by++)
2728
		// call PIT_PushThing on the first actor in range
2730
				P_BlockThingsIterator (bx, by, PIT_PushThing);
2729
		bit.nextThing();
2731
		return;
2730
		return;
2732
	}
2731
	}
2733
2732
(-)common/p_enemy.cpp (-31 / +24 lines)
Lines 1377-1419 Link Here
1377
		yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
1377
		yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
1378
1378
1379
		vileobj = actor;
1379
		vileobj = actor;
1380
		for (bx=xl ; bx<=xh ; bx++)
1380
	
1381
		BlockThingsIteratorColumnMajor bit(xl, yl, xh, yh, PIT_VileCheck);
1382
		if (bit.nextThing() != NULL)
1381
		{
1383
		{
1382
			for (by=yl ; by<=yh ; by++)
1384
			// got one!
1383
			{
1385
			temp = actor->target;
1384
				// Call PIT_VileCheck to check
1386
			actor->target = corpsehit->ptr();
1385
				// whether object is a corpse
1387
			A_FaceTarget (actor);
1386
				// that canbe raised.
1388
			actor->target = temp;
1387
				if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
1388
				{
1389
					// got one!
1390
					temp = actor->target;
1391
					actor->target = corpsehit->ptr();
1392
					A_FaceTarget (actor);
1393
					actor->target = temp;
1394
1389
1395
					P_SetMobjState (actor, S_VILE_HEAL1, true);
1390
			P_SetMobjState (actor, S_VILE_HEAL1, true);
1396
					S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
1391
			S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
1397
					info = corpsehit->info;
1392
			info = corpsehit->info;
1398
1393
1399
					P_SetMobjState (corpsehit,info->raisestate, true);
1394
			P_SetMobjState (corpsehit,info->raisestate, true);
1400
1395
1401
					// [Nes] - Classic demo compatability: Ghost monster bug.
1396
			// [Nes] - Classic demo compatability: Ghost monster bug.
1402
					if ((demoplayback || demorecording) && democlassic) {
1397
			if ((demoplayback || demorecording) && democlassic) {
1403
						corpsehit->height <<= 2;
1398
				corpsehit->height <<= 2;
1404
					} else {
1399
			} else {
1405
						corpsehit->height = P_ThingInfoHeight(info);	// [RH] Use real mobj height
1400
				corpsehit->height = P_ThingInfoHeight(info);	// [RH] Use real mobj height
1406
						corpsehit->radius = info->radius;	// [RH] Use real radius
1401
				corpsehit->radius = info->radius;	// [RH] Use real radius
1407
					}
1402
			}
1408
1403
1409
					corpsehit->flags = info->flags;
1404
			corpsehit->flags = info->flags;
1410
					corpsehit->health = info->spawnhealth;
1405
			corpsehit->health = info->spawnhealth;
1411
					corpsehit->target = AActor::AActorPtr();
1406
			corpsehit->target = AActor::AActorPtr();
1412
1407
1413
					return;
1408
			return;
1414
				}
1409
		}		
1415
			}
1416
		}
1417
	}
1410
	}
1418
1411
1419
	// Return to normal attack.
1412
	// Return to normal attack.
(-)common/p_maputl.cpp (-14 / +89 lines)
Lines 649-679 Link Here
649
	return true;		// everything was checked
649
	return true;		// everything was checked
650
}
650
}
651
651
652
653
//
652
//
654
// P_BlockThingsIterator
653
// BlockThingsIterator
655
//
654
//
656
BOOL P_BlockThingsIterator (int x, int y, BOOL(*func)(AActor*), AActor *actor)
655
// Abstract base class for column-major and row-major iteration classes.
656
//
657
BlockThingsIterator::BlockThingsIterator(int _bx1, int _by1, int _bx2, int _by2, BOOL(*_func)(AActor*)) :
658
	bx1(MAX(_bx1, 0)), by1(MAX(_by1, 0)),
659
	bx2(MIN(_bx2, bmapwidth - 1)), by2(MIN(_by2, bmapheight - 1)), func(_func),
660
	x(bx1), y(by1), mo(NULL)
657
{
661
{
658
	if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
662
}
659
		return true;
663
664
AActor* BlockThingsIterator::nextThing(int x, int y)
665
{
666
	if (mo == NULL)
667
		mo = blocklinks[y * bmapwidth + x];
660
	else
668
	else
661
 	{
669
		mo = mo->bmapnode.Next(x, y);
662
		AActor *mobj = (actor != NULL ? actor : blocklinks[y*bmapwidth+x]);
663
		while (mobj)
664
 		{
665
 			if (!func (mobj))
666
 				return false;
667
670
668
			mobj = mobj->bmapnode.Next(x, y);
671
	while (mo)
672
	{
673
		// Is this thing in the set of already checked things?
674
		// with co_blockmapfix, a thing can be in more than one block but
675
		// it should still only be checked once.
676
		if (checked.find(mo) == checked.end())
677
		{
678
			// add to the set of checked things
679
			checked.insert(mo);
680
			if (!func(mo))
681
				return mo;
669
		}
682
		}
683
		
684
		mo = mo->bmapnode.Next(x, y);
670
	}
685
	}
671
	return true;
686
	
687
	return NULL;
672
}
688
}
673
689
674
690
691
//
692
// BlockThingsIteratorColumnMajor
693
//
694
// Allows iteration through all of the things located in a grid of blocks,
695
// applying a function to each thing found.
696
//
697
BlockThingsIteratorColumnMajor::BlockThingsIteratorColumnMajor(int _bx1, int _by1, int _bx2, int _by2, BOOL(*_func)(AActor*)) :
698
	BlockThingsIterator(_bx1, _by1, _bx2, _by2, _func)
699
{ }
675
700
701
AActor* BlockThingsIteratorColumnMajor::nextThing()
702
{
703
	for (; x <= bx2; x++)
704
	{
705
		for (; y <= by2; y++)
706
		{
707
			AActor* res = BlockThingsIterator::nextThing(x, y);
708
			if (res)
709
				return res;
710
		}
711
712
		y = by1;
713
	}
714
715
	return NULL;
716
}
717
676
//
718
//
719
// BlockThingsIteratorRowMajor
720
//
721
// Allows iteration through all of the things located in a grid of blocks,
722
// applying a function to each thing found.
723
//
724
// The only usage of row-major iteration in the original Doom is P_RadiusAttack
725
// but demo compatibilty necessitates its consideration here.
726
//
727
BlockThingsIteratorRowMajor::BlockThingsIteratorRowMajor(int _bx1, int _by1, int _bx2, int _by2, BOOL(*_func)(AActor*)) :
728
	BlockThingsIterator(_bx1, _by1, _bx2, _by2, _func)
729
{ }
730
731
AActor* BlockThingsIteratorRowMajor::nextThing()
732
{
733
	for (; y <= by2; y++)
734
	{
735
		for (; x <= bx2; x++)
736
		{
737
			AActor* res = BlockThingsIterator::nextThing(x, y);
738
			if (res)
739
				return res;
740
		}
741
742
		x = bx1;
743
	}
744
745
	return NULL;
746
}
747
748
749
750
//
677
// INTERCEPT ROUTINES
751
// INTERCEPT ROUTINES
678
//
752
//
679
// denis - make intercepts array resizeable
753
// denis - make intercepts array resizeable
Lines 965-971 Link Here
965
1039
966
		if (flags & PT_ADDTHINGS)
1040
		if (flags & PT_ADDTHINGS)
967
		{
1041
		{
968
			if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts))
1042
			BlockThingsIteratorColumnMajor bit(mapx, mapy, mapx, mapy, PIT_AddThingIntercepts);
1043
			if (bit.nextThing() != NULL)
969
				return false;	// early out
1044
				return false;	// early out
970
		}
1045
		}
971
1046
(-)common/p_map.cpp (-166 / +92 lines)
Lines 95-101 Link Here
95
EXTERN_CVAR (co_fixweaponimpacts)
95
EXTERN_CVAR (co_fixweaponimpacts)
96
EXTERN_CVAR (co_boomlinecheck)
96
EXTERN_CVAR (co_boomlinecheck)
97
EXTERN_CVAR (co_zdoomphys)
97
EXTERN_CVAR (co_zdoomphys)
98
EXTERN_CVAR (co_blockmapfix)
99
EXTERN_CVAR (co_boomsectortouch)
98
EXTERN_CVAR (co_boomsectortouch)
100
EXTERN_CVAR (sv_friendlyfire)
99
EXTERN_CVAR (sv_friendlyfire)
101
EXTERN_CVAR (sv_unblockplayers)
100
EXTERN_CVAR (sv_unblockplayers)
Lines 173-187 Link Here
173
//		was being teleported between two non-overlapping height ranges.
172
//		was being teleported between two non-overlapping height ranges.
174
BOOL P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, BOOL telefrag)
173
BOOL P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, BOOL telefrag)
175
{
174
{
176
	int 				xl;
177
	int 				xh;
178
	int 				yl;
179
	int 				yh;
180
	int 				bx;
181
	int 				by;
182
183
	subsector_t*		newsubsec;
184
185
	// kill anything occupying the position
175
	// kill anything occupying the position
186
	tmthing = thing;
176
	tmthing = thing;
187
177
Lines 194-200 Link Here
194
	tmbbox[BOXRIGHT] = x + tmthing->radius;
184
	tmbbox[BOXRIGHT] = x + tmthing->radius;
195
	tmbbox[BOXLEFT] = x - tmthing->radius;
185
	tmbbox[BOXLEFT] = x - tmthing->radius;
196
186
197
	newsubsec = R_PointInSubsector (x,y);
187
	subsector_t* newsubsec = R_PointInSubsector (x,y);
198
	ceilingline = NULL;
188
	ceilingline = NULL;
199
189
200
	// The base floor/ceiling is from the subsector
190
	// The base floor/ceiling is from the subsector
Lines 211-225 Link Here
211
	StompAlwaysFrags = tmthing->player || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag;
201
	StompAlwaysFrags = tmthing->player || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag;
212
202
213
	// stomp on any things contacted
203
	// stomp on any things contacted
214
	xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
204
	int xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
215
	xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
205
	int xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
216
	yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
206
	int yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
217
	yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
207
	int yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
218
208
219
	for (bx=xl ; bx<=xh ; bx++)
209
	BlockThingsIteratorColumnMajor bit(xl, yl, xh, yh, PIT_StompThing);
220
		for (by=yl ; by<=yh ; by++)
210
	if (bit.nextThing() != NULL)
221
			if (!P_BlockThingsIterator(bx,by,PIT_StompThing))
211
		return false;
222
				return false;
223
212
224
	// the move is ok,
213
	// the move is ok,
225
	// so link the thing into its new position
214
	// so link the thing into its new position
Lines 796-853 Link Here
796
		if (thing->player)	// [RH] Fake taller height to catch stepping up into things.
785
		if (thing->player)	// [RH] Fake taller height to catch stepping up into things.
797
			thing->height += 24*FRACUNIT;
786
			thing->height += 24*FRACUNIT;
798
787
799
		for (int bx = xl; bx <= xh; bx++)
788
		BlockThingsIteratorColumnMajor bit(xl, yl, xh, yh, PIT_CheckThing);
789
		while (bit.nextThing())
800
		{
790
		{
801
			for (int by = yl; by <= yh; by++)
791
			// [RH] If a thing can be stepped up on, we need to continue checking
792
			// other things in the blocks and see if we hit something that is
793
			// definitely blocking. Otherwise, we need to check the lines, or we
794
			// could end up stuck inside a wall.
795
			if (BlockingMobj == NULL)
796
			{ // Thing slammed into something; don't let it move now.
797
				thing->height = realheight;
798
				return false;
799
			}
800
			else if (!BlockingMobj->player && thing->player &&
801
				BlockingMobj->z + BlockingMobj->height - thing->z <= 24*FRACUNIT)
802
			{
802
			{
803
				AActor *robin = NULL;
803
				if (thingblocker == NULL ||	BlockingMobj->z > thingblocker->z)
804
				do
804
					thingblocker = BlockingMobj;
805
				{
805
				
806
					if (!P_BlockThingsIterator (bx, by, PIT_CheckThing, robin))
806
				BlockingMobj = NULL;
807
					{ // [RH] If a thing can be stepped up on, we need to continue checking
808
					  // other things in the blocks and see if we hit something that is
809
					  // definitely blocking. Otherwise, we need to check the lines, or we
810
					  // could end up stuck inside a wall.
811
						if (BlockingMobj == NULL)
812
						{ // Thing slammed into something; don't let it move now.
813
							thing->height = realheight;
814
							return false;
815
						}
816
						else if (!BlockingMobj->player && thing->player &&
817
							BlockingMobj->z + BlockingMobj->height - thing->z <= 24*FRACUNIT)
818
						{
819
							if (thingblocker == NULL ||	BlockingMobj->z > thingblocker->z)
820
								thingblocker = BlockingMobj;
821
							
822
							robin = BlockingMobj->bmapnode.Next(bx, by);
823
							BlockingMobj = NULL;
824
						}
825
						else if (thing->player &&
826
							thing->z + thing->height - BlockingMobj->z <= 24*FRACUNIT)
827
						{
828
							if (thingblocker)
829
							{ // There is something to step up on. Return this thing as
830
							  // the blocker so that we don't step up.
831
								thing->height = realheight;
832
								return false;
833
							}
834
							// Nothing is blocking us, but this actor potentially could
835
							// if there is something else to step on.
836
							robin = BlockingMobj->bmapnode.Next(bx, by);
837
							BlockingMobj = NULL;
838
						}
839
						else
840
						{ // Definitely blocking
841
							thing->height = realheight;
842
							return false;
843
						}
844
					}
845
					else
846
					{
847
						robin = NULL;
848
					}
849
				} while (robin);
850
			}
807
			}
808
			else if (thing->player &&
809
				thing->z + thing->height - BlockingMobj->z <= 24*FRACUNIT)
810
			{
811
				if (thingblocker)
812
				{ // There is something to step up on. Return this thing as
813
				  // the blocker so that we don't step up.
814
					thing->height = realheight;
815
					return false;
816
				}
817
				// Nothing is blocking us, but this actor potentially could
818
				// if there is something else to step on.
819
				BlockingMobj = NULL;
820
			}
821
			else
822
			{ // Definitely blocking
823
				thing->height = realheight;
824
				return false;
825
			}
851
		}
826
		}
852
827
853
		BlockingMobj = NULL;
828
		BlockingMobj = NULL;
Lines 860-869 Link Here
860
	else
835
	else
861
	{
836
	{
862
		// vanilla Doom's check for blocking things
837
		// vanilla Doom's check for blocking things
863
		for (int bx=xl ; bx<=xh ; bx++)
838
		BlockThingsIteratorColumnMajor bit(xl, yl, xh, yh, PIT_CheckThing);
864
			for (int by=yl ; by<=yh ; by++)
839
		if (bit.nextThing() != NULL)
865
				if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))
840
			return false;
866
					return false;
867
841
868
		if (tmflags & MF_NOCLIP)
842
		if (tmflags & MF_NOCLIP)
869
			return true;
843
			return true;
Lines 907-944 Link Here
907
881
908
bool P_TestMobjZ (AActor *actor)
882
bool P_TestMobjZ (AActor *actor)
909
{
883
{
910
	int	xl,xh,yl,yh,bx,by;
911
	fixed_t x, y;
912
913
	if (actor->flags & MF_NOCLIP)
884
	if (actor->flags & MF_NOCLIP)
914
		return true;
885
		return true;
915
886
916
	if (!(actor->flags & MF_SOLID))
887
	if (!(actor->flags & MF_SOLID))
917
		return true;
888
		return true;
918
889
919
	tmx = x = actor->x;
890
	tmx = actor->x;
920
	tmy = y = actor->y;
891
	tmy = actor->y;
921
	tmthing = actor;
892
	tmthing = actor;
922
893
923
	tmbbox[BOXTOP] = y + actor->radius;
894
	tmbbox[BOXTOP] = actor->y + actor->radius;
924
	tmbbox[BOXBOTTOM] = y - actor->radius;
895
	tmbbox[BOXBOTTOM] = actor->y - actor->radius;
925
	tmbbox[BOXRIGHT] = x + actor->radius;
896
	tmbbox[BOXRIGHT] = actor->x + actor->radius;
926
	tmbbox[BOXLEFT] = x - actor->radius;
897
	tmbbox[BOXLEFT] = actor->x - actor->radius;
927
//
928
// the bounding box is extended by MAXRADIUS because actors are grouped
929
// into mapblocks based on their origin point, and can overlap into adjacent
930
// blocks by up to MAXRADIUS units
931
//
932
	xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
933
	xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
934
	yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
935
	yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
936
898
937
	for (bx = xl; bx <= xh; bx++)
899
	//
938
		for (by = yl; by <= yh; by++)
900
	// the bounding box is extended by MAXRADIUS because actors are grouped
939
			if (!P_BlockThingsIterator (bx, by, PIT_CheckOnmobjZ))
901
	// into mapblocks based on their origin point, and can overlap into adjacent
940
				return false;
902
	// blocks by up to MAXRADIUS units
903
	//
904
	int xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
905
	int xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
906
	int yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
907
	int yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
941
908
909
	BlockThingsIteratorColumnMajor bit(xl, yl, xh, yh, PIT_CheckOnmobjZ);
910
	if (bit.nextThing() != NULL)
911
		return false;
912
942
	return true;
913
	return true;
943
}
914
}
944
915
Lines 949-958 Link Here
949
//
920
//
950
void P_FakeZMovement(AActor *mo)
921
void P_FakeZMovement(AActor *mo)
951
{
922
{
952
//
923
	// adjust height
953
// adjust height
954
//
955
	mo->z += mo->momz;
924
	mo->z += mo->momz;
925
956
	if ((mo->flags&MF_FLOAT) && mo->target)
926
	if ((mo->flags&MF_FLOAT) && mo->target)
957
	{ // float down towards target if too close
927
	{ // float down towards target if too close
958
		if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT))
928
		if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT))
Lines 966-987 Link Here
966
		}
936
		}
967
	}
937
	}
968
	if (mo->player && mo->flags2&MF2_FLY && (mo->z > mo->floorz))
938
	if (mo->player && mo->flags2&MF2_FLY && (mo->z > mo->floorz))
969
	{
970
		mo->z += finesine[(FINEANGLES/80*level.time)&FINEMASK]/8;
939
		mo->z += finesine[(FINEANGLES/80*level.time)&FINEMASK]/8;
971
	}
972
940
973
//
941
	// clip movement
974
// clip movement
942
975
//
943
	if (mo->z <= mo->floorz)	// hit the floor
976
	if (mo->z <= mo->floorz)
977
	{ // hit the floor
978
		mo->z = mo->floorz;
944
		mo->z = mo->floorz;
979
	}
980
945
981
	if (mo->z + mo->height > mo->ceilingz)
946
	if (mo->z + mo->height > mo->ceilingz)		// hit the ceiling
982
	{ // hit the ceiling
983
		mo->z = mo->ceilingz - mo->height;
947
		mo->z = mo->ceilingz - mo->height;
984
	}
985
}
948
}
986
949
987
950
Lines 2747-2784 Link Here
2747
//
2710
//
2748
BOOL PIT_RadiusAttack (AActor *thing)
2711
BOOL PIT_RadiusAttack (AActor *thing)
2749
{
2712
{
2750
    fixed_t	dx;
2751
    fixed_t	dy;
2752
    fixed_t	dist;
2753
2754
	if (!serverside || !(thing->flags & MF_SHOOTABLE))
2713
	if (!serverside || !(thing->flags & MF_SHOOTABLE))
2755
		return true;
2714
		return true;
2756
2715
2757
    // Boss spider and cyborg
2716
    // Boss spider and cyborg
2758
    // take no damage from concussion.
2717
    // take no damage from concussion.
2759
    if (thing->type == MT_CYBORG
2718
    if (thing->type == MT_CYBORG || thing->type == MT_SPIDER)
2760
	|| thing->type == MT_SPIDER)
2719
		return true;
2761
	return true;
2762
2720
2763
    dx = abs(thing->x - bombspot->x);
2721
	fixed_t dx = abs(thing->x - bombspot->x);
2764
    dy = abs(thing->y - bombspot->y);
2722
	fixed_t dy = abs(thing->y - bombspot->y);
2765
2723
2766
    dist = dx>dy ? dx : dy;
2724
	fixed_t dist = (MAX(dx, dy) - thing->radius) >> FRACBITS;
2767
    dist = (dist - thing->radius) >> FRACBITS;
2768
2725
2769
    if (dist < 0)
2726
	if (dist < 0)
2770
	dist = 0;
2727
		dist = 0;
2771
2728
2772
    if (dist >= bombdamage)
2729
	if (dist >= bombdamage)
2773
	return true;	// out of range
2730
		return true;	// out of range
2774
2731
2775
	if (P_CheckSight(thing, bombspot))
2732
	if (P_CheckSight(thing, bombspot))
2776
    {
2733
	{
2777
		// must be in direct path
2734
		// must be in direct path
2778
		P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist, bombmod);
2735
		P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist, bombmod);
2779
    }
2736
	}
2780
2737
2781
    return true;
2738
	return true;
2782
}
2739
}
2783
2740
2784
BOOL PIT_ZdoomRadiusAttack (AActor *thing)
2741
BOOL PIT_ZdoomRadiusAttack (AActor *thing)
Lines 2890-2933 Link Here
2890
	BOOL (*pAttackFunc)(AActor*) = co_zdoomphys ?
2847
	BOOL (*pAttackFunc)(AActor*) = co_zdoomphys ?
2891
		PIT_ZdoomRadiusAttack : PIT_RadiusAttack;
2848
		PIT_ZdoomRadiusAttack : PIT_RadiusAttack;
2892
2849
2893
	if (co_blockmapfix)
2850
	// apply pAttackFunc on all things in the block range
2894
	{
2851
	BlockThingsIteratorRowMajor bit(xl, yl, xh, yh, pAttackFunc);
2895
		// [SL] 2012-12-03 - With co_blockmapfix, an actor can get radius
2852
	bit.nextThing();
2896
		// damage more than once since an actor can be in more than one block.
2897
		// So we make a list of unique actors in the surrounding blocks and
2898
		// then call the radius attack function once for each actor.
2899
2900
		std::set<AActor*> actorset;
2901
		for (int y=yl ; y<=yh ; y++)
2902
		{
2903
			for (int x=xl ; x<=xh ; x++)
2904
			{			
2905
				AActor *mobj = blocklinks[y*bmapwidth+x];
2906
				while (mobj)
2907
				{
2908
					actorset.insert(mobj);
2909
					mobj = mobj->bmapnode.Next(x, y);
2910
				}
2911
			}
2912
		}
2913
2914
		std::set<AActor*>::iterator itr = actorset.begin();
2915
		while (itr != actorset.end())
2916
		{
2917
			pAttackFunc(*itr);
2918
			++itr;
2919
		}
2920
	}
2921
	else
2922
	{
2923
		for (int y=yl ; y<=yh ; y++)
2924
			for (int x=xl ; x<=xh ; x++)
2925
				P_BlockThingsIterator (x, y, pAttackFunc);
2926
	}
2927
}
2853
}
2928
2854
2929
2855
2930
2931
//
2856
//
2932
// SECTOR HEIGHT CHANGING
2857
// SECTOR HEIGHT CHANGING
2933
// After modifying a sectors floor or ceiling height,
2858
// After modifying a sectors floor or ceiling height,
Lines 3056-3068 Link Here
3056
	}
2981
	}
3057
	else
2982
	else
3058
	{
2983
	{
3059
		int x, y;
3060
3061
		// re-check heights for all things near the moving sector
2984
		// re-check heights for all things near the moving sector
3062
		for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
2985
		int xl = sector->blockbox[BOXLEFT];
3063
			for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
2986
		int yl = sector->blockbox[BOXBOTTOM];
3064
				P_BlockThingsIterator (x, y, PIT_ChangeSector);
2987
		int xh = sector->blockbox[BOXRIGHT];
2988
		int yh = sector->blockbox[BOXTOP];
3065
2989
2990
		BlockThingsIteratorColumnMajor bit(xl, yl, xh, yh, PIT_ChangeSector);
2991
		bit.nextThing();
3066
	}
2992
	}
3067
2993
3068
	return nofit;
2994
	return nofit;

Return to bug 976