Id: To index
Original: Legend
Status:
Mutant: Show

Testcases to display

Filter by kind

Filter by status

1:
#
include
 
"mobsystem.h"
2:
3:
#
include
 
"game.h"
4:
#
include
 
"rendersystem.h"
5:
6:
#
include
 
<
string
>
7:
using
 
namespace
 
std
::
string_literals
;
8:
9:
MobInfo
 
MI
(
MobCategory
 
category
,
 
std
::
string
 
name
,
 
int32_t
 
health
,
 
int32_t
 
speed
)
 
{
10:    
MobInfo
 
mi
;
11:    
mi
.
category
 
=
 
category
;
12:    
mi
.
name
 
=
 
name
;
13:    
mi
.
health
 
=
 
health
;
14:    
mi
.
speed
 
=
 
speed
;
15:    
return
 
mi
;
16:
}
17:
18:
MobInfo
 
MI
(
MobCategory
 
category
,
 
std
::
string
 
name
,
 
int32_t
 
health
,
 
int32_t
 
speed
,
19:           
int32_t
 
strength
)
 
{
20:    
MobInfo
 
mi
;
21:    
mi
.
category
 
=
 
category
;
22:    
mi
.
name
 
=
 
name
;
23:    
mi
.
health
 
=
 
health
;
24:    
mi
.
speed
 
=
 
speed
;
25:    
mi
.
attacks
 
=
 
true
;
26:    
mi
.
strength
 
=
 
strength
;
27:    
return
 
mi
;
28:
}
29:
30:
const
 
std
::
unordered_map
<
MobType
,
 
MobInfo
>
 
MobDatabase
{
31:    
{
MobType
::
Unknown
,
 
MI
(
MobCategory
::
Unknown
,
 
"Unknown"s
,
 
0
,
 
1
)
}
,
32:    
{
MobType
::
Rabbit
,
 
MI
(
MobCategory
::
Rabbit
,
 
"Rabbit"s
,
 
1
,
 
7
)
}
,
33:    
{
MobType
::
RabbitWere
,
 
MI
(
MobCategory
::
Rabbit
,
 
"Were-Rabbit"s
,
 
1
,
 
6
,
 
1
)
}
,
34:    
{
MobType
::
Snake
,
 
MI
(
MobCategory
::
Snake
,
 
"Snake"s
,
 
1
,
 
5
)
}
,
35:    
{
MobType
::
OrcWeak
,
 
MI
(
MobCategory
::
Orc
,
 
"Little Orc"s
,
 
5
,
 
3
,
 
3
)
}
,
36:    
{
MobType
::
OrcStrong
,
 
MI
(
MobCategory
::
Orc
,
 
"Big Orc"s
,
 
6
,
 
2
,
 
5
)
}
,
37:    
{
MobType
::
Player
,
 
MI
(
MobCategory
::
Player
,
 
"Player"s
,
 
5
,
 
6
,
 
3
)
}
,
38:
}
;
39:
40:
void
 
MobSystem
::
update
(
)
 
{
41:    
for
 
(
auto
&
 
mob
 
:
 
game_
.
mobs
.
values
(
)
)
 
{
42:        
if
 
(
mob
.
info
->
category
 
==
 
MobCategory
::
Player
)
43:            
continue
;
44:
45:        
mob
.
tick
 
+=
 
mob
.
info
->
speed
;
46:        
mob
.
tick
 
=
 
std
::
min
(
mob
.
tick
,
 
2
 
*
 
Mob
::
TicksPerAction
 
-
 
1
)
;
47:        
if
 
(
mob
.
tick
 
>=
 
Mob
::
TicksPerAction
)
 
{
48:            
auto
&
 
e
 
=
 
game_
.
entities
[
mob
.
entity
]
;
49:            
updateMob
(
e
,
 
mob
)
;
50:            
mob
.
tick
 
-=
 
Mob
::
TicksPerAction
;
51:        
}
52:    
}
53:
}
54:
55:
void
 
MobSystem
::
handleEvent
(
const
 
EvAny
&
 
any
)
 
