2 * Copyright (C) 2010 gonzoj
4 * Please check the CREDITS file for further information.
6 * This program 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.
11 * This program 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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "d2pointers.h"
27 #include "d2structs.h"
36 #define CLEAR(a, n, t) memset(a, 0, n * sizeof(t))
38 typedef struct level_info
46 #define PRINT(info) printf("level_info.act_no: %i\n", info.act_no); printf("level_info.level_id: %i\n", info.level_id); printf("level_info.x: %i\n", info.x); printf("level_info.y: %i\n", info.y);
49 level_info
*info_level
= NULL
;
51 #define INIT(info) info = NULL; n_##info = 0;
52 #define ADD(type, info, i) info = realloc(info, ++n_##info * sizeof(type)); memcpy(info + n_##info - 1, &i, sizeof(type));
53 #define REMOVE_ALL(info) if (info) free(info); info = NULL; n_##info = 0;
54 #define SIZE(info) n_##info
55 #define ELEMENT(info, i) info[i]
60 { 0, 5055, 5054, 5053, 5052, 5051, 5050, 5049, 3714, 5047, 5046, 5045, 5044,
61 5043, 5042, 5041, 5040, 5039, 5038, 5037, 5036, 5035, 5034, 5033, 5032,
62 5031, 5030, 5029, 5028, 5027, 5026, 5025, 5024, 5023, 5022, 5021, 5020,
63 5019, 5018, 788, 852, 851, 850, 849, 848, 847, 846, 845, 844, 843, 842,
64 841, 840, 839, 838, 837, 836, 835, 834, 833, 832, 831, 830, 829, 828,
65 827, 826, 826, 826, 826, 826, 826, 826, 825, 824, 820, 819, 818, 817,
66 816, 815, 814, 813, 812, 810, 811, 809, 808, 806, 805, 807, 804, 845,
67 844, 803, 802, 801, 800, 799, 798, 797, 796, 795, 790, 792, 793, 794,
68 791, 789, 22646, 22647, 22648, 22649, 22650, 22651, 22652, 22653, 22654,
69 22655, 22656, 22657, 22660, 21865, 21866, 21867, 22658, 22659, 22662,
70 22663, 22664, 22665, 22667, 22666, 11155, 11156, 11157, 5018 };
73 { 1, 40, 75, 103, 109, 137 };
82 draw_presets(room2
*room2
)
85 for (unit
= room2
->preset
; unit
!= NULL
; unit
= unit
->next
)
92 switch (unit
->txt_file_no
)
108 switch (unit
->txt_file_no
)
112 if (room2
->level
->level_no
== 79)
120 if (room2
->level
->level_no
== 25)
138 if (room2
->level
->level_no
== 46)
146 if (room2
->level
->level_no
!= 75 && room2
->level
->level_no
!= 103)
154 if (room2
->level
->level_no
== 107)
163 if (unit
->txt_file_no
> 572)
169 object_txt
*obj
= D2COMMON_get_object_txt(unit
->txt_file_no
);
170 if (obj
->automap
== 310)
172 cell_no
= obj
->subclass
& 1 ? 310 : 0;
176 cell_no
= obj
->automap
;
187 if (room2
->room_tiles
== NULL
)
191 for (tile
= room2
->room_tiles
; tile
!= NULL
; tile
= tile
->next
)
193 if (*(tile
->num
) == unit
->txt_file_no
)
195 info
.level_id
= tile
->room2
->level
->level_no
;
199 if (info
.level_id
== 0)
203 unit_any
*hero
= D2CLIENT_get_player_unit();
204 info
.act_no
= hero
->act_no
;
205 info
.x
= unit
->x
+ (room2
->x
* 5) - (8 << 1);
206 info
.y
= unit
->y
+ (room2
->y
* 5) - 10;
207 DEBUG_DO(printf("add level info #%i\n", n_info_level
);)
208 DEBUG_DO(PRINT(info
);)
209 ADD(level_info
, info_level
, info
)
215 automap_cell
*cell
= D2CLIENT_new_automap_cell();
216 cell
->cell_no
= cell_no
;
217 int x
= unit
->x
+ room2
->x
* 5;
218 int y
= unit
->y
+ room2
->y
* 5;
219 cell
->pixel_x
= ((x
- y
) * 16) / 10 + 1;
220 cell
->pixel_y
= ((x
+ y
) * 8) / 10 - 3;
221 D2CLIENT_add_automap_cell(cell
,
222 &((*p_D2CLIENT_automap_layer
)->objects
));
228 reveal_level(level
*level
)
230 DEBUG_DO(printf("init automap layer...\n");)
231 if (!init_automap_layer(level
->level_no
))
233 printf("err: could not init automap layer for level %i\n",
237 DEBUG_DO(printf("automap_layer: 0x%08X\n", (vaddr
) *p_D2CLIENT_automap_layer
);)
238 DEBUG_DO(printf("get player struct...\n");)
239 unit_any
*unit
= D2CLIENT_get_player_unit();
242 printf("err: could not get player unit\n");
245 DEBUG_DO(printf("unit: 0x%08X\n", (vaddr
) unit
);)
247 for (room2
= level
->room2_first
; room2
!= NULL
; room2
= room2
->next
)
249 DEBUG_DO(printf("room2: 0x%08X\n", (vaddr
) room2
);)
251 if (room2
->room1
== NULL
)
253 DEBUG_DO(printf("add room data...\n");)
254 D2COMMON_add_room_data(level
->misc
->act
, level
->level_no
, room2
->x
,
255 room2
->y
, unit
->path
->room1
);
256 if (room2
->room1
== NULL
)
258 printf("err: could not add room data\n");
263 DEBUG_DO(printf("room1: 0x%08X\n", (vaddr
) room2
->room1
);)
264 DEBUG_DO(printf("reveal room...\n");)
265 D2CLIENT_reveal_automap_room(room2
->room1
, 1, *p_D2CLIENT_automap_layer
);
266 DEBUG_DO(printf("draw presets...\n");)
270 DEBUG_DO(printf("remove room data...\n");)
271 D2COMMON_remove_room_data(level
->misc
->act
, level
->level_no
,
272 room2
->x
, room2
->y
, unit
->path
->room1
);
275 DEBUG_DO(printf("init automap layer back...\n");)
276 init_automap_layer(unit
->path
->room1
->room2
->level
->level_no
);
283 DEBUG_DO(printf("get player unit...\n");)
284 unit_any
*unit
= D2CLIENT_get_player_unit();
285 DEBUG_DO(printf("unit: 0x%08X\n", (vaddr
) unit
);)
289 printf("err: could not get player unit\n");
292 for (n_level
= town_levels
[unit
->act_no
] + 1; n_level
293 < town_levels
[unit
->act_no
+ 1]; n_level
++)
299 DEBUG_DO(printf("get level struct...\n");)
300 level
*level
= get_level(unit
->act
->misc
, n_level
);
301 DEBUG_DO(printf("level: 0x%08X\n", (vaddr
) level
);)
304 printf("err: could not get a valid level struct\n");
307 if (level
->room2_first
== NULL
)
309 DEBUG_DO(printf("try to init level...\n");)
310 D2COMMON_init_level(level
);
311 if (level
->room2_first
== NULL
)
313 printf("err: could not init level %i\n", n_level
);
317 DEBUG_DO(printf("reveal level %i...\n", n_level
);)
318 if (!reveal_level(level
))
320 printf("err: could not reveal level %i\n", n_level
);
323 DEBUG_DO(printf("revealed all levels\n");)
324 DEBUG_DO(printf("revealed act %i\n", unit
->act_no
+ 1);)
331 unit_any
*hero
= *p_D2CLIENT_player_unit
;
336 if (!revealed_act
[hero
->act_no
])
338 manage_threads(SuspendThread
);
341 revealed_act
[hero
->act_no
] = 1;
342 print_ingame(D2FONT_GOLD
, "[snoogans] %s%s %i", FONT_COLOR(0),
343 "revealed act", hero
->act_no
+ 1);
347 print_ingame(D2FONT_GOLD
, "[snoogans] %s%s %i", FONT_COLOR(1),
348 "failed to reveal act", hero
->act_no
+ 1);
350 manage_threads(ResumeThread
);
357 unit_any
*player
= D2CLIENT_get_player_unit();
360 printf("err: could not get player struct\n");
363 int level_no
= player
->path
->room1
->room2
->level
->level_no
;
364 if (level_no
== 1 || level_no
== 40 || level_no
== 75 || level_no
== 103
370 for (room1
= player
->act
->room1
; room1
!= NULL
; room1
= room1
->next
)
373 for (unit
= room1
->unit_first
; unit
!= NULL
; unit
= unit
->list_next
)
375 if (!valid_monster(unit
))
381 if (unit
->monster_data
->boss
& 1 && !(unit
->monster_data
->champ
384 draw_cross(unit
->path
->x
, unit
->path
->y
, D2GFX_WHITE
, 1);
385 if (unit
->monster_data
->boss
& 1
386 && !(unit
->monster_data
->champ
& 1))
388 ms_wchar_t
*wname
= D2CLIENT_get_unit_name(unit
);
392 ms_wchar_to_char(wname
, name
);
393 draw_text(unit
->path
->x
- 6, unit
->path
->y
- 6,
394 D2FONT_GOLD
, 1, D2FONT_SMALL
, 1, "%s", name
);
398 /* check immunities */
401 else if (D2COMMON_get_unit_stat(unit
, 36, 0) >= 100)
403 draw_cross(unit
->path
->x
, unit
->path
->y
, D2GFX_GOLD
, 1);
406 else if (D2COMMON_get_unit_stat(unit
, 43, 0) >= 100)
408 draw_cross(unit
->path
->x
, unit
->path
->y
, D2GFX_BLUE
, 1);
411 else if (D2COMMON_get_unit_stat(unit
, 39, 0) >= 100)
413 draw_cross(unit
->path
->x
, unit
->path
->y
, D2GFX_RED
, 1);
416 else if (D2COMMON_get_unit_stat(unit
, 41, 0) >= 100)
418 draw_cross(unit
->path
->x
, unit
->path
->y
, D2GFX_YELLOW
, 1);
421 else if (D2COMMON_get_unit_stat(unit
, 45, 0) >= 100)
423 draw_cross(unit
->path
->x
, unit
->path
->y
, D2GFX_GREEN
, 1);
426 else if (D2COMMON_get_unit_stat(unit
, 37, 0) >= 100)
428 draw_cross(unit
->path
->x
, unit
->path
->y
, D2GFX_ORANGE
, 1);
432 draw_cross(unit
->path
->x
, unit
->path
->y
, D2GFX_WHITE
, 1);
435 else if (unit
->type
== 3)
437 int missile_color
= (player
->id
== unit
->owner_id
) ? D2GFX_GREEN
439 draw_box(unit
->path
->x
- 3, unit
->path
->y
- 3, 3, 3,
440 missile_color
, 1, 5);
449 unit_any
*player
= D2CLIENT_get_player_unit();
451 for (i
= 0; i
< SIZE(info_level
); i
++)
453 level_info info
= ELEMENT(info_level
, i
);
454 if (info
.act_no
!= player
->act_no
)
458 ms_wchar_t
*local_text
= D2LANG_get_local_text(
459 area_local_id
[info
.level_id
]);
462 int font
= D2FONT_WHITE
;
463 char level_name
[512];
464 ms_wchar_to_char(local_text
, level_name
);
465 if (info
.level_id
== player
->act
->misc
->staff_tomb_level
)
469 draw_text(info
.x
, info
.y
, font
, 1, D2FONT_SMALL
, 1, "%s", level_name
);
476 static int hp_warning
= 1;
477 static int ping_warning
= 1;
481 if (get_hp_percent() < 25) /* hardcoded :( */
483 print_ingame(D2FONT_GOLD
, "[snoogans] %schicken exit (%i%)", FONT_COLOR(1), 25);
484 D2CLIENT_exit_game();
487 else if (get_hp_percent() < 33 && hp_warning
) /* hardcoded :( */
489 print_ingame(D2FONT_GOLD
, "[snoogans] %scritical health points (%i%)", FONT_COLOR(1), 33);
492 else if (get_hp_percent() >= 33 && !hp_warning
)
496 if (*p_D2CLIENT_ping
> 1000) /* hardcoded :( */
498 print_ingame(D2FONT_GOLD
, "[snoogans] %schicken exit (%i ms)", FONT_COLOR(1), 1000);
499 D2CLIENT_exit_game();
502 else if (*p_D2CLIENT_ping
> 300 && ping_warning
) /* hardcoded :( */
504 print_ingame(D2FONT_GOLD
, "[snoogans] %scritical ping (%i ms)", FONT_COLOR(1), 300);
507 else if (*p_D2CLIENT_ping
<= 300 && !ping_warning
)
520 print_ingame(D2FONT_GOLD
, "[snoogans] %s%s", FONT_COLOR(0),
521 "loaded snoogans.so v 0.4");
523 CLEAR(revealed_act
, 5, int);
527 if (!ingame() && *p_D2WIN_first_control
)
529 CLEAR(revealed_act
, 5, int);
530 REMOVE_ALL(info_level
)
535 chicken(); /* chicken feature, maybe better included in the ingame hook */
536 if (!D2CLIENT_get_ui_var(0x01))
540 if (viewing_unit
&& viewing_unit
->id
)
542 if (!viewing_unit
->inventory
)
545 D2CLIENT_set_ui_var(0x01, 1, 0);
547 else if (!D2CLIENT_find_server_side_unit(viewing_unit
->id
,
551 D2CLIENT_set_ui_var(0x01, 1, 0);
553 else if (viewing_unit
->mode
== 0 || viewing_unit
->mode
== 17)
556 D2CLIENT_set_ui_var(0x01, 1, 0);
559 unit_any
*unit
= D2CLIENT_get_selected_unit();
560 if (unit
&& unit
->inventory
&& unit
->mode
!= 0 && unit
->mode
!= 17
563 if (!D2CLIENT_get_ui_var(0x01))
568 game_info
*info
= D2CLIENT_get_game_info();
571 strcpy(last_game_name
, info
->game_name
);
578 print_ingame(D2FONT_GOLD
, "[snoogans] %s%s", FONT_COLOR(0), "unloaded");
580 REMOVE_ALL(info_level
)
592 pthread_join(mh_thread
, NULL
);