1 /*-------------------------------------------------------------------------------
2 
3 BARONY
4 File: actsummontrap.cpp
5 Desc: behavior function for summoning trap
6 
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9 
10 -------------------------------------------------------------------------------*/
11 
12 #include "main.hpp"
13 #include "game.hpp"
14 #include "stat.hpp"
15 #include "entity.hpp"
16 #include "items.hpp"
17 #include "monster.hpp"
18 #include "net.hpp"
19 #include "collision.hpp"
20 #include "magic/magic.hpp"
21 #include "sound.hpp"
22 #include "player.hpp"
23 #include "mod_tools.hpp"
24 
25 #define SUMMONTRAP_MONSTER my->skill[0]
26 #define SUMMONTRAP_COUNT my->skill[1]
27 #define SUMMONTRAP_INTERVAL my->skill[2]
28 #define SUMMONTRAP_SPAWNCYCLES my->skill[3]
29 #define SUMMONTRAP_POWERTODISABLE my->skill[4]
30 #define SUMMONTRAP_FAILURERATE my->skill[5]
31 #define SUMMONTRAP_FIRED my->skill[6]
32 #define SUMMONTRAP_INITIALIZED my->skill[7]
33 #define SUMMONTRAP_TICKS_TO_FIRE my->skill[8]
34 
actSummonTrap(Entity * my)35 void actSummonTrap(Entity* my)
36 {
37 	if ( my->skill[28] == 0 || (SUMMONTRAP_INITIALIZED && SUMMONTRAP_FIRED) )
38 	{
39 		return;
40 	}
41 
42 	// received on signal
43 	if ( (my->skill[28] == 2 && !SUMMONTRAP_POWERTODISABLE) || my->skill[28] == 1 && SUMMONTRAP_POWERTODISABLE )
44 	{
45 		if ( SUMMONTRAP_TICKS_TO_FIRE > 0 )
46 		{
47 			--SUMMONTRAP_TICKS_TO_FIRE;
48 		}
49 
50 		// if the time interval between between spawns is reached, or if the mechanism is switched on for the first time.
51 		if ( SUMMONTRAP_TICKS_TO_FIRE == 0 || !SUMMONTRAP_INITIALIZED )
52 		{
53 			SUMMONTRAP_TICKS_TO_FIRE = (TICKS_PER_SECOND * SUMMONTRAP_INTERVAL);
54 
55 			if ( !SUMMONTRAP_FIRED && SUMMONTRAP_SPAWNCYCLES > 0 )
56 			{
57 				bool useCustomMonsters = monsterCurveCustomManager.curveExistsForCurrentMapName(map.name);
58 				bool fixedCustomMonster = true;
59 				Monster customMonsterType = NOTHING;
60 				bool pickedRandomMonsters = (SUMMONTRAP_MONSTER == -1);
61 
62 				if ( SUMMONTRAP_MONSTER > 0 && SUMMONTRAP_MONSTER < NUMMONSTERS )
63 				{
64 					// spawn the monster given to the trap.
65 				}
66 				else if ( SUMMONTRAP_MONSTER == 0 || SUMMONTRAP_MONSTER >= NUMMONSTERS )
67 				{
68 					// spawn the monster scaled to current level.
69 					if ( useCustomMonsters )
70 					{
71 						fixedCustomMonster = false;
72 						customMonsterType = static_cast<Monster>(monsterCurveCustomManager.rollMonsterFromCurve(map.name));
73 					}
74 					else
75 					{
76 						SUMMONTRAP_MONSTER = monsterCurve(currentlevel);
77 					}
78 				}
79 				else
80 				{
81 					// pick a completely random monster (barring some exceptions).
82 					SUMMONTRAP_MONSTER = rand() % NUMMONSTERS;
83 					while ( SUMMONTRAP_MONSTER == LICH || SUMMONTRAP_MONSTER == SHOPKEEPER || SUMMONTRAP_MONSTER == DEVIL
84 						|| SUMMONTRAP_MONSTER == MIMIC || SUMMONTRAP_MONSTER == BUGBEAR || SUMMONTRAP_MONSTER == OCTOPUS
85 						|| SUMMONTRAP_MONSTER == MINOTAUR || SUMMONTRAP_MONSTER == LICH_FIRE || SUMMONTRAP_MONSTER == LICH_ICE
86 						|| SUMMONTRAP_MONSTER == NOTHING || SUMMONTRAP_MONSTER == SENTRYBOT || SUMMONTRAP_MONSTER == SPELLBOT
87 						|| SUMMONTRAP_MONSTER == GYROBOT || SUMMONTRAP_MONSTER == DUMMYBOT )
88 					{
89 						SUMMONTRAP_MONSTER = rand() % NUMMONSTERS;
90 					}
91 				}
92 
93 				int count = 0;
94 				for ( count = 0; count < SUMMONTRAP_COUNT; count++ )
95 				{
96 					Entity* monster = nullptr;
97 					int typeToSpawn = SUMMONTRAP_MONSTER;
98 					if ( useCustomMonsters && customMonsterType != NOTHING )
99 					{
100 						typeToSpawn = customMonsterType;
101 					}
102 					monster = summonMonster(static_cast<Monster>(typeToSpawn), my->x, my->y);
103 					if ( monster && monster->getStats() )
104 					{
105 						if ( useCustomMonsters )
106 						{
107 							std::string variantName = "default";
108 							if ( fixedCustomMonster )
109 							{
110 								variantName = monsterCurveCustomManager.rollFixedMonsterVariant(map.name, typeToSpawn);
111 							}
112 							else
113 							{
114 								variantName = monsterCurveCustomManager.rollMonsterVariant(map.name, typeToSpawn);
115 							}
116 							if ( variantName.compare("default") != 0 )
117 							{
118 								Monster tmp = NOTHING;
119 								monsterCurveCustomManager.createMonsterFromFile(monster, monster->getStats(), variantName, tmp);
120 							}
121 						}
122 						else
123 						{
124 							monster->getStats()->MISC_FLAGS[STAT_FLAG_DISABLE_MINIBOSS] = 1; // disable champion normally.
125 						}
126 					}
127 				}
128 
129 				playSoundEntity(my, 153, 128);
130 
131 				if ( !SUMMONTRAP_INITIALIZED )
132 				{
133 					if ( SUMMONTRAP_MONSTER < KOBOLD )
134 					{
135 						//messagePlayer(clientnum, language[2352], language[90 + SUMMONTRAP_MONSTER]);
136 					}
137 					else if ( SUMMONTRAP_MONSTER >= KOBOLD )
138 					{
139 						//messagePlayer(clientnum, language[2352], language[2000 + (SUMMONTRAP_MONSTER - 21)]);
140 					}
141 					SUMMONTRAP_INITIALIZED = 1; // trap is starting up for the first time.
142 				}
143 
144 				if ( pickedRandomMonsters )
145 				{
146 					SUMMONTRAP_MONSTER = -1;
147 				}
148 
149 				if ( (SUMMONTRAP_FAILURERATE != 0) && (rand() % 100 < SUMMONTRAP_FAILURERATE) )
150 				{
151 					// trap breaks!
152 					SUMMONTRAP_FIRED = 1;
153 					playSoundEntity(my, 76, 128);
154 					return;
155 				}
156 
157 				if ( SUMMONTRAP_SPAWNCYCLES > 0 )
158 				{
159 					--SUMMONTRAP_SPAWNCYCLES; // decrement the amount of spawn chances left.
160 					if ( SUMMONTRAP_SPAWNCYCLES == 0 )
161 					{
162 						// trap is finished running
163 						SUMMONTRAP_FIRED = 1;
164 						playSoundEntity(my, 76, 128);
165 					}
166 				}
167 				else
168 				{
169 					// trap keeps running.
170 				}
171 			}
172 		}
173 	}
174 	else
175 	{
176 		SUMMONTRAP_TICKS_TO_FIRE = 0;
177 	}
178 	return;
179 }
180