{
56:    
if
 
(
any
.
is
<
EvTryWalk
>
(
)
)
 
{
57:        
const
 
auto
&
 
ev
 
=
 
any
.
get
<
EvTryWalk
>
(
)
;
58:        
auto
&
 
mob
 
=
 
game_
.
mobs
[
ev
.
mob
]
;
59:        
auto
&
 
info
 
=
 
*
mob
.
info
;
60:
61:        
// check position is clear
62:        
bool
 
blocked
 
=
 
false
;
63:        
for
 
(
auto
&
 
other
 
:
 
game_
.
mobs
.
values
(
)
)
 
{
64:            
if
 
(/* other.id != mob.id && */truefalse
other
.
id
 
!=
 
mob
.
id
 
&&||/* && other.position == ev.to */
 
other
.
position
 
==
 
ev
.
to
)
 
{
65:                
blocked
 
=
 
true
;
66:                
break
;
67:            
}
68:        
}
69:
70:        
if
 
(
!
game_
.
worldBounds
.
contains
(
ev
.
to
)
)
 
{
71:            
blocked
 
=
 
true
;
72:        
}
73:
74:        
if
 
(
!
blocked
)
 
{
75:            
mob
.
position
 
=
 
ev
.
to
;
76:
77:            
// Mob overrides sprite position
78:            
auto
&
 
sprite
 
=
 
game_
.
sprites
[
game_
.
entities
[
mob
.
entity
]
.
sprite
]
;
79:            
sprite
.
position
 
=
 
mob
.
position
;
80:
81:            
// Additional pieces
82:            
switch
 
(
info
.
category
)
 
{
83:            
default
:
84:                
break
;
85:            
case
 
MobCategory
::
Snake
:
 
{
86:                
if
 
(
randInt
(
0
,
 
3
)
 
<
 
3
)
 
{
87:                    
game_
.
groundTile
(
mob
.
position
)
 
=
 
'_'
;
88:                
}
89:
90:                
game_
.
sprites
[
mob
.
extraSprite
]
.
position
 
=
 
mob
.
position
 
+
 
mob
.
dir
;
91:                
break
;
92:            
}
93:            
case
 
MobCategory
::
Orc
:
 
{
94:                
if
 
(
randInt
(
0
,
 
1
)
 
==
 
0
)
 
{
95:                    
// smash ground
96:                    
game_
.
groundTile
(
mob
.
position
)
 
=
 
'_'
;
97:                
}
98:                
game_
.
sprites
[
mob
.
extraSprite
]
.
position
 
=
 
mob
.
position
 
+
 
vec2i
{
-
1
,
 
1
}
;
99:                
game_
.
sprites
[
mob
.
extraSprite2
]
.
position
 
=
 
mob
.
position
 
+
 
vec2i
{
1
,
 
1
}
;
100:                
break
;
101:            
}
102:            
}
103:
104:            
game_
.
queueEvent
(
EvWalked
{
mob
.
id
,
 
ev
.
from
,
 
mob
.
position
}
)
;
105:        
}
106:    
}
 
else
 
if
 
(
any
.
is
<
EvWalked
>
(
)
)
 
{
107:        
// ...
108:    
}
 
else
 
if
 
(
any
.
is
<
EvAttack
>
(
)
)
 
{
109:        
const
 
auto
&
 
ev
 
=
 
any
.
get
<
EvAttack
>
(
)
;
110:        
auto
&
 
mob
 
=
 
game_
.
mobs
[
ev
.
mob
]
;
111:        
auto
&
 
mobInfo
 
=
 
*
mob
.
info
;
112:        
auto
&
 
targetMob
 
=
 
game_
.
mobs
[
ev
.
target
]
;
113:        
// auto& targetMobInfo = *targetMob.info;
114:
115:        
if
 
(/* mob && */truefalse
mob
 
&&||/* && targetMob */
 
targetMob
)
 
{
116:            
targetMob
.
health
 
-=
 
mobInfo
.
strength
;
117:            
if
 
(
targetMob
.
health
 
<=
 
0
)
 
{
118:                
game_
.
queueEvent
(
EvKillMob
{
targetMob
.
id
}
)
;
119:            
}
 
else
 
{
120:                
// Flash-hit
121:                
const
 
int
 
flashDuration
 
=
 
2
;
122:                
auto
&
 
e
 
=
 
game_
.
entities
[
targetMob
.
entity
]
;
123:                
game_
.
sprites
[
e
.
sprite
]
.
flashTimer
 
=
 
flashDuration
;
124:                
if
 
(
targetMob
.
extraSprite
)
125:                    
game_
.
sprites
[
targetMob
.
extraSprite
]
.
flashTimer
 
=
 
flashDuration
;
126:                
if
 
(
targetMob
.
extraSprite2
)
127:                    
game_
.
sprites
[
targetMob
.
extraSprite2
]
.
flashTimer
 
=
 
flashDuration
;
128:            
}
129:        
}
130:    
}
131:
}
132:
133:
void
 
MobSystem
::
updateMob
(
Entity
&
 
e
,
 
Mob
&
 
mob
)
 
