/*******************************************************************************
Name: gl_super_sneak
Location: global script
Description: Displays the currently visible area for critters
when the player is in sneak mode
Passes an object around the critter within
a certain range to run obj_can_see_obj() on
and drops a poop at that location if it returns success
Created: by QuantumApprentice
Updated: 12.30.2022
*******************************************************************************/
#include "..\headers\command.h"
#include "..\headers\sfall.h"
#include "..\headers\define.h"
#include "..\headers\define_extra.h"
procedure start;
procedure poop(variable temp_obj, variable tile);
procedure sneak_check;
procedure hook_sneak;
procedure perception_hook;
procedure destroy_poops;
procedure check_tiles(variable tile_array, variable temp_critter_obj);
procedure expand_tile_array(variable tile_array);
procedure deal_with_poops_outside_sneak_range(variable tile_array);
procedure store_tiles(variable tile_array, variable hex_array);
procedure objects_in_radius_not_dude_obj;
procedure hex_square(variable hex_array, variable trash_array);
procedure manual_unwrap(variable hex_array, variable trash_array);
// defines
#define visible 0
#define invisible 1
#define move_w_hex_array
//global variables
variable critter_array
variable poop_array
variable dude_obj_tile
variable dude_obj_elevation
variable counter = 0
variable hex_counter = 0;
procedure start begin
dude_obj_tile := dude_tile;
dude_obj_elevation := dude_elevation;
poop_array := create_array(1, 0);
fix_array(poop_array);
// hex_array := create_array(270, 0);
// fix_array(hex_array);
if game_loaded then begin
register_hook_proc(HOOK_SNEAK, hook_sneak);
register_hook_proc(HOOK_WITHINPERCEPTION, perception_hook);
display_msg("Super Sneak Script loaded!");
end
end
//only sfall_arg_at(1) will ever be the dude_obj (no clue why this is)
procedure perception_hook begin
variable target = get_sfall_arg_at(1);
if (target == dude_obj) then begin
float_msg(dude_obj, "tile: " + dude_obj_tile, FLOAT_COLOR_WHISPER);
if(using_skill(dude_obj, SKILL_SNEAK)) then begin
if (dude_obj_tile != dude_tile) then begin
dude_obj_tile := dude_tile;
call sneak_check;
end
end else begin
call destroy_poops;
end
end
end
// destroy all poops and free the array
procedure destroy_poops begin
if (len_array(poop_array) > 1) then begin
variable stupid;
foreach stupid in poop_array begin
if (obj_pid(stupid) == PID_SMALL_GOO_3) then begin
destroy_object(stupid);
end
end
free_array(poop_array);
poop_array := create_array(1, 0);
fix_array(poop_array);
end
end
procedure hook_sneak begin
call sneak_check;
display_msg("hook_sneak running...");
end
procedure poop(variable temp_critter_obj, variable tile) begin
//usage counter//////////////////////////////////////////////////////
// display_msg("how often? " + counter);
// counter++;
//counter end////////////////////////////////////////////////////////
variable already_checked := false;
variable invisible_obj;
variable critter;
foreach critter in critter_array begin
if not (already_checked) then begin
if(obj_can_see_obj(critter, temp_critter_obj)) then begin
already_checked := true;
invisible_obj = tile_contains_pid_obj(tile, dude_obj_elevation, PID_SMALL_GOO_3);
if (invisible_obj /*and not (obj_is_visible_flag(invisible_obj))*/) then begin
if not(obj_is_visible_flag(invisible_obj)) then begin
set_obj_visibility(invisible_obj, visible);
end
end
else begin
//TODO: use tile numbers in a shader?
// or possibly spawn something more lightweight than PID_SMALL_GOO_3?
// Alternatives:
// draw_image()
// win_fill_color()
// load_shader()
// activate_shader()
variable temp_poo := create_object_sid(PID_SMALL_GOO_3, tile, dude_obj_elevation, -1);
variable len_poop_array = len_array(poop_array);
poop_array[len_poop_array-1] := temp_poo;
resize_array(poop_array, len_poop_array + 1);
end
end
else begin
invisible_obj = tile_contains_pid_obj(tile, dude_obj_elevation, PID_SMALL_GOO_3);
if (obj_is_visible_flag(invisible_obj)) then set_obj_visibility(invisible_obj, invisible);
end
end
end
end
procedure sneak_check begin
call objects_in_radius_not_dude_obj;
variable sneak_range := 10;
variable last_tile := tile_num_in_direction(dude_obj_tile, 0, sneak_range);
// Store corner tile numbers for all 6 directions
// These are used as waypoints to travel around the player
variable tile_array = create_array(6, 0);
tile_array[0] := tile_num_in_direction(dude_obj_tile, 0, 1);
tile_array[1] := tile_num_in_direction(dude_obj_tile, 1, 1);
tile_array[2] := tile_num_in_direction(dude_obj_tile, 2, 1);
tile_array[3] := tile_num_in_direction(dude_obj_tile, 3, 1);
tile_array[4] := tile_num_in_direction(dude_obj_tile, 4, 1);
tile_array[5] := tile_num_in_direction(dude_obj_tile, 5, 1);
variable temp_critter_obj;
temp_critter_obj := create_object_sid( PID_RAT, 0, dude_obj_elevation, -1);
////TODO: set critter to sneaking?//////////////////////////////////
// set_object_data(temp_critter_obj, SKILL_SNEAK, 1);
// display_msg("" + has_skill(temp_critter_obj, SKILL_SNEAK));
// display_msg("temp_obj " + temp_critter_obj);
#ifdef move_w_hex_array
////////////////////////////////////////////////////////
//create an array containing all hexes around the player
//that need to be checked with obj_can_see_obj()
//TODO: make hex_array[]/trash_array[] the right size
// variable hex_array := create_array(401, 0);
variable hex_array:= [
-1010, -810, -610, -410, -210, 10, 210, 410, 610, 810, 1010,
/*-2009, -1809, -1609, -1409, -1209,*/ -1009, -809, -609, -409, -209, 9, 209, 409, 609, 809, 1009, 1209, //1409, 1609, 1809, 2009,
/*-2008, -1808, -1608, -1408,*/ -1208, -1008, -808, -608, -408, -208, 8, 208, 408, 608, 808, 1008, 1208, //1408, 1608, 1808, 2008,
/*-2007, -1807, -1607, -1407,*/ -1207, -1007, -807, -607, -407, -207, 7, 207, 407, 607, 807, 1007, 1207, //1407, 1607, 1807, 2007,
/*-2006, -1806, -1606,*/ -1406, -1206, -1006, -806, -606, -406, -206, 6, 206, 406, 606, 806, 1006, 1206, 1406, //1606, 1806, 2006,
/*-2005, -1805, -1605,*/ -1405, -1205, -1005, -805, -605, -405, -205, 5, 205, 405, 605, 805, 1005, 1205, 1405, 1605, //1805, 2005,
/*-2004, -1804,*/ -1604, -1404, -1204, -1004, -804, -604, -404, -204, 4, 204, 404, 604, 804, 1004, 1204, 1404, 1604, //1804, 2004,
/*-2003, -1803,*/ -1603, -1403, -1203, -1003, -803, -603, -403, -203, 3, 203, 403, 603, 803, 1003, 1203, 1403, 1603, 1803, //2003,
/*-2002,*/ -1802, -1602, -1402, -1202, -1002, -802, -602, -402, -202, 2, 202, 402, 602, 802, 1002, 1202, 1402, 1602, 1802, //2002,
/*-2001,*/ -1801, -1601, -1401, -1201, -1001, -801, -601, -401, -201, 1, 201, 401, 601, 801, 1001, 1201, 1401, 1601, 1801, 2001,
-2000, -1800, -1600, -1400, -1200, -1000, -800, -600, -400, -200,-10, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000,
/*-1999,*/ -1799, -1599, -1399, -1199, -999, -799, -599, -399, -199, -9, 199, 399, 599, 799, 999, 1199, 1399, 1599, 1799, 1999,
/*-1998,*/ -1798, -1598, -1398, -1198, -998, -798, -598, -398, -198, -8, 198, 398, 598, 798, 998, 1198, 1398, 1598, 1798, //1998,
/*-1997, -1797,*/ -1597, -1397, -1197, -997, -797, -597, -397, -197, -7, 197, 397, 597, 797, 997, 1197, 1397, 1597, 1797, //1997,
/*-1996, -1796,*/ -1596, -1396, -1196, -996, -796, -596, -396, -196, -6, 196, 396, 596, 796, 996, 1196, 1396, 1596, //1796, 1996,
/*-1995, -1795, -1595,*/ -1395, -1195, -995, -795, -595, -395, -195, -5, 195, 395, 595, 795, 995, 1195, 1395, 1595, //1795, 1995,
/*-1994, -1794, -1594,*/ -1394, -1194, -994, -794, -594, -394, -194, -4, 194, 394, 594, 794, 994, 1194, 1394, //1594, 1794, 1994,
/*-1993, -1793, -1593, -1393,*/ -1193, -993, -793, -593, -393, -193, -3, 193, 393, 593, 793, 993, 1193, 1393, //1593, 1793, 1993,
/*-1992, -1792, -1592, -1392,*/ -1192, -992, -792, -592, -392, -192, -2, 192, 392, 592, 792, 992, 1192, //1392, 1592, 1792, 1992,
/*-1991, -1791, -1591, -1391, -1191,*/ -991, -791, -591, -391, -191, -1, 191, 391, 591, 791, 991, 1191, //1391, 1591, 1791, 1991,
-990, -790, -590, -390, -190, 190, 390, 590, 790, 990
];
// // variable trash_array := create_array(271, 0);
// variable trash_array := [
// -2200, 2200, -2190, 2190, 10, -10,
// -2201, 2201, -2191, 2191, 210, -210, 190, -190,
// -2202, 2202, -2192, 2192, 410, -410, 390, -390,
// -2203, 2203, -2193, 2193, 610, -610, 590, -590,
// -2204, 2204, -2194, 2194, 810, -810, 790, -790,
// -2205, 2205, -2195, 2195, 1010,-1010, 990, -990,
// -2206, 2206, -2196, 2196, 1210,-1210, 1190, -1190,
// -2207, 2207, -2197, 2197, 1410,-1410, 1390, -1390,
// -2208, 2208, -2198, 2198, 1610,-1610, 1590, -1590,
// -2209, 2209, -2199, 2199, 1810,-1810, 1790, -1790,
// -2210, 2210, 2010,-2010, 1990, -1990
// ];
variable trash_array := [
11,
-1211, -1011, -811, -611, -411, -211, 211, 411, 611, 811, 1011, 1211,
-1210, 1210, 1410,
/*-2009, -1809, -1609,*/ -1409, -1209, /*-1009, -809, -609, -409, -209, 209, 409, 809, 1009, 1209,*/ 1409,/*1609, 1809, 2009,*/
/*-2008, -1808, -1608,*/ -1408,/* -1208, -1008, 808, 1008, 1208,*/ 1408, 1608, //1808, 2008,
/*-2007, -1807,*/-1607, -1407, /*1207, 1407,*/1607, /*1807, 2007,*/
/*-2006, -1806,*/ -1606, /*1406,*/1606, 1806, //2006,
/*-2005,*/-1805, -1605, /*1605,*/1805, //2005,
/*-2004,*/-1804, /*1604,*/1804, 2004,
-2003, -1803, /*1803,*/ 2003,
-2002, /*1802,*/ 2002, 2202,
-2201, -2001, /*2001,*/ 2201,
-2200, /*2000,*/ 2200,
-2199, -1999, /*1999,*/ 2199,
-1998, 1998, 2198,
-1997, -1797, 1997,
/*-1996,*/ -1796, 1796, 1996,
/*-1995,*/ -1795, -1595, 1795, //1995,
/*-1994, -1794,*/ -1594, 1594, 1794, //1994,
/*-1993, -1793,*/ -1593, -1393, 1593,//1793, 1993,
/*-1992, -1792, -1592,*/ -1392, /*-1192,*/ /*1192,*/ 1392, 1592,/*1792, 1992,*/
/*-1991, -1791, -1591,*/ -1391, -1191, /*-991, -390, -190, 190, 390, */ /*791, 991, 1191,*/ 1391, /*1591, 1791, 1991,*/
-1190, 1190, 1390,
-1189, -989, -789, -589, -389, -189, 189, 389, 589, 789, 989, 1189, /*1389, 1589,*/
-11
];
//stores hexes in a square pattern around dude_obj without the walk function
// call hex_square(hex_array, trash_array);
//Stores hexes in a hex pattern around dude_obj without walk function
call manual_unwrap(hex_array, trash_array);
hex_counter = 0;
variable hex;
foreach hex in hex_array begin
////uncomment to display "viewable area" around player
// create_object(PID_SMALL_GOO_3, hex, dude_obj_elevation);
move_to(temp_critter_obj, hex, dude_obj_elevation);
call poop(temp_critter_obj, hex);
end
// Set poops to invisible
// (1 = invisible for some reason so I created defines for readability)
foreach hex in trash_array begin
////uncomment to display "invisible ring" around player
//create_object(PID_BLOOD_1, hex, dude_obj_elevation);
variable obj_to_set_invisible = tile_contains_pid_obj(hex, elevation(dude_obj), PID_SMALL_GOO_3);
if(obj_to_set_invisible) then begin
set_obj_visibility(obj_to_set_invisible, invisible);
end
end
#else
////Uncomment this to store hexes in array
// while not (tile_array[0] == last_tile) do begin
// call store_tiles(tile_array, hex_array);
// end
////////////////////////////////////////////////////////
//instead of an array of hexes, just get the next hex number
//using tile_num_in_direction() and move temp_critter_obj
while not (tile_array[0] == last_tile) do begin
call check_tiles(tile_array, temp_critter_obj);
call expand_tile_array(tile_array);
end
// reset last_tile to new position for one more set of waypoints
// deal with outer ring of vision
last_tile := tile_num_in_direction(dude_tile, 0, sneak_range + 1);
while not (tile_array[0] == last_tile) do begin
call expand_tile_array(tile_array);
call deal_with_poops_outside_sneak_range(tile_array);
end
#endif
//cleanup
destroy_object(temp_critter_obj);
free_array(tile_array);
free_array(critter_array);
free_array(hex_array);
end
//store hex numbers around the player using tile_num_in_direction()
procedure store_tiles(variable tile_array, variable hex_array) begin
variable tile_var := tile_array[0];
variable i;
for (i:=0; i<6; i++;) begin
// Store all the tiles that need to be checked in an array
variable next_dir := (i+1) % 6;
while not (tile_var == tile_array[next_dir]) do begin
tile_var := tile_num_in_direction(tile_var, rotation_to_tile(tile_var, tile_array[next_dir]), 1);
hex_array[hex_counter] := tile_var;
hex_counter++;
display_msg("counter: " + hex_counter);
end
end
call expand_tile_array(tile_array);
end
//move temp_critter_obj around the player and spawn poops
//where the other critter/s can see it
procedure check_tiles(variable tile_array, variable temp_critter_obj) begin
//TODO: set_object_data() to match player pass/fail sneak check
// also have to set critter to use sneak mode
variable tile_var := tile_array[0];
variable i;
for (i:=0; i<6; i++) begin
// Move temp_critter_obj around the player
variable next_dir := (i+1) % 6;
while not (tile_var == tile_array[next_dir]) do begin
////////////////////////////////////////////////////////
move_to(temp_critter_obj, tile_var, dude_obj_elevation);
////////////////////////////////////////////////////////
call poop(temp_critter_obj, tile_var);
tile_var := tile_num_in_direction(tile_var, rotation_to_tile(tile_var, tile_array[next_dir]), 1);
end
end
end
//copy all non-dude_obj critters to a new array for easy sorting
procedure objects_in_radius_not_dude_obj begin
variable visual_range := 20;
critter_array = create_array(1, 0);
variable temp := objects_in_radius(dude_obj_tile, visual_range, dude_obj_elevation, OBJ_TYPE_CRITTER);
variable i, j:=0;
for (i := 0; i < len_array(temp); i++) begin
if not (temp[i] == dude_obj) and not (is_critter_dead(temp[i])) then begin
critter_array[j] := temp[i];
j++;
resize_array(critter_array, j+1);
end
end
free_array(temp);
end
procedure expand_tile_array(variable tile_array) begin
variable j;
for (j := 0; j < 6; j++) begin
tile_array[j] := tile_num_in_direction(tile_array[j], j, 1);
end
end
procedure deal_with_poops_outside_sneak_range(variable tile_array) begin
variable k;
variable tile_var := tile_array[0];
for (k:=0; k<6; k++) begin
variable next_dir := (k+1) % 6;
while not (tile_var == tile_array[next_dir]) do begin
tile_var := tile_num_in_direction(tile_var, rotation_to_tile(tile_var, tile_array[next_dir]), 1);
variable obj_to_set_invisible = tile_contains_pid_obj(tile_var, elevation(dude_obj), PID_SMALL_GOO_3);
if(obj_to_set_invisible) then begin
// Set poops to invisible
// (1 = invisible for some reason so I created defines for readability)
set_obj_visibility(obj_to_set_invisible, invisible);
end
end
end
end
procedure hex_square(variable hex_array, variable trash_array) begin
variable tile_var := tile_num_in_direction(dude_obj_tile, 0, 10);
variable i, j;
for (i := 0; i < 11; i++) begin
hex_array[hex_counter] := tile_var + i;
trash_array[i] := hex_array[i] - 200;
trash_array[i+10] := hex_array[i] + 2000;
// create_object_sid(PID_SMALL_GOO_3, hex_array[hex_counter], dude_obj_elevation, -1);
hex_counter++;
end
variable trash_counter := 20;
for(i := 0; i < 2001; i+=200) begin
trash_array[trash_counter] := hex_array[0] - 1 + i;
trash_array[trash_counter + 10] := hex_array[9] + 1 + i;
trash_counter++;
end
for (i := 0; i < 2001; i+=200) begin
for (j := 0; j < 11; j++) begin
hex_array[hex_counter] := hex_array[i] + j;
// Uncomment to see viewable area
// create_object_sid(PID_SMALL_GOO_3, hex_array[hex_counter], dude_obj_elevation, -1);
hex_counter++;
end
end
end
procedure manual_unwrap(variable hex_array, variable trash_array) begin
variable i;
for (i := 0; i<401; i++) begin
hex_array[i] += dude_obj_tile;
end
for (i := 0; i<401; i++) begin
trash_array[i] += dude_obj_tile;
end
end