1-- GunFu Deadlands
2-- Copyright 2009-2011 Christiaan Janssen, September 2009-October 2011
3--
4-- This file is part of GunFu Deadlands.
5--
6--     GunFu Deadlands is free software: you can redistribute it and/or modify
7--     it under the terms of the GNU General Public License as published by
8--     the Free Software Foundation, either version 3 of the License, or
9--     (at your option) any later version.
10--
11--     GunFu Deadlands is distributed in the hope that it will be useful,
12--     but WITHOUT ANY WARRANTY; without even the implied warranty of
13--     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14--     GNU General Public License for more details.
15--
16--     You should have received a copy of the GNU General Public License
17--     along with GunFu Deadlands.  If not, see <http://www.gnu.org/licenses/>.
18
19Entities = {}
20
21function Entities.add_element( index, point, length )
22	if index==1 then Entities.new_player( point[1], point[2] )
23	elseif index>1 and index<6 then
24		table.insert( Level.enemies, Entities.new_element( index, point ) )
25	else
26		table.insert(Level.buildings, Entities.new_element( index, point, length ) )
27	end
28end
29
30Entities.entitylist = {
31	player			= 1,
32	blue_bandit		= 2,
33	red_bandit		= 3,
34	green_bandit	= 4,
35	yellow_bandit	= 5,
36	saloon			= 6,
37	sheriff_box		= 7,
38	church			= 8,
39	bank			= 9,
40	mansion			= 10,
41	house			= 11,
42	warehouse		= 12,
43	barber			= 13,
44	generic_house 	= 14,
45	smith 			= 15,
46	stable 			= 16,
47	tiny_house 		= 17,
48	barrel			= 18,
49	crate 			= 19,
50	well			= 20,
51	pile			= 21,
52	herb			= 22,
53	cactus			= 23,
54	bush			= 24,
55	mill			= 25,
56	dead_branch		= 26,
57	dead_tree		= 27,
58	barrier_horiz	= 28,
59	barrier_vert	= 29,
60	fence_horiz		= 30,
61	fence_vert		= 31,
62}
63Entities.entitystrings = {
64	"player",
65	"blue_bandit",
66	"red_bandit",
67	"green_bandit",
68	"yellow_bandit",
69	"saloon",
70	"sheriff_box",
71	"church",
72	"bank",
73	"mansion",
74	"house",
75	"warehouse",
76	"barber",
77	"generic_house",
78	"smith",
79	"stable",
80	"tiny_house",
81	"barrel",
82	"crate",
83	"well",
84	"pile",
85	"herb",
86	"cactus",
87	"bush",
88	"mill",
89	"dead_branch",
90	"dead_tree",
91	"barrier_horiz",
92	"barrier_vert",
93	"fence_horiz",
94	"fence_vert",
95}
96
97function Entities.getidfromstring( str )
98	for i,v in ipairs(Entities.entitystrings) do
99		if str==v then
100			return i
101		end
102	end
103	-- not found
104	return -1
105end
106
107function Entities.hasalength( id )
108	if id==Entities.entitylist.barrier_horiz or
109		id==Entities.entitylist.barrier_vert or
110		id==Entities.entitylist.fence_horiz or
111		id==Entities.entitylist.fence_vert then
112		return true
113	end
114	return false
115end
116
117function Entities.new_element( index, point, length )
118	if not length then length = 1 end
119	if not point then point = {0,0} end
120
121	if index == Entities.entitylist.player then return Entities.new_player(point[1],point[2])
122	elseif index==Entities.entitylist.blue_bandit then return Entities.new_blue_bandit(point[1],point[2])
123	elseif index==Entities.entitylist.red_bandit then return Entities.new_red_bandit( point[1],point[2] )
124	elseif index==Entities.entitylist.green_bandit then return Entities.new_green_bandit( point[1],point[2] )
125	elseif index==Entities.entitylist.yellow_bandit then return Entities.new_yellow_bandit( point[1],point[2] )
126	elseif index==Entities.entitylist.saloon then return Entities.new_saloon( point[1],point[2] )
127	elseif index==Entities.entitylist.sheriff_box then return Entities.new_sheriff_box(point[1],point[2])
128	elseif index==Entities.entitylist.church then return Entities.new_church(point[1],point[2])
129	elseif index==Entities.entitylist.bank then return Entities.new_bank(point[1],point[2])
130	elseif index==Entities.entitylist.mansion then return Entities.new_mansion(point[1],point[2])
131	elseif index==Entities.entitylist.house then return Entities.new_house(point[1],point[2])
132	elseif index==Entities.entitylist.warehouse then return Entities.new_warehouse(point[1],point[2])
133	elseif index==Entities.entitylist.barrel then return Entities.new_barrel(point[1],point[2])
134	elseif index==Entities.entitylist.dead_branch then return Entities.new_dead_branch(point[1],point[2])
135	elseif index==Entities.entitylist.dead_tree then return Entities.new_dead_tree(point[1],point[2])
136	elseif index==Entities.entitylist.herb then return Entities.new_herb(point[1],point[2])
137	elseif index==Entities.entitylist.cactus then return Entities.new_cactus(point[1],point[2])
138	elseif index==Entities.entitylist.bush then return Entities.new_bush(point[1],point[2])
139	elseif index==Entities.entitylist.mill then return Entities.new_mill(point[1],point[2])
140	elseif index==Entities.entitylist.crate then return Entities.new_crate(point[1],point[2])
141	elseif index==Entities.entitylist.barber then return Entities.new_barber(point[1],point[2])
142	elseif index==Entities.entitylist.generic_house then return Entities.new_generic_house(point[1],point[2])
143	elseif index==Entities.entitylist.smith then return Entities.new_smith(point[1],point[2])
144	elseif index==Entities.entitylist.stable then return Entities.new_stable(point[1],point[2])
145	elseif index==Entities.entitylist.tiny_house then return Entities.new_tiny_house(point[1],point[2])
146	elseif index==Entities.entitylist.pile then return Entities.new_pile(point[1],point[2])
147	elseif index==Entities.entitylist.well then return Entities.new_well(point[1],point[2])
148	elseif index==Entities.entitylist.barrier_horiz then return Entities.new_barrier_horiz(point[1],point[2], length)
149	elseif index==Entities.entitylist.barrier_vert then return Entities.new_barrier_vert(point[1],point[2], length)
150	elseif index==Entities.entitylist.fence_horiz then return Entities.new_fence_horiz(point[1],point[2], length)
151	elseif index==Entities.entitylist.fence_vert then return Entities.new_fence_vert(point[1],point[2], length)
152	end
153end
154
155function Entities.new_player(px, py)
156
157	Player.id = Entities.entitylist.player
158	Player.sprite = Graphics.images.guy_standing
159
160	Player.alive = true
161
162	Player.pos = {px,py}
163	Player.starting_pos = {px,py}
164	Player.dir = {0,0}
165	Player.key_dir = {0,0}
166	Player.speed = 200
167	Player.speed_walking = 200
168	Player.speed_jumping = 300 -- so it gives you an advantage
169	Player.spritesize={Graphics.images.guy_standing:getWidth(),Graphics.images.guy_standing:getHeight()}
170	Player.collisionbox = {5,1,12,20}
171
172	Player.prediction_short = {px,py}
173	Player.dir_prediction = { 0, 0 }
174	Player.prediction_short_dt = 0.05
175	Player.prediction_timer = 0
176	Player.prediction_delay = 0.25 -- 250ms
177
178	Player.firing = false
179	Player.firing_rate = 5  -- shots per second
180	Player.firing_timer = 0 -- timer until next shot
181
182	Player.jumping = false
183	Player.readytojump = true
184	Player.spinning_dir = {0,0}
185	Player.jump_timer = 0
186
187	Player.isplayer = true
188
189	Player.total_bullets = 6
190	Player.bullet_pocket = Player.total_bullets
191	Player.bullet_loadingdelay = 0.9 -- seconds
192	Player.reload_timer = 0
193
194	Player.eyesight = 350
195
196	Player.isbuilding = false
197
198
199
200	BulletTime.init()
201
202	return nil
203end
204
205-- building type (building.solid):
206-- 1- solid - no one can cross it
207-- 2- semisolid - only bullets can cross it
208-- 3- semitransparent - bullets and player can cross it
209-- 4- transparent (ceilings) - bullets, player and enemies can cross it
210-- 5- transparent (floors) - again, anyone can cross it, but it's rendered under the characters
211
212-- game objects
213function Entities.new_saloon( px, py )
214	-- adds a "saloon" building at px, py
215	return	{
216			id = Entities.entitylist.saloon,
217			sprite = Graphics.images.saloon,
218			spritesize = {Graphics.images.saloon:getWidth(), Graphics.images.saloon:getHeight()},
219			pos = {px, py},
220			solid = 1,
221			collision = { { px-60, py-45, px+59, py+44 } , },
222			isbuilding = true,
223		}
224
225end
226
227function Entities.new_sheriff_box(px, py)
228	return {
229			id = Entities.entitylist.sheriff_box,
230			sprite = Graphics.images.sheriff_box,
231			spritesize = {Graphics.images.sheriff_box:getWidth(), Graphics.images.sheriff_box:getHeight()},
232			pos = {px, py},
233			solid = 1,
234			collision = {
235				{ px-47, py-30, px+46, py+29 },
236				 },
237			isbuilding = true,
238		}
239end
240
241function Entities.new_church(px,py)
242	return {
243			id = Entities.entitylist.church,
244			sprite = Graphics.images.church,
245			spritesize = {Graphics.images.church:getWidth(), Graphics.images.church:getHeight()},
246			pos = {px, py},
247			solid = 1,
248			collision = {
249				{ px-22, py-18, px+21, py+49 },
250				{ px-7, py-42, px+6, py },
251				},
252			isbuilding = true,
253		}
254
255end
256
257function Entities.new_bank(px,py)
258	return {
259			id = Entities.entitylist.bank,
260			sprite = Graphics.images.bank,
261			spritesize = {Graphics.images.bank:getWidth(), Graphics.images.bank:getHeight()},
262			pos = {px, py},
263			solid = 1,
264			collision = { { px-61, py-31, px+60, py+31 } },
265			isbuilding = true,
266		}
267end
268
269function Entities.new_mansion(px,py)
270	return {
271			id = Entities.entitylist.mansion,
272			sprite = Graphics.images.mansion,
273			spritesize = {Graphics.images.mansion:getWidth(), Graphics.images.mansion:getHeight()},
274			pos = {px, py},
275			solid = 1,
276			collision = { { px-60, py-45, px+59, py+45 } },
277			isbuilding = true,
278		}
279end
280
281function Entities.new_house(px,py)
282	return {
283			id = Entities.entitylist.house,
284			sprite = Graphics.images.house,
285			spritesize = {Graphics.images.house:getWidth(), Graphics.images.house:getHeight()},
286			pos = {px, py},
287			solid = 1,
288			collision = { { px-30, py-30, px+29, py+30 } , },
289			isbuilding = true,
290		}
291end
292
293function Entities.new_warehouse(px,py)
294	return {
295			id = Entities.entitylist.warehouse,
296			sprite = Graphics.images.warehouse,
297			spritesize = {Graphics.images.warehouse:getWidth(), Graphics.images.warehouse:getHeight()},
298			pos = {px, py},
299			solid = 1,
300			collision = { { px-27, py-58, px+27, py+58 } , },
301			isbuilding = true,
302		}
303end
304
305function Entities.new_barrel(px,py)
306	return {
307			id = Entities.entitylist.barrel,
308			sprite = Graphics.images.barrel,
309			spritesize = {Graphics.images.barrel:getWidth(), Graphics.images.barrel:getHeight()},
310			pos = {px, py},
311			solid = 1,
312			collision = { { px-6, py-9, px+5, py+8 } },
313			isbuilding = true,
314		}
315end
316
317function Entities.new_barrier_horiz(px,py, len)
318	return {
319			id = Entities.entitylist.barrier_horiz,
320			sprite = Graphics.images.barrier_horiz,
321			spritesize = {Graphics.images.barrier_horiz:getWidth(), Graphics.images.barrier_horiz:getHeight()},
322			pos = {px, py},
323			len = {1, len, 31},
324			solid = 1,
325			collision = { { px-math.floor(31*len/2), py-12, px+math.floor(31*len/2), py+12 } },
326			isbuilding = true,
327		}
328end
329
330function Entities.new_barrier_vert(px,py, len)
331	return {
332			id = Entities.entitylist.barrier_vert,
333			sprite = Graphics.images.barrier_vert,
334			spritesize = {Graphics.images.barrier_vert:getWidth(), Graphics.images.barrier_vert:getHeight()},
335			pos = {px, py},
336			len = {2, len, 32},
337			solid = 1,
338			collision = { { px-3, py-math.floor(32*len/2), px+3, py+math.floor(32*len/2) } },
339			isbuilding = true,
340		}
341end
342
343function Entities.new_dead_branch(px, py)
344	return {
345			id = Entities.entitylist.dead_branch,
346			sprite = Graphics.images.dead_branch,
347			spritesize = {Graphics.images.dead_branch:getWidth(), Graphics.images.dead_branch:getHeight()},
348			pos = {px, py},
349			solid = 1,
350			collision = { { px+1, py+1, px+17, py+23 } },
351			isbuilding = true,
352		}
353end
354
355function Entities.new_dead_tree(px, py)
356	return {
357			id = Entities.entitylist.dead_tree,
358			sprite = Graphics.images.dead_tree,
359			spritesize = {Graphics.images.dead_tree:getWidth(), Graphics.images.dead_tree:getHeight()},
360			pos = {px, py},
361			solid = 1,
362			collision = {  { px-13, py+23, px-2, py+50 } },
363			isbuilding = true,
364		}
365end
366
367function Entities.new_fence_horiz(px, py, len)
368	return {
369			id = Entities.entitylist.fence_horiz,
370			sprite = Graphics.images.fence_horiz,
371			spritesize = {Graphics.images.fence_horiz:getWidth(), Graphics.images.fence_horiz:getHeight()},
372			pos = {px, py},
373			len = {1, len, 14},
374			solid = 2,
375			collision = { { px-math.floor(14*len/2), py-7, px+math.floor(14*len/2), py+7 }  },
376			isbuilding = true,
377		}
378end
379
380function Entities.new_fence_vert(px, py, len)
381
382	return {
383			id = Entities.entitylist.fence_vert,
384			sprite = Graphics.images.fence_vert,
385			spritesize = {Graphics.images.fence_vert:getWidth(), Graphics.images.fence_vert:getHeight()},
386			pos = {px, py},
387			len = {2, len, 18},
388			solid = 2,
389			collision = {  { px-2, py-math.floor(18*len/2), px, py+math.floor(18*len/2) }  },
390			isbuilding = true,
391		}
392end
393
394function Entities.new_herb(px, py)
395	return {
396			id = Entities.entitylist.herb,
397			sprite = Graphics.images.herb,
398			spritesize = {Graphics.images.herb:getWidth(), Graphics.images.herb:getHeight()},
399			solid = 5,
400			pos = {px, py},
401			collision = {},
402			isbuilding = true,
403		}
404end
405
406function Entities.new_mill(px, py)
407	return {
408			id = Entities.entitylist.mill,
409			sprite = Graphics.images.mill,
410			spritesize = {Graphics.images.mill:getWidth(), Graphics.images.mill:getHeight()},
411			solid = 4,
412			pos = {px, py},
413			collision = {},
414			isbuilding = true,
415		}
416
417end
418
419function Entities.new_crate(px, py)
420	return	{
421			id = Entities.entitylist.crate,
422			sprite = Graphics.images.crate,
423			spritesize = {Graphics.images.crate:getWidth(), Graphics.images.crate:getHeight()},
424			pos = {px, py},
425			solid = 1,
426			collision = { { px-7, py-9, px+7, py+9 } , },
427			isbuilding = true,
428		}
429end
430
431function Entities.new_generic_house(px, py)
432	return	{
433			id = Entities.entitylist.generic_house,
434			sprite = Graphics.images.generic_house,
435			spritesize = {Graphics.images.generic_house:getWidth(), Graphics.images.generic_house:getHeight()},
436			pos = {px, py},
437			solid = 1,
438			collision = { { px-64, py-34, px+64, py+34 } , },
439			isbuilding = true,
440		}
441end
442
443function Entities.new_smith(px, py)
444	return	{
445			id = Entities.entitylist.smith,
446			sprite = Graphics.images.smith,
447			spritesize = {Graphics.images.smith:getWidth(), Graphics.images.smith:getHeight()},
448			pos = {px, py},
449			solid = 1,
450			collision = { { px-53, py-39, px+53, py+39 } , },
451			isbuilding = true,
452		}
453end
454
455function Entities.new_barber(px, py)
456	return	{
457			id = Entities.entitylist.barber,
458			sprite = Graphics.images.barber,
459			spritesize = {Graphics.images.barber:getWidth(), Graphics.images.barber:getHeight()},
460			pos = {px, py},
461			solid = 1,
462			collision = { { px-48, py-28, px+48, py+28 } , },
463			isbuilding = true,
464		}
465end
466
467function Entities.new_stable(px, py)
468	return	{
469			id = Entities.entitylist.stable,
470			sprite = Graphics.images.stable,
471			spritesize = {Graphics.images.stable:getWidth(), Graphics.images.stable:getHeight()},
472			pos = {px, py},
473			solid = 1,
474			collision = { { px-25, py-100, px+25, py+100 } , },
475			isbuilding = true,
476		}
477end
478
479function Entities.new_pile(px, py)
480	return	{
481			id = Entities.entitylist.pile,
482			sprite = Graphics.images.pile,
483			spritesize = {Graphics.images.pile:getWidth(), Graphics.images.pile:getHeight()},
484			pos = {px, py},
485			solid = 1,
486			collision = { { px-29, py-12, px+28, py+13 } , },
487			isbuilding = true,
488		}
489end
490
491function Entities.new_well(px, py)
492	return	{
493			id = Entities.entitylist.well,
494			sprite = Graphics.images.well,
495			spritesize = {Graphics.images.well:getWidth(), Graphics.images.well:getHeight()},
496			pos = {px, py},
497			solid = 1,
498			collision = { { px-9, py-16, px+9, py+16 } , },
499			isbuilding = true,
500		}
501end
502
503function Entities.new_tiny_house(px, py)
504	return	{
505			id = Entities.entitylist.tiny_house,
506			sprite = Graphics.images.tiny_house,
507			spritesize = {Graphics.images.tiny_house:getWidth(), Graphics.images.tiny_house:getHeight()},
508			pos = {px, py},
509			solid = 1,
510			collision = { { px-30, py-30, px+30, py+30 } , },
511			isbuilding = true,
512		}
513end
514
515function Entities.new_cactus(px, py)
516	return {
517			id = Entities.entitylist.cactus,
518			sprite = Graphics.images.cactus,
519			spritesize = {Graphics.images.cactus:getWidth(), Graphics.images.cactus:getHeight()},
520			solid = 5,
521			pos = {px, py},
522			collision = {},
523			isbuilding = true,
524		}
525end
526
527function Entities.new_bush(px, py)
528	return {
529			id = Entities.entitylist.bush,
530			sprite = Graphics.images.bush,
531			spritesize = {Graphics.images.bush:getWidth(), Graphics.images.bush:getHeight()},
532			pos = {px, py},
533			solid = 3,
534			collision = {{ px-10, py-12, px+10, py+16 }  },
535			isbuilding = true,
536		}
537end
538
539
540function Entities.new_blue_bandit( px, py )
541
542		return {
543				id = Entities.entitylist.blue_bandit,
544				color = Colors.lt_blue,
545				pos = {px, py},
546				starting_pos = {px, py},
547				dir = {0,0},
548				shoot_dir = {1,0},
549				target_dir = {1,0},
550				prediction_short = {px, py},
551				dir_prediction = { 0, 0 },
552				spritesize = {Graphics.images.blue_bandit_standing:getWidth(), Graphics.images.blue_bandit_standing:getHeight()},
553				collisionbox = {5,0,11,20},
554				sprite = Graphics.images.blue_bandit_standing,
555				sprite_standing = Graphics.images.blue_bandit_standing,
556				sprite_gun_left = Graphics.images.blue_bandit_gun_left,
557				sprite_gun_right = Graphics.images.blue_bandit_gun_right,
558				sprite_ninja_gun_left = Graphics.images.ninja_bandit_blue_gun_left,
559				sprite_ninja_gun_right = Graphics.images.ninja_bandit_blue_gun_right,
560				sprite_walking_right = Graphics.animations.new_blue_bandit_walk_right(),
561				sprite_walking_up = Graphics.animations.new_blue_bandit_walk_up(),
562				sprite_walking_dn = Graphics.animations.new_blue_bandit_walk_up(),
563				sprite_dying = Graphics.animations.new_blue_bandit_dying_right(),
564				sprite_ninja_standing = Graphics.images.ninja_bandit_standing,
565				sprite_ninja_walking_right = Graphics.animations.new_ninja_bandit_walk_right(),
566				sprite_ninja_walking_up = Graphics.animations.new_ninja_bandit_walk_up(),
567				sprite_ninja_walking_dn = Graphics.animations.new_ninja_bandit_walk_dn(),
568				sprite_ninja_dying = Graphics.animations.new_ninja_bandit_dying_right(),
569				destination = { px, py },
570				lastpos = { px, py },
571				suspicion_timer = 0,
572				suspicion_delay = 3.5,
573				state = 1,
574				former_state = 0,
575				sight_dist = 800,
576				wandering_timer = 0,
577				wandering_delay = 1.11,
578				speed = 100,
579				angular_velocity = math.pi / 180 * 180, --  180 degrees per sec
580				aiming_angular_velocity = math.pi / 180 * 180 * 2,
581				acceptable_arc = math.pi / 180 * 5,
582				initial_reaction_time = 0.015 * 4,
583				last_seen_bullet = {0,0},
584				blocked_timer = 0,
585				blocked_delay = 0.28, -- 1 second
586				changedir_timer = 0,
587				changedir_delay = 1.5, -- 1.5 seconds
588				lastplayerpos = {0,0},
589				dodging_timer = 0,
590				dodging_delay = 2.66,
591				scared_timer = 0,
592				scared_delay = 3.35,
593				shooting_timer = 0,
594				shooting_delay = 0.4,
595				accuracy = 0.15, -- lower is better
596				firingmode = 1,
597				death_timer = Graphics.get_deathtime() ,
598				scream = Sounds.scream_blue,
599				scream_slow = Sounds.scream_blue_slow,
600				shot_sound = Sounds.shot_blue,
601				see_player_timer = 0,
602				player_was_seen = false,
603				see_bullet_timer = 0,
604				bullet_was_seen = false,
605				ninja_see_player_timer = 0,
606				ninja_player_was_seen = false,
607				prediction_timer = 0,
608				shotgun_arc = 10,
609				prediction_short_dt = 0.05,
610				prediction_delay = 0.25, -- 250ms
611				see_delay = 0.1, -- 100ms
612				bullet_see_delay = 0.05,
613				isplayer = false,
614				isbuilding = false,
615			}
616end
617
618function Entities.new_red_bandit( px, py )
619
620		return {
621				id = Entities.entitylist.red_bandit,
622				color = Colors.lt_red,
623				pos = {px, py},
624				starting_pos = {px, py},
625				dir = {0,0},
626				shoot_dir = {1,0},
627				target_dir = {1,0},
628				prediction_short = {px, py},
629				dir_prediction = { 0, 0 },
630				spritesize = {Graphics.images.red_bandit_standing:getWidth(), Graphics.images.red_bandit_standing:getHeight()},
631				collisionbox = {3,1,14,20},
632				sprite = Graphics.images.red_bandit_standing,
633				sprite_standing = Graphics.images.red_bandit_standing,
634				sprite_gun_left = Graphics.images.red_bandit_gun_left,
635				sprite_gun_right = Graphics.images.red_bandit_gun_right,
636				sprite_ninja_gun_left = Graphics.images.ninja_bandit_red_gun_left,
637				sprite_ninja_gun_right = Graphics.images.ninja_bandit_red_gun_right,
638				sprite_walking_right = Graphics.animations.new_red_bandit_walk_right(),
639				sprite_walking_up = Graphics.animations.new_red_bandit_walk_up(),
640				sprite_walking_dn = Graphics.animations.new_red_bandit_walk_up(),
641				sprite_dying = Graphics.animations.new_red_bandit_dying_right(),
642				sprite_ninja_standing = Graphics.images.ninja_bandit_standing,
643				sprite_ninja_walking_right = Graphics.animations.new_ninja_bandit_walk_right(),
644				sprite_ninja_walking_up = Graphics.animations.new_ninja_bandit_walk_up(),
645				sprite_ninja_walking_dn = Graphics.animations.new_ninja_bandit_walk_dn(),
646				sprite_ninja_dying = Graphics.animations.new_ninja_bandit_dying_right(),
647				suspicion_timer = 0,
648				suspicion_delay = 1.5,
649				destination = { px, py },
650				lastpos = { px, py },
651				state = 1,
652				former_state = 0,
653				sight_dist = 800,
654				wandering_timer = 0,
655				wandering_delay = 4.57,
656				speed = 70,
657				angular_velocity = math.pi / 180 * 120, --  120 degrees per sec
658				aiming_angular_velocity = math.pi / 180 * 120 * 2,
659				acceptable_arc = math.pi / 180 * 5,
660				initial_reaction_time = 0.022 * 4,
661				last_seen_bullet = {0,0},
662				blocked_timer = 0,
663				blocked_delay = 0.45, -- second
664				changedir_timer = 0,
665				changedir_delay = 1.9, -- seconds
666				lastplayerpos = {0,0},
667				dodging_timer = 0,
668				dodging_delay = 2.34,
669				scared_timer = 0,
670				scared_delay = 8.33,
671				shooting_timer = 0,
672				shooting_delay = 0.2,
673				accuracy = 0.20,
674				firingmode = 2,
675				alternatefire = true,
676				death_timer = Graphics.get_deathtime() ,
677				scream = Sounds.scream_red,
678				scream_slow = Sounds.scream_red_slow,
679				shot_sound = Sounds.shot_red,
680				see_player_timer = 0,
681				player_was_seen = false,
682				see_bullet_timer = 0,
683				bullet_was_seen = false,
684				ninja_see_player_timer = 0,
685				ninja_player_was_seen = false,
686				prediction_timer = 0,
687				shotgun_arc = 10,
688				prediction_short_dt = 0.05,
689				prediction_delay = 0.25, -- 250ms
690				see_delay = 0.1, -- 100ms
691				bullet_see_delay = 0.05,
692				isplayer = false,
693				isbuilding = false,
694			}
695end
696
697function Entities.new_green_bandit( px, py )
698
699		return {
700				id = Entities.entitylist.green_bandit,
701				color = Colors.green,
702				pos = {px, py},
703				starting_pos = {px, py},
704				dir = {0,0},
705				shoot_dir = {1,0},
706				target_dir = {1,0},
707				prediction_short = {px, py},
708				dir_prediction = { 0, 0 },
709				spritesize = {Graphics.images.green_bandit_standing:getWidth(), Graphics.images.green_bandit_standing:getHeight()},
710				collisionbox = {5,0,12,20},
711				sprite = Graphics.images.green_bandit_standing,
712				sprite_standing = Graphics.images.green_bandit_standing,
713				sprite_gun_left = Graphics.images.green_bandit_gun_left,
714				sprite_gun_right = Graphics.images.green_bandit_gun_right,
715				sprite_ninja_gun_left = Graphics.images.ninja_bandit_green_gun_left,
716				sprite_ninja_gun_right = Graphics.images.ninja_bandit_green_gun_right,
717				sprite_walking_right = Graphics.animations.new_green_bandit_walk_right(),
718				sprite_walking_up = Graphics.animations.new_green_bandit_walk_up(),
719				sprite_walking_dn = Graphics.animations.new_green_bandit_walk_up(),
720				sprite_dying = Graphics.animations.new_green_bandit_dying_right(),
721				sprite_ninja_standing = Graphics.images.ninja_bandit_standing,
722				sprite_ninja_walking_right = Graphics.animations.new_ninja_bandit_walk_right(),
723				sprite_ninja_walking_up = Graphics.animations.new_ninja_bandit_walk_up(),
724				sprite_ninja_walking_dn = Graphics.animations.new_ninja_bandit_walk_dn(),
725				sprite_ninja_dying = Graphics.animations.new_ninja_bandit_dying_right(),
726				destination = { px, py },
727				lastpos = { px, py },
728				suspicion_timer = 0,
729				suspicion_delay = 2.0,
730				state = 1,
731				former_state = 0,
732				sight_dist = 800,
733				wandering_timer = 0,
734				wandering_delay = 1.33,
735				speed = 90,
736				angular_velocity = math.pi / 180 * 150, --  150 degrees per sec
737				aiming_angular_velocity = math.pi / 180 * 120 * 2,
738				acceptable_arc = math.pi / 180 * 5,
739				initial_reaction_time = 0.05 * 4,
740				last_seen_bullet = {0,0},
741				blocked_timer = 0,
742				blocked_delay = 0.58, -- 1 second
743				changedir_timer = 0,
744				changedir_delay = 1.95, -- 1.5 seconds
745				lastplayerpos = {0,0},
746				dodging_timer = 0,
747				dodging_delay = 1.52,
748				scared_timer = 0,
749				scared_delay = 6.62,
750				shooting_timer = 0,
751				shooting_delay = 0.55,
752				accuracy = 0.25,
753				firingmode = 3,
754				death_timer = Graphics.get_deathtime() ,
755				scream = Sounds.scream_green,
756				scream_slow = Sounds.scream_green_slow,
757				shot_sound = Sounds.shot_green,
758				see_player_timer = 0,
759				player_was_seen = false,
760				see_bullet_timer = 0,
761				bullet_was_seen = false,
762				ninja_see_player_timer = 0,
763				ninja_player_was_seen = false,
764				prediction_timer = 0,
765				shotgun_arc = 10,
766				prediction_short_dt = 0.05,
767				prediction_delay = 0.25, -- 250ms
768				see_delay = 0.1, -- 100ms
769				bullet_see_delay = 0.05,
770				isplayer = false,
771				isbuilding = false,
772			}
773end
774
775function Entities.new_yellow_bandit( px, py )
776
777		return {
778				id = Entities.entitylist.yellow_bandit,
779				color = Colors.yellow,
780				pos = {px, py},
781				starting_pos = {px, py},
782				dir = {0,0},
783				shoot_dir = {1,0},
784				target_dir = {1,0},
785				prediction_short = {px, py},
786				dir_prediction = { 0, 0 },
787				spritesize = {Graphics.images.yellow_bandit_standing:getWidth(), Graphics.images.yellow_bandit_standing:getHeight()},
788				collisionbox = {6,3,11,19},
789				sprite = Graphics.images.yellow_bandit_standing,
790				sprite_standing = Graphics.images.yellow_bandit_standing,
791				sprite_gun_left = Graphics.images.yellow_bandit_gun_left,
792				sprite_gun_right = Graphics.images.yellow_bandit_gun_right,
793				sprite_ninja_gun_left = Graphics.images.ninja_bandit_yellow_gun_left,
794				sprite_ninja_gun_right = Graphics.images.ninja_bandit_yellow_gun_right,
795				sprite_walking_right = Graphics.animations.new_yellow_bandit_walk_right(),
796				sprite_walking_up = Graphics.animations.new_yellow_bandit_walk_up(),
797				sprite_walking_dn = Graphics.animations.new_yellow_bandit_walk_up(),
798				sprite_dying = Graphics.animations.new_yellow_bandit_dying_right(),
799				sprite_ninja_standing = Graphics.images.ninja_bandit_standing,
800				sprite_ninja_walking_right = Graphics.animations.new_ninja_bandit_walk_right(),
801				sprite_ninja_walking_up = Graphics.animations.new_ninja_bandit_walk_up(),
802				sprite_ninja_walking_dn = Graphics.animations.new_ninja_bandit_walk_dn(),
803				sprite_ninja_dying = Graphics.animations.new_ninja_bandit_dying_right(),
804				suspicion_timer = 0,
805				suspicion_delay = 5.5,
806				destination = { px, py },
807				lastpos = { px, py },
808				state = 1,
809				former_state = 0,
810				sight_dist = 800,
811				wandering_timer = 0,
812				wandering_delay = 0.41,
813				speed = 140,
814				angular_velocity = math.pi / 180 * 170, --  170 degrees per sec
815				aiming_angular_velocity = math.pi / 180 * 190 * 2,
816				acceptable_arc = math.pi / 180 * 5,
817				initial_reaction_time = 0.008 * 4,
818				last_seen_bullet = {0,0},
819				blocked_timer = 0,
820				blocked_delay = 0.25, -- 1 second
821				changedir_timer = 0,
822				changedir_delay = 1.0, -- 1.5 seconds
823				lastplayerpos = {0,0},
824				dodging_timer = 0,
825				dodging_delay = 3.11,
826				scared_timer = 0,
827				scared_delay = 8.56,
828				shooting_timer = 0,
829				shooting_delay = 0.35,
830				accuracy = 0.01,
831				firingmode = 1,
832				death_timer = Graphics.get_deathtime() ,
833				scream = Sounds.scream_yellow,
834				scream_slow = Sounds.scream_yellow_slow,
835				shot_sound = Sounds.shot_yellow,
836				see_player_timer = 0,
837				player_was_seen = false,
838				see_bullet_timer = 0,
839				bullet_was_seen = false,
840				ninja_see_player_timer = 0,
841				ninja_player_was_seen = false,
842				prediction_timer = 0,
843				shotgun_arc = 10,
844				prediction_short_dt = 0.05,
845				prediction_delay = 0.25, -- 250ms
846				see_delay = 0.1, -- 100ms
847				bullet_see_delay = 0.05,
848				isplayer = false,
849				isbuilding = false,
850			}
851end
852