6 #include "../../command.h" |
6 #include "../../command.h" |
7 #include "../../player.h" |
7 #include "../../player.h" |
8 #include "../ai.h" |
8 #include "../ai.h" |
9 #include "../ai_threads.h" |
9 #include "../ai_threads.h" |
10 |
10 |
|
11 void AIObject::SetDoCommandDelay(uint ticks) |
|
12 { |
|
13 assert(ticks > 0); |
|
14 AIObject::GetDoCommandStruct(_current_player)->delay = ticks; |
|
15 } |
|
16 |
|
17 uint AIObject::GetDoCommandDelay() |
|
18 { |
|
19 return AIObject::GetDoCommandStruct(_current_player)->delay; |
|
20 } |
|
21 |
|
22 void AIObject::SetDoCommandMode(AIModeProc *proc) |
|
23 { |
|
24 AIObject::GetDoCommandStruct(_current_player)->mode = proc; |
|
25 } |
|
26 |
|
27 AIModeProc *AIObject::GetDoCommandMode() |
|
28 { |
|
29 return AIObject::GetDoCommandStruct(_current_player)->mode; |
|
30 } |
|
31 |
11 bool AIObject::CmdFailed(int32 res) |
32 bool AIObject::CmdFailed(int32 res) |
12 { |
33 { |
13 return ::CmdFailed(res); |
34 return ::CmdFailed(res); |
14 } |
35 } |
15 |
36 |
16 bool AIObject::CmdSucceeded(int32 res) |
37 bool AIObject::CmdSucceeded(int32 res) |
17 { |
38 { |
18 return !::CmdFailed(res); |
39 return !::CmdFailed(res); |
|
40 } |
|
41 |
|
42 AIObject::AIDoCommandStruct *AIObject::GetDoCommandStruct(PlayerID player) |
|
43 { |
|
44 static bool initialized = false; |
|
45 /* Storage for data on per-AI level */ |
|
46 static AIObject::AIDoCommandStruct command_struct[MAX_PLAYERS]; |
|
47 |
|
48 if (!initialized) { |
|
49 initialized = true; |
|
50 /* Set default values */ |
|
51 for (int i = 0; i < MAX_PLAYERS; i++) { |
|
52 command_struct[i].mode = NULL; |
|
53 command_struct[i].delay = 1; |
|
54 } |
|
55 } |
|
56 |
|
57 return &command_struct[player]; |
19 } |
58 } |
20 |
59 |
21 int32 AIObject::DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc) |
60 int32 AIObject::DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc) |
22 { |
61 { |
23 PlayerID old_lp; |
62 PlayerID old_lp; |
27 /* The test already resets _cmd_text, so backup the pointer */ |
66 /* The test already resets _cmd_text, so backup the pointer */ |
28 tmp_cmdtext = _cmd_text; |
67 tmp_cmdtext = _cmd_text; |
29 |
68 |
30 /* First, do a test-run to see if we can do this */ |
69 /* First, do a test-run to see if we can do this */ |
31 res = ::DoCommand(tile, p1, p2, flags & ~DC_EXEC, procc); |
70 res = ::DoCommand(tile, p1, p2, flags & ~DC_EXEC, procc); |
32 /* The command failed, or you didn't want to execute, or you are quering, return */ |
71 /* The command failed, so return */ |
33 if (this->CmdFailed(res) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST)) return res; |
72 if (this->CmdFailed(res)) return res; |
|
73 |
|
74 /* Check what the callback wants us to do */ |
|
75 if (this->GetDoCommandMode() != NULL && !this->GetDoCommandMode()(tile, p1, p2, flags, procc)) return res; |
34 |
76 |
35 /* Restore _cmd_text */ |
77 /* Restore _cmd_text */ |
36 _cmd_text = tmp_cmdtext; |
78 _cmd_text = tmp_cmdtext; |
37 |
79 |
38 /* If we did a DC_EXEC, and the command did not return an error, execute it |
80 /* If we did a DC_EXEC, and the command did not return an error, execute it |
49 _local_player = _current_player; |
91 _local_player = _current_player; |
50 ::NetworkSend_Command(tile, p1, p2, procc, CcAI); |
92 ::NetworkSend_Command(tile, p1, p2, procc, CcAI); |
51 _local_player = old_lp; |
93 _local_player = old_lp; |
52 |
94 |
53 /* Suspend the AI till the command is really executed */ |
95 /* Suspend the AI till the command is really executed */ |
54 AI_SuspendPlayer(_current_player, -1); |
96 AI_SuspendPlayer(_current_player, -this->GetDoCommandDelay()); |
55 /* Check if the callback still agrees with us, else return error */ |
97 /* Check if the callback still agrees with us, else return error */ |
56 if (!AI_GetCallbackResult(_current_player)) res = CMD_ERROR; |
98 if (!AI_GetCallbackResult(_current_player)) res = CMD_ERROR; |
57 } else { |
99 } else { |
58 #else |
100 #else |
59 { |
101 { |
60 #endif |
102 #endif |
61 /* For SinglePlayer we execute the command immediatly */ |
103 /* For SinglePlayer we execute the command immediatly */ |
62 ::DoCommandP(tile, p1, p2, NULL, procc); |
104 ::DoCommandP(tile, p1, p2, NULL, procc); |
63 /* Suspend the AI player for 1 tick, so it simulates MultiPlayer */ |
105 /* Suspend the AI player for 1 tick, so it simulates MultiPlayer */ |
64 AI_SuspendPlayer(_current_player, 1); |
106 AI_SuspendPlayer(_current_player, this->GetDoCommandDelay()); |
65 } |
107 } |
66 |
108 |
67 return res; |
109 return res; |
68 } |
110 } |