{
134:    
auto
&
 
info
 
=
 
*
mob
.
info
;
135:    
auto
&
 
sprite
 
=
 
game_
.
sprites
[
e
.
sprite
]
;
136:    
vec2i
 
pos
 
=
 
mob
.
position
;
137:
138:    
const
 
int
 
margin
 
=
 
6
;
 
// min distance from edge mobs prefer to be
139:    
auto
 
dirToNearestEdge
 
=
 
[
&
]
(
vec2i
 
pos
)
 
->
 
vec2i
 
{
140:        
const
 
auto
&
 
b
 
=
 
game_
.
worldBounds
;
141:
142:        
if
 
(
pos
.
y
 
>
 
b
.
top
 
-
 
margin
)
143:            
return
 
{
0
,
 
-
1
}
;
144:        
else
 
if
 
(
pos
.
y
 
<
 
b
.
top
 
-
 
b
.
height
 
+
 
margin
)
145:            
return
 
{
0
,
 
1
}
;
146:        
else
 
if
 
(
pos
.
x
 
<
 
b
.
left
 
+
 
margin
)
147:            
return
 
{
1
,
 
0
}
;
148:        
else
 
if
 
(
pos
.
x
 
>
 
b
.
left
 
+
 
b
.
width
 
-
 
margin
)
149:            
return
 
{
-
1
,
 
0
}
;
150:        
return
 
{
0
,
 
0
}
;
151:    
}
;
152:
153:    
switch
 
(
info
.
category
)
 
{
154:    
case
 
MobCategory
::
Rabbit
:
 
{
155:        
if
 
(
randInt
(
0
,
 
500
)
 
==
 
0
)
 
{
156:            
// Too many rabbits!
157:            
// game_.queueEvent(EvSpawnMob { MobType::Rabbit, pos });
158:        
}
 
else
 
{
159:            
// Move randomly
160:            
vec2i
 
dir
 
=
 
dirToNearestEdge
(
pos
)
;
161:            
if
 
(
dir
 
==
 
vec2i
{
0
,
 
0
}
)
 
{
162:                
dir
 
=
 
vec2i
{
randInt
(
-
1
,
 
1
)
,
 
randInt
(
-
1
,
 
1
)
}
;
163:            
}
164:            
game_
.
queueEvent
(
EvTryWalk
{
mob
.
id
,
 
pos
,
 
pos
 
+
 
dir
}
)
;
165:        
}
166:        
break
;
167:    
}
168:    
case
 
MobCategory
::
Snake
:
 
{
169:        
if
 
(
randInt
(
0
,
 
6
)
 
==
 
0
)
 
{
170:            
if
 
(
mob
.
dir
.
x
 
!=
 
0
)
 
{
171:                
mob
.
dir
 
=
 
choose
<
vec2i
>
(
{
{
0
,
 
1
}
,
 
{
0
,
 
-
1
}
}
)
;
172:            
}
 
else
 
{
173:                
mob
.
dir
 
=
 
choose
<
vec2i
>
(
{
{
1
,
 
0
}
,
 
{
-
1
,
 
0
}
}
)
;
174:            
}
175:
176:            
vec2i
 
dir
 
=
 
dirToNearestEdge
(
pos
)
;
177:            
if
 
(
dir
 
!=
 
vec2i
{
0
,
 
0
}
)
178:                
mob
.
dir
 
=
 
dir
;
179:        
}
 
else
 
{
180:            
if
 
(
mob
.
dir
.
y
 
==
 
1
)
181:                
sprite
.
frame
 
=
 
0
;
182:            
else
 
if
 
(
mob
.
dir
.
y
 
==
 
-
1
)
183:                
sprite
.
frame
 
=
 
1
;
184:            
else
 
if
 
(
mob
.
dir
.
x
 
==
 
1
)
185:                
sprite
.
frame
 
=
 
2
;
186:            
else
 
if
 
(
mob
.
dir
.
x
 
==
 
-
1
)
187:                
sprite
.
frame
 
=
 
3
;
188:
189:            
game_
.
queueEvent
(
EvTryWalk
{
mob
.
id
,
 
pos
,
 
pos
 
+
 
mob
.
dir
}
)
;
190:        
}
191:        
break
;
192:    
}
193:    
case
 
MobCategory
::
Orc
:
 
{
194:        
if
 
(
randInt
(
0
,
 
2
)
 
==
 
0
)
 
{
195:            
game_
.
groundTile
(
pos
)
 
=
 
choose
(
{
'_'
,
 
'_'
}
)
;
196:        
}
197:
198:        
vec2i
 
dir
 
=
 
dirToNearestEdge
(
pos
)
;
199:        
if
 
(
dir
 
==
 
vec2i
{
0
,
 
0
}
)
 
{
200:            
if
 
(
randInt
(
0
,
 
3
)
 
==
 
0
)
 
{
201:                
// stay here
202:            
}
 
else
 
{
203:                
// move randomly
204:                
int32_t
 
move
 
=
 
choose
(
{
-
1
,
 
1
}
)
;
205:                
dir
 
=
 
choose
(
{
vec2i
{
move
,
 
0
}
,
 
vec2i
{
0
,
 
move
}
}
)
;
206:            
}
207:        
}
208:
209:        
if
 
(
dir
 
!=
 
vec2i
{
0
,
 
0
}
)
 
{
210:            
game_
.
queueEvent
(
EvTryWalk
{
mob
.
id
,
 
pos
,
 
pos
 
+
 
dir
}
)
;
211:        
}
212:        
break
;
213:    
}
214:    
default
:
215:        
break
;
216:    
}
217:
}