SHARE
TWEET

ZDoom Factions

skroton May 29th, 2016 (edited) 224 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #library "FACTION"
  2.  
  3. #include "zcommon.acs"
  4.  
  5. #libdefine MAX_SIGNED_LONG 2147483647
  6.  
  7. #libdefine NUM_FACTIONS 50
  8.  
  9. global int 51:faction_a[];  /* 0-63 = Player TIDs, 100 onwards = faction indexes and tids */
  10.  
  11. int total_faction = (NUM_FACTIONS - 1); /* counts 0 as first faction, so for instance if there are 10 total factions this should be 9 */
  12.  
  13. int faction_indexes[NUM_FACTIONS] = { 0 }; /* index locations for global array management */
  14.                            
  15. int targets[200][2]; /* array of targets to be used for targets in script; map level because compatibility and really no difference */
  16.  
  17. str faction_s[50] = { "NULL" }; /* string array to store class names for assigning factions based on class names */
  18.  
  19. /* below function from ijon tichy's commonFuncs.h */
  20. function int magnitudeThree_f(int x, int y, int z)
  21. {
  22.     int len, ang;
  23.  
  24.     ang = VectorAngle(x, y);
  25.     if (((ang + 0.125) % 0.5) > 0.25) { len = FixedDiv(y, sin(ang)); }
  26.     else { len = FixedDiv(x, cos(ang)); }
  27.  
  28.     ang = VectorAngle(len, z);
  29.     if (((ang + 0.125) % 0.5) > 0.25) { len = FixedDiv(z, sin(ang)); }
  30.     else { len = FixedDiv(len, cos(ang)); }
  31.  
  32.     return len;
  33. }
  34.  
  35. /* below function from ijon tichy's commonFuncs.h */
  36. function int distance_tid(int tid1, int tid2)
  37. {
  38.     int x1 = GetActorX(tid1);
  39.     int y1 = GetActorY(tid1);
  40.     int z1 = GetActorZ(tid1);
  41.  
  42.     int x2 = GetActorX(tid2);
  43.     int y2 = GetActorY(tid2);
  44.     int z2 = GetActorZ(tid2);
  45.  
  46.     return magnitudeThree_f(x2-x1, y2-y1, z2-z1);
  47. }
  48.  
  49. function int setup_array_index (void) /* function to set up array index before being used */
  50. {
  51.   if(faction_indexes[0] == 100){ return 0; } /* if faction array is already set up, don't set it up */
  52.  
  53.   if(GetCVar("faction_debug_msg")){ log(s:"initializing faction index array"); } /* debugging log */
  54.  
  55.   for(int i = 0; i <= total_faction; i++){ /* for all faction array elements */
  56.     if(GetCVar("faction_debug_msg")){ log(s:"index for faction ", i:i, s:" set to ", i:100 + (i * 5)); } /* debugging log */
  57.     faction_indexes[i] = 100 + (i * 5); } /* create index locations starting at 100, 5 apart */
  58.   return 0;
  59. }
  60.  
  61. function int store_faction_tid (int faction, int tid) /* faction to place tid, tid to place */
  62. {
  63.   int index, index_loc; /* index for faction global array, location of faction index in faction tid global array */
  64.   index_loc = faction_indexes[faction]; /* grab index location for faction from map index array */
  65.   index = faction_a[index_loc]; /* grab index for faction from map array */
  66.  
  67.   if(GetCVar("faction_debug_msg")){ log(s:"storing tid ", i: tid, s:" for faction ", i: faction, s:" in location ", i:(index_loc + index)); } /* debugging log */
  68.  
  69.   faction_a[index_loc + index + 1] = tid; /* store the tid in the proper location in the faction tid array */
  70.   faction_a[index_loc] = index + 1; /* increment the faction index by one to track that we added new tid to faction tid array */
  71.  
  72.   if(GetCVar("faction_debug_msg")){ log(s:"faction ", i: faction, s:" index updated to ", i: faction_a[index_loc]); } /* debugging log */
  73.  
  74.   return 0;
  75. }
  76.  
  77. function int get_faction_tid (int faction, int loc) /* faction to get tid from, location in array */
  78. {
  79.   int index_loc; /* location of faction index in faction tid global array */
  80.   index_loc = faction_indexes[faction]; /* grab index location for faction from map index array */
  81.   return faction_a[index_loc + loc]; /* return the tid stored in the specified location */
  82. }
  83.  
  84. function int get_array_location (int faction, int loc) /* faction, location in faction array */
  85. {
  86.   return faction_indexes[faction] + loc; /* return the specified location */
  87. }
  88.  
  89. function int manage_faction_array (int faction) /* faction in array to manage */
  90. {
  91.   /* index for faction global array, location of faction index in faction tid global array, location of index after this one */
  92.   int index, index_loc, index_loc_next;
  93.  
  94.   /* loop variable, end of faction array, location of last faction index */
  95.   int i, faction_end, last_faction;
  96.  
  97.   index_loc = faction_indexes[faction]; /* grab index location for faction from map index array */
  98.   index_loc_next = faction_indexes[faction + 1]; /* grab next index location for faction from map index array */
  99.  
  100.   index = faction_a[index_loc]; /* grab index for faction from map array */
  101.   if(index > /* if the number of tids stored in the specified faction array */
  102.    (index_loc_next - index_loc - 3 )){ /* is within 2 elements of encroaching on next array */
  103.     last_faction = faction_indexes[total_faction]; /* get the location of the index for the last faction */
  104.    
  105.     if(GetCVar("faction_debug_msg")){ log(s:"faction ", i:faction, s:" is full so factions ", i:faction+1, s:" and onward are moving up 5 spaces in the array."); } /* debugging log */
  106.  
  107.     faction_end = last_faction + faction_a[last_faction] + 1; /* get the last element locaction in the array */
  108.  
  109.     for(i = faction_end; i >= index_loc_next; i-- ){  /* working backwards, move everything in array forward by 5 */
  110.       faction_a[i + 5] = faction_a[i];
  111.       faction_a[i] = 0; } /* zero out array element onced moved */
  112.      
  113.     for(i = (faction + 1); i <= total_faction; i++ ){  /* update all faction indexes, starting with one after the managed faction */
  114.       faction_indexes[i] += 5; }}/* increase faction index at i by 5 to make room for managed faction */
  115.  
  116.   return 0;
  117. }
  118.  
  119. function int get_faction(int tid)
  120. {
  121.   if(tid){ /* if the tid is not 0 */
  122.     return (CheckActorInventory(tid,"faction_counter") - 1); } /* return how many faction counters - 1 the actor with tid has (what their faction is)  */
  123.   return (CheckInventory("faction_counter") - 1); /* return how many faction counters - 1 the activator has (what their faction is) */
  124. }
  125.  
  126. function int set_faction(int tid, int faction)
  127. {
  128.   TakeInventory("faction_counter", MAX_SIGNED_LONG); /* remove any faction counters the actor might have, even though they shouldn't */
  129.   GiveInventory("faction_counter", faction + 1); /* give them a number of counters corresponding to their faction + 1, so we can know if they have a faction set even if faction is 0 */
  130.   return (CheckActorInventory(tid,"faction_counter") - 1);
  131. }
  132.  
  133. function int clear_targets (void) /* function for clearing out targets in target array */
  134. {
  135.   for(int i = 0; i < 200; i++){ /* for all target positions in array */
  136.     targets[i][0] = 0; /* set all tids in array to 0 */
  137.     targets[i][1] = 0;} /* set all distances in array to 0 */
  138.   return 0;
  139. }
  140.  
  141. function int store_target (int tid, int dist) /* function for clearing out targets in target array */
  142. {
  143.   int index; /* index for the target array */
  144.   index = targets[0][0]; /* get the index */
  145.   targets[0][0] += 1; /* update index to reflect that we added another target to array */
  146.   targets[index + 1][0] = tid; /* store the tid for the target in the array */
  147.   targets[index + 1][1] = dist; /* store the distance for the target in the array */
  148.   return targets[index + 1][0] == tid && targets[index +1][1] == dist; /* return if target is stored in array */
  149. }
  150.  
  151. script "start_fights" OPEN /* script to give every monster an item to get them to have factions */
  152. {
  153.   int xCount, yCount;
  154.  
  155.   /* from http://forum.zdoom.org/viewtopic.php?p=845858#p845858 */
  156.   for(xCount=-6; xCount<7; xCount++){
  157.    for(yCount=-6; yCount<7; yCount++){
  158.       SpawnForced("RadiusGiveActorFaction", 335544320*xCount, 335544320*yCount, 0, 0, 0); }}
  159.  
  160.   Delay(5);
  161.  
  162.   for(xCount=-6; xCount<7; xCount++){
  163.    for(yCount=-6; yCount<7; yCount++){
  164.       SpawnForced("RadiusGiveActorFactionLook", 335544320*xCount, 335544320*yCount, 0, 0, 0); }}
  165.  
  166.   Delay(105);
  167.   restart;
  168. }
  169.  
  170. script "player_tid" ENTER /* player tid script */
  171. {
  172.   int player_num, cur_tid, new_tid; /* player number, current tid, new tid */
  173.  
  174.   while(true){ /* script will loop continuously */
  175.     player_num = PlayerNumber(); /* get player number */
  176.     cur_tid = ActivatorTID(); /* get player current tid */
  177.     if(!faction_a[player_num] /* IF there's no value for the player tid in the array */
  178.      ||  !ActivatorTID() /* OR the player currently has no tid or tid is 0 */
  179.      || ThingCount(T_NONE,cur_tid) > 1){ /* OR more than one thing has the same tid as the player */
  180.       new_tid = UniqueTID(); /* get a new unique tid */
  181.       faction_a[player_num] = new_tid; /* put it in the array */
  182.       Thing_ChangeTid(0, new_tid); } /* give the player the new tid */
  183.     delay(1); } /* 1 tic delay for loop, means we can be somewhat sure players tids won't have issues */
  184. }
  185.  
  186. script "get_faction_start" (void) /* script to sort out what faction actor should belong to */
  187. {
  188.   int faction, i; /* faction to put actor into, loop variable */
  189.   str class; /* actor class */
  190.  
  191.   class = GetActorClass(0); /* get actor class */
  192.  
  193.   for(i = 0; i < 50 && faction < 0; i++){ /* for all strings in array, so long as a match or NULL string hasn't been found */
  194.     if(StrCmp(class, faction_s[i]) == 0){ /* if found a match with class name */
  195.       faction = i; } /* set faction to i */
  196.     else if(StrCmp("NULL", faction_s[i]) == 0){ /* if found a NULL string */
  197.       faction = i; /* set faction to i */
  198.       faction_s[i] = class; }} /* store class name to array so others with same class name will be grouped to faction */
  199.  
  200.   ACS_NamedExecuteWithResult("faction_tid_start", faction + 1); /* add one to faction, args set faction one higher than they are */
  201. }
  202.  
  203. script "faction_tid_start" (int faction) /* script to give actor unique tid and store it in faction array and on actor */
  204. {
  205.   int new_tid; /* new tid */
  206.  
  207.   if(CheckInventory("faction_counter")){ terminate; } /* if they have already run this script, stop */
  208.  
  209.   --faction; /* set supplied faction congruent to acs listing of factions */
  210.  
  211.   setup_array_index(); /* make sure the array index has already been set up */
  212.  
  213.   if(faction < total_faction){ /* if faction isn't last faction, which doesn't need to be managed really */
  214.     manage_faction_array(faction); } /* make sure there's enough room in the faction */
  215.   new_tid = UniqueTID(); /* get a new unique tid */
  216.   store_faction_tid(faction, new_tid); /* put it in the faction array */
  217.   Thing_ChangeTid(0, new_tid); /* give the activator the new tid */
  218.   set_faction(0, faction); /* set the faction on the actor with inventory counter items */
  219. }
  220.  
  221. script "faction_look" (int flags, int max_dist, int min_dist_wakeup) /* script for actor to look for members of enemy factions */
  222. {
  223.   /* activator tid, target tid, location in faction array, faction index location, faction index */
  224.   int act_tid, tar_tid, loc, index_loc, index;
  225.  
  226.   /* faction of activator, faction currently checking, if found target */
  227.   int faction, check_faction, found_target;
  228.  
  229.   /* loop variable, distance for loops, flag for player target finding being done */
  230.   int i, dist, play_tar;
  231.  
  232.   /* specified enemy faction, player and target flags */
  233.   int enemy_faction, play_flag, tar_flag;
  234.  
  235.   if(flags){ /* if any flag has been set */
  236.     play_flag = flags % 100; /* separate play_flag and tar_flag from enemy_faction */
  237.     enemy_faction = flags - play_flag; /* extract enemy_faction from flags */
  238.     flags = play_flag; /* store flags - enemy_faction in flags for next part */
  239.     play_flag = flags % 10; /* extract play_flag from flags */
  240.     tar_flag = flags - play_flag; } /* extract tar_flag from flags */
  241.  
  242.   --enemy_faction; /* set supplied enemy faction congruent to acs listing of factions */
  243.  
  244.   /*
  245.   --player flags
  246.   0 won't target players
  247.   1 process players like other targets
  248.   2 prioritize player targetsd
  249.  
  250.   --target processsing flags
  251.   0 pick first valid target
  252.   1 pick random target from valid targets
  253.   2 pick closest target
  254.   */
  255.  
  256.   clear_targets(); /* clear targets in target array prior to use */
  257.  
  258.   max_dist = max_dist << 16; /* convert to fixed point */
  259.   min_dist_wakeup = min_dist_wakeup << 16; /* convert to fixed point */
  260.  
  261.   faction = get_faction(0); /* get faction of activator */
  262.  
  263.   act_tid = ActivatorTID(); /* get activator tid */
  264.  
  265.   /* minimum distance to player check */
  266.  
  267.   if(min_dist_wakeup){ /* if a minimum distance to a player to wake up is set */
  268.     dist = 0; /* set dist to 0 */
  269.     /* for all player tids in array, and while no player close enough has been found */
  270.     for(i = 0; i < 64 && !dist; i++){
  271.       if(faction_a[i]){ /* if there is actually a tid stored in the the noted location */
  272.         if(GetCVar("faction_debug_msg")){ log(s:"player ", i:i, s:" with tid ", i:faction_a[i], s:" is ", f:distance_tid(0, faction_a[i]), s:" map units away "); } /* debugging log */
  273.         dist = distance_tid(0, faction_a[i]) <= min_dist_wakeup; /* check if player is at least as close as min distance, will exit loop if true */
  274.         if(dist){ /* if the player is at least as close to activator as min distance */
  275.           if(GetCVar("faction_debug_msg")){ log(s:"player ", i:i, s:" with tid ", i:faction_a[i], s:" is close enough."); }}}}} /* debugging log */
  276.  
  277.   if(!dist && min_dist_wakeup){ /* if min distance to player check was unsuccessful */
  278.     terminate; } /* stop looking */
  279.  
  280.  
  281.   dist = 0; /* reset dist for next loop */
  282.  
  283.   if(play_flag){ /* if player flags instruct to look for player targets as well */
  284.     for(i = 0; i < 64 && /* for all player tids stored in the array, and so long as */
  285.      ( (!found_target && !tar_flag) || /* no target has been found and we are going with the first target OR */
  286.      (tar_flag) ) ; i++){ /* we are storing targets to sort through later */
  287.       tar_tid = faction_a[i]; /* grab tid stored in the the noted location */
  288.       if( tar_tid && /* if actually retrieved target tid AND */
  289.        CheckSight(0, tar_tid, 0) ){ /* if activator can see this member of enemy faction */
  290.         dist = distance_tid(0, tar_tid); /* get distance between the activator and the target */
  291.         if(!max_dist || /* there is no check for max distance OR */
  292.          (dist <= max_dist) ){ /* the target is within max distance */
  293.           store_target(tar_tid, dist); /* store the target in the array */
  294.           if(play_flag == 2){ /* if prioritizing player flags */
  295.             play_tar = 1; } /* note that a player target has been found */
  296.           found_target = 1; }}}} /* flag that a target has been found */
  297.  
  298.  
  299.   while( (check_faction <= total_faction) && /* while all factions haven't been checked yet AND */
  300.    (!play_tar) && /* players targetting hasn't resulted in final target AND */
  301.    ( (!found_target && !tar_flag) || /* no target has been found and we are going with the first target OR */
  302.    (tar_flag) ) ){ /* we are storing targets to sort through later */
  303.     if( (check_faction != faction) && /* don't look for targets in the monster's own faction AND */
  304.     ( (check_faction == enemy_faction) || /* if the faction being checked is the same as the enemy_faction OR */
  305.     (enemy_faction < 0) ) ){ /* no enemy faction was specified */
  306.       loc = 1; /* set faction location to 1, normally 0 would be first in array but faction index takes up [0] spot */
  307.       index_loc = faction_indexes[check_faction]; /* grab index location for faction from map index array */
  308.       index = faction_a[index_loc]; /* grab index for faction from map array */
  309.       while(loc <= index /* while we haven't checked all entries in faction */
  310.        && ( (!found_target && !tar_flag) || /* no target has been found and we are going with the first target OR */
  311.        (tar_flag) ) ){ /* we are storing targets to sort through later */
  312.         tar_tid = get_faction_tid(check_faction, loc); /* get next faction tid */
  313.         if( tar_tid && /* if actually retrieved target tid AND */
  314.          CheckSight(0, tar_tid, 0) ){ /* if activator can see this member of enemy faction */
  315.           dist = distance_tid(0, tar_tid); /* get distance between the activator and the target */
  316.           if(!max_dist || /* there is no check for max distance OR */
  317.            (dist <= max_dist) ){ /* the target is within max distance */
  318.             store_target(tar_tid, dist); /* store the target in the array */
  319.             found_target = 1; }} /* flag that a target has been found */
  320.         ++loc; }} /* check next location in array */
  321.     ++check_faction; } /* check next faction in array */
  322.  
  323.  
  324.   if(found_target){ /* if a target was successfully found */
  325.  
  326.     if(!tar_flag){ /* if we are going with the first target found */
  327.       tar_tid = targets[1][0]; } /* set the target tid to the first tid in the array */
  328.      
  329.     else if(tar_flag == 1){ /* if we are picking a random target from available targets */
  330.       tar_tid = targets[random(1, targets[0][0])][0]; } /* randomly select from 1 to the total number of targets in the array */
  331.      
  332.     else if(tar_flag == 2){ /* if we are picking the closest to attck */
  333.       dist = 0; /* set distance variable to 0 for the folloing loop */
  334.       for(i = 1; i <= targets[0][0]; i++){ /* for all tids stored in target array, up to the last stored */
  335.         if(targets[i][1] < dist || dist == 0){ /* if distance of potential target is smaller than current smallest, or first checked */
  336.           tar_tid = i; /* store current i, using tar_tid as temp */
  337.           dist = targets[i][1]; }} /* store distance for selection as new smallest distance */
  338.       tar_tid = targets[tar_tid][0]; } /* set tid for target with lowest distance to final target */
  339.          
  340.     if(GetCVar("faction_debug_msg")){ log(s:GetActorClass(0), s:" in faction ", i: faction, s:" found a target:", i:tar_tid, s:" which is a ", s:GetActorClass(tar_tid), s:" in faction " , i: check_faction - 1); } /* debugging log */
  341.     Thing_Hate(0, tar_tid, 0); } /* make activator go after target */
  342. }
  343.  
  344.  
  345. //script "faction_look_decorate" (void) /* script to check if monster already has target before making it hate new one to */
  346. //{
  347. //  if(GetActorProperty(0, APROP_TargetTID)){ /* if activator has a target already */
  348. //    ACS_NamedExecuteWithResult("faction_look"); } /* start the faction_look script */
  349. //}
  350.  
  351. script "clear_faction_array" UNLOADING /* script to clear faction array for next map */
  352. {
  353.  
  354.   /* loop variable, start of faction array, end of faction array, location of last faction index */
  355.   int i, faction_start, faction_end, last_faction;
  356.  
  357.   last_faction = faction_indexes[total_faction]; /* get the location of the index for the last faction */
  358.   faction_start = faction_indexes[0]; /* get the location of the index for the first faction, which is also beginning of array */
  359.   faction_end = last_faction + faction_a[last_faction] + 1; /* get the last element locaction in the array */
  360.  
  361.   for(i = faction_start; i <= faction_end; i++ ){ faction_a[i] = 0; }  /* clear all values used for faction in the global array */
  362. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top