Subversion Repositories Games.Carmageddon

Rev

Rev 1 | Rev 20 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "pedestrn.h"
  2. #include "brender.h"
  3. #include "car.h"
  4. #include "constants.h"
  5. #include "displays.h"
  6. #include "errors.h"
  7. #include "globvars.h"
  8. #include "globvrkm.h"
  9. #include "globvrpb.h"
  10. #include "graphics.h"
  11. #include "harness/trace.h"
  12. #include "input.h"
  13. #include "loading.h"
  14. #include "network.h"
  15. #include "opponent.h"
  16. #include "pd/sys.h"
  17. #include "piping.h"
  18. #include "powerup.h"
  19. #include "pratcam.h"
  20. #include "raycast.h"
  21. #include "replay.h"
  22. #include "shortcut.h"
  23. #include "sound.h"
  24. #include "spark.h"
  25. #include "structur.h"
  26. #include "trig.h"
  27. #include "utility.h"
  28. #include "world.h"
  29. #include <stdlib.h>
  30. #include <time.h>
  31.  
  32. #define FLAG_WAVING_BASTARD_REF 99
  33. #define ACTIVE_PED_DXDZ 11.f
  34.  
  35. #define FOURCC(A, B, C, D) (((A & 0xff) << 24) | ((B & 0xff) << 16) | ((C & 0xff) << 8) | ((D & 0xff) << 0))
  36. #define PEDESTRIAN_MAGIC FOURCC('P', 'e', 'd', '!')
  37. #define ActorToPedestrianData(ACTOR) ((tPedestrian_data*)((ACTOR)->type_data))
  38.  
  39. #define GET_PEDESTRIAN_INDEX(P) ((P)-gPedestrian_array)
  40.  
  41. int gDetect_peds = 1;
  42. int gReally_stupid_ped_bug_enable = 0;
  43. int gPed_sound_disable = 0;
  44. int gVesuvians_last_time = 0;
  45. int gSend_peds = 1;
  46. tU32 gLast_ped_message_send = 0;
  47. tPedestrian_instruction* gInitial_instruction = NULL;
  48. char* gRate_commands[3] = { "fixed", "speed", "variable" };
  49. char* gCollide_commands[1] = { "collide" };
  50. char* gInstruc_commands[10] = {
  51.     "point",
  52.     "xpoint",
  53.     "bchoice",
  54.     "fchoice",
  55.     "dead",
  56.     "bmarker",
  57.     "fmarker",
  58.     "baction",
  59.     "faction",
  60.     "reverse"
  61. };
  62. float gMin_ped_gib_speeds[4] = { 10000.f, .005f, .002f, .001f };
  63. float gPed_gib_distrib[4] = { 0.f, 0.33f, 0.34f, 0.33f };
  64. float gPed_gib_speeds[4] = { 0.f, 1.f, 1.f, 1.f };
  65. int gPed_size_counts[4] = { 3, 5, 5, 5 };
  66. char* gPed_gib_names[4][5] = {
  67.     { "BIGGIBS.PIX", "BIGGIBS2.PIX", "BIGGIBS3.PIX", "", "" },
  68.     { "ELBOW.PIX", "PELVIS.PIX", "HEAD.PIX", "RIBS.PIX", "BONE.PIX" },
  69.     { "HAND.PIX", "CHUNK02.PIX", "EYEBALL.PIX", "COLON.PIX", "CHUNK01.PIX" },
  70.     { "CHUNK04.PIX", "SPLAT1.PIX", "CHUNK03.PIX", "SPLAT2.PIX", "SPLATOUT.PIX" }
  71. };
  72. char* gPed_geb_names[4][5] = {
  73.     { "GBIGGIBS.PIX", "GBIGGIB2.PIX", "GBIGGIB3.PIX", "", "" },
  74.     { "GELBOW.PIX", "GPELVIS.PIX", "GHEAD.PIX", "GRIBS.PIX", "GBONE.PIX" },
  75.     { "GHAND.PIX", "GCHUNK02.PIX", "GEYEBALL.PIX", "GCOLON.PIX", "GCHUNK01.PIX" },
  76.     { "GCHUNK04.PIX", "GSPLAT1.PIX", "GCHUNK03.PIX", "GSPLAT2.PIX", "GSPLATOT.PIX" }
  77. };
  78. int gPed_gib_maxes[4][5] = {
  79.     { 1, 1, 1, 0, 0 },
  80.     { 3, 3, 3, 3, 3 },
  81.     { 3, 3, 2, 3, 3 },
  82.     { 3, 3, 3, 3, 3 },
  83. };
  84. br_scalar gExploding_ped_scale[3] = { 0.0028f, 0.0033f, 0.0045f };
  85. br_vector3 gZero_v__pedestrn; // suffix added to avoid duplicate symbol
  86. int gPed_instruc_count = 0;
  87. int gPed_count;
  88. br_actor* gPath_actor = NULL;
  89. br_actor* gCurrent_ped_path_actor = NULL;
  90. int gPedestrians_on = 0;
  91. int gVesuvian_corpses = 0;
  92. br_material* gPed_material = NULL;
  93. int gPed_gib_counts[4][5];
  94. tPedestrian_instruction gPed_instrucs[100];
  95. tPed_gib gPed_gibs[30];
  96. tPed_gib_materials gPed_gib_materials[4];
  97. tProximity_ray gProximity_rays[20];
  98. int gPed_colliding;
  99. float gZombie_factor;
  100. int gRespawn_variance;
  101. br_scalar gPed_scale_factor;
  102. int gTotal_peds;
  103. int gPedestrian_harvest;
  104. br_vector3 gPed_pos_camera;
  105. int gMin_respawn_time;
  106. br_material* gPath_mat_calc;
  107. float gPedestrian_speed_factor;
  108. int gExploding_pedestrians;
  109. int gBlind_pedestrians;
  110. br_material* gPath_mat_normal;
  111. br_material* gInit_pos_mat_calc;
  112. int gPed_other;
  113. int gAttracted_pedestrians;
  114. int gPed_ref_num;
  115. br_scalar gMax_distance_squared;
  116. br_model* gPed_model;
  117. float gDanger_level;
  118. br_vector3 gDanger_direction;
  119. int gInit_ped_instruc;
  120. int gCurrent_lollipop_index;
  121. int gVesuvians_this_time;
  122. int gNumber_of_ped_gibs;
  123. tPedestrian_data* gFlag_waving_bastard;
  124. int gNumber_of_pedestrians = 0;
  125. br_pixelmap* gProx_ray_shade_table;
  126. tPedestrian_data* gPedestrian_array;
  127. tU32 gLast_ped_splat_time;
  128. int gCurrent_ped_multiplier;
  129.  
  130. // IDA: void __usercall PedModelUpdate(br_model *pModel@<EAX>, br_scalar x0, br_scalar y0, br_scalar x1, br_scalar y1, br_scalar x2, br_scalar y2, br_scalar x3, br_scalar y3)
  131. void PedModelUpdate(br_model* pModel, br_scalar x0, br_scalar y0, br_scalar x1, br_scalar y1, br_scalar x2, br_scalar y2, br_scalar x3, br_scalar y3) {
  132.     LOG_TRACE("(%p, %f, %f, %f, %f, %f, %f, %f, %f)", pModel, x0, y0, x1, y1, x2, y2, x3, y3);
  133.  
  134.     BrVector2Set(&pModel->vertices[0].p, x0, y0);
  135.     BrVector2Set(&pModel->vertices[1].p, x1, y1);
  136.     BrVector2Set(&pModel->vertices[2].p, x2, y2);
  137.     BrVector2Set(&pModel->vertices[3].p, x3, y3);
  138.     BrModelUpdate(pModel, BR_MATF_I_FROM_U);
  139. }
  140.  
  141. // IDA: int __usercall ActorIsPedestrian@<EAX>(br_actor *pActor@<EAX>)
  142. int ActorIsPedestrian(br_actor* pActor) {
  143.     LOG_TRACE("(%p)", pActor);
  144.  
  145.     if (pActor->model == NULL) {
  146.         return 0;
  147.     }
  148.     if (pActor->type_data == NULL) {
  149.         return 0;
  150.     }
  151.     return ActorToPedestrianData(pActor)->magic_number == PEDESTRIAN_MAGIC;
  152. }
  153.  
  154. // IDA: br_scalar __usercall PedHeightFromActor@<ST0>(br_actor *pActor@<EAX>)
  155. br_scalar PedHeightFromActor(br_actor* pActor) {
  156.     LOG_TRACE("(%p)", pActor);
  157.     if (!ActorIsPedestrian(pActor)) {
  158.         return 0.f;
  159.     }
  160.     return ActorToPedestrianData(pActor)->height2;
  161. }
  162.  
  163. // IDA: int __usercall GetPedestrianValue@<EAX>(br_actor *pActor@<EAX>)
  164. int GetPedestrianValue(br_actor* pActor) {
  165.     LOG_TRACE("(%p)", pActor);
  166.  
  167.     return ActorToPedestrianData(pActor)->credits_value;
  168. }
  169.  
  170. // IDA: int __usercall PedestrianActorIsPerson@<EAX>(br_actor *pActor@<EAX>)
  171. int PedestrianActorIsPerson(br_actor* pActor) {
  172.     LOG_TRACE("(%p)", pActor);
  173.  
  174.     return ActorToPedestrianData(pActor)->ref_number < 100 && ActorToPedestrianData(pActor)->hit_points != -100;
  175. }
  176.  
  177. // IDA: br_actor* __usercall GetPedestrianActor@<EAX>(int pIndex@<EAX>)
  178. br_actor* GetPedestrianActor(int pIndex) {
  179.     LOG_TRACE("(%d)", pIndex);
  180.  
  181.     if (pIndex >= 0 && pIndex < gPed_count) {
  182.         return gPedestrian_array[pIndex].actor;
  183.     } else {
  184.         return NULL;
  185.     }
  186. }
  187.  
  188. // IDA: br_pixelmap* __usercall GetPedestrianTexture@<EAX>(br_actor *pActor@<EAX>, int *pFlipped@<EDX>)
  189. br_pixelmap* GetPedestrianTexture(br_actor* pActor, int* pFlipped) {
  190.     LOG_TRACE("(%p, %p)", pActor, pFlipped);
  191.  
  192.     if (!ActorIsPedestrian(pActor)) {
  193.         return NULL;
  194.     }
  195.     *pFlipped = ActorToPedestrianData(pActor)->flipped;
  196.     return ActorToPedestrianData(pActor)->colour_map;
  197. }
  198.  
  199. // IDA: void __cdecl TogglePedestrians()
  200. void TogglePedestrians(void) {
  201.     LOG_TRACE("()");
  202.  
  203.     if (!gProgram_state.sausage_eater_mode) {
  204.         gPedestrians_on = !gPedestrians_on;
  205.         if (gPedestrians_on) {
  206.             NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_LetTheCarnageContinue));
  207.         } else {
  208.             NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_NiceAndFluffyMode));
  209.         }
  210.     }
  211. }
  212.  
  213. // IDA: void __cdecl InitPedGibs()
  214. void InitPedGibs(void) {
  215.     int i;
  216.     int j;
  217.     br_model* the_model;
  218.     br_pixelmap* the_pix;
  219.     br_material* the_material;
  220.     LOG_TRACE("()");
  221.  
  222.     for (i = 0; i < COUNT_OF(gPed_gibs); i++) {
  223.         PossibleService();
  224.         gPed_gibs[i].size = -1;
  225.         the_model = BrModelAllocate(NULL, 4, 2);
  226.         the_model->flags |= BR_MODF_UPDATEABLE;
  227.         the_model->faces[0].vertices[0] = 0;
  228.         the_model->faces[0].vertices[1] = 2;
  229.         the_model->faces[0].vertices[2] = 1;
  230.         the_model->faces[0].material = NULL;
  231.         the_model->faces[0].smoothing = 1;
  232.         the_model->faces[1].vertices[0] = 0;
  233.         the_model->faces[1].vertices[1] = 3;
  234.         the_model->faces[1].vertices[2] = 2;
  235.         the_model->faces[1].material = NULL;
  236.         the_model->faces[1].smoothing = 1;
  237.         BrVector3Set(&the_model->vertices[0].p, -1.0f, 0.0f, 0.0f);
  238.         BrVector2Set(&the_model->vertices[0].map, 0.0f, 1.0f);
  239.         BrVector3Set(&the_model->vertices[1].p, -1.0f, 1.0f, 0.0f);
  240.         BrVector2Set(&the_model->vertices[1].map, 0.0f, 0.0f);
  241.         BrVector3Set(&the_model->vertices[2].p, 1.0f, 1.0f, 0.0f);
  242.         BrVector2Set(&the_model->vertices[2].map, 1.0f, 0.0f);
  243.         BrVector3Set(&the_model->vertices[3].p, 1.0f, 0.0f, 0.0f);
  244.         BrVector2Set(&the_model->vertices[3].map, 1.0f, 1.0f);
  245.         BrModelAdd(the_model);
  246.         gPed_gibs[i].actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
  247.         gPed_gibs[i].actor->parent = NULL;
  248.         gPed_gibs[i].actor->model = the_model;
  249.         gPed_gibs[i].actor->render_style = BR_RSTYLE_NONE;
  250.     }
  251.     for (i = 0; i < COUNT_OF(gPed_size_counts); i++) {
  252.         for (j = 0; j < gPed_size_counts[i]; j++) {
  253.             PossibleService();
  254.             if (gProgram_state.sausage_eater_mode) {
  255.                 the_pix = LoadPixelmap(gPed_geb_names[i][j]);
  256.             } else {
  257.                 the_pix = LoadPixelmap(gPed_gib_names[i][j]);
  258.             }
  259.             BrMapAdd(the_pix);
  260.             gPed_gib_materials[i].count = gPed_size_counts[i];
  261.             gPed_gib_materials[i].materials[j] = BrMaterialAllocate(NULL);
  262.             BrMaterialAdd(gPed_gib_materials[i].materials[j]);
  263.             the_material = gPedestrian_array[0].actor->material;
  264.             gPed_gib_materials[i].materials[j]->flags = the_material->flags;
  265.             gPed_gib_materials[i].materials[j]->ka = the_material->ka;
  266.             gPed_gib_materials[i].materials[j]->kd = the_material->kd;
  267.             gPed_gib_materials[i].materials[j]->ks = the_material->ks;
  268.             gPed_gib_materials[i].materials[j]->power = the_material->power;
  269.             gPed_gib_materials[i].materials[j]->index_base = the_material->index_base;
  270.             gPed_gib_materials[i].materials[j]->index_range = the_material->index_range;
  271.             gPed_gib_materials[i].materials[j]->colour_map = the_pix;
  272.             gPed_gib_materials[i].materials[j]->map_transform = the_material->map_transform;
  273.             gPed_gib_materials[i].materials[j]->index_shade = the_material->index_shade;
  274.             BrMaterialUpdate(gPed_gib_materials[i].materials[j], BR_MATU_ALL);
  275.         }
  276.     }
  277. }
  278.  
  279. // IDA: void __usercall SetPedMaterialForRender(br_actor *pActor@<EAX>)
  280. void SetPedMaterialForRender(br_actor* pActor) {
  281.     tPedestrian_data* ped;
  282.     int changed;
  283.     LOG_TRACE("(%p)", pActor);
  284.  
  285.     ped = ActorToPedestrianData(pActor);
  286.     pActor->material->colour_map = ped->colour_map;
  287.     if (ped->flipped) {
  288.         changed = pActor->material->map_transform.m[0][0] != 1.f;
  289.         if (changed) {
  290.             pActor->material->map_transform.m[0][0] = 1.f;
  291.         }
  292.     } else {
  293.         changed = pActor->material->map_transform.m[0][0] != -1.f;
  294.         if (changed) {
  295.             pActor->material->map_transform.m[0][0] = -1.f;
  296.         }
  297.     }
  298.     if (changed) {
  299.         BrMaterialUpdate(pActor->material, BR_MATU_MAP_TRANSFORM);
  300.     }
  301.     BrMaterialUpdate(pActor->material, BR_MATU_COLOURMAP);
  302. }
  303.  
  304. // IDA: void __cdecl PedCallBack(br_actor *pActor, br_model *pModel, br_material *pMaterial, void *pRender_data, br_uint_8 pStyle, int pOn_screen)
  305. void PedCallBack(br_actor* pActor, br_model* pModel, br_material* pMaterial, void* pRender_data, br_uint_8 pStyle, int pOn_screen) {
  306.     tPedestrian_data* ped;
  307.     LOG_TRACE("(%p, %p, %p, %p, %d, %d)", pActor, pModel, pMaterial, pRender_data, pStyle, pOn_screen);
  308.  
  309.     ped = ActorToPedestrianData(pActor);
  310.     pActor->material->colour_map = ped->colour_map;
  311.     if (ped->flipped) {
  312.         pActor->material->map_transform.m[0][0] = 1.f;
  313.     } else {
  314.         pActor->material->map_transform.m[0][0] = -1.f;
  315.     }
  316.     BrMaterialUpdate(pActor->material, BR_MATU_ALL);
  317.     BrZbModelRender(pActor, pModel, pMaterial, pStyle, BrOnScreenCheck(&pModel->bounds), 0);
  318. }
  319.  
  320. // IDA: void __cdecl InitPeds()
  321. void InitPeds(void) {
  322.     LOG_TRACE("()");
  323.  
  324.     gPed_model = BrModelAllocate(NULL, 4, 2);
  325.     gPed_model->faces[0].vertices[0] = 0;
  326.     gPed_model->faces[0].vertices[1] = 2;
  327.     gPed_model->faces[0].vertices[2] = 1;
  328.     gPed_model->faces[0].material = NULL;
  329.     gPed_model->faces[0].smoothing = 1;
  330.     gPed_model->faces[1].vertices[0] = 0;
  331.     gPed_model->faces[1].vertices[1] = 3;
  332.     gPed_model->faces[1].vertices[2] = 2;
  333.     gPed_model->faces[1].material = NULL;
  334.     gPed_model->faces[1].smoothing = 1;
  335.     BrVector3Set(&gPed_model->vertices[0].p, -0.5f, 0.0f, 0.0f);
  336.     BrVector2Set(&gPed_model->vertices[0].map, 0.0001f, 0.9999f);
  337.     BrVector3Set(&gPed_model->vertices[1].p, -0.5f, 1.0f, 0.0f);
  338.     BrVector2Set(&gPed_model->vertices[1].map, 0.0001f, 0.0001f);
  339.     BrVector3Set(&gPed_model->vertices[2].p, 0.5f, 1.0f, 0.0f);
  340.     BrVector2Set(&gPed_model->vertices[2].map, 0.9999f, 0.0001f);
  341.     BrVector3Set(&gPed_model->vertices[3].p, 0.5f, 0.0f, 0.0f);
  342.     BrVector2Set(&gPed_model->vertices[3].map, 0.9999f, 0.9999f);
  343.     BrModelAdd(gPed_model);
  344. }
  345.  
  346. // IDA: void __usercall MungeModelSize(br_actor *pActor@<EAX>, br_scalar pScaling_factor)
  347. void MungeModelSize(br_actor* pActor, br_scalar pScaling_factor) {
  348.     br_pixelmap* the_pix;
  349.     br_scalar half_width;
  350.     br_scalar half_height;
  351.     LOG_TRACE("(%p, %f)", pActor, pScaling_factor);
  352.  
  353.     the_pix = pActor->material->colour_map;
  354.     half_width = (the_pix->width / 2) * pScaling_factor * gPed_scale_factor;
  355.     half_height = (the_pix->height / 2) * pScaling_factor * gPed_scale_factor;
  356.     PedModelUpdate(pActor->model,
  357.         -half_width, -half_height,
  358.         -half_width, half_height,
  359.         half_width, half_height,
  360.         half_width, -half_height);
  361. }
  362.  
  363. // IDA: int __usercall BurstPedestrian@<EAX>(tPedestrian_data *pPedestrian@<EAX>, float pSplattitudinalitude, int pAllow_explosion)
  364. int BurstPedestrian(tPedestrian_data* pPedestrian, float pSplattitudinalitude, int pAllow_explosion) {
  365.     int i;
  366.     int j;
  367.     int gib_index;
  368.     int next_gib_index;
  369.     int size_threshold;
  370.     int current_size;
  371.     //int max_size; // Pierre-Marie Baty -- unused variable
  372.     int gib_count;
  373.     int exploded;
  374.     tPed_gib* the_ped_gib;
  375.     br_scalar min_speed;
  376.     br_scalar max_speed;
  377.     tU32 the_time;
  378.     LOG_TRACE("(%p, %f, %d)", pPedestrian, pSplattitudinalitude, pAllow_explosion);
  379.  
  380. #if defined(DETHRACE_FIX_BUGS)
  381.     min_speed = 0;
  382.     max_speed = 0;
  383. #endif
  384.     exploded = 0;
  385.     for (i = 0; i < COUNT_OF(gPed_gib_counts); i++) {
  386.         for (j = 0; j < gPed_size_counts[i]; j++) {
  387.             gPed_gib_counts[i][j] = 0;
  388.         }
  389.     }
  390.  
  391.     the_time = GetTotalTime();
  392.     size_threshold = COUNT_OF(gMin_ped_gib_speeds) - 1;
  393.     for (i = 1; i < COUNT_OF(gMin_ped_gib_speeds); i++) {
  394.         if (gMin_ped_gib_speeds[i] <= pSplattitudinalitude) {
  395.             size_threshold = i;
  396.             break;
  397.         }
  398.     }
  399.     if (gExploding_pedestrians) {
  400.         size_threshold = 1;
  401.     } else if (size_threshold == 1 && (!pAllow_explosion || !PercentageChance(50))) {
  402.         size_threshold = 2;
  403.     }
  404.     gib_count = pSplattitudinalitude * 10000.f;
  405.     if (gib_count > 15) {
  406.         gib_count = 15;
  407.     }
  408.     gib_index = 0;
  409.     the_ped_gib = &gPed_gibs[gib_index];
  410.     if (size_threshold == 1) {
  411.         while (the_ped_gib->size >= 0) {
  412.             gib_index++;
  413.             the_ped_gib++;
  414.             if (gib_index >= COUNT_OF(gPed_gibs)) {
  415.                 return 0;
  416.             }
  417.         }
  418.         if (pPedestrian->number_of_exploding_sounds != 0) {
  419.             DRS3StopSound(pPedestrian->last_sound);
  420.             pPedestrian->last_sound = DRS3StartSound2(gPedestrians_outlet,
  421.                 pPedestrian->exploding_sounds[IRandomBetween(0, pPedestrian->number_of_exploding_sounds - 1)],
  422.                 1,
  423.                 -1,
  424.                 -1,
  425.                 65536.f / gPed_scale_factor,
  426.                 -1);
  427.         }
  428.         the_ped_gib->size = 0;
  429.         the_ped_gib->start_time = the_time;
  430.         the_ped_gib->end_time = -1;
  431.         the_ped_gib->last_frame = 0;
  432.         the_ped_gib->flip_period = 0;
  433.         the_ped_gib->x_speed = 0.f;
  434.         the_ped_gib->y_speed = 0.f;
  435.         if (the_ped_gib->actor->parent != NULL) {
  436.             BrActorRemove(the_ped_gib->actor);
  437.         }
  438.         BrActorAdd(pPedestrian->actor, the_ped_gib->actor);
  439.         the_ped_gib->actor->render_style = BR_RSTYLE_FACES;
  440.         BrMatrix34Identity(&the_ped_gib->actor->t.t.mat);
  441.         the_ped_gib->actor->t.t.translate.t.v[Y] += pPedestrian->actor->t.t.mat.m[1][1] * 2.f / (pPedestrian->height2 * 3.f);
  442.         the_ped_gib->actor->t.t.translate.t.v[Z] = 0.01f;
  443.         the_ped_gib->actor->material = gPed_gib_materials[0].materials[0];
  444.         the_ped_gib->gib_index = 0;
  445.         the_ped_gib->parent_index = GET_PEDESTRIAN_INDEX(pPedestrian);
  446.         MungeModelSize(the_ped_gib->actor, gExploding_ped_scale[0]);
  447.         exploded = 1;
  448.     }
  449.     current_size = 4;
  450.     j = 0;
  451.     for (i = 0; i < gib_count; i++) {
  452.         while (the_ped_gib->size >= 0) {
  453.             gib_index++;
  454.             the_ped_gib++;
  455.             if (gib_index >= COUNT_OF(gPed_gibs)) {
  456.                 return exploded;
  457.             }
  458.         }
  459.         if (j <= i && size_threshold < current_size && current_size > 1) {
  460.             current_size--;
  461.             j += gib_count * gPed_gib_distrib[current_size];
  462.             min_speed = gPed_gib_speeds[current_size] * pSplattitudinalitude * .003f + .00005f;
  463.             max_speed = gPed_gib_speeds[current_size] * pSplattitudinalitude * .2f + .00030f;
  464.         }
  465.         the_ped_gib->size = current_size;
  466.         the_ped_gib->start_time = the_time + 150;
  467.         the_ped_gib->end_time = the_time + 2000;
  468.         the_ped_gib->flip_period = IRandomBetween(50, 200);
  469.         the_ped_gib->x_speed = SRandomBetween(min_speed, max_speed);
  470.         the_ped_gib->y_speed = SRandomBetween(min_speed, max_speed);
  471.         if (PercentageChance(50)) {
  472.             the_ped_gib->x_speed = -the_ped_gib->x_speed;
  473.         }
  474.         if (PercentageChance(25)) {
  475.             the_ped_gib->y_speed = -the_ped_gib->y_speed;
  476.         }
  477.         if (the_ped_gib->actor->parent != NULL) {
  478.             BrActorRemove(the_ped_gib->actor);
  479.         }
  480.         BrActorAdd(pPedestrian->actor, the_ped_gib->actor);
  481.         the_ped_gib->actor->render_style = BR_RSTYLE_FACES;
  482.         BrMatrix34Identity(&the_ped_gib->actor->t.t.mat);
  483.         the_ped_gib->actor->t.t.translate.t.v[Y] += pPedestrian->actor->t.t.mat.m[1][1] / (pPedestrian->height2 * 2.f);
  484.         do {
  485.             next_gib_index = IRandomBetween(0, gPed_gib_materials[the_ped_gib->size].count - 1);
  486.         } while (gPed_gib_maxes[the_ped_gib->size][next_gib_index] <= gPed_gib_counts[the_ped_gib->size][next_gib_index]);
  487.         gPed_gib_counts[the_ped_gib->size][next_gib_index]++;
  488.         the_ped_gib->actor->material = gPed_gib_materials[the_ped_gib->size].materials[next_gib_index];
  489.         the_ped_gib->gib_index = next_gib_index;
  490.         the_ped_gib->parent_index = GET_PEDESTRIAN_INDEX(pPedestrian);
  491.         MungeModelSize(the_ped_gib->actor, .0023f);
  492.     }
  493.     pPedestrian->last_sound = DRS3StartSound3D(gPedestrians_outlet,
  494.         4020,
  495.         &pPedestrian->pos,
  496.         &gZero_v__pedestrn,
  497.         1,
  498.         255,
  499.         65536,
  500.         -1);
  501.     PipeSingleSound(gPedestrians_outlet, 4020, 255, 0, 65536, &pPedestrian->pos);
  502.     return exploded;
  503. }
  504.  
  505. // IDA: void __cdecl ResetAllPedGibs()
  506. void ResetAllPedGibs(void) {
  507.     int i;
  508.     tPed_gib* the_ped_gib;
  509.     LOG_TRACE("()");
  510.  
  511.     for (i = 0; i < COUNT_OF(gPed_gibs); i++) {
  512.         the_ped_gib = &gPed_gibs[i];
  513.         if (the_ped_gib->size >= 0) {
  514.             the_ped_gib->size = -1;
  515.             if (the_ped_gib->actor->parent != NULL) {
  516.                 BrActorRemove(the_ped_gib->actor);
  517.             }
  518.             the_ped_gib->actor->parent = NULL;
  519.             the_ped_gib->actor->render_style = BR_RSTYLE_NONE;
  520.         }
  521.     }
  522. }
  523.  
  524. // IDA: void __usercall AdjustPedGib(int pIndex@<EAX>, int pSize@<EDX>, int pGib_index@<EBX>, int pPed_index@<ECX>, br_matrix34 *pTrans)
  525. void AdjustPedGib(int pIndex, int pSize, int pGib_index, int pPed_index, br_matrix34* pTrans) {
  526.     tPed_gib* the_ped_gib;
  527.     LOG_TRACE("(%d, %d, %d, %d, %p)", pIndex, pSize, pGib_index, pPed_index, pTrans);
  528.  
  529.     the_ped_gib = &gPed_gibs[pIndex];
  530.     the_ped_gib->size = pSize;
  531.     the_ped_gib->gib_index = pGib_index;
  532.     if (the_ped_gib->actor->parent != NULL) {
  533.         BrActorRemove(the_ped_gib->actor);
  534.     }
  535.     BrActorAdd(gPedestrian_array[pPed_index].actor, the_ped_gib->actor);
  536.     the_ped_gib->actor->t.t.mat = *pTrans;
  537.     the_ped_gib->actor->render_style = BR_RSTYLE_FACES;
  538.     the_ped_gib->actor->material = gPed_gib_materials[gPed_gibs[pIndex].size].materials[pGib_index];
  539.     MungeModelSize(the_ped_gib->actor, 0.0023f);
  540. }
  541.  
  542. // IDA: void __usercall MungePedGibs(tU32 pFrame_period@<EAX>)
  543. void MungePedGibs(tU32 pFrame_period) {
  544.     int i;
  545.     int frame;
  546.     tPed_gib* the_ped_gib;
  547.     //br_scalar s_frame_period; // Pierre-Marie Baty -- unused variable
  548.     tU32 the_time;
  549.     tPedestrian_data* pedestrian;
  550.     LOG_TRACE("(%d)", pFrame_period);
  551.  
  552.     StartPipingSession(ePipe_chunk_ped_gib);
  553.     the_time = GetTotalTime();
  554.     for (i = 0; i < COUNT_OF(gPed_gibs); i++) {
  555.         the_ped_gib = &gPed_gibs[i];
  556.         if (the_ped_gib->size > 0) {
  557.             if (the_time >= the_ped_gib->end_time) {
  558.                 the_ped_gib->size = -1;
  559.                 if (the_ped_gib->actor->parent != NULL) {
  560.                     BrActorRemove(the_ped_gib->actor);
  561.                 }
  562.                 the_ped_gib->actor->parent = NULL;
  563.                 the_ped_gib->actor->render_style = BR_RSTYLE_NONE;
  564.             } else if (the_time >= the_ped_gib->start_time) {
  565.                 pedestrian = &gPedestrian_array[the_ped_gib->parent_index];
  566.                 the_ped_gib->actor->render_style = BR_RSTYLE_FACES;
  567.                 if ((the_time / the_ped_gib->flip_period) % 2 != 0) {
  568.                     the_ped_gib->actor->t.t.mat.m[0][0] = 1.f / pedestrian->width;
  569.                     the_ped_gib->actor->t.t.mat.m[1][1] = 1.f / pedestrian->height2;
  570.                 } else {
  571.                     the_ped_gib->actor->t.t.mat.m[0][0] = -1.f / pedestrian->width;
  572.                     the_ped_gib->actor->t.t.mat.m[1][1] = -1.f / pedestrian->height2;
  573.                 }
  574.  
  575.                 the_ped_gib->actor->t.t.translate.t.v[X] += the_ped_gib->x_speed * pFrame_period / pedestrian->width;
  576.                 the_ped_gib->actor->t.t.translate.t.v[Y] += the_ped_gib->y_speed * pFrame_period / pedestrian->height2;
  577.                 the_ped_gib->y_speed -= gFrame_period * gGravity_multiplier * 1.420289855072464e-6;
  578.                 AddPedGibToPipingSession(i, &the_ped_gib->actor->t.t.mat, the_ped_gib->size, the_ped_gib->gib_index, the_ped_gib->parent_index);
  579.             }
  580.         } else if (the_ped_gib->size == 0) {
  581.             frame = (the_time - the_ped_gib->start_time) / 100 - 1;
  582.             if (frame < 0) {
  583.                 frame = 0;
  584.             } else if (frame > the_ped_gib->last_frame + 1) {
  585.                 frame = the_ped_gib->last_frame + 1;
  586.             }
  587.             the_ped_gib->last_frame = frame;
  588.             if (frame < gPed_gib_materials[0].count) {
  589.                 the_ped_gib->actor->t.t.mat.m[0][0] = 1.f / gPedestrian_array[the_ped_gib->parent_index].width;
  590.                 the_ped_gib->actor->t.t.mat.m[1][1] = 1.f / gPedestrian_array[the_ped_gib->parent_index].height2;
  591.                 the_ped_gib->actor->material = gPed_gib_materials[0].materials[frame];
  592.                 MungeModelSize(the_ped_gib->actor, gExploding_ped_scale[frame]);
  593.                 if (frame == 1 && the_ped_gib->actor->t.t.translate.t.v[Z] == 0.01f) {
  594.                     the_ped_gib->actor->t.t.translate.t.v[Z] = -0.01f;
  595.                 }
  596.                 AddPedGibToPipingSession(i, &the_ped_gib->actor->t.t.mat, the_ped_gib->size, frame, the_ped_gib->parent_index);
  597.             } else {
  598.                 the_ped_gib->size = -1;
  599.                 BrActorRemove(the_ped_gib->actor);
  600.                 the_ped_gib->actor->parent = NULL;
  601.                 the_ped_gib->actor->render_style = BR_RSTYLE_NONE;
  602.             }
  603.         }
  604.     }
  605.     EndPipingSession();
  606. }
  607.  
  608. // IDA: void __usercall KillPedestrian(tPedestrian_data *pPedestrian@<EAX>)
  609. void KillPedestrian(tPedestrian_data* pPedestrian) {
  610.     LOG_TRACE("(%p)", pPedestrian);
  611.  
  612.     if (pPedestrian->hit_points != -100) {
  613.         if (pPedestrian->ref_number < 100) {
  614.             gProgram_state.peds_killed++;
  615.         }
  616.         pPedestrian->hit_points = -100;
  617.         if (IsActionReplayAvailable()) {
  618.             AddPedestrianToPipingSession(
  619.                 GET_PEDESTRIAN_INDEX(pPedestrian),
  620.                 &pPedestrian->actor->t.t.mat,
  621.                 pPedestrian->current_action,
  622.                 pPedestrian->current_frame,
  623.                 pPedestrian->hit_points,
  624.                 pPedestrian->done_initial,
  625.                 (pPedestrian->actor->parent == gDont_render_actor) ? -1 : pPedestrian->killers_ID,
  626.                 pPedestrian->spin_period,
  627.                 pPedestrian->jump_magnitude,
  628.                 &pPedestrian->offset);
  629.         }
  630.     }
  631.     if (pPedestrian->actor->parent != gDont_render_actor) {
  632.         pPedestrian->actor->render_style = BR_RSTYLE_NONE;
  633.     }
  634. }
  635.  
  636. // IDA: void __usercall CalcPedWidthNHeight(tPedestrian_data *pPedestrian@<EAX>, br_pixelmap *pPixelmap@<EDX>, br_scalar *pHeight@<EBX>, br_scalar *pWidth@<ECX>)
  637. void CalcPedWidthNHeight(tPedestrian_data* pPedestrian, br_pixelmap* pPixelmap, br_scalar* pHeight, br_scalar* pWidth) {
  638.     br_pixelmap* reference_pixel_bastard;
  639.     br_scalar scale_to_use;
  640.     LOG_TRACE("(%p, %p, %p, %p)", pPedestrian, pPixelmap, pHeight, pWidth);
  641.  
  642.     if (pPedestrian->ref_number < 100) {
  643.         scale_to_use = gPed_scale_factor;
  644.     } else {
  645.         scale_to_use = 1.0f;
  646.     }
  647.     reference_pixel_bastard = pPedestrian->sequences->frames[0].pixelmap;
  648.     *pHeight = (float)pPixelmap->height
  649.         / (float)reference_pixel_bastard->height
  650.         * pPedestrian->height
  651.         * scale_to_use;
  652.     *pWidth = (float)pPixelmap->width / (float)pPixelmap->height * *pHeight;
  653. }
  654.  
  655. // IDA: int __usercall PedestrianNextInstruction@<EAX>(tPedestrian_data *pPedestrian@<EAX>, float pDanger_level, int pPosition_explicitly, int pMove_pc)
  656. int PedestrianNextInstruction(tPedestrian_data* pPedestrian, float pDanger_level, int pPosition_explicitly, int pMove_pc) {
  657.     tPedestrian_instruction* instruction;
  658.     float most_dangerous;
  659.     float chance_value;
  660.     int result;
  661.     int start_index;
  662.     int end_index;
  663.     int i;
  664.     int j;
  665.     int choice;
  666.     //int the_marker_ref; // Pierre-Marie Baty -- unused variable
  667.     LOG_TRACE("(%p, %f, %d, %d)", pPedestrian, pDanger_level, pPosition_explicitly, pMove_pc);
  668.  
  669.     if (pPedestrian->number_of_instructions <= 1) {
  670.         pPedestrian->current_instruction = 0;
  671.         instruction = &pPedestrian->instruction_list[0];
  672.         pPedestrian->to_pos = instruction->data.point_data.position;
  673.         BrVector3Set(&pPedestrian->direction, 1.f, 0.f, 0.f);
  674.         if (pPosition_explicitly) {
  675.             pPedestrian->pos = pPedestrian->actor->t.t.translate.t = pPedestrian->to_pos;
  676.         }
  677.         return 0;
  678.     }
  679.     result = 0;
  680.     if (pMove_pc) {
  681.         pPedestrian->current_instruction += pPedestrian->instruction_direction;
  682.         if (pPedestrian->current_instruction >= pPedestrian->number_of_instructions) {
  683.             pPedestrian->current_instruction = 0;
  684.             result = 1;
  685.         } else if (pPedestrian->current_instruction < 0) {
  686.             pPedestrian->current_instruction = pPedestrian->number_of_instructions - 1;
  687.             result = 1;
  688.         }
  689.     }
  690.     instruction = &pPedestrian->instruction_list[pPedestrian->current_instruction];
  691.     pPedestrian->irreversable = 0;
  692.     if (instruction->type != ePed_instruc_point && instruction->type != ePed_instruc_reverse) {
  693.         KillPedestrian(pPedestrian);
  694.         return 0;
  695.     }
  696.  
  697.     switch (instruction->type) {
  698.  
  699.     case ePed_instruc_xpoint:
  700.         pPedestrian->irreversable = 1;
  701.         // fall through
  702.     case ePed_instruc_point:
  703.         BrVector3Copy(&pPedestrian->to_pos, &instruction->data.point_data.position);
  704.         BrVector3Sub(&pPedestrian->direction, &pPedestrian->to_pos, &pPedestrian->actor->t.t.translate.t);
  705.         if (pPedestrian->to_pos.v[Y] >= 500.f) {
  706.             pPedestrian->direction.v[Y] = 0.f;
  707.         }
  708.         if (Vector3IsZero(&pPedestrian->direction) && instruction != gInitial_instruction) {
  709.             if (gInitial_instruction == NULL) {
  710.                 gInitial_instruction = instruction;
  711.             }
  712.             PedestrianNextInstruction(pPedestrian, pDanger_level, pPosition_explicitly, 1);
  713.         } else {
  714.             BrVector3Normalise(&pPedestrian->direction, &pPedestrian->direction);
  715.             if (pPosition_explicitly) {
  716.                 pPedestrian->pos = pPedestrian->actor->t.t.translate.t = pPedestrian->to_pos;
  717.             }
  718.         }
  719.         break;
  720.     case ePed_instruc_bchoice:
  721.     case ePed_instruc_fchoice:
  722.         if ((instruction->type == ePed_instruc_fchoice && pPedestrian->instruction_direction > 0)
  723.             || (instruction->type == ePed_instruc_bchoice && pPedestrian->instruction_direction < 0)) {
  724.             most_dangerous = -1.f;
  725. #if defined(DETHRACE_FIX_BUGS)
  726.             start_index = 0;
  727.             end_index = 0;
  728. #endif
  729.             for (i = 0; i < instruction->data.choice_data.number_of_choices; i++) {
  730.                 if (instruction->data.choice_data.choices[i].danger_level <= pDanger_level) {
  731.                     if (instruction->data.choice_data.choices[i].danger_level > most_dangerous) {
  732.                         most_dangerous = instruction->data.choice_data.choices[i].danger_level;
  733.                         start_index = i;
  734.                         end_index = i;
  735.                     } else if (instruction->data.choice_data.choices[i].danger_level == most_dangerous) {
  736.                         end_index = i;
  737.                     }
  738.                 }
  739.             }
  740.             pPedestrian->current_instruction = -1;
  741.             chance_value = FRandomBetween(0.f, 99.f);
  742.             choice = start_index;
  743.             for (i = start_index; i <= end_index; i++) {
  744.                 chance_value -= instruction->data.choice_data.choices[i].percentage_chance;
  745.                 if (chance_value < 0.f) {
  746.                     choice = i;
  747.                     break;
  748.                 }
  749.             }
  750.             for (i = 0; i < pPedestrian->number_of_instructions; i++) {
  751.                 if (((pPedestrian->instruction_list[i].type == ePed_instruc_bmarker && pPedestrian->instruction_direction < 0)
  752.                         || (pPedestrian->instruction_list[i].type == ePed_instruc_fmarker && pPedestrian->instruction_direction > 0))) {
  753.                     if (pPedestrian->instruction_list[i].data.marker_data.marker_ref == instruction->data.choice_data.choices[choice].marker_ref) {
  754.                         pPedestrian->current_instruction = i;
  755.                         break;
  756.                     }
  757.                 }
  758.             }
  759.             if (pPedestrian->current_instruction < 0) {
  760.                 FatalError(kFatalError_PedInstructionMarkerNotFound);
  761.             }
  762.         }
  763.         result = PedestrianNextInstruction(pPedestrian, pDanger_level, pPosition_explicitly, 1);
  764.         break;
  765.     case ePed_instruc_dead:
  766.         KillPedestrian(pPedestrian);
  767.         break;
  768.     case ePed_instruc_bmarker:
  769.         if (pPedestrian->instruction_direction > 0) {
  770.             for (i = 0; i < pPedestrian->number_of_instructions; i++) {
  771.                 if (pPedestrian->instruction_list[i].type == ePed_instruc_bchoice) {
  772.                     for (j = 0; j < pPedestrian->instruction_list[i].data.choice_data.number_of_choices; j++) {
  773.                         if (pPedestrian->instruction_list[i].data.choice_data.choices[j].marker_ref == pPedestrian->instruction_list[pPedestrian->current_instruction].data.marker_data.marker_ref) {
  774.                             pPedestrian->current_instruction = i;
  775.                         }
  776.                     }
  777.                 }
  778.             }
  779.         }
  780.         result = PedestrianNextInstruction(pPedestrian, pDanger_level, pPosition_explicitly, 1);
  781.         break;
  782.     case ePed_instruc_fmarker:
  783.         if (pPedestrian->instruction_direction < 0) {
  784.             for (i = 0; i < pPedestrian->number_of_instructions; i++) {
  785.                 if (pPedestrian->instruction_list[i].type == ePed_instruc_fchoice) {
  786.                     for (j = 0; j < pPedestrian->instruction_list[i].data.choice_data.number_of_choices; j++) {
  787.                         if (pPedestrian->instruction_list[i].data.choice_data.choices[j].marker_ref == pPedestrian->instruction_list[pPedestrian->current_instruction].data.marker_data.marker_ref) {
  788.                             pPedestrian->current_instruction = i;
  789.                         }
  790.                     }
  791.                 }
  792.             }
  793.         }
  794.         result = PedestrianNextInstruction(pPedestrian, pDanger_level, pPosition_explicitly, 1);
  795.         break;
  796.     case ePed_instruc_baction:
  797.         if (pPedestrian->instruction_direction < 0) {
  798.             pPedestrian->current_action_mode = instruction->data.action_data.action_index;
  799.         }
  800.         result = PedestrianNextInstruction(pPedestrian, pDanger_level, pPosition_explicitly, 1);
  801.         break;
  802.     case ePed_instruc_faction:
  803.         if (pPedestrian->instruction_direction > 0) {
  804.             pPedestrian->current_action_mode = instruction->data.action_data.action_index;
  805.         }
  806.         result = PedestrianNextInstruction(pPedestrian, pDanger_level, pPosition_explicitly, 1);
  807.         break;
  808.     case ePed_instruc_reverse:
  809.         pPedestrian->instruction_direction = -pPedestrian->instruction_direction;
  810.         PedestrianNextInstruction(pPedestrian, pDanger_level, pPosition_explicitly, 1);
  811.         result = 1;
  812.         break;
  813.     }
  814.     return result;
  815. }
  816.  
  817. // IDA: void __usercall MungePedestrianSequence(tPedestrian_data *pPedestrian@<EAX>, int pAction_changed@<EDX>)
  818. void MungePedestrianSequence(tPedestrian_data* pPedestrian, int pAction_changed) {
  819.     tPedestrian_action* the_action;
  820.     int i;
  821.     int the_sequence;
  822.     int current_looping;
  823.     br_scalar ped_movement_angle;
  824.     float heading_difference;
  825.     tPedestrian_sequence* sequence_ptr;
  826.     LOG_TRACE("(%p, %d)", pPedestrian, pAction_changed);
  827.  
  828.     if (pPedestrian->ref_number < 100) {
  829.         ped_movement_angle = FastScalarArcTan2(pPedestrian->direction.v[X], pPedestrian->direction.v[Z]);
  830.         if (ped_movement_angle < pPedestrian->car_to_ped) {
  831.             ped_movement_angle += 360.f;
  832.         }
  833.         heading_difference = ped_movement_angle - pPedestrian->car_to_ped;
  834.     } else {
  835.         heading_difference = gCamera_to_horiz_angle;
  836.     }
  837.     for (i = 0; i < pPedestrian->action_list[pPedestrian->current_action].number_of_bearings; i++) {
  838.         if (heading_difference <= pPedestrian->action_list[pPedestrian->current_action].sequences[i].max_bearing) {
  839.             the_sequence = pPedestrian->action_list[pPedestrian->current_action].sequences[i].sequence_index;
  840.             if (pPedestrian->current_sequence == the_sequence) {
  841.                 break;
  842.             }
  843.             sequence_ptr = &pPedestrian->sequences[the_sequence];
  844.             current_looping = pPedestrian->sequences[pPedestrian->current_sequence].looping_frame_start;
  845.             if (pAction_changed || current_looping > pPedestrian->current_frame) {
  846.                 pPedestrian->current_frame = -1;
  847.                 pPedestrian->done_initial = 0;
  848.             } else if (pPedestrian->current_action != pPedestrian->fatal_car_impact_action
  849.                 && pPedestrian->current_action != pPedestrian->fatal_ground_impact_action
  850.                 && pPedestrian->current_action != pPedestrian->giblets_action) {
  851.                 pPedestrian->current_frame += sequence_ptr->looping_frame_start - current_looping - 1;
  852.                 pPedestrian->done_initial = 1;
  853.             } else if (pPedestrian->current_frame >= sequence_ptr->number_of_frames) {
  854.                 pPedestrian->current_frame = sequence_ptr->number_of_frames - 1;
  855.             }
  856.             pPedestrian->last_frame = 0;
  857.             pPedestrian->current_sequence = the_sequence;
  858.             break;
  859.         }
  860.     }
  861. }
  862.  
  863. // IDA: void __usercall DetachPedFromCar(tPedestrian_data *pPedestrian@<EAX>)
  864. void DetachPedFromCar(tPedestrian_data* pPedestrian) {
  865.     LOG_TRACE("(%p)", pPedestrian);
  866.  
  867.     if (pPedestrian->actor->parent != gDont_render_actor) {
  868.         BrActorRelink(gDont_render_actor, pPedestrian->actor);
  869.         pPedestrian->actor->render_style = BR_RSTYLE_NONE;
  870.         pPedestrian->mid_air = 1;
  871.         if (pPedestrian->to_pos.v[Y] < 500.f) {
  872.             pPedestrian->to_pos.v[Y] += 1000.4f;
  873.         }
  874.         BrVector3Set(&pPedestrian->offset, 0.f, 0.f, 0.f);
  875.     }
  876. }
  877.  
  878. // IDA: void __usercall SetPedPos(tPedestrian_data *pPedestrian@<EAX>)
  879. void SetPedPos(tPedestrian_data* pPedestrian) {
  880.     //br_vector3 temp_v; // Pierre-Marie Baty -- unused variable
  881.     LOG_TRACE("(%p)", pPedestrian);
  882.  
  883.     if (pPedestrian->actor->parent == gDont_render_actor) {
  884.         pPedestrian->pos = pPedestrian->actor->t.t.translate.t;
  885.     } else {
  886.         BrMatrix34ApplyP(&pPedestrian->pos,
  887.             &pPedestrian->actor->t.t.translate.t,
  888.             &pPedestrian->actor->parent->t.t.mat);
  889.     }
  890. }
  891.  
  892. // IDA: void __usercall DetachPedActorFromCar(br_actor *pActor@<EAX>)
  893. void DetachPedActorFromCar(br_actor* pActor) {
  894.     LOG_TRACE("(%p)", pActor);
  895.  
  896.     DetachPedFromCar(ActorToPedestrianData(pActor));
  897.     SetPedPos(ActorToPedestrianData(pActor));
  898. }
  899.  
  900. // IDA: void __usercall MungePedestrianFrames(tPedestrian_data *pPedestrian@<EAX>)
  901. void MungePedestrianFrames(tPedestrian_data* pPedestrian) {
  902.     tPedestrian_sequence* the_sequence;
  903.     float f_the_time;
  904.     float frame_period;
  905.     int frame_offset;
  906.     //int number_of_frames; // Pierre-Marie Baty -- unused variable
  907.     int new_frame;
  908.     tU32 the_time;
  909.     LOG_TRACE("(%p)", pPedestrian);
  910.  
  911.     the_time = GetTotalTime();
  912.     f_the_time = the_time;
  913.     the_sequence = &pPedestrian->sequences[pPedestrian->current_sequence];
  914.     if (pPedestrian->done_initial) {
  915.         frame_offset = the_sequence->number_of_frames - the_sequence->looping_frame_start;
  916.         if (frame_offset == 0 && pPedestrian->current_frame < the_sequence->looping_frame_start) {
  917.             pPedestrian->current_frame = the_sequence->looping_frame_start - 1;
  918.         }
  919.     } else {
  920.         frame_offset = the_sequence->looping_frame_start;
  921.     }
  922.     switch (the_sequence->frame_rate_type) {
  923.     case ePed_frame_fixed:
  924.         frame_period = 0.f;
  925.         break;
  926.     case ePed_frame_speed:
  927.         if (pPedestrian->done_initial) {
  928.             frame_period = the_sequence->frame_rate_factor1 / pPedestrian->current_speed * gPed_scale_factor;
  929.         } else {
  930.             frame_period = 1000.f / the_sequence->frame_rate_factor2;
  931.         }
  932.         break;
  933.     case ePed_frame_variable:
  934.         frame_period = 1000.f / FRandomBetween(the_sequence->frame_rate_factor1, the_sequence->frame_rate_factor2);
  935.         break;
  936.     default:
  937.         TELL_ME_IF_WE_PASS_THIS_WAY();
  938.         break;
  939.     }
  940.     if (frame_period == 0.f) {
  941.         pPedestrian->current_frame = 0;
  942.     } else if (!pPedestrian->done_initial) {
  943.         if (f_the_time - pPedestrian->last_frame >= frame_period) {
  944.             if (pPedestrian->actor->parent != gDont_render_actor
  945.                 || !pPedestrian->mid_air
  946.                 || pPedestrian->current_frame < frame_offset - 2
  947.                 || (pPedestrian->current_action != pPedestrian->fatal_ground_impact_action && pPedestrian->current_action != pPedestrian->fatal_car_impact_action)) {
  948.                 if (pPedestrian->reverse_frames) {
  949.                     pPedestrian->current_frame--;
  950.                     if (pPedestrian->current_frame < 0) {
  951.                         pPedestrian->reverse_frames = 0;
  952.                         ChangeActionTo(pPedestrian, 0, 1);
  953.                     }
  954.                 } else {
  955.                     pPedestrian->current_frame++;
  956.                 }
  957.             }
  958.             if (pPedestrian->last_frame == 0 || the_sequence->frame_rate_type == ePed_frame_variable) {
  959.                 pPedestrian->last_frame = the_time;
  960.             } else {
  961.                 pPedestrian->last_frame += frame_period;
  962.             }
  963.         }
  964.         if (gPedestrian_harvest
  965.             && pPedestrian->ref_number < 100
  966.             && pPedestrian->actor->parent != gDont_render_actor
  967.             && pPedestrian->current_action == pPedestrian->fatal_car_impact_action
  968.             && pPedestrian->current_frame >= 2) {
  969.             pPedestrian->current_frame = 0;
  970.             if (PercentageChance(20)
  971.                 && pPedestrian->number_of_actions >= 2
  972.                 && pPedestrian->action_list[1].number_of_sounds != 0) {
  973.                 DRS3StartSound3D(gPedestrians_outlet, pPedestrian->action_list[1].sounds[0],
  974.                     &pPedestrian->pos, &gZero_v__pedestrn, 1, 255, gZombie_factor * 65536.f, -1);
  975.             }
  976.         } else if (frame_offset <= pPedestrian->current_frame) {
  977.             pPedestrian->done_initial = 1;
  978.             if (the_sequence->number_of_frames == the_sequence->looping_frame_start) {
  979.                 pPedestrian->current_frame--;
  980.             }
  981.             if (pPedestrian->current_action != pPedestrian->fatal_car_impact_action) {
  982.                 if (pPedestrian->current_action != pPedestrian->non_fatal_car_impact_action
  983.                     && pPedestrian->current_action != pPedestrian->non_fatal_ground_impact_action) {
  984.                     MungePedestrianFrames(pPedestrian);
  985.                 } else {
  986.                     ChangeActionTo(pPedestrian, pPedestrian->after_impact_action, 1);
  987.                     MungePedestrianPath(pPedestrian, gDanger_level, &gDanger_direction);
  988.                 }
  989.             } else {
  990.                 if (pPedestrian->actor->parent != gDont_render_actor) {
  991.                     pPedestrian->actor->t.t.translate.t = pPedestrian->offset;
  992.                 }
  993.                 DetachPedFromCar(pPedestrian);
  994.                 pPedestrian->spin_period = 0.f;
  995.                 if (pPedestrian->ref_number >= 100) {
  996.                     KillPedestrian(pPedestrian);
  997.                 }
  998.             }
  999.             return;
  1000.         }
  1001.     } else if (frame_offset != 0) {
  1002.         if (f_the_time - pPedestrian->last_frame >= frame_period) {
  1003.             if (pPedestrian->reverse_frames) {
  1004.                 pPedestrian->current_frame--;
  1005.                 if (pPedestrian->current_frame < 0) {
  1006.                     pPedestrian->reverse_frames = 0;
  1007.                     ChangeActionTo(pPedestrian, 0, 1);
  1008.                 }
  1009.             } else {
  1010.                 pPedestrian->current_frame++;
  1011.                 if (pPedestrian->last_frame == 0 || the_sequence->frame_rate_type == ePed_frame_variable) {
  1012.                     pPedestrian->last_frame = the_time;
  1013.                 } else {
  1014.                     pPedestrian->last_frame += frame_period;
  1015.                 }
  1016.             }
  1017.         }
  1018.         if (pPedestrian->current_frame >= the_sequence->looping_frame_start + frame_offset) {
  1019.             pPedestrian->current_frame = the_sequence->looping_frame_start;
  1020.         }
  1021.     }
  1022.     new_frame = pPedestrian->current_frame;
  1023.     pPedestrian->colour_map = the_sequence->frames[MAX(0, new_frame)].pixelmap;
  1024. }
  1025.  
  1026. // IDA: void __usercall MungePedModel(tPedestrian_data *pPedestrian@<EAX>)
  1027. void MungePedModel(tPedestrian_data* pPedestrian) {
  1028.     //br_vector3 old_pos; // Pierre-Marie Baty -- unused variable
  1029.     //br_vector3 delta_pos; // Pierre-Marie Baty -- unused variable
  1030.     br_scalar height_over2;
  1031.     //br_matrix34 mat; // Pierre-Marie Baty -- unused variable
  1032.     br_scalar x_offset;
  1033.     br_scalar y_offset;
  1034.     br_scalar temp_scalar;
  1035.     //br_scalar* component_address; // Pierre-Marie Baty -- unused variable
  1036.     //br_pixelmap* current_pixel_bastard; // Pierre-Marie Baty -- unused variable
  1037.     //br_pixelmap* reference_pixel_bastard; // Pierre-Marie Baty -- unused variable
  1038.     //br_vertex* vertices; // Pierre-Marie Baty -- unused variable
  1039.     //int model_changed; // Pierre-Marie Baty -- unused variable
  1040.     tPed_frame_info* the_frame;
  1041.     //tCar_spec* murderer; // Pierre-Marie Baty -- unused variable
  1042.     br_actor* old_parent;
  1043.     LOG_TRACE("(%p)", pPedestrian);
  1044.  
  1045.     old_parent = NULL;
  1046.     CalcPedWidthNHeight(pPedestrian, pPedestrian->colour_map, &pPedestrian->height2, &pPedestrian->width);
  1047.     the_frame = &pPedestrian->sequences[pPedestrian->current_sequence].frames[MAX(pPedestrian->current_frame, 0)];
  1048.     if (pPedestrian->ref_number >= 100 && pPedestrian->current_action == pPedestrian->fatal_car_impact_action) {
  1049.         x_offset = the_frame->offset.v[X] * 2.0f;
  1050.         y_offset = the_frame->offset.v[Y];
  1051.         pPedestrian->height2 *= 2.0f;
  1052.         pPedestrian->width *= 2.0f;
  1053.     } else {
  1054.         x_offset = the_frame->offset.v[X];
  1055.         y_offset = the_frame->offset.v[Y];
  1056.     }
  1057.     pPedestrian->flipped = the_frame->flipped;
  1058.     if (pPedestrian->actor->parent != gDont_render_actor) {
  1059.         old_parent = pPedestrian->actor->parent;
  1060.         BrActorRelink(gDont_render_actor, pPedestrian->actor);
  1061.     }
  1062.     BrMatrix34Scale(&pPedestrian->actor->t.t.mat, pPedestrian->width, pPedestrian->height2, 1.0f);
  1063.     if (pPedestrian->spin_period != 0.0f && pPedestrian->actor->model != NULL) {
  1064.         height_over2 = pPedestrian->height2 / 2.0f;
  1065.         BrMatrix34PostTranslate(&pPedestrian->actor->t.t.mat, 0.0f, -height_over2, 0.0f);
  1066.         if (pPedestrian->spin_period >= 0.0f) {
  1067.             temp_scalar = (float)(GetTotalTime() - pPedestrian->last_action_change) / pPedestrian->spin_period * 360.0f;
  1068.         } else {
  1069.             temp_scalar = ((float)(GetTotalTime() - pPedestrian->last_action_change) / pPedestrian->spin_period * 360.0f + 360.0f);
  1070.         }
  1071.         DRMatrix34PostRotateZ(&pPedestrian->actor->t.t.mat, BrDegreeToAngle(temp_scalar));
  1072.         BrMatrix34PostTranslate(&pPedestrian->actor->t.t.mat, 0.0f, height_over2, 0.0f);
  1073.     }
  1074.     temp_scalar = FastScalarArcTan2Angle(gCamera_to_world.m[2][0], gCamera_to_world.m[2][2]);
  1075.     DRMatrix34PostRotateY(&pPedestrian->actor->t.t.mat, temp_scalar);
  1076.     if (old_parent != NULL
  1077.         && pPedestrian->current_action == pPedestrian->fatal_car_impact_action
  1078.         && !pPedestrian->done_initial
  1079.         && pPedestrian->actor->model != NULL) {
  1080.  
  1081.         y_offset += FastScalarSin(((br_scalar)MAX(pPedestrian->current_frame, 0)
  1082.                         / (br_scalar)(pPedestrian->sequences[pPedestrian->current_sequence].looping_frame_start - 1) * 180.0f))
  1083.             * pPedestrian->jump_magnitude;
  1084.     }
  1085.     if (old_parent != NULL) {
  1086.         BrMatrix34PostTranslate(&pPedestrian->actor->t.t.mat,
  1087.             old_parent->t.t.translate.t.v[X] + x_offset,
  1088.             old_parent->t.t.translate.t.v[Y] + y_offset,
  1089.             old_parent->t.t.translate.t.v[Z]);
  1090.         BrActorRelink(old_parent, pPedestrian->actor);
  1091.         BrVector3Accumulate(&pPedestrian->actor->t.t.translate.t, &pPedestrian->offset);
  1092.     } else if (pPedestrian->spin_period == 0.0f) {
  1093.         BrMatrix34PostTranslate(&pPedestrian->actor->t.t.mat,
  1094.             pPedestrian->pos.v[X] + x_offset - pPedestrian->offset.v[X],
  1095.             pPedestrian->pos.v[Y] + y_offset - pPedestrian->offset.v[Y],
  1096.             pPedestrian->pos.v[Z]);
  1097.         BrVector3Set(&pPedestrian->offset, x_offset, y_offset, 0.0f);
  1098.     } else {
  1099.         BrMatrix34PostTranslate(&pPedestrian->actor->t.t.mat,
  1100.             pPedestrian->offset.v[X] + x_offset,
  1101.             pPedestrian->offset.v[Y] + y_offset,
  1102.             pPedestrian->offset.v[Z]);
  1103.     }
  1104.     gCurrent_lollipop_index = AddToLollipopQueue(pPedestrian->actor, gCurrent_lollipop_index);
  1105. }
  1106.  
  1107. // IDA: void __usercall ChangeActionTo(tPedestrian_data *pPedestrian@<EAX>, int pAction_index@<EDX>, int pRedo_frames_etc@<EBX>)
  1108. void ChangeActionTo(tPedestrian_data* pPedestrian, int pAction_index, int pRedo_frames_etc) {
  1109.     tPedestrian_action* the_action;
  1110.     int the_sound;
  1111.     tU32 the_pitch;
  1112.     LOG_TRACE("(%p, %d, %d)", pPedestrian, pAction_index, pRedo_frames_etc);
  1113.  
  1114.     if (pAction_index == pPedestrian->current_action || pAction_index >= pPedestrian->number_of_actions) {
  1115.         return;
  1116.     }
  1117.  
  1118.     pPedestrian->last_action_change = GetTotalTime();
  1119.     pPedestrian->current_action = pAction_index;
  1120.     pPedestrian->current_frame = -1;
  1121.     pPedestrian->last_frame = 0;
  1122.     pPedestrian->done_initial = 0;
  1123.     if (pRedo_frames_etc) {
  1124.         MungePedestrianSequence(pPedestrian, 1);
  1125.         MungePedestrianFrames(pPedestrian);
  1126.         MungePedModel(pPedestrian);
  1127.     }
  1128.     the_action = &pPedestrian->action_list[pAction_index];
  1129.     if (!gPed_sound_disable && the_action->number_of_sounds != 0) {
  1130.         if (pAction_index == pPedestrian->last_sound_action && GetTotalTime() - pPedestrian->last_sound_make < 4000) {
  1131.             return;
  1132.         }
  1133.         DRS3StopSound(pPedestrian->last_sound);
  1134.         the_sound = the_action->sounds[IRandomBetween(0, the_action->number_of_sounds - 1)];
  1135.         the_pitch = 65536.f / gPed_scale_factor * gZombie_factor;
  1136.         pPedestrian->last_sound = DRS3StartSound3D(gPedestrians_outlet, the_sound, &pPedestrian->pos, &gZero_v__pedestrn, 1, 255, the_pitch, -1);
  1137.         pPedestrian->last_sound_action = pAction_index;
  1138.         pPedestrian->last_sound_make = GetTotalTime();
  1139.         PipeSingleSound(gPedestrians_outlet, the_sound, 255, 0, the_pitch, &pPedestrian->pos);
  1140.     }
  1141. }
  1142.  
  1143. // IDA: int __usercall MungePedestrianAction@<EAX>(tPedestrian_data *pPedestrian@<EAX>, float pDanger_level)
  1144. int MungePedestrianAction(tPedestrian_data* pPedestrian, float pDanger_level) {
  1145.     tU32 time_diff;
  1146.     int i;
  1147.     int choice;
  1148.     int start_index;
  1149.     int end_index;
  1150.     float chance_value;
  1151.     float most_dangerous;
  1152.     LOG_TRACE("(%p, %f)", pPedestrian, pDanger_level);
  1153.  
  1154.     if (pPedestrian->current_action == pPedestrian->fatal_car_impact_action
  1155.         || pPedestrian->current_action == pPedestrian->non_fatal_car_impact_action
  1156.         || pPedestrian->current_action == pPedestrian->fatal_ground_impact_action
  1157.         || pPedestrian->current_action == pPedestrian->non_fatal_car_impact_action
  1158.         || pPedestrian->current_action == pPedestrian->giblets_action
  1159.         || pPedestrian->mid_air) {
  1160.         return 0;
  1161.     }
  1162.     time_diff = GetTotalTime() - pPedestrian->last_action_change;
  1163.     if (pPedestrian->current_action_mode >= 0) {
  1164.         ChangeActionTo(pPedestrian, pPedestrian->current_action_mode, 0);
  1165.         return 1;
  1166.     }
  1167.     most_dangerous = -1.f;
  1168. #if defined(DETHRACE_FIX_BUGS)
  1169.     start_index = 0;
  1170.     end_index = 0;
  1171. #endif
  1172.     for (i = 0; i < pPedestrian->number_of_actions; i++) {
  1173.         if (pPedestrian->action_list[i].danger_level < 999.f
  1174.             && pPedestrian->action_list[i].danger_level <= pDanger_level
  1175.             && pPedestrian->action_list[i].reaction_time <= time_diff
  1176.             && (gFlag_waving_bastard != pPedestrian || pPedestrian->current_action != 7 || pPedestrian->action_list[i].danger_level != 0.f)) {
  1177.             if (pPedestrian->action_list[i].danger_level > most_dangerous) {
  1178.                 most_dangerous = pPedestrian->action_list[i].danger_level;
  1179.                 start_index = i;
  1180.                 end_index = i;
  1181.             } else if (pPedestrian->action_list[i].danger_level == most_dangerous) {
  1182.                 end_index = i;
  1183.             }
  1184.         }
  1185.     }
  1186.     if (most_dangerous <= -1.f) {
  1187.         return 0;
  1188.     }
  1189.     chance_value = FRandomBetween(0.f, 99.f);
  1190.     choice = start_index;
  1191.     for (i = start_index; i <= end_index; i++) {
  1192.         chance_value -= pPedestrian->action_list[i].percentage_chance;
  1193.         if (chance_value < 0.f) {
  1194.             choice = i;
  1195.             break;
  1196.         }
  1197.     }
  1198.     ChangeActionTo(pPedestrian, choice, 1);
  1199.     return 1;
  1200. }
  1201.  
  1202. // IDA: void __cdecl MakeFlagWavingBastardWaveHisFlagWhichIsTheProbablyTheLastThingHeWillEverDo()
  1203. void MakeFlagWavingBastardWaveHisFlagWhichIsTheProbablyTheLastThingHeWillEverDo(void) {
  1204.     LOG_TRACE("()");
  1205.  
  1206.     if (gFlag_waving_bastard != NULL
  1207.         && gFlag_waving_bastard->current_action != gFlag_waving_bastard->fatal_car_impact_action
  1208.         && gFlag_waving_bastard->current_action != gFlag_waving_bastard->fatal_ground_impact_action) {
  1209.         ChangeActionTo(gFlag_waving_bastard, 7, 1);
  1210.     }
  1211. }
  1212.  
  1213. // IDA: void __usercall MungePedestrianPath(tPedestrian_data *pPedestrian@<EAX>, float pDanger_level, br_vector3 *pDanger_direction)
  1214. void MungePedestrianPath(tPedestrian_data* pPedestrian, float pDanger_level, br_vector3* pDanger_direction) {
  1215.     tPedestrian_action* the_action;
  1216.     float terminal_speed;
  1217.     //float new_falling_speed; // Pierre-Marie Baty -- unused variable
  1218.     float grav_times_period;
  1219.     float ped_gravity;
  1220.     br_vector3 movement_vector;
  1221.     br_vector3 over_shoot;
  1222.     br_vector3 cast_point;
  1223.     br_scalar old_y;
  1224.     br_scalar new_y;
  1225.     int damage;
  1226.     tU32 the_pitch;
  1227.     LOG_TRACE("(%p, %f, %p)", pPedestrian, pDanger_level, pDanger_direction);
  1228.  
  1229.     if (gAttracted_pedestrians) {
  1230.         BrVector3Scale(pDanger_direction, pDanger_direction, -1.f);
  1231.     }
  1232.     old_y = pPedestrian->actor->t.t.translate.t.v[Y];
  1233.     if (pPedestrian->current_action != pPedestrian->fatal_car_impact_action
  1234.         && pPedestrian->current_action != pPedestrian->fatal_ground_impact_action
  1235.         && pPedestrian->current_action != pPedestrian->giblets_action) {
  1236.         the_action = &pPedestrian->action_list[pPedestrian->current_action];
  1237.         if (!pPedestrian->done_initial) {
  1238.             terminal_speed = the_action->initial_speed;
  1239.         } else {
  1240.             terminal_speed = the_action->looping_speed;
  1241.         }
  1242.         if (pPedestrian->current_speed < terminal_speed) {
  1243.             pPedestrian->current_speed += gFrame_period * pPedestrian->acceleration;
  1244.         }
  1245.         if (pPedestrian->current_speed > terminal_speed) {
  1246.             pPedestrian->current_speed = terminal_speed;
  1247.         }
  1248.         pPedestrian->current_speed *= gPedestrian_speed_factor;
  1249.         if (!pPedestrian->irreversable && pDanger_level != 0.f && BrVector3Dot(&pPedestrian->direction, pDanger_direction) > 0.f) {
  1250.             pPedestrian->instruction_direction = -pPedestrian->instruction_direction;
  1251.             gInitial_instruction = NULL;
  1252.             if (PedestrianNextInstruction(pPedestrian, pDanger_level, 0, 1) != 0) {
  1253.                 ChangeActionTo(pPedestrian, 0, 0);
  1254.             }
  1255.         }
  1256.         if (pPedestrian->last_special_volume != NULL
  1257.             && pPedestrian->last_special_volume->viscosity_multiplier != 1.f) {
  1258.             BrVector3Scale(&movement_vector, &pPedestrian->direction, gFrame_period * pPedestrian->current_speed * 20.f / pPedestrian->last_special_volume->viscosity_multiplier);
  1259.         } else {
  1260.             BrVector3Scale(&movement_vector, &pPedestrian->direction, gFrame_period * pPedestrian->current_speed);
  1261.         }
  1262.         BrVector3Accumulate(&pPedestrian->actor->t.t.translate.t, &movement_vector);
  1263.         BrVector3Accumulate(&pPedestrian->pos, &movement_vector);
  1264.         BrVector3Sub(&over_shoot, &pPedestrian->actor->t.t.translate.t, &pPedestrian->to_pos);
  1265.         if (BrVector3Dot(&pPedestrian->direction, &over_shoot) > 0.f) {
  1266.             gInitial_instruction = NULL;
  1267.             PedestrianNextInstruction(pPedestrian, pDanger_level, 0, 1);
  1268.         }
  1269.     }
  1270.  
  1271.     pPedestrian->last_special_volume = FindSpecialVolume(&pPedestrian->actor->t.t.translate.t, pPedestrian->last_special_volume);
  1272.     if (pPedestrian->last_special_volume == NULL) {
  1273.         ped_gravity = 1.42029e-6f;
  1274.     } else {
  1275.         ped_gravity = pPedestrian->last_special_volume->gravity_multiplier * 1.42029e-6f;
  1276.     }
  1277.     ped_gravity *= gGravity_multiplier;
  1278.     if (gVesuvian_corpses
  1279.         && (pPedestrian->current_action == pPedestrian->fatal_car_impact_action || pPedestrian->current_action == pPedestrian->fatal_ground_impact_action)) {
  1280.         if (PercentageChance(100 / (gVesuvians_last_time != 0 ? gVesuvians_last_time : 1))) {
  1281.             BurstPedestrian(pPedestrian, .001f, 0);
  1282.         }
  1283.         gVesuvians_this_time++;
  1284.     }
  1285.     if (pPedestrian->to_pos.v[Y] < 500.f) {
  1286.         pPedestrian->falling_speed = 0.f;
  1287.         pPedestrian->mid_air = 0;
  1288.     } else {
  1289.         BrVector3Copy(&cast_point, &pPedestrian->actor->t.t.translate.t);
  1290.         if (cast_point.v[Y] >= 500.f) {
  1291.             cast_point.v[Y] -= 999.6f;
  1292.             pPedestrian->pos.v[Y] = pPedestrian->actor->t.t.translate.t.v[Y] = FindYVerticallyBelow2(&cast_point);
  1293.             pPedestrian->falling_speed = 0.f;
  1294.             pPedestrian->mid_air = 0;
  1295.             pPedestrian->spin_period = 0;
  1296.             BrVector3Set(&pPedestrian->offset, 0.f, 0.f, 0.f);
  1297.         } else {
  1298.             if (pPedestrian->current_speed == 0.f && !pPedestrian->mid_air) {
  1299.                 pPedestrian->mid_air = 0;
  1300.             } else {
  1301.                 cast_point.v[Y] = old_y + .4f;
  1302.                 new_y = FindYVerticallyBelow2(&cast_point);
  1303.                 if (new_y > old_y) {
  1304.                     pPedestrian->spin_period = 0.f;
  1305.                     BrVector3Set(&pPedestrian->offset, 0.f, 0.f, 0.f);
  1306.                     pPedestrian->mid_air = 0;
  1307.                     pPedestrian->falling_speed = 0.f;
  1308.                     pPedestrian->pos.v[Y] = pPedestrian->actor->t.t.translate.t.v[Y] = new_y;
  1309.                 } else {
  1310.                     grav_times_period = ped_gravity * gFrame_period;
  1311.                     pPedestrian->falling_speed += grav_times_period;
  1312.                     pPedestrian->actor->t.t.translate.t.v[Y] -= gFrame_period * pPedestrian->falling_speed;
  1313.                     pPedestrian->pos.v[Y] = pPedestrian->actor->t.t.translate.t.v[Y];
  1314.                     if (pPedestrian->spin_period != 0.f) {
  1315.                         pPedestrian->offset.v[Y] -= gFrame_period * pPedestrian->falling_speed;
  1316.                     }
  1317.                     if (pPedestrian->hit_points > 0
  1318.                         && pPedestrian->falling_sound >= 0
  1319.                         && pPedestrian->falling_speed >= 0.0008f) {
  1320.                         DRS3StopSound(pPedestrian->last_sound);
  1321.                         the_pitch = 65536.f / gPed_scale_factor;
  1322.                         pPedestrian->last_sound = DRS3StartSound3D(gPedestrians_outlet,
  1323.                             pPedestrian->falling_sound,
  1324.                             &pPedestrian->pos,
  1325.                             &gZero_v__pedestrn,
  1326.                             1,
  1327.                             255,
  1328.                             the_pitch,
  1329.                             -1);
  1330.                         PipeSingleSound(gPedestrians_outlet,
  1331.                             pPedestrian->falling_sound,
  1332.                             255,
  1333.                             0,
  1334.                             the_pitch,
  1335.                             &pPedestrian->pos);
  1336.                         pPedestrian->falling_sound = -1;
  1337.                     }
  1338.                     if (new_y <= pPedestrian->actor->t.t.translate.t.v[Y]) {
  1339.                         pPedestrian->mid_air = 1;
  1340.                     } else {
  1341.                         pPedestrian->pos.v[Y] = pPedestrian->actor->t.t.translate.t.v[Y] = new_y;
  1342.                         if (pPedestrian->spin_period != 0.f) {
  1343.                             pPedestrian->offset.v[Y] = pPedestrian->pos.v[Y];
  1344.                         }
  1345.                         if (pPedestrian->hit_points < 0) {
  1346.                             BrVector3Copy(&pPedestrian->to_pos, &pPedestrian->pos);
  1347.                         }
  1348.                         damage = (pPedestrian->falling_speed - 0.0015f) * 100000.f;
  1349.                         if (damage > 0 || pPedestrian->hit_points < 0) {
  1350.                             if (pPedestrian->hit_points >= 0 && (pPedestrian->hit_points -= damage, pPedestrian->hit_points > 0)) {
  1351.                                 if (pPedestrian->hit_points < damage) {
  1352.                                     ChangeActionTo(pPedestrian, pPedestrian->non_fatal_ground_impact_action, 1);
  1353.                                 }
  1354.                             } else {
  1355.                                 if (pPedestrian->hit_points <= -100) {
  1356.                                     pPedestrian->hit_points = -99;
  1357.                                 }
  1358.                                 if (pPedestrian->ref_number < 100
  1359.                                     && pPedestrian->current_action != pPedestrian->fatal_car_impact_action
  1360.                                     && pPedestrian->current_action != pPedestrian->fatal_ground_impact_action
  1361.                                     && pPedestrian->current_action != pPedestrian->giblets_action) {
  1362.                                     gProgram_state.peds_killed++;
  1363.                                     ChangeActionTo(pPedestrian, pPedestrian->fatal_ground_impact_action, 1);
  1364.                                 }
  1365.                                 pPedestrian->spin_period = 0.f;
  1366.                                 BrVector3Set(&pPedestrian->offset, 0.f, 0.f, 0.f);
  1367.                                 if (pPedestrian->mid_air) {
  1368.                                     BurstPedestrian(pPedestrian, pPedestrian->falling_speed * 3.f, 0);
  1369.                                 }
  1370.                             }
  1371.                         }
  1372.                         pPedestrian->falling_speed = 0.f;
  1373.                         pPedestrian->mid_air = 0;
  1374.                     }
  1375.                 }
  1376.             }
  1377.         }
  1378.     }
  1379. }
  1380.  
  1381. // IDA: float __usercall CalcPedestrianDangerLevel@<ST0>(tPedestrian_data *pPedestrian@<EAX>, br_vector3 *pDanger_direction@<EDX>)
  1382. float CalcPedestrianDangerLevel(tPedestrian_data* pPedestrian, br_vector3* pDanger_direction) {
  1383.     br_vector3* ped_pos;
  1384.     int i;
  1385.     float most_dangerous;
  1386.     float this_danger;
  1387.     br_scalar distance_squared;
  1388.     br_scalar car_movement_angle;
  1389.     br_scalar car_to_pedestrian_angle;
  1390.     br_scalar heading_difference;
  1391.     br_scalar camera_view_angle;
  1392.     tCar_spec* car;
  1393.     LOG_TRACE("(%p, %p)", pPedestrian, pDanger_direction);
  1394.  
  1395.     most_dangerous = 0.f;
  1396.     ped_pos = &pPedestrian->actor->t.t.translate.t;
  1397.     for (i = 0; i < gNum_active_cars; i++) {
  1398.         car = gActive_car_list[i];
  1399.         if (car->driver == eDriver_local_human) {
  1400.             camera_view_angle = FastScalarArcTan2(ped_pos->v[X] - gCamera_to_world.m[3][X], ped_pos->v[Z] - gCamera_to_world.m[3][Z]);
  1401.             pPedestrian->car_to_ped = camera_view_angle;
  1402.         }
  1403.         if (gBlind_pedestrians) {
  1404.             return car->keys.horn ? 100.f : 0.f;
  1405.         }
  1406.         distance_squared = (ped_pos->v[X] - car->pos.v[X]) * (ped_pos->v[X] - car->pos.v[X])
  1407.             + 10.f * (ped_pos->v[Y] - car->pos.v[Y]) * 10.f * (ped_pos->v[Y] - car->pos.v[Y])
  1408.             + (ped_pos->v[Z] - car->pos.v[Z]) * (ped_pos->v[Z] - car->pos.v[Z]);
  1409.         if (distance_squared < gMax_distance_squared) {
  1410.             car_movement_angle = FastScalarArcTan2(car->direction.v[X], car->direction.v[Z]);
  1411.             car_to_pedestrian_angle = FastScalarArcTan2(ped_pos->v[X] - car->pos.v[X], ped_pos->v[Z] - car->pos.v[Z]);
  1412.             if (car_to_pedestrian_angle > car_movement_angle) {
  1413.                 car_movement_angle += 360.f;
  1414.             }
  1415.             heading_difference = car_movement_angle - car_to_pedestrian_angle;
  1416.             if (heading_difference > 180.f) {
  1417.                 heading_difference = 360.f - heading_difference;
  1418.             }
  1419.             if (heading_difference < 30.f || car->speed == 0.f || car->keys.horn) {
  1420.                 if (car->keys.horn) {
  1421.                     this_danger = 10.f / distance_squared;
  1422.                 } else {
  1423.                     if (car->speed != 0.f) {
  1424.                         this_danger = 30.f - heading_difference + 5.f;
  1425.                     } else {
  1426.                         this_danger = 5.f;
  1427.                     }
  1428.                     this_danger = (fabsf(car->speed) + 3e-5f) * this_danger / distance_squared * 400.f;
  1429.                 }
  1430.                 if (this_danger > most_dangerous) {
  1431.                     most_dangerous = this_danger;
  1432.                     BrVector3Sub(pDanger_direction, &car->pos, ped_pos);
  1433.                     if (car->driver == eDriver_local_human) {
  1434.                         pPedestrian->frightened_of_us = 1;
  1435.                     } else if (!pPedestrian->mid_air) {
  1436.                         pPedestrian->frightened_of_us = 0;
  1437.                     }
  1438.                 }
  1439.             }
  1440.         }
  1441.     }
  1442.     if (most_dangerous > 999.f) {
  1443.         most_dangerous = 999.f;
  1444.     }
  1445.     return most_dangerous;
  1446. }
  1447.  
  1448. // IDA: tPed_hit_position __usercall MoveToEdgeOfCar@<EAX>(tPedestrian_data *pPedestrian@<EAX>, tCollision_info *pCar@<EDX>, br_actor *pCar_actor@<EBX>, br_scalar pPed_x, br_scalar pPed_z, br_scalar pCar_bounds_min_x, br_scalar pCar_bounds_max_x, br_scalar pCar_bounds_min_z, br_scalar pCar_bounds_max_z, br_vector3 *pMin_ped_bounds_car, br_vector3 *pMax_ped_bounds_car)
  1449. tPed_hit_position MoveToEdgeOfCar(tPedestrian_data* pPedestrian, tCollision_info* pCar, br_actor* pCar_actor, br_scalar pPed_x, br_scalar pPed_z, br_scalar pCar_bounds_min_x, br_scalar pCar_bounds_max_x, br_scalar pCar_bounds_min_z, br_scalar pCar_bounds_max_z, br_vector3* pMin_ped_bounds_car, br_vector3* pMax_ped_bounds_car) {
  1450.     //br_vector3 car_plus_ped; // Pierre-Marie Baty -- unused variable
  1451.     //br_vector3 delta_vector; // Pierre-Marie Baty -- unused variable
  1452.     br_vector3 ped_move_in_car;
  1453.     br_vector3 ped_move_in_global;
  1454.     br_vector3 scaled_car_direction;
  1455.     br_vector3 scaled_ped_direction;
  1456.     br_matrix34 global_to_car;
  1457.     br_scalar z_to_use;
  1458.     br_scalar x_to_use;
  1459.     br_scalar t;
  1460.     br_scalar x;
  1461.     br_scalar z;
  1462.     tPed_hit_position result;
  1463.  
  1464. #ifdef DETHRACE_FIX_BUGS
  1465.     x_to_use = 0.0f;
  1466. #endif
  1467.     if (fabsf(pPedestrian->current_speed) >= fabsf(pCar->speed)) {
  1468.         BrVector3Scale(&ped_move_in_global, &pPedestrian->direction, -fabsf(pPedestrian->current_speed));
  1469.     } else {
  1470.         BrVector3Scale(&ped_move_in_global, &pCar->direction, fabsf(pCar->speed));
  1471.     }
  1472.     if (fabsf(ped_move_in_global.v[X]) < 5e-5f || fabsf(ped_move_in_global.v[Z]) < 5e-5f) {
  1473.         return ePed_hit_unknown;
  1474.     }
  1475.     BrActorToActorMatrix34(&global_to_car, gDont_render_actor, pCar_actor);
  1476.     BrMatrix34ApplyV(&ped_move_in_car, &ped_move_in_global, &global_to_car);
  1477.     if (ped_move_in_car.v[X] >= 0.f) {
  1478.         x = pCar_bounds_max_x - pMin_ped_bounds_car->v[X];
  1479.     } else {
  1480.         x = pCar_bounds_min_x - pMax_ped_bounds_car->v[X];
  1481.     }
  1482.     if (ped_move_in_car.v[Z] >= 0.f) {
  1483.         z = pCar_bounds_max_z - pMin_ped_bounds_car->v[Z];
  1484.     } else {
  1485.         z = pCar_bounds_min_z - pMax_ped_bounds_car->v[Z];
  1486.     }
  1487.  
  1488.     if (ped_move_in_car.v[Z] != 0.f) {
  1489.         t = z / ped_move_in_car.v[Z] * ped_move_in_car.v[X];
  1490.     }
  1491.     if (ped_move_in_car.v[Z] == 0.f || t + pPed_x < pCar_bounds_min_x || t + pPed_x > pCar_bounds_max_x) {
  1492.         if (ped_move_in_car.v[X] == 0.f) {
  1493.             return ePed_hit_unknown;
  1494.         }
  1495.         t = x / ped_move_in_car.v[X];
  1496.         z_to_use = t * ped_move_in_car.v[Z];
  1497.         if (z_to_use + pPed_z < pCar_bounds_min_z || z_to_use + pPed_z > pCar_bounds_max_z) {
  1498.             return ePed_hit_unknown;
  1499.         }
  1500.         x_to_use = x;
  1501.         if (ped_move_in_car.v[X] >= 0.f) {
  1502.             result = ePed_hit_rside;
  1503.         } else {
  1504.             result = ePed_hit_lside;
  1505.         }
  1506.     } else {
  1507.         z_to_use = z;
  1508.         if (ped_move_in_car.v[Z] >= 0.f) {
  1509.             result = ePed_hit_back;
  1510.         } else {
  1511.             result = ePed_hit_front;
  1512.         }
  1513.     }
  1514.     BrVector3Set(&scaled_car_direction, 1.01f * x_to_use, 0.f, 1.01f * z_to_use);
  1515.     BrMatrix34TApplyV(&scaled_ped_direction, &scaled_car_direction, &global_to_car);
  1516.     scaled_ped_direction.v[Y] = 0.f;
  1517.     if (pCar->speed == 0.f || gFrame_period * fabsf(pCar->speed) > BrVector3Length(&scaled_ped_direction) / 10.f) {
  1518.         BrVector3Accumulate(&pPedestrian->actor->t.t.translate.t, &scaled_ped_direction);
  1519.         BrVector3Accumulate(&pPedestrian->pos, &scaled_ped_direction);
  1520.     }
  1521.     return result;
  1522. }
  1523.  
  1524. // IDA: void __cdecl CheckLastPed()
  1525. void CheckLastPed(void) {
  1526.     LOG_TRACE("()");
  1527.  
  1528.     if (gNet_mode == eNet_mode_none && gProgram_state.peds_killed >= gTotal_peds) {
  1529.         NewTextHeadupSlot(4, 0, 5000, -4, GetMiscString(kMiscString_EveryPedestrianWasted));
  1530.         RaceCompleted(eRace_over_peds);
  1531.     }
  1532. }
  1533.  
  1534. // IDA: int __usercall BloodyWheels@<EAX>(tCar_spec *pCar@<EAX>, br_vector3 *pPed_car@<EDX>, br_scalar pSize, br_vector3 *pPed_glob)
  1535. int BloodyWheels(tCar_spec* pCar, br_vector3* pPed_car, br_scalar pSize, br_vector3* pPed_glob) {
  1536.     int wheel;
  1537.     int squish;
  1538.     br_scalar ped_m_z;
  1539.     br_scalar ped_m_x;
  1540.     br_scalar dist_sqr;
  1541.     br_scalar size_sqr;
  1542.     LOG_TRACE("(%p, %p, %f, %p)", pCar, pPed_car, pSize, pPed_glob);
  1543.  
  1544.     size_sqr = pSize + .05f;
  1545.     dist_sqr = size_sqr * WORLD_SCALE * size_sqr * WORLD_SCALE;
  1546.     squish = 0;
  1547.     for (wheel = 0; wheel < COUNT_OF(pCar->blood_remaining); wheel++) {
  1548.         ped_m_x = pCar->wpos[wheel].v[X] - pPed_car->v[X] * WORLD_SCALE;
  1549.         ped_m_z = pCar->wpos[wheel].v[Z] - pPed_car->v[Z] * WORLD_SCALE;
  1550.         if (pCar->blood_remaining[wheel] == 0.f && ped_m_x * ped_m_x + ped_m_z * ped_m_z < dist_sqr) {
  1551.             pCar->blood_remaining[wheel] = SRandomBetween(2.f, 8.f);
  1552.             pCar->special_start[wheel] = *pPed_glob;
  1553.             squish = 1;
  1554.         }
  1555.     }
  1556.     return squish;
  1557. }
  1558.  
  1559. // IDA: int __usercall FancyATossOffMate@<EAX>(tPedestrian_data *pPedestrian@<EAX>, tCollision_info *pCar@<EDX>, float pImpact_speed)
  1560. int FancyATossOffMate(tPedestrian_data* pPedestrian, tCollision_info* pCar, float pImpact_speed) {
  1561.     LOG_TRACE("(%p, %p, %f)", pPedestrian, pCar, pImpact_speed);
  1562.  
  1563.     return !gPedestrian_harvest
  1564.         && pPedestrian->ref_number < 100
  1565.         && (pCar->driver > 1 || ((tCar_spec*)pCar)->number_of_wheels_on_ground >= 4)
  1566.         && PercentageChance(50)
  1567.         && pImpact_speed >= .0035f;
  1568. }
  1569.  
  1570. // IDA: void __usercall CheckPedestrianDeathScenario(tPedestrian_data *pPedestrian@<EAX>)
  1571. void CheckPedestrianDeathScenario(tPedestrian_data* pPedestrian) {
  1572.     int norman;
  1573.     int i;
  1574.     int tossing;
  1575.     int orig_gib_flag;
  1576.     int exploded;
  1577.     int proximity_rayed;
  1578.     int fated;
  1579.     int billiards_shot;
  1580.     int credits_value;
  1581.     br_vector3* car_pos;
  1582.     br_vector3* ped_pos;
  1583.     br_vector3 min_ped_bounds;
  1584.     br_vector3 max_ped_bounds;
  1585.     br_vector3 min_ped_bounds_car;
  1586.     br_vector3 max_ped_bounds_car;
  1587.     //br_vector3 ped_to_car_vector; // Pierre-Marie Baty -- unused variable
  1588.     br_vector3 up;
  1589.     br_vector3 zero_v;
  1590.     //br_scalar attitude; // Pierre-Marie Baty -- unused variable
  1591.     br_scalar distance_squared;
  1592.     br_scalar ped_centre_x;
  1593.     br_scalar ped_centre_y;
  1594.     br_scalar car_bounds_min_x;
  1595.     br_scalar car_bounds_max_x;
  1596.     br_scalar car_bounds_min_z;
  1597.     br_scalar car_bounds_max_z;
  1598.     br_scalar prev_car_bounds_min_x;
  1599.     br_scalar prev_car_bounds_max_x;
  1600.     br_scalar prev_car_bounds_min_z;
  1601.     br_scalar prev_car_bounds_max_z;
  1602.     br_scalar scalar_frame_time;
  1603.     br_scalar gross_dismiss;
  1604.     br_actor* car_actor;
  1605.     //br_actor* incident_actor; // Pierre-Marie Baty -- unused variable
  1606.     br_matrix34 ped_to_car;
  1607.     tCollision_info* the_car;
  1608.     float impact_speed;
  1609.     float volume_damage;
  1610.     tU32 the_time;
  1611.     tPed_hit_position hit_pos;
  1612.     LOG_TRACE("(%p)", pPedestrian);
  1613.  
  1614.     tossing = 0;
  1615.     billiards_shot = 0;
  1616.     the_time = GetTotalTime();
  1617.     orig_gib_flag = pPedestrian->giblets_being_sat_upon;
  1618.     pPedestrian->giblets_being_sat_upon = 0;
  1619.     ped_pos = &pPedestrian->actor->t.t.translate.t;
  1620.     if (!gDetect_peds || pPedestrian->giblets_action == pPedestrian->current_action || pPedestrian->actor->model == NULL) {
  1621.         return;
  1622.     }
  1623.     scalar_frame_time = gFrame_period;
  1624.     BrVector3Set(&min_ped_bounds, -0.5f, 0.f, 0.f);
  1625.     BrVector3Set(&max_ped_bounds, 0.5f, 1.f, 0.f);
  1626.     if (pPedestrian->last_special_volume != NULL) {
  1627.         volume_damage = gFrame_period * pPedestrian->last_special_volume->ped_damage_per_ms;
  1628.         if (volume_damage != 0.f
  1629.             && pPedestrian->current_action != pPedestrian->fatal_car_impact_action
  1630.             && pPedestrian->current_action != pPedestrian->fatal_ground_impact_action) {
  1631.             if (volume_damage <= 1.0f) {
  1632.                 volume_damage = 1.0f;
  1633.             }
  1634.             pPedestrian->hit_points -= volume_damage;
  1635.             if (pPedestrian->hit_points <= 0) {
  1636.                 ChangeActionTo(pPedestrian, pPedestrian->fatal_ground_impact_action, 1);
  1637.             }
  1638.         }
  1639.     }
  1640.     for (norman = 0, i = 0; 1; i++) {
  1641.         while (i >= (norman == 0 ? gNum_active_cars : gNum_active_non_cars) && norman < 2) {
  1642.             norman++;
  1643.             i = 0;
  1644.         }
  1645.         if (norman > 1) {
  1646.             pPedestrian->collided_last_time = 0;
  1647.             return;
  1648.         }
  1649.         the_car = (norman == 0 ? (tCollision_info*)gActive_car_list[i] : &gActive_non_car_list[i]->collision_info);
  1650.         if (the_car->doing_nothing_flag && the_car->driver != eDriver_local_human) {
  1651.             continue;
  1652.         }
  1653.         car_actor = the_car->car_master_actor;
  1654.         car_pos = &car_actor->t.t.translate.t;
  1655.         impact_speed = fabsf(the_car->speed);
  1656.         if (BrVector3Dot(&pPedestrian->direction, &the_car->direction) > 0.f
  1657.             && impact_speed < fabsf(pPedestrian->current_speed)) {
  1658.             impact_speed = 0.0f;
  1659.         }
  1660.         distance_squared = Vector3DistanceSquared(ped_pos, car_pos);
  1661.         proximity_rayed = pPedestrian->ref_number < 100
  1662.             && pPedestrian->current_action != pPedestrian->fatal_car_impact_action
  1663.             && pPedestrian->current_action != pPedestrian->fatal_ground_impact_action
  1664.             && the_car->driver > eDriver_non_car
  1665.             && !((tCar_spec*)the_car)->knackered
  1666.             && !gCountdown
  1667.             && distance_squared < ((tCar_spec*)the_car)->proxy_ray_distance;
  1668.         fated = pPedestrian->fate == (tCar_spec*)the_car;
  1669.         if (MAX(scalar_frame_time * impact_speed * scalar_frame_time * impact_speed * 2.f, 1.44f) <= distance_squared && !proximity_rayed && !fated) {
  1670.             continue;
  1671.         }
  1672.         if (car_actor == NULL) {
  1673.             continue;
  1674.         }
  1675.         BrActorToActorMatrix34(&ped_to_car, pPedestrian->actor, car_actor);
  1676.         BrMatrix34ApplyP(&min_ped_bounds_car, &min_ped_bounds, &ped_to_car);
  1677.         BrMatrix34ApplyP(&max_ped_bounds_car, &max_ped_bounds, &ped_to_car);
  1678.         // use gross_dismiss as temporary
  1679.         if (max_ped_bounds_car.v[X] < min_ped_bounds_car.v[X]) {
  1680.             SwapValuesUsingTemporary(max_ped_bounds_car.v[X], min_ped_bounds_car.v[X], gross_dismiss);
  1681.         }
  1682.         if (max_ped_bounds_car.v[Y] < min_ped_bounds_car.v[Y]) {
  1683.             SwapValuesUsingTemporary(max_ped_bounds_car.v[Y], min_ped_bounds_car.v[Y], gross_dismiss);
  1684.         }
  1685.         if (max_ped_bounds_car.v[Z] < min_ped_bounds_car.v[Z]) {
  1686.             SwapValuesUsingTemporary(max_ped_bounds_car.v[Z], min_ped_bounds_car.v[Z], gross_dismiss);
  1687.         }
  1688.         car_bounds_min_x = the_car->bounds[0].min.v[X];
  1689.         car_bounds_max_x = the_car->bounds[0].max.v[X];
  1690.         car_bounds_min_z = the_car->bounds[0].min.v[Z];
  1691.         car_bounds_max_z = the_car->bounds[0].max.v[Z];
  1692.         prev_car_bounds_min_x = car_bounds_min_x - the_car->velocity_car_space.v[X] * scalar_frame_time;
  1693.         prev_car_bounds_max_x = car_bounds_max_x - the_car->velocity_car_space.v[X] * scalar_frame_time;
  1694.         prev_car_bounds_min_z = car_bounds_min_z - the_car->velocity_car_space.v[Z] * scalar_frame_time;
  1695.         prev_car_bounds_max_z = car_bounds_max_z - the_car->velocity_car_space.v[Z] * scalar_frame_time;
  1696.         if (!proximity_rayed) {
  1697.             if (!fated) {
  1698.                 if (the_car->velocity_car_space.v[X] <= 0.0f) {
  1699.                     if (the_car->velocity_car_space.v[Z] <= 0.0f) {
  1700.                         if (max_ped_bounds_car.v[X] <= car_bounds_min_x
  1701.                             || min_ped_bounds_car.v[X] >= prev_car_bounds_max_x
  1702.                             || max_ped_bounds_car.v[Z] <= car_bounds_min_z
  1703.                             || min_ped_bounds_car.v[Z] >= prev_car_bounds_max_z
  1704.                             || (min_ped_bounds_car.v[X] > car_bounds_max_x
  1705.                                 && max_ped_bounds_car.v[Z] < prev_car_bounds_min_z
  1706.                                 && prev_car_bounds_max_x - car_bounds_max_x != 0.0f
  1707.                                 && (prev_car_bounds_min_z - car_bounds_min_z) / (prev_car_bounds_max_x - car_bounds_max_x) > (max_ped_bounds_car.v[Z] - car_bounds_min_z) / (min_ped_bounds_car.v[X] - car_bounds_max_x))
  1708.                             || (max_ped_bounds_car.v[X] < prev_car_bounds_min_x
  1709.                                 && min_ped_bounds_car.v[Z] > car_bounds_max_z
  1710.                                 && car_bounds_min_x - prev_car_bounds_min_x != 0.0f
  1711.                                 && (car_bounds_max_z - prev_car_bounds_max_z) / (car_bounds_min_x - prev_car_bounds_min_x) > (min_ped_bounds_car.v[Z] - prev_car_bounds_max_z) / (max_ped_bounds_car.v[X] - prev_car_bounds_min_x))) {
  1712.                             continue;
  1713.                         }
  1714.                     } else if (max_ped_bounds_car.v[X] <= car_bounds_min_x
  1715.                         || min_ped_bounds_car.v[X] >= prev_car_bounds_max_x
  1716.                         || max_ped_bounds_car.v[Z] <= prev_car_bounds_min_z
  1717.                         || min_ped_bounds_car.v[Z] >= car_bounds_max_z
  1718.                         || (max_ped_bounds_car.v[X] < prev_car_bounds_min_x
  1719.                             && max_ped_bounds_car.v[Z] < car_bounds_min_z
  1720.                             && car_bounds_min_x - prev_car_bounds_min_x != 0.0f
  1721.                             && ((car_bounds_min_z - prev_car_bounds_min_z) / (car_bounds_min_x - prev_car_bounds_min_x) < (max_ped_bounds_car.v[Z] - prev_car_bounds_min_z) / (max_ped_bounds_car.v[X] - prev_car_bounds_min_x)))
  1722.                         || (min_ped_bounds_car.v[X] > car_bounds_max_x
  1723.                             && min_ped_bounds_car.v[Z] > prev_car_bounds_max_z
  1724.                             && prev_car_bounds_max_x - car_bounds_max_x != 0.0f
  1725.                             && (prev_car_bounds_max_z - car_bounds_max_z) / (prev_car_bounds_max_x - car_bounds_max_x) < (min_ped_bounds_car.v[Z] - car_bounds_max_z) / (min_ped_bounds_car.v[X] - car_bounds_max_x))) {
  1726.                         continue;
  1727.                     }
  1728.                 } else if (the_car->velocity_car_space.v[Z] <= 0.0f) {
  1729.                     if (max_ped_bounds_car.v[X] <= prev_car_bounds_min_x
  1730.                         || min_ped_bounds_car.v[X] >= car_bounds_max_x
  1731.                         || max_ped_bounds_car.v[Z] <= car_bounds_min_z
  1732.                         || min_ped_bounds_car.v[Z] >= prev_car_bounds_max_z
  1733.                         || (max_ped_bounds_car.v[X] < car_bounds_min_x
  1734.                             && max_ped_bounds_car.v[Z] < prev_car_bounds_min_z
  1735.                             && prev_car_bounds_min_x - car_bounds_min_x != 0.0f
  1736.                             && (prev_car_bounds_min_z - car_bounds_min_z) / (prev_car_bounds_min_x - car_bounds_min_x) < (max_ped_bounds_car.v[Z] - car_bounds_min_z) / (max_ped_bounds_car.v[X] - car_bounds_min_x))
  1737.                         || (min_ped_bounds_car.v[X] > prev_car_bounds_max_x
  1738.                             && min_ped_bounds_car.v[Z] > car_bounds_max_z
  1739.                             && car_bounds_max_x - prev_car_bounds_max_x != 0.0f
  1740.                             && (car_bounds_max_z - prev_car_bounds_max_z) / (car_bounds_max_x - prev_car_bounds_max_x) < (min_ped_bounds_car.v[Z] - prev_car_bounds_max_z) / (min_ped_bounds_car.v[X] - prev_car_bounds_max_x))) {
  1741.                         continue;
  1742.                     }
  1743.                 } else if (max_ped_bounds_car.v[X] <= prev_car_bounds_min_x
  1744.                     || min_ped_bounds_car.v[X] >= car_bounds_max_x
  1745.                     || max_ped_bounds_car.v[Z] <= prev_car_bounds_min_z
  1746.                     || min_ped_bounds_car.v[Z] >= car_bounds_max_z
  1747.                     || (min_ped_bounds_car.v[X] > prev_car_bounds_max_x
  1748.                         && max_ped_bounds_car.v[Z] < car_bounds_min_z
  1749.                         && car_bounds_max_x - prev_car_bounds_max_x != 0.0f
  1750.                         && (car_bounds_min_z - prev_car_bounds_min_z) / (car_bounds_max_x - prev_car_bounds_max_x) > (max_ped_bounds_car.v[Z] - prev_car_bounds_min_z) / (min_ped_bounds_car.v[X] - prev_car_bounds_max_x))
  1751.                     || (max_ped_bounds_car.v[X] < car_bounds_min_x
  1752.                         && min_ped_bounds_car.v[Z] > prev_car_bounds_max_z
  1753.                         && prev_car_bounds_min_x - car_bounds_min_x != 0.0f
  1754.                         && (prev_car_bounds_max_z - car_bounds_max_z) / (prev_car_bounds_min_x - car_bounds_min_x) > (min_ped_bounds_car.v[Z] - car_bounds_max_z) / (max_ped_bounds_car.v[X] - car_bounds_min_x))) {
  1755.                     continue;
  1756.                 }
  1757.             }
  1758.             proximity_rayed = 0;
  1759.         }
  1760.         if (pPedestrian->fate != (tCar_spec*)the_car
  1761.             && !proximity_rayed
  1762.             && (the_car->bounds[0].max.v[Y] < min_ped_bounds_car.v[Y]
  1763.                 || the_car->bounds[0].min.v[Y] > max_ped_bounds_car.v[Y])) {
  1764.             continue;
  1765.         }
  1766.         pPedestrian->fate = NULL;
  1767.         if (pPedestrian->current_action == pPedestrian->fatal_car_impact_action
  1768.             || pPedestrian->current_action == pPedestrian->fatal_ground_impact_action) {
  1769.             if (pPedestrian->ref_number < 100) {
  1770.                 if (the_car->driver <= 1 || BloodyWheels((tCar_spec*)the_car, (br_vector3*)ped_to_car.m[3], MIN(-pPedestrian->min_x, pPedestrian->max_x), &pPedestrian->actor->t.t.translate.t)) {
  1771.                     if (!orig_gib_flag) {
  1772.                         BurstPedestrian(pPedestrian, impact_speed, 0);
  1773.                     }
  1774.                     pPedestrian->giblets_being_sat_upon = 1;
  1775.                 }
  1776.             }
  1777.             continue;
  1778.         }
  1779.         break;
  1780.     }
  1781.     pPedestrian->killers_ID = the_car->car_ID;
  1782.     ped_centre_x = (max_ped_bounds_car.v[X] + min_ped_bounds_car.v[X]) / 2.0f;
  1783.     ped_centre_y = (max_ped_bounds_car.v[Z] + min_ped_bounds_car.v[Z]) / 2.0f;
  1784.     if (proximity_rayed) {
  1785.         hit_pos = ePed_hit_unknown;
  1786.     } else {
  1787.         hit_pos = MoveToEdgeOfCar(pPedestrian,
  1788.             the_car,
  1789.             car_actor,
  1790.             ped_centre_x,
  1791.             ped_centre_y,
  1792.             car_bounds_min_x,
  1793.             car_bounds_max_x,
  1794.             car_bounds_min_z,
  1795.             car_bounds_max_z,
  1796.             &min_ped_bounds_car,
  1797.             &max_ped_bounds_car);
  1798.         pPedestrian->mid_air = 0;
  1799.     }
  1800.     if (the_car->driver <= eDriver_non_car && the_car->who_last_hit_me != NULL && pPedestrian->ref_number != 114) {
  1801.         the_car = (tCollision_info*)the_car->who_last_hit_me;
  1802.         billiards_shot = 1;
  1803.     }
  1804.     pPedestrian->hit_points -= impact_speed * 35000.0f;
  1805.     if (pPedestrian->hit_points < -99) {
  1806.         pPedestrian->hit_points = -99;
  1807.     }
  1808.     if (impact_speed == 0.0f && !proximity_rayed && !pPedestrian->collided_last_time) {
  1809.         pPedestrian->instruction_direction = -pPedestrian->instruction_direction;
  1810.         gInitial_instruction = 0;
  1811.         PedestrianNextInstruction(pPedestrian, 500.0f, 0, 1);
  1812.         pPedestrian->collided_last_time = 1;
  1813.         return;
  1814.     }
  1815.  
  1816.     pPedestrian->hit_points = -1;
  1817.     if (proximity_rayed || gPed_scale_factor != 1.0f || pPedestrian->ref_number >= 100) {
  1818.         pPedestrian->jump_magnitude = 0.0f;
  1819.     } else {
  1820.         pPedestrian->jump_magnitude = impact_speed * 30.0f;
  1821.     }
  1822.     if (pPedestrian->jump_magnitude > 0.4f) {
  1823.         pPedestrian->jump_magnitude = 0.4f;
  1824.     }
  1825.     pPedestrian->jump_magnitude /= gGravity_multiplier;
  1826.     if (pPedestrian->ref_number < 100 && (gNet_mode == eNet_mode_none || pPedestrian->murderer == -1)) {
  1827.         gProgram_state.peds_killed++;
  1828.     }
  1829.     if (pPedestrian->ref_number < 100 && the_car->driver >= eDriver_net_human) {
  1830.         if (pPedestrian->murderer == -1 && gNet_mode == eNet_mode_host && gCurrent_net_game->type == eNet_game_type_carnage) {
  1831.             NetPlayerFromCar((tCar_spec*)the_car)->score++;
  1832.         }
  1833.         if (gNet_mode != eNet_mode_none) {
  1834.             pPedestrian->murderer = NetPlayerFromCar((tCar_spec*)the_car)->ID;
  1835.         }
  1836.     }
  1837.     if (proximity_rayed) {
  1838.         for (i = 0; i < COUNT_OF(gProximity_rays); ++i) {
  1839.             if (gProximity_rays[i].start_time == 0) {
  1840.                 gProximity_rays[i].start_time = GetTotalTime();
  1841.                 gProximity_rays[i].car = (tCar_spec*)the_car;
  1842.                 gProximity_rays[i].ped = pPedestrian;
  1843.                 if (the_car->driver == eDriver_local_human) {
  1844.                     DRS3StartSound(gCar_outlet, 5500);
  1845.                 } else {
  1846.                     DRS3StartSound3D(
  1847.                         gCar_outlet, 5500, &the_car->pos, &gZero_v__pedestrn,
  1848.                         1, 255, 65536, 65536);
  1849.                 }
  1850.                 break;
  1851.             }
  1852.         }
  1853.     } else {
  1854.         if (FancyATossOffMate(pPedestrian, the_car, impact_speed)) {
  1855.             pPedestrian->mid_air = 1;
  1856.             if (pPedestrian->to_pos.v[Y] < 500.0f) {
  1857.                 pPedestrian->to_pos.v[Y] += 1000.4f;
  1858.             }
  1859.             pPedestrian->falling_speed -= impact_speed * 0.02f;
  1860.             if (pPedestrian->falling_speed > -0.001f) {
  1861.                 pPedestrian->falling_speed = -0.001f;
  1862.             }
  1863.             tossing = 1;
  1864.             pPedestrian->actor->t.t.translate.t.v[Y] += impact_speed * 15.0f;
  1865.             pPedestrian->pos = pPedestrian->actor->t.t.translate.t;
  1866.         } else {
  1867.             pPedestrian->actor->render_style = BR_RSTYLE_NONE;
  1868.             BrActorRelink(car_actor, pPedestrian->actor);
  1869.         }
  1870.         pPedestrian->offset = pPedestrian->actor->t.t.translate.t;
  1871.     }
  1872.     if (proximity_rayed
  1873.         || ((impact_speed < 0.004f || !PercentageChance(50) || gPed_scale_factor != 1.0f) && !tossing)
  1874.         || pPedestrian->ref_number >= 100
  1875.         || gPedestrian_harvest) {
  1876.         pPedestrian->spin_period = 0.0f;
  1877.     } else if (PercentageChance(50)) {
  1878.         pPedestrian->spin_period = FRandomBetween(100.0f, tossing ? 300.f : 2000.f);
  1879.         ;
  1880.     } else {
  1881.         pPedestrian->spin_period = -FRandomBetween(100.0f, tossing ? 300.0f : 2000.f);
  1882.     }
  1883.     if (proximity_rayed || tossing) {
  1884.         ChangeActionTo(pPedestrian, pPedestrian->fatal_ground_impact_action, 1);
  1885.     } else {
  1886.         ChangeActionTo(pPedestrian, pPedestrian->fatal_car_impact_action, 1);
  1887.     }
  1888.     if (pPedestrian->ref_number >= 100) {
  1889.         exploded = 0;
  1890.     } else {
  1891.         exploded = BurstPedestrian(pPedestrian, impact_speed, 1);
  1892.         ReportMurderToPoliceDepartment((tCar_spec*)the_car);
  1893.     }
  1894.     BrVector3Set(&zero_v, 0.f, 0.f, 0.f);
  1895.     if (gNet_mode != eNet_mode_none && gCurrent_net_game->options.powerup_respawn && pPedestrian->ref_number >= 100) {
  1896.         pPedestrian->respawn_time = GetRaceTime() + IRandomBetween(0, gRespawn_variance) + gMin_respawn_time;
  1897.     }
  1898.     if (the_car->driver != eDriver_local_human || gRace_finished || pPedestrian->ref_number >= 100) {
  1899.         DRS3StartSound3D(
  1900.             gPedestrians_outlet,
  1901.             pPedestrian->exploding_sounds[IRandomBetween(0, pPedestrian->number_of_exploding_sounds - 1)],
  1902.             &pPedestrian->pos,
  1903.             &zero_v,
  1904.             1,
  1905.             255,
  1906.             65536,
  1907.             65536);
  1908.         if ((the_car->driver == eDriver_local_human || pPedestrian->ref_number == 114) && !gRace_finished && !billiards_shot) {
  1909.             GotPowerup((tCar_spec*)the_car, pPedestrian->ref_number - 100);
  1910.         }
  1911.     } else {
  1912.         PipeSinglePedIncident(pPedestrian - gPedestrian_array, car_actor);
  1913.         AwardTime(gPed_time_value[gProgram_state.skill_level]);
  1914.         if (the_time - gLast_ped_splat_time > 1000) {
  1915.             gCurrent_ped_multiplier = 1;
  1916.         } else if (gCurrent_ped_multiplier < 5) {
  1917.             gCurrent_ped_multiplier++;
  1918.         }
  1919.         gLast_ped_splat_time = the_time;
  1920.         credits_value = pPedestrian->credits_value;
  1921.         credits_value *= gCurrent_ped_multiplier;
  1922.         if (exploded) {
  1923.             credits_value *= 2;
  1924.         }
  1925.         BrVector3Set(&up, 0.f, 1.f, 0.f);
  1926.         if (billiards_shot) {
  1927.             credits_value *= 4;
  1928.             PratcamEvent(30);
  1929.             DoFancyHeadup(kFancyHeadupNiceShotSir);
  1930.         } else if (fabsf(the_car->omega.v[X]) <= 5.0f
  1931.             && fabsf(the_car->omega.v[Z]) <= 5.0f
  1932.             && BrVector3Dot(&the_car->car_master_actor->t.t.look_up.up, &up) >= 0.1f
  1933.             && pPedestrian->offset.v[1] >= -0.1f) {
  1934.             if (((hit_pos != ePed_hit_lside && hit_pos != ePed_hit_rside)
  1935.                     || (fabsf(the_car->velocity_car_space.v[X]) <= fabsf(the_car->velocity_car_space.v[Z])
  1936.                         && fabsf(the_car->omega.v[Y] / the_car->velocity_car_space.v[Z]) <= 600.0f))
  1937.                 && (hit_pos != ePed_hit_back || the_car->velocity_car_space.v[Z] <= 0.0f)) {
  1938.                 if (gCurrent_ped_multiplier >= 2) {
  1939.                     DoFancyHeadup(gCurrent_ped_multiplier + kFancyHeadup2xComboBonus - 2);
  1940.                 } else {
  1941.                     PratcamEvent(30);
  1942.                     if (exploded) {
  1943.                         DoFancyHeadup(kFancyHeadupSplatterBonus);
  1944.                         PratcamEvent(30);
  1945.                     }
  1946.                 }
  1947.             } else {
  1948.                 credits_value *= 2;
  1949.                 DoFancyHeadup(kFancyHeadupExtraStyleBonus);
  1950.             }
  1951.         } else {
  1952.             credits_value *= 4;
  1953.             PratcamEvent(30);
  1954.             DoFancyHeadup(kFancyHeadupBonusForArtisticImpression);
  1955.         }
  1956.         PratcamEvent(29);
  1957.         EarnCredits(credits_value);
  1958.     }
  1959.     if (the_car->driver == eDriver_local_human && gProgram_state.cockpit_on) {
  1960.         NewScreenWobble(FRandomBetween(300.f * impact_speed, 500.f * impact_speed),
  1961.             FRandomBetween(1000.f * impact_speed, 2000.f * impact_speed),
  1962.             FRandomBetween(15.f / impact_speed, 25.f / impact_speed));
  1963.     }
  1964.     if (!gRace_finished) {
  1965.         CheckLastPed();
  1966.     }
  1967.     pPedestrian->collided_last_time = 1;
  1968. }
  1969.  
  1970. // IDA: void __usercall SendPedestrian(tPedestrian_data *pPedestrian@<EAX>, int pIndex@<EDX>)
  1971. void SendPedestrian(tPedestrian_data* pPedestrian, int pIndex) {
  1972.     tNet_contents* the_contents;
  1973.     tNet_message* the_message;
  1974.     int size_decider;
  1975.     LOG_TRACE("(%p, %d)", pPedestrian, pIndex);
  1976.  
  1977.     if (!gSend_peds) {
  1978.         return;
  1979.     }
  1980.     if (pPedestrian->ref_number >= 100 && pPedestrian->hit_points >= 1) {
  1981.         return;
  1982.     }
  1983.     if (pPedestrian->sent_dead_message >= 4) {
  1984.         return;
  1985.     }
  1986.     if (pPedestrian->hit_points >= 0 || pPedestrian->hit_points == -100) {
  1987.         if (Vector3AreEqual(&pPedestrian->instruction_list[pPedestrian->current_instruction].data.point_data.position, &pPedestrian->to_pos)) {
  1988.             size_decider = 0;
  1989.         } else {
  1990.             size_decider = 1;
  1991.         }
  1992.         the_message = NULL;
  1993.         the_contents = NetGetBroadcastContents(NETMSGID_PEDESTRIAN, size_decider);
  1994.     } else {
  1995.         size_decider = 2;
  1996.         if (pPedestrian->current_frame == pPedestrian->sequences[pPedestrian->current_sequence].number_of_frames - 1) {
  1997.             pPedestrian->sent_dead_message++;
  1998.         }
  1999.         the_message = NetBuildMessage(NETMSGID_PEDESTRIAN, size_decider);
  2000.         the_contents = &the_message->contents;
  2001.     }
  2002.     the_contents->data.pedestrian.index = pIndex;
  2003.     the_contents->data.pedestrian.action_instruction = (pPedestrian->current_instruction << 4) + pPedestrian->current_action + 1;
  2004.     the_contents->data.pedestrian.flags = 0;
  2005.     if (pPedestrian->done_initial) {
  2006.         the_contents->data.pedestrian.flags |= 0x01;
  2007.     }
  2008.     if (pPedestrian->mid_air) {
  2009.         the_contents->data.pedestrian.flags |= 0x02;
  2010.     }
  2011.     if (pPedestrian->instruction_direction < 0) {
  2012.         the_contents->data.pedestrian.flags |= 0x04;
  2013.     }
  2014.     if (pPedestrian->hit_points == -100) {
  2015.         the_contents->data.pedestrian.flags |= 0x10;
  2016.     } else if (pPedestrian->hit_points < 0) {
  2017.         the_contents->data.pedestrian.flags |= 0x08;
  2018.     }
  2019.     if (size_decider != 0) {
  2020.         the_contents->data.pedestrian.flags |= 0x20;
  2021.     }
  2022.     if (size_decider == 2) {
  2023.         the_contents->data.pedestrian.flags |= 0x40;
  2024.     }
  2025.     the_contents->data.pedestrian.pos = pPedestrian->pos;
  2026.     the_contents->data.pedestrian.speed = pPedestrian->current_speed;
  2027.     if (size_decider != 0) {
  2028.         the_contents->data.pedestrian.to_pos = pPedestrian->to_pos;
  2029.         if (size_decider == 2) {
  2030.             the_contents->data.pedestrian.frame = pPedestrian->current_frame;
  2031.             the_contents->data.pedestrian.offset = pPedestrian->offset;
  2032.             the_contents->data.pedestrian.murderer = pPedestrian->murderer;
  2033.             if (pPedestrian->ref_number < 100) {
  2034.                 the_contents->data.pedestrian.respawn_time_or_spin_period = pPedestrian->spin_period;
  2035.             } else {
  2036.                 the_contents->data.pedestrian.respawn_time_or_spin_period = pPedestrian->respawn_time;
  2037.             }
  2038.         }
  2039.     }
  2040.     if (the_message != NULL) {
  2041.         NetGuaranteedSendMessageToAllPlayers(gCurrent_net_game, the_message, NULL);
  2042.     }
  2043. }
  2044.  
  2045. // IDA: void __usercall DoPedestrian(tPedestrian_data *pPedestrian@<EAX>, int pIndex@<EDX>)
  2046. void DoPedestrian(tPedestrian_data* pPedestrian, int pIndex) {
  2047.     //float danger_level; // Pierre-Marie Baty -- unused variable
  2048.     float start_speed;
  2049.     int action_changed;
  2050.     int alive;
  2051.     int old_frame;
  2052.     int start_ins;
  2053.     int start_act;
  2054.     int start_hp;
  2055.     int start_ins_dir;
  2056.     //br_vector3 danger_direction; // Pierre-Marie Baty -- unused variable
  2057.     br_vector3 old_pos;
  2058.     LOG_TRACE("(%p, %d)", pPedestrian, pIndex);
  2059.  
  2060.     pPedestrian->active = 1;
  2061.     pPedestrian->munged = 1;
  2062.     if (pPedestrian->done_initial
  2063.         && pPedestrian->sequences[pPedestrian->current_sequence].number_of_frames == pPedestrian->sequences[pPedestrian->current_sequence].looping_frame_start) {
  2064.         pPedestrian->done_initial = 0;
  2065.     }
  2066.     if (gAction_replay_mode) {
  2067.         old_frame = pPedestrian->current_frame;
  2068.         pPedestrian->car_to_ped = FastScalarArcTan2(
  2069.             pPedestrian->pos.v[X] - gCamera_to_world.m[3][X],
  2070.             pPedestrian->pos.v[Z] - gCamera_to_world.m[3][Z]);
  2071.         MungePedestrianSequence(pPedestrian, 0);
  2072.         if (old_frame <= pPedestrian->sequences[pPedestrian->current_sequence].number_of_frames) {
  2073.             pPedestrian->current_frame = old_frame;
  2074.         } else {
  2075.             pPedestrian->current_frame = 0;
  2076.         }
  2077.         pPedestrian->colour_map = pPedestrian->sequences[MAX(pPedestrian->current_sequence, 0)].frames[MAX(pPedestrian->current_frame, 0)].pixelmap;
  2078.         gCurrent_lollipop_index = -1;
  2079.         MungePedModel(pPedestrian);
  2080.     } else {
  2081.         old_pos = pPedestrian->pos;
  2082.         start_speed = pPedestrian->current_speed;
  2083.         start_ins = pPedestrian->current_instruction;
  2084.         start_act = pPedestrian->current_action;
  2085.         start_hp = pPedestrian->hit_points;
  2086.         start_ins_dir = pPedestrian->instruction_direction;
  2087.         alive = pPedestrian->current_action != pPedestrian->fatal_car_impact_action
  2088.             && pPedestrian->current_action != pPedestrian->fatal_ground_impact_action
  2089.             && pPedestrian->current_action != pPedestrian->giblets_action;
  2090.         if (alive && pPedestrian->ref_number < 100) {
  2091.             gDanger_level = CalcPedestrianDangerLevel(pPedestrian, &gDanger_direction);
  2092.             action_changed = MungePedestrianAction(pPedestrian, gDanger_level);
  2093.         } else {
  2094.             action_changed = 0;
  2095.         }
  2096.         MungePedestrianSequence(pPedestrian, action_changed);
  2097.         MungePedestrianFrames(pPedestrian);
  2098.         if (pPedestrian->ref_number < 100) {
  2099.             MungePedestrianPath(pPedestrian, gDanger_level, &gDanger_direction);
  2100.             if (Vector3AreEqual(&pPedestrian->pos, &old_pos)
  2101.                 && (gReally_stupid_ped_bug_enable || (pPedestrian->actor->parent == gDont_render_actor && pPedestrian->done_initial && pPedestrian->sequences[pPedestrian->current_sequence].frame_rate_type == ePed_frame_speed))) {
  2102.                 ChangeActionTo(pPedestrian, 0, 0);
  2103.             }
  2104.         }
  2105.         MungePedModel(pPedestrian);
  2106.         if (pPedestrian->current_action != pPedestrian->giblets_action) {
  2107.             CheckPedestrianDeathScenario(pPedestrian);
  2108.         }
  2109.         SetPedPos(pPedestrian);
  2110.         if (IsActionReplayAvailable()) {
  2111.             AddPedestrianToPipingSession(pIndex,
  2112.                 &pPedestrian->actor->t.t.mat,
  2113.                 pPedestrian->current_action,
  2114.                 pPedestrian->current_frame,
  2115.                 pPedestrian->hit_points,
  2116.                 pPedestrian->done_initial,
  2117.                 pPedestrian->actor->parent != gDont_render_actor ? pPedestrian->killers_ID : -1,
  2118.                 pPedestrian->spin_period,
  2119.                 pPedestrian->jump_magnitude,
  2120.                 &pPedestrian->offset);
  2121.         }
  2122.         if (gNet_mode != eNet_mode_none && !pPedestrian->reverse_frames
  2123.             && !(Vector3AreEqual(&pPedestrian->pos, &old_pos)
  2124.                 && pPedestrian->current_speed == start_speed
  2125.                 && pPedestrian->current_instruction == start_ins
  2126.                 && pPedestrian->current_action == start_act
  2127.                 && pPedestrian->hit_points == start_hp
  2128.                 && pPedestrian->instruction_direction == start_ins_dir)) {
  2129.             SendPedestrian(pPedestrian, pIndex);
  2130.         }
  2131.     }
  2132. }
  2133.  
  2134. // IDA: void __usercall AdjustPedestrian(int pIndex@<EAX>, int pAction_index@<EDX>, int pFrame_index@<EBX>, int pHit_points@<ECX>, int pDone_initial, tU16 pParent, br_actor *pParent_actor, float pSpin_period, br_scalar pJump_magnitude, br_vector3 *pOffset, br_vector3 *pTrans)
  2135. void AdjustPedestrian(int pIndex, int pAction_index, int pFrame_index, int pHit_points, int pDone_initial, tU16 pParent, br_actor* pParent_actor, float pSpin_period, br_scalar pJump_magnitude, br_vector3* pOffset, br_vector3* pTrans) {
  2136.     tPedestrian_data* pedestrian;
  2137.     br_actor* parent;
  2138.     br_vector3 old_pos;
  2139.     LOG_TRACE("(%d, %d, %d, %d, %d, %d, %p, %f, %f, %p, %p)", pIndex, pAction_index, pFrame_index, pHit_points, pDone_initial, pParent, pParent_actor, pSpin_period, pJump_magnitude, pOffset, pTrans);
  2140.  
  2141.     pedestrian = &gPedestrian_array[pIndex];
  2142.     if (pAction_index < 0 || pAction_index >= pedestrian->number_of_actions) {
  2143.         pAction_index = 0;
  2144.     }
  2145.     pedestrian->current_action = pAction_index;
  2146.     pedestrian->hit_points = pHit_points;
  2147.     pedestrian->done_initial = pDone_initial;
  2148.     old_pos = pedestrian->actor->t.t.translate.t;
  2149.     parent = pedestrian->actor->parent;
  2150.     if (pParent == (tU16)-1) {
  2151.         if (parent != gDont_render_actor) {
  2152.             BrActorRelink(gDont_render_actor, pedestrian->actor);
  2153.         }
  2154.         pedestrian->actor->render_style = BR_RSTYLE_NONE;
  2155.     } else {
  2156.         if (parent != pParent_actor) {
  2157.             BrActorRelink(pParent_actor, pedestrian->actor);
  2158.         }
  2159.         pedestrian->actor->render_style = BR_RSTYLE_NONE;
  2160.     }
  2161.     if (pHit_points > 0) {
  2162.         pedestrian->spin_period = 0.f;
  2163.         pedestrian->jump_magnitude = 0.f;
  2164.         BrVector3Set(&pedestrian->offset, 0.f, 0.f, 0.f);
  2165.     } else {
  2166.         pedestrian->spin_period = pSpin_period;
  2167.         pedestrian->jump_magnitude = pJump_magnitude;
  2168.         pedestrian->offset = *pOffset;
  2169.     }
  2170.     if (pedestrian->hit_points == -100) {
  2171.         pedestrian->actor->render_style = BR_RSTYLE_NONE;
  2172.     }
  2173.     pedestrian->actor->t.t.translate.t = *pTrans;
  2174.     SetPedPos(pedestrian);
  2175.     if (pFrame_index >= pedestrian->sequences[pedestrian->current_sequence].number_of_frames || pFrame_index < 0) {
  2176.         pFrame_index = 0;
  2177.     }
  2178.     pedestrian->current_frame = pFrame_index;
  2179.     BrVector3Sub(&pedestrian->direction, &pedestrian->actor->t.t.translate.t, &old_pos);
  2180.     BrVector3Normalise(&pedestrian->direction, &pedestrian->direction);
  2181.     if (GetReplayRate() < 0.f) {
  2182.         BrVector3Scale(&pedestrian->direction, &pedestrian->direction, -1.f);
  2183.     }
  2184.     MungePedestrianSequence(pedestrian, 0);
  2185. }
  2186.  
  2187. // IDA: void __usercall SquirtPathVertex(br_vertex *pFirst_vertex@<EAX>, br_vector3 *pPoint@<EDX>)
  2188. void SquirtPathVertex(br_vertex* pFirst_vertex, br_vector3* pPoint) {
  2189.     LOG_TRACE("(%p, %p)", pFirst_vertex, pPoint);
  2190.  
  2191.     pFirst_vertex[0].p = *pPoint;
  2192.     pFirst_vertex[1].p = *pPoint;
  2193.     pFirst_vertex[1].p.v[Y] += .1f;
  2194.     pFirst_vertex[2].p = *pPoint;
  2195.     pFirst_vertex[2].p.v[X] += -.05f;
  2196.     pFirst_vertex[2].p.v[Y] += .05f;
  2197.     pFirst_vertex[2].p.v[Z] += -.05f;
  2198.     pFirst_vertex[3].p = *pPoint;
  2199.     pFirst_vertex[3].p.v[X] += .05f;
  2200.     pFirst_vertex[3].p.v[Y] += .05f;
  2201.     pFirst_vertex[3].p.v[Z] += .05f;
  2202. }
  2203.  
  2204. // IDA: void __cdecl ResetAllPedestrians()
  2205. void ResetAllPedestrians(void) {
  2206.     int i;
  2207.     tPedestrian_data* the_pedestrian;
  2208.     LOG_TRACE("()");
  2209.  
  2210.     for (i = 0; i < gPed_count; i++) {
  2211.         the_pedestrian = &gPedestrian_array[i];
  2212.         the_pedestrian->actor->render_style = BR_RSTYLE_NONE;
  2213.     }
  2214. }
  2215.  
  2216. // IDA: void __usercall GroundPedestrian(tPedestrian_data *pPedestrian@<EAX>)
  2217. void GroundPedestrian(tPedestrian_data* pPedestrian) {
  2218.     br_scalar new_y;
  2219.     br_vector3 cast_point;
  2220.     tPedestrian_sequence* sequence;
  2221.     LOG_TRACE("(%p)", pPedestrian);
  2222.  
  2223.     if (pPedestrian->actor->parent != gDont_render_actor) {
  2224.         pPedestrian->actor->render_style = BR_RSTYLE_NONE;
  2225.         BrActorRelink(gDont_render_actor, pPedestrian->actor);
  2226.     }
  2227.     pPedestrian->mid_air = 0;
  2228.     BrVector3Set(&cast_point,
  2229.         pPedestrian->pos.v[X],
  2230.         pPedestrian->pos.v[Y] + 0.4f,
  2231.         pPedestrian->pos.v[Z]);
  2232.     new_y = FindYVerticallyBelow2(&cast_point);
  2233.     pPedestrian->actor->t.t.translate.t.v[Y] = pPedestrian->pos.v[Y] = new_y;
  2234.     pPedestrian->spin_period = 0.f;
  2235.     sequence = &pPedestrian->sequences[pPedestrian->current_sequence];
  2236.     if (sequence->number_of_frames == sequence->looping_frame_start) {
  2237.         pPedestrian->current_frame = sequence->number_of_frames - 1;
  2238.         pPedestrian->done_initial = 0;
  2239.     } else {
  2240.         pPedestrian->current_frame = sequence->looping_frame_start;
  2241.         pPedestrian->done_initial = 1;
  2242.     }
  2243.     BrVector3Set(&pPedestrian->offset, 0.f, 0.f, 0.f);
  2244.     if (IsActionReplayAvailable()) {
  2245.         AddPedestrianToPipingSession(GET_PEDESTRIAN_INDEX(pPedestrian),
  2246.             &pPedestrian->actor->t.t.mat,
  2247.             pPedestrian->current_action,
  2248.             pPedestrian->current_frame,
  2249.             pPedestrian->hit_points,
  2250.             pPedestrian->done_initial,
  2251.             pPedestrian->actor->parent == gDont_render_actor ? -1 : pPedestrian->killers_ID,
  2252.             pPedestrian->spin_period,
  2253.             pPedestrian->jump_magnitude,
  2254.             &pPedestrian->offset);
  2255.     }
  2256. }
  2257.  
  2258. // IDA: void __usercall RevivePedestrian(tPedestrian_data *pPedestrian@<EAX>, int pAnimate@<EDX>)
  2259. void RevivePedestrian(tPedestrian_data* pPedestrian, int pAnimate) {
  2260.     LOG_TRACE("(%p, %d)", pPedestrian, pAnimate);
  2261.  
  2262.     pPedestrian->sent_dead_message = 0;
  2263.     pPedestrian->respawn_time = 0;
  2264.     pPedestrian->current_sequence = 0;
  2265.     if (pAnimate) {
  2266.         if (pPedestrian->fatal_ground_impact_action >= 0) {
  2267.             pPedestrian->current_action = pPedestrian->fatal_ground_impact_action;
  2268.         } else {
  2269.             pPedestrian->current_action = pPedestrian->fatal_car_impact_action;
  2270.         }
  2271.         MungePedestrianSequence(pPedestrian, 1);
  2272.         pPedestrian->current_frame = pPedestrian->sequences[pPedestrian->current_sequence].number_of_frames - 1;
  2273.         pPedestrian->reverse_frames = 1;
  2274.         MungePedestrianFrames(pPedestrian);
  2275.     } else {
  2276.         pPedestrian->current_action = 0;
  2277.         pPedestrian->current_frame = 0;
  2278.         pPedestrian->colour_map = pPedestrian->sequences->frames[0].pixelmap;
  2279.         pPedestrian->reverse_frames = 0;
  2280.     }
  2281.     pPedestrian->current_action_mode = -1;
  2282.     pPedestrian->done_initial = 0;
  2283.     pPedestrian->current_speed = 0.f;
  2284.     pPedestrian->instruction_direction = 1;
  2285.     pPedestrian->spin_period = 0.f;
  2286.     pPedestrian->falling_speed = 0.f;
  2287.     pPedestrian->mid_air = 0;
  2288.     pPedestrian->last_special_volume = NULL;
  2289.     pPedestrian->last_sound = 0;
  2290.     pPedestrian->giblets_being_sat_upon = 0;
  2291.     pPedestrian->last_sound_action = -1;
  2292.     pPedestrian->last_sound_make = 0;
  2293.     pPedestrian->hit_points = 10;
  2294.     pPedestrian->current_instruction = pPedestrian->first_instruction;
  2295.     pPedestrian->killers_ID = -1;
  2296.     pPedestrian->fate = NULL;
  2297.     gInitial_instruction = NULL;
  2298.     PedestrianNextInstruction(pPedestrian, 0.f, 1, 0);
  2299.     BrVector3Copy(&pPedestrian->from_pos, &pPedestrian->actor->t.t.translate.t);
  2300.     MungePedModel(pPedestrian);
  2301.     pPedestrian->pos.v[Y] += pPedestrian->sequences[pPedestrian->current_sequence].frames[0].offset.v[Y];
  2302. }
  2303.  
  2304. // IDA: void __usercall MungePedestrians(tU32 pFrame_period@<EAX>)
  2305. void MungePedestrians(tU32 pFrame_period) {
  2306.     int i;
  2307.     //int mirror_on; // Pierre-Marie Baty -- unused variable
  2308.     tPedestrian_data* the_pedestrian;
  2309.     //br_vector3 ped_pos; // Pierre-Marie Baty -- unused variable
  2310.     //br_vector3 ped_pos_car; // Pierre-Marie Baty -- unused variable
  2311.     //br_vector3 ped_pos_temp; // Pierre-Marie Baty -- unused variable
  2312.     //br_matrix34 ped_pos_matrix; // Pierre-Marie Baty -- unused variable
  2313.     //br_camera* camera_ptr; // Pierre-Marie Baty -- unused variable
  2314.     //br_scalar max_distance; // Pierre-Marie Baty -- unused variable
  2315.     //br_scalar distance_squared; // Pierre-Marie Baty -- unused variable
  2316.     br_scalar x_delta;
  2317.     //br_scalar y_delta; // Pierre-Marie Baty -- unused variable
  2318.     br_scalar z_delta;
  2319.     tS32 diff;
  2320.     LOG_TRACE("(%d)", pFrame_period);
  2321.  
  2322.     gVesuvians_this_time = 0;
  2323.     // dword_550A9C = 32;
  2324.     gMax_distance_squared = 121.f;
  2325.     if (!gAction_replay_mode) {
  2326.         MungePedGibs(pFrame_period);
  2327.     }
  2328.     if (!gAction_replay_mode) {
  2329.         StartPipingSession(ePipe_chunk_pedestrian);
  2330.     }
  2331.     gSend_peds = PDGetTotalTime() - gLast_ped_message_send >= 50;
  2332.     if (gSend_peds) {
  2333.         gLast_ped_message_send = PDGetTotalTime();
  2334.     }
  2335.     // BrVector3(&br_vector3_00550ac0, 0.f, 0.f, 0.f);
  2336.     if (gAction_replay_mode) {
  2337.         for (i = 0; i < gPed_count; i++) {
  2338.             the_pedestrian = &gPedestrian_array[i];
  2339.             x_delta = fabsf(the_pedestrian->pos.v[X] - gCamera_to_world.m[3][X]);
  2340.             z_delta = fabsf(the_pedestrian->pos.v[Z] - gCamera_to_world.m[3][Z]);
  2341.             if ((the_pedestrian->actor->parent != gDont_render_actor || (x_delta <= ACTIVE_PED_DXDZ && z_delta <= ACTIVE_PED_DXDZ))
  2342.                 && (gPedestrians_on || the_pedestrian->ref_number >= 100)
  2343.                 && the_pedestrian->hit_points != -100) {
  2344.                 gCurrent_lollipop_index = -1;
  2345.                 DoPedestrian(the_pedestrian, i);
  2346.             }
  2347.         }
  2348.     } else {
  2349.         for (i = 0; i < gPed_count; i++) {
  2350.             the_pedestrian = &gPedestrian_array[i];
  2351.             x_delta = fabsf(the_pedestrian->pos.v[X] - gCamera_to_world.m[3][X]);
  2352.             z_delta = fabsf(the_pedestrian->pos.v[Z] - gCamera_to_world.m[3][Z]);
  2353.             if (the_pedestrian->actor->parent == gDont_render_actor
  2354.                 && (x_delta > ACTIVE_PED_DXDZ || z_delta > ACTIVE_PED_DXDZ)) {
  2355.                 the_pedestrian->active = 0;
  2356.             } else if (the_pedestrian->hit_points == -100) {
  2357.                 if (the_pedestrian->respawn_time == 0) {
  2358.                     if (the_pedestrian->mid_air || the_pedestrian->actor->parent != gDont_render_actor) {
  2359.                         KillPedestrian(the_pedestrian);
  2360.                     }
  2361.                     the_pedestrian->active = 0;
  2362.                 } else {
  2363.                     diff = GetRaceTime() - the_pedestrian->respawn_time;
  2364.                     if (diff >= 0) {
  2365.                         RevivePedestrian(the_pedestrian, diff < 1000);
  2366.                     } else {
  2367.                         if (the_pedestrian->mid_air || the_pedestrian->actor->parent != gDont_render_actor) {
  2368.                             KillPedestrian(the_pedestrian);
  2369.                         }
  2370.                         the_pedestrian->active = 0;
  2371.                     }
  2372.                 }
  2373.             } else if (!gPedestrians_on && the_pedestrian->ref_number < 100) {
  2374.                 if (the_pedestrian->mid_air || the_pedestrian->actor->parent != gDont_render_actor) {
  2375.                     KillPedestrian(the_pedestrian);
  2376.                 }
  2377.                 the_pedestrian->active = 0;
  2378.             } else if (!the_pedestrian->mid_air || the_pedestrian->active) {
  2379.                 gCurrent_lollipop_index = -1;
  2380.                 DoPedestrian(the_pedestrian, i);
  2381.             } else {
  2382.                 GroundPedestrian(the_pedestrian);
  2383.             }
  2384.         }
  2385.     }
  2386.     if (!gAction_replay_mode) {
  2387.         EndPipingSession();
  2388.     }
  2389.     gVesuvians_last_time = gVesuvians_this_time;
  2390.     if (gCurrent_ped_path_actor != NULL) {
  2391.         SquirtPathVertex(&gCurrent_ped_path_actor->model->vertices[gCurrent_ped_path_actor->model->nvertices - 4],
  2392.             gOur_pos);
  2393.         BrModelUpdate(gCurrent_ped_path_actor->model, BR_MODU_ALL);
  2394.     }
  2395. }
  2396.  
  2397. // IDA: void __cdecl RespawnPedestrians()
  2398. void RespawnPedestrians(void) {
  2399.     int i;
  2400.     tPedestrian_data* the_pedestrian;
  2401.     LOG_TRACE("()");
  2402.  
  2403.     for (i = 0; i < gPed_count; i++) {
  2404.         the_pedestrian = &gPedestrian_array[i];
  2405.         if (the_pedestrian->ref_number < 100) {
  2406. #if defined(DETHRACE_FIX_BUGS)
  2407.             // Only animate the respawn when we are in viewing distance.
  2408.             // This is done such that the "Peds visible on map" powerup draws far away items.
  2409.             // (far away animated pedestrians would otherwise remain invisible on the map)
  2410.             br_scalar x_delta;
  2411.             br_scalar z_delta;
  2412.             int ped_respawn_animate;
  2413.             x_delta = fabsf(the_pedestrian->pos.v[X] - gCamera_to_world.m[3][X]);
  2414.             z_delta = fabsf(the_pedestrian->pos.v[Z] - gCamera_to_world.m[3][Z]);
  2415.             ped_respawn_animate = x_delta <= ACTIVE_PED_DXDZ && z_delta <= ACTIVE_PED_DXDZ;
  2416. #else
  2417. #define ped_respawn_animate 1
  2418. #endif
  2419.             if (the_pedestrian->hit_points == -100) {
  2420.                 RevivePedestrian(the_pedestrian, ped_respawn_animate);
  2421.             } else if ((the_pedestrian->current_action == the_pedestrian->fatal_car_impact_action || the_pedestrian->current_action == the_pedestrian->fatal_ground_impact_action || the_pedestrian->current_action == the_pedestrian->giblets_action)
  2422.                 && the_pedestrian->actor->parent == gDont_render_actor) {
  2423.                 RevivePedestrian(the_pedestrian, ped_respawn_animate);
  2424.             }
  2425.         }
  2426.     }
  2427. }
  2428.  
  2429. // IDA: int __cdecl GetPedCount()
  2430. int GetPedCount(void) {
  2431.     LOG_TRACE("()");
  2432.  
  2433.     return gPed_count;
  2434. }
  2435.  
  2436. // IDA: int __usercall GetPedPosition@<EAX>(int pIndex@<EAX>, br_vector3 *pPos@<EDX>)
  2437. int GetPedPosition(int pIndex, br_vector3* pPos) {
  2438.     tPedestrian_data* pedestrian;
  2439.     LOG_TRACE("(%d, %p)", pIndex, pPos);
  2440.  
  2441.     pedestrian = &gPedestrian_array[pIndex];
  2442.     if (pedestrian->ref_number < 100) {
  2443.  
  2444.         // Item is a human
  2445.         if (pedestrian->hit_points == -100
  2446.             || pedestrian->current_action == pedestrian->fatal_car_impact_action
  2447.             || pedestrian->current_action == pedestrian->fatal_ground_impact_action
  2448.             || pedestrian->current_action == pedestrian->giblets_action) {
  2449.             return 0;
  2450.         } else {
  2451.             BrVector3Copy(pPos, &pedestrian->pos);
  2452.             return 1;
  2453.         }
  2454.     } else {
  2455.         // Item is a power-up/mine
  2456.         if (pedestrian->hit_points == -100) {
  2457.             return 0;
  2458.         } else {
  2459.             BrVector3Copy(pPos, &pedestrian->pos);
  2460.             return -1;
  2461.         }
  2462.     }
  2463. }
  2464.  
  2465. // IDA: void __usercall CreatePedestrian(FILE *pG@<EAX>, tPedestrian_instruction *pInstructions@<EDX>, int pInstruc_count@<EBX>, int pInit_instruc@<ECX>, int pRef_num, int pForce_read)
  2466. void CreatePedestrian(FILE* pG, tPedestrian_instruction* pInstructions, int pInstruc_count, int pInit_instruc, int pRef_num, int pForce_read) {
  2467.     tPath_name the_path;
  2468.     char s[256];
  2469.     char s2[256];
  2470.     char* str;
  2471.     char* str2;
  2472.     tPedestrian_data* the_pedestrian;
  2473.     tPedestrian_sequence* the_sequence;
  2474.     tPedestrian_action* the_action;
  2475.     //br_model* the_model; // Pierre-Marie Baty -- unused variable
  2476.     int the_ref;
  2477.     int i;
  2478.     int j;
  2479.     int k;
  2480.     //int l; // Pierre-Marie Baty -- unused variable
  2481.     //int temp_int; // Pierre-Marie Baty -- unused variable
  2482.     int new_frames;
  2483.     tPed_collide_type collide_frame;
  2484.     float temp_float1;
  2485.     float temp_float2;
  2486.     br_scalar height;
  2487.     br_scalar width_over_2;
  2488.     br_scalar minnest_min;
  2489.     br_scalar maxest_min;
  2490.     br_scalar minnest_max;
  2491.     br_scalar maxest_max;
  2492.     LOG_TRACE("(%p, %p, %d, %d, %d, %d)", pG, pInstructions, pInstruc_count, pInit_instruc, pRef_num, pForce_read);
  2493.  
  2494.     PossibleService();
  2495.     the_pedestrian = &gPedestrian_array[gPed_count];
  2496.     gPed_count++;
  2497.     the_pedestrian->ref_number = pRef_num;
  2498.     the_pedestrian->magic_number = PEDESTRIAN_MAGIC;
  2499.     the_pedestrian->cloned = 0;
  2500.     if (!pForce_read) {
  2501.         for (i = 0; i < gPed_count - 1; i++) {
  2502.             if (gPedestrian_array[i].ref_number == the_pedestrian->ref_number) {
  2503.                 *the_pedestrian = gPedestrian_array[i];
  2504.                 the_pedestrian->cloned = 1;
  2505.                 break;
  2506.             }
  2507.         }
  2508.     }
  2509.     the_pedestrian->actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
  2510.     the_pedestrian->actor->render_style = BR_RSTYLE_NONE;
  2511.     the_pedestrian->actor->type_data = the_pedestrian;
  2512.     BrActorAdd(gDont_render_actor, the_pedestrian->actor);
  2513.     the_pedestrian->actor->model = gPed_model;
  2514.     if (the_pedestrian->cloned) {
  2515.         the_pedestrian->actor->material = gPed_material;
  2516.     } else {
  2517.         rewind(pG);
  2518.         do {
  2519.             GetALineAndDontArgue(pG, s);
  2520.             str = strtok(s, "\t ,/");
  2521.             sscanf(str, "%d", &the_ref);
  2522.             if (the_pedestrian->ref_number != the_ref) {
  2523.                 while (1) {
  2524.                     PossibleService();
  2525.                     GetALineAndDontArgue(pG, s);
  2526.                     if (strcmp(s, "END OF PEDESTRIANS") == 0) {
  2527.                         BrActorRemove(the_pedestrian->actor);
  2528.                         BrActorFree(the_pedestrian->actor);
  2529.                         gPed_count--;
  2530.                         DRS3StartSound(gEffects_outlet, 3100);
  2531.                         return;
  2532.                     }
  2533.                     if (strcmp(s, "NEXT PEDESTRIAN") == 0) {
  2534.                         break;
  2535.                     }
  2536.                 }
  2537.             }
  2538.         } while (the_pedestrian->ref_number != the_ref);
  2539.  
  2540.         temp_float1 = GetAFloat(pG);
  2541.         the_pedestrian->height = temp_float1;
  2542.         the_pedestrian->credits_value = GetAnInt(pG);
  2543.         the_pedestrian->hit_points = GetAnInt(pG);
  2544.         the_pedestrian->active = 0;
  2545.         GetALineAndDontArgue(pG, s2);
  2546.         str2 = strtok(s2, "\t ,/");
  2547.         sscanf(str2, "%d", &the_pedestrian->number_of_exploding_sounds);
  2548.         for (j = 0; j < the_pedestrian->number_of_exploding_sounds; j++) {
  2549.             str2 = strtok(NULL, "\t ,/");
  2550.             sscanf(str2, "%d", &the_pedestrian->exploding_sounds[j]);
  2551.         }
  2552.         the_pedestrian->falling_sound = GetAnInt(pG);
  2553.         the_pedestrian->acceleration = GetAFloat(pG);
  2554.         the_pedestrian->image_index = GetAnInt(pG);
  2555.         LoadNShadeTables(&gPedestrians_storage_space, pG, 1);
  2556.         LoadNPixelmaps(&gPedestrians_storage_space, pG, 1);
  2557.         GetALineAndDontArgue(pG, s2);
  2558.         if (gPed_material == NULL) {
  2559.             str2 = strtok(s2, "\t ,/");
  2560.             PathCat(the_path, gApplication_path, "MATERIAL");
  2561.             PathCat(the_path, the_path, s2);
  2562.             gPed_material = BrMaterialLoad(the_path);
  2563.             if (gPed_material == NULL) {
  2564.                 FatalError(kFatalError_FindPedestrianMaterial_S, s2);
  2565.             }
  2566.             gPed_material->flags &= ~BR_MATF_TWO_SIDED;
  2567.             gPed_material->flags &= ~(BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_SMOOTH);
  2568.             gPed_material->index_shade = NULL;
  2569.             gPed_material->colour_map = gPedestrians_storage_space.pixelmaps[0];
  2570.             BrMaterialAdd(gPed_material);
  2571.         }
  2572.         gPed_material->colour_map = gPedestrians_storage_space.pixelmaps[0];
  2573.         the_pedestrian->actor->material = gPed_material;
  2574.         the_pedestrian->fatal_car_impact_action = GetAnInt(pG);
  2575.         the_pedestrian->non_fatal_car_impact_action = GetAnInt(pG);
  2576.         the_pedestrian->after_impact_action = GetAnInt(pG);
  2577.         the_pedestrian->fatal_ground_impact_action = GetAnInt(pG);
  2578.         the_pedestrian->non_fatal_ground_impact_action = GetAnInt(pG);
  2579.         the_pedestrian->giblets_action = GetAnInt(pG);
  2580.         the_pedestrian->current_sequence = 0;
  2581.         the_pedestrian->current_frame = 0;
  2582.         the_pedestrian->current_action = 0;
  2583.         the_pedestrian->current_action_mode = -1;
  2584.         the_pedestrian->done_initial = 0;
  2585.         the_pedestrian->current_speed = 0.0f;
  2586.         the_pedestrian->instruction_direction = 1;
  2587.         the_pedestrian->spin_period = 0.0f;
  2588.         the_pedestrian->falling_speed = 0.0f;
  2589.         the_pedestrian->mid_air = 0;
  2590.         the_pedestrian->last_special_volume = NULL;
  2591.         the_pedestrian->last_sound = 0;
  2592.         the_pedestrian->giblets_being_sat_upon = 0;
  2593.         the_pedestrian->last_sound_action = -1;
  2594.         the_pedestrian->last_sound_make = 0;
  2595.         the_pedestrian->fate = NULL;
  2596.         the_pedestrian->munged = 0;
  2597.         the_pedestrian->collided_last_time = 0;
  2598.         the_pedestrian->reverse_frames = 0;
  2599.         the_pedestrian->respawn_time = 0;
  2600.         the_pedestrian->killers_ID = -1;
  2601.         the_pedestrian->murderer = -1;
  2602.         the_pedestrian->sent_dead_message = 0;
  2603.         minnest_min = BR_SCALAR_MAX;
  2604.         maxest_min = BR_SCALAR_MIN;
  2605.         minnest_max = BR_SCALAR_MAX;
  2606.         maxest_max = BR_SCALAR_MIN;
  2607.         the_pedestrian->number_of_actions = GetAnInt(pG);
  2608.         the_pedestrian->action_list = BrMemAllocate(sizeof(tPedestrian_action) * the_pedestrian->number_of_actions, kMem_ped_action_list);
  2609.         the_action = the_pedestrian->action_list;
  2610.         for (i = 0; i < the_pedestrian->number_of_actions; i++) {
  2611.             PossibleService();
  2612.             GetPairOfFloats(pG, &the_action->danger_level, &the_action->percentage_chance);
  2613.             GetPairOfFloats(pG, &the_action->initial_speed, &the_action->looping_speed);
  2614.             the_action->reaction_time = (tU32)(GetAFloat(pG) * 1000.0f);
  2615.             GetALineAndDontArgue(pG, s2);
  2616.             str2 = strtok(s2, "\t ,/");
  2617.             sscanf(str2, "%d", &the_action->number_of_sounds);
  2618.             for (j = 0; j < the_action->number_of_sounds; j++) {
  2619.                 str2 = strtok(NULL, "\t ,/");
  2620.                 sscanf(str2, "%d", &the_action->sounds[j]);
  2621.             }
  2622.             the_action->number_of_bearings = GetAnInt(pG);
  2623.             if (the_action->number_of_bearings > COUNT_OF(the_action->sequences)) {
  2624.                 FatalError(kFatalError_PedSeqTooManyBearings);
  2625.             }
  2626.             for (j = 0; j < the_action->number_of_bearings; j++) {
  2627.                 GetPairOfFloats(pG, &the_action->sequences[j].max_bearing, &temp_float1);
  2628.                 the_action->sequences[j].sequence_index = (int)temp_float1;
  2629.             }
  2630.             the_action++;
  2631.         }
  2632.         the_pedestrian->number_of_sequences = GetAnInt(pG);
  2633.         the_pedestrian->last_frame = 0;
  2634.         the_pedestrian->last_action_change = 0;
  2635.         the_pedestrian->sequences = BrMemAllocate(sizeof(tPedestrian_sequence) * the_pedestrian->number_of_sequences, kMem_ped_sequences);
  2636.         the_sequence = the_pedestrian->sequences;
  2637.         for (i = 0; i < the_pedestrian->number_of_sequences; i++) {
  2638.             PossibleService();
  2639.             collide_frame = GetALineAndInterpretCommand(pG, gCollide_commands, COUNT_OF(gCollide_commands));
  2640.             the_sequence->frame_rate_type = GetALineAndInterpretCommand(pG, gRate_commands, COUNT_OF(gRate_commands));
  2641.  
  2642.             if (the_sequence->frame_rate_type == ePed_frame_speed || the_sequence->frame_rate_type == ePed_frame_variable) {
  2643.                 GetPairOfFloats(pG, &the_sequence->frame_rate_factor1, &the_sequence->frame_rate_factor2);
  2644.             }
  2645.             the_sequence->number_of_frames = 0;
  2646.             the_sequence->looping_frame_start = -1;
  2647.             for (j = 0; j < 2; j++) {
  2648.                 new_frames = GetAnInt(pG);
  2649.                 if (new_frames + the_sequence->number_of_frames > COUNT_OF(the_sequence->frames)) {
  2650.                     FatalError(kFatalError_PedSeqTooManyFrames);
  2651.                 }
  2652.                 for (k = the_sequence->number_of_frames; k < new_frames + the_sequence->number_of_frames; k++) {
  2653.                     GetAString(pG, s);
  2654.                     the_sequence->frames[k].pixelmap = BrMapFind(s);
  2655.                     if (the_sequence->frames[k].pixelmap == NULL) {
  2656.                         the_sequence->frames[k].pixelmap = LoadPixelmap(s);
  2657.                         if (the_sequence->frames[k].pixelmap == NULL) {
  2658.                             FatalError(kFatalError_FindPedestrianPixelmap_S, s);
  2659.                         }
  2660.                         BrMapAdd(the_sequence->frames[k].pixelmap);
  2661.                     }
  2662.                     GetALineAndDontArgue(pG, s);
  2663.                     str = strtok(s, "\t ,/");
  2664.                     sscanf(str, "%f", &temp_float1);
  2665.                     str = strtok(NULL, "\t ,/");
  2666.                     sscanf(str, "%f", &temp_float2);
  2667.                     str = strtok(NULL, "\t ,/");
  2668.                     the_sequence->frames[k].offset.v[0] = temp_float1;
  2669.                     the_sequence->frames[k].offset.v[1] = temp_float2;
  2670.                     the_sequence->frames[k].flipped = strcmp(str, "flipped") == 0;
  2671.                     if (collide_frame) {
  2672.                         CalcPedWidthNHeight(
  2673.                             the_pedestrian,
  2674.                             the_sequence->frames[k].pixelmap,
  2675.                             &height,
  2676.                             &width_over_2);
  2677.                         if (the_sequence->frames[k].offset.v[0] - width_over_2 < minnest_min) {
  2678.                             minnest_min = the_sequence->frames[k].offset.v[0] - width_over_2;
  2679.                         }
  2680.                         if (the_sequence->frames[k].offset.v[0] - width_over_2 > maxest_min) {
  2681.                             maxest_min = the_sequence->frames[k].offset.v[0] - width_over_2;
  2682.                         }
  2683.                         if (the_sequence->frames[k].offset.v[0] + width_over_2 < minnest_max) {
  2684.                             minnest_max = the_sequence->frames[k].offset.v[0] + width_over_2;
  2685.                         }
  2686.                         if (the_sequence->frames[k].offset.v[0] + width_over_2 > maxest_max) {
  2687.                             maxest_max = the_sequence->frames[k].offset.v[0] + width_over_2;
  2688.                         }
  2689.                     }
  2690.                 }
  2691.                 the_sequence->number_of_frames += new_frames;
  2692.                 if (the_sequence->looping_frame_start < 0) {
  2693.                     the_sequence->looping_frame_start = the_sequence->number_of_frames;
  2694.                 }
  2695.             }
  2696.             the_sequence++;
  2697.         }
  2698.         the_pedestrian->min_x = maxest_min;
  2699.         the_pedestrian->max_x = minnest_max;
  2700.     }
  2701.     PossibleService();
  2702.     the_pedestrian->number_of_instructions = pInstruc_count;
  2703.     the_pedestrian->first_instruction = pInit_instruc;
  2704.     the_pedestrian->current_instruction = pInit_instruc;
  2705.     the_pedestrian->instruction_list = pInstructions;
  2706.     the_pedestrian->colour_map = the_pedestrian->sequences->frames[0].pixelmap;
  2707.     BrVector3Set(&the_pedestrian->offset, 0.0f, 0.0f, 0.0f);
  2708.     gInitial_instruction = 0;
  2709.     PedestrianNextInstruction(the_pedestrian, 0.0f, 1, 0);
  2710.     the_pedestrian->from_pos = the_pedestrian->actor->t.t.translate.t;
  2711.     MungePedModel(the_pedestrian);
  2712. }
  2713.  
  2714. // IDA: void __cdecl ResetProxRay()
  2715. void ResetProxRay(void) {
  2716.     int i;
  2717.     LOG_TRACE("()");
  2718.  
  2719.     for (i = 0; i < COUNT_OF(gProximity_rays); i++) {
  2720.         gProximity_rays[i].start_time = 0;
  2721.     }
  2722. }
  2723.  
  2724. // IDA: void __cdecl PedMaterialFromHell()
  2725. void PedMaterialFromHell(void) {
  2726.     LOG_TRACE("()");
  2727. }
  2728.  
  2729. // IDA: void __cdecl ResetPedMaterial()
  2730. void ResetPedMaterial(void) {
  2731.     //int i; // Pierre-Marie Baty -- unused variable
  2732.     //int j; // Pierre-Marie Baty -- unused variable
  2733.     LOG_TRACE("()");
  2734. }
  2735.  
  2736. // IDA: void __usercall LoadInPedestrians(FILE *pF@<EAX>, int pSubs_count@<EDX>, tPed_subs *pSubs_array@<EBX>)
  2737. void LoadInPedestrians(FILE* pF, int pSubs_count, tPed_subs* pSubs_array) {
  2738.     tPath_name the_path;
  2739.     char s[256];
  2740.     char s2[256];
  2741.     char* str;
  2742.     //char* str2; // Pierre-Marie Baty -- unused variable
  2743.     FILE* g;
  2744.     //int the_ref; // Pierre-Marie Baty -- unused variable
  2745.     int i;
  2746.     int j;
  2747.     int k;
  2748.     //int l; // Pierre-Marie Baty -- unused variable
  2749.     int knock_out;
  2750.     int check_for_duplicates;
  2751.     int duplicates_found;
  2752.     int temp_int;
  2753.     int ref_number;
  2754.     int instruc_count;
  2755.     int ped_count;
  2756.     int init_instruc;
  2757.     float temp_float1;
  2758.     //float temp_float2; // Pierre-Marie Baty -- unused variable
  2759.     tPedestrian_instruction* instructions;
  2760.     tPedestrian_instruction* the_instruction;
  2761.     //tPed_choice* the_choice; // Pierre-Marie Baty -- unused variable
  2762.     LOG_TRACE("(%p, %d, %p)", pF, pSubs_count, pSubs_array);
  2763.  
  2764.     knock_out = 0;
  2765.     check_for_duplicates = 0;
  2766.     duplicates_found = 0;
  2767.     gTotal_peds = 0;
  2768.     gFlag_waving_bastard = NULL;
  2769.     gPedestrians_on = 1;
  2770.     gPed_scale_factor = 1.0f;
  2771.     gAttracted_pedestrians = 0;
  2772.     gExploding_pedestrians = 0;
  2773.     gBlind_pedestrians = 0;
  2774.     gPedestrian_speed_factor = 1.0f;
  2775.     if (gProgram_state.sausage_eater_mode) {
  2776.         PathCat(the_path, gApplication_path, "BORING.TXT");
  2777.     } else {
  2778.         PathCat(the_path, gApplication_path, "PEDESTRN.TXT");
  2779.     }
  2780.     g = DRfopen(the_path, "rt");
  2781.     if (g == NULL) {
  2782.         FatalError(kFatalError_OpenPedestrianFile);
  2783.     }
  2784.     gPed_count = 0;
  2785.     gLast_ped_splat_time = 0;
  2786.     temp_int = GetAnInt(pF);
  2787.     if (gAusterity_mode) {
  2788.         ped_count = temp_int / 2 + 2;
  2789.     } else {
  2790.         ped_count = temp_int;
  2791.     }
  2792.     gPedestrian_array = BrMemAllocate(sizeof(tPedestrian_data) * (ped_count + (gAusterity_mode ? 0 : 200)), kMem_ped_array_stain);
  2793.     if (PDKeyDown(KEY_CTRL_ANY) && PDKeyDown(KEY_SHIFT_ANY) && PDKeyDown(KEY_A)) {
  2794.         check_for_duplicates = 1;
  2795.         DRS3StartSound(gEffects_outlet, 3202);
  2796.         DRS3StartSound(gEffects_outlet, 3202);
  2797.     }
  2798.     for (i = 0; i < ped_count; i++) {
  2799.         PossibleService();
  2800.         ref_number = GetAnInt(pF);
  2801.         for (j = 0; j < pSubs_count; ++j) {
  2802.             if (pSubs_array[j].orig == ref_number) {
  2803.                 ref_number = pSubs_array[j].subs;
  2804.                 break;
  2805.             }
  2806.         }
  2807.         instruc_count = GetAnInt(pF);
  2808.         init_instruc = GetAnInt(pF) - 1;
  2809.         instructions = BrMemAllocate(sizeof(tPedestrian_instruction) * instruc_count, kMem_ped_instructions);
  2810.  
  2811.         for (j = 0, the_instruction = instructions; j < instruc_count; j++, the_instruction++) {
  2812.             PossibleService();
  2813.             the_instruction->type = GetALineAndInterpretCommand(pF, gInstruc_commands, COUNT_OF(gInstruc_commands));
  2814.             if (the_instruction->type != ePed_instruc_point && the_instruction->type != ePed_instruc_reverse) {
  2815.                 FatalError(kFatalError_FindPedestrianRefNum_S, "");
  2816.             }
  2817.             switch (the_instruction->type) {
  2818.             case ePed_instruc_point:
  2819.                 GetThreeFloats(pF, &the_instruction->data.point_data.position.v[0], &the_instruction->data.point_data.position.v[1], &the_instruction->data.point_data.position.v[2]);
  2820.                 the_instruction->data.point_data.irreversable = 0;
  2821.                 break;
  2822.  
  2823.             case ePed_instruc_xpoint:
  2824.                 GetThreeFloats(pF, &the_instruction->data.point_data.position.v[0], &the_instruction->data.point_data.position.v[1], &the_instruction->data.point_data.position.v[2]);
  2825.                 the_instruction->data.point_data.irreversable = 1;
  2826.                 break;
  2827.  
  2828.             case ePed_instruc_bchoice:
  2829.             case ePed_instruc_fchoice:
  2830.                 GetALineAndDontArgue(pF, s);
  2831.                 str = strtok(s, "\t ,/");
  2832.                 sscanf(str, "%d", &the_instruction->data.choice_data.number_of_choices);
  2833.                 if (the_instruction->data.choice_data.number_of_choices > COUNT_OF(the_instruction->data.choice_data.choices)) {
  2834.                     FatalError(kFatalError_PedSeqTooManyChoices);
  2835.                 }
  2836.                 for (k = 0; k < the_instruction->data.choice_data.number_of_choices; k++) {
  2837.                     str = strtok(NULL, "\t ,/");
  2838.                     sscanf(str, "%f", &temp_float1);
  2839.                     the_instruction->data.choice_data.choices[k].danger_level = (tU16)temp_float1;
  2840.                     str = strtok(NULL, "\t ,/");
  2841.                     sscanf(str, "%f", &temp_float1);
  2842.                     the_instruction->data.choice_data.choices[k].percentage_chance = (tU8)temp_float1;
  2843.                     str = strtok(NULL, "\t ,/");
  2844.                     sscanf(str, "%d", &temp_int);
  2845.                     the_instruction->data.choice_data.choices[k].marker_ref = (tU8)temp_int;
  2846.                 }
  2847.                 break;
  2848.  
  2849.             case ePed_instruc_dead:
  2850.                 the_instruction->data.death_data.death_sequence = GetAnInt(pF);
  2851.                 break;
  2852.  
  2853.             case ePed_instruc_bmarker:
  2854.             case ePed_instruc_fmarker:
  2855.                 the_instruction->data.marker_data.marker_ref = GetAnInt(pF);
  2856.                 break;
  2857.  
  2858.             case ePed_instruc_baction:
  2859.             case ePed_instruc_faction:
  2860.                 the_instruction->data.action_data.action_index = GetAnInt(pF);
  2861.                 break;
  2862.  
  2863.             case ePed_instruc_reverse:
  2864.                 break;
  2865.             }
  2866.         }
  2867.         if (gAusterity_mode) {
  2868.             if (knock_out & 1 && ref_number != FLAG_WAVING_BASTARD_REF) {
  2869.                 i--;
  2870.                 ped_count--;
  2871.                 instruc_count = 0;
  2872.                 BrMemFree(instructions);
  2873.             }
  2874.             ++knock_out;
  2875.         }
  2876.         if (check_for_duplicates) {
  2877.             for (j = 0; j < i; j++) {
  2878.                 if (Vector3AreEqual(&gPedestrian_array[j].instruction_list->data.point_data.position, &instructions->data.point_data.position)) {
  2879.                     i--;
  2880.                     ped_count--;
  2881.                     instruc_count = 0;
  2882.                     BrMemFree(instructions);
  2883.                     duplicates_found++;
  2884.                 }
  2885.             }
  2886.         }
  2887.         if (instruc_count > 0) {
  2888.             if (gAusterity_mode && ref_number >= 100) {
  2889.                 // swap MINE for LANDMINE and only one type of powerup ?
  2890.                 if (ref_number == 114) {
  2891.                     CreatePedestrian(g, instructions, instruc_count, init_instruc, 146, 0);
  2892.                 } else {
  2893.                     CreatePedestrian(g, instructions, instruc_count, init_instruc, 100, 0);
  2894.                 }
  2895.             } else {
  2896.                 CreatePedestrian(g, instructions, instruc_count, init_instruc, ref_number, 0);
  2897.             }
  2898.             gPedestrian_array[i].ref_number = ref_number;
  2899.             if (ref_number == FLAG_WAVING_BASTARD_REF) {
  2900.                 gFlag_waving_bastard = &gPedestrian_array[i];
  2901.             }
  2902.             if (ref_number < 100) {
  2903.                 gTotal_peds++;
  2904.             }
  2905.         }
  2906.     }
  2907.     fclose(g);
  2908.     if (duplicates_found) {
  2909.         WriteOutPeds();
  2910.         sprintf(s2,
  2911.             "DUPLICATE PED EXPLOSION!!\n"
  2912.             "%d DOPPELGANGERS FOUND AND DESTROYED.\n"
  2913.             "NEW PED LIST WRITTEN TO PEDPATHS.TXT\n"
  2914.             "\n"
  2915.             "\n"
  2916.             "NOW DON'T DO IT AGAIN!!\n",
  2917.             duplicates_found);
  2918.         PDFatalError(s2);
  2919.     }
  2920.     InitPedGibs();
  2921.     ResetProxRay();
  2922.     gPedestrian_harvest = 0;
  2923.     gVesuvian_corpses = 0;
  2924.     gProx_ray_shade_table = GenerateShadeTable(8, gRender_palette, 215, 255, 233, 0.5f, 0.75f, 0.9f);
  2925.     ResetPedMaterial();
  2926. }
  2927.  
  2928. // IDA: br_actor* __usercall BuildPedPaths@<EAX>(tPedestrian_instruction *pInstructions@<EAX>, int pInstruc_count@<EDX>, int pInit_instruc@<EBX>)
  2929. br_actor* BuildPedPaths(tPedestrian_instruction* pInstructions, int pInstruc_count, int pInit_instruc) {
  2930.     int vertex_count;
  2931.     int last_vertex_count;
  2932.     int face_count;
  2933.     int j;
  2934.     int point_count;
  2935.     br_vector3 the_point;
  2936.     br_material* the_mat;
  2937.     br_model* the_model;
  2938.     br_actor* the_actor;
  2939.     LOG_TRACE("(%p, %d, %d)", pInstructions, pInstruc_count, pInit_instruc);
  2940.  
  2941.     vertex_count = 4;
  2942.     face_count = 2;
  2943.     for (j = 0; j < pInstruc_count; j++) {
  2944.         if (pInstructions[j].type == ePed_instruc_point || pInstructions[j].type == ePed_instruc_xpoint) {
  2945.             vertex_count += 4;
  2946.             face_count += 4;
  2947.         }
  2948.     }
  2949.     face_count -= 4;
  2950.     the_model = BrModelAllocate(NULL, vertex_count, face_count);
  2951.     the_model->flags |= BR_MODU_VERTEX_COLOURS | BR_MODU_VERTEX_POSITIONS;
  2952.  
  2953.     vertex_count = 0;
  2954.     face_count = 0;
  2955.     point_count = 0;
  2956.     for (j = 0; j < pInstruc_count; j++) {
  2957.         if (pInstructions[j].type == ePed_instruc_point || pInstructions[j].type == ePed_instruc_xpoint) {
  2958.             the_point = pInstructions[j].data.point_data.position;
  2959.             if (the_point.v[Y] < 500.f) {
  2960.                 the_mat = gPath_mat_normal;
  2961.             } else {
  2962.                 the_point.v[Y] -= 999.6f;
  2963.                 the_point.v[Y] = FindYVerticallyBelow2(&the_point);
  2964.                 if (the_point.v[Y] < -100.f) {
  2965.                     the_point.v[Y] = 1000.f;
  2966.                     the_point.v[Y] = FindYVerticallyBelow2(&the_point);
  2967.                 }
  2968.                 if (point_count == 0 || pInstructions[j - 1].data.point_data.position.v[Y] < 500.f) {
  2969.                     the_mat = gPath_mat_normal;
  2970.                 } else {
  2971.                     the_mat = gPath_mat_calc;
  2972.                 }
  2973.             }
  2974.             SquirtPathVertex(&the_model->vertices[vertex_count], &the_point);
  2975.             vertex_count += 4;
  2976. #if defined(DETHRACE_FIX_BUGS)
  2977.             last_vertex_count = vertex_count;
  2978. #endif
  2979.             if (point_count != 0) {
  2980.                 // Connect previous path vertex cross with current path vertex cross
  2981.                 the_model->faces[face_count].vertices[0] = vertex_count - 4;
  2982.                 the_model->faces[face_count].vertices[1] = vertex_count - 3;
  2983.                 the_model->faces[face_count].vertices[2] = last_vertex_count - 4;
  2984.                 the_model->faces[face_count].material = the_mat;
  2985.                 face_count++;
  2986.                 the_model->faces[face_count].vertices[0] = vertex_count - 3;
  2987.                 the_model->faces[face_count].vertices[1] = last_vertex_count - 3;
  2988.                 the_model->faces[face_count].vertices[2] = last_vertex_count - 4;
  2989.                 the_model->faces[face_count].material = the_mat;
  2990.                 face_count++;
  2991.                 the_model->faces[face_count].vertices[0] = vertex_count - 2;
  2992.                 the_model->faces[face_count].vertices[1] = vertex_count - 1;
  2993.                 the_model->faces[face_count].vertices[2] = last_vertex_count - 2;
  2994.                 the_model->faces[face_count].material = the_mat;
  2995.                 face_count++;
  2996.                 the_model->faces[face_count].vertices[0] = vertex_count - 1;
  2997.                 the_model->faces[face_count].vertices[1] = last_vertex_count - 1;
  2998.                 the_model->faces[face_count].vertices[2] = last_vertex_count - 2;
  2999.                 the_model->faces[face_count].material = the_mat;
  3000.                 face_count++;
  3001.             }
  3002.             point_count++;
  3003.             last_vertex_count = vertex_count;
  3004.             if (j == pInit_instruc) {
  3005.                 the_model->vertices[vertex_count].p = the_point;
  3006.                 the_model->vertices[vertex_count].p.v[Y] += .3f;
  3007.                 the_model->vertices[vertex_count].p.v[Z] += .05f;
  3008.                 the_model->vertices[vertex_count + 1].p = the_point;
  3009.                 the_model->vertices[vertex_count + 1].p.v[Y] += .3f;
  3010.                 the_model->vertices[vertex_count + 1].p.v[Z] += -.05f;
  3011.                 the_model->vertices[vertex_count + 2].p = the_point;
  3012.                 the_model->vertices[vertex_count + 2].p.v[Y] += .3f;
  3013.                 the_model->vertices[vertex_count + 2].p.v[X] += .05f;
  3014.                 the_model->vertices[vertex_count + 3].p = the_point;
  3015.                 the_model->vertices[vertex_count + 3].p.v[Y] += .3f;
  3016.                 the_model->vertices[vertex_count + 3].p.v[X] += -.05f;
  3017.                 vertex_count += 4;
  3018.                 the_model->faces[face_count].vertices[0] = vertex_count - 8;
  3019.                 the_model->faces[face_count].vertices[1] = vertex_count - 4;
  3020.                 the_model->faces[face_count].vertices[2] = vertex_count - 3;
  3021.                 the_model->faces[face_count].material = gInit_pos_mat_calc;
  3022.                 face_count++;
  3023.                 the_model->faces[face_count].vertices[0] = vertex_count - 8;
  3024.                 the_model->faces[face_count].vertices[1] = vertex_count - 2;
  3025.                 the_model->faces[face_count].vertices[2] = vertex_count - 1;
  3026.                 the_model->faces[face_count].material = gInit_pos_mat_calc;
  3027.                 face_count++;
  3028.             }
  3029.         }
  3030.     }
  3031.     BrModelUpdate(the_model, BR_MODU_ALL);
  3032.     BrModelAdd(the_model);
  3033.     the_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
  3034.     the_actor->model = the_model;
  3035.     BrActorAdd(gPath_actor, the_actor);
  3036.     return the_actor;
  3037. }
  3038.  
  3039. // IDA: void __cdecl WriteOutPeds()
  3040. void WriteOutPeds(void) {
  3041.     int i;
  3042.     int j;
  3043.     int k;
  3044.     //int point_count; // Pierre-Marie Baty -- unused variable
  3045.     //int min_ped; // Pierre-Marie Baty -- unused variable
  3046.     //int min_point; // Pierre-Marie Baty -- unused variable
  3047.     //br_vector3 the_point; // Pierre-Marie Baty -- unused variable
  3048.     //br_vector3 last_point; // Pierre-Marie Baty -- unused variable
  3049.     //br_scalar min_distance; // Pierre-Marie Baty -- unused variable
  3050.     //br_scalar the_distance; // Pierre-Marie Baty -- unused variable
  3051.     //char s[255]; // Pierre-Marie Baty -- unused variable
  3052.     tPedestrian_data* the_pedestrian;
  3053.     tPedestrian_instruction* the_instruction;
  3054.     tPed_choice* the_choice;
  3055.     FILE* f;
  3056.     tPath_name the_path;
  3057.     LOG_TRACE("()");
  3058.  
  3059.     PathCat(the_path, gApplication_path, "PEDPATHS.TXT");
  3060.     f = DRfopen(the_path, "wt");
  3061.     fprintf(f, "// ****** START OF PEDESTRIAN STUFF ******\n\n");
  3062.     fprintf(f, "0\t\t\t\t// Ped subs table index\n\n");
  3063.     fprintf(f, "%d\t\t\t\t// Number of pedestrians\n\n", gPed_count);
  3064.     for (i = 0, the_pedestrian = gPedestrian_array; i < gPed_count; i++, the_pedestrian++) {
  3065.         fprintf(f, "// Pedestrian number %d\n\n", i + 1);
  3066.         fprintf(f, "%d\t\t\t\t// Ref num\n", the_pedestrian->ref_number);
  3067.         fprintf(f, "%d\t\t\t\t// Number of instructions\n", the_pedestrian->number_of_instructions);
  3068.         fprintf(f, "%d\t\t\t\t// Initial instruction\n\n", the_pedestrian->first_instruction + 1);
  3069.         for (j = 0, the_instruction = the_pedestrian->instruction_list; j < the_pedestrian->number_of_instructions; j++, the_instruction++) {
  3070.             switch (the_instruction->type) {
  3071.             case ePed_instruc_point:
  3072.                 fprintf(f, "\tpoint\n");
  3073.                 fprintf(f, "\t%.3f,%.3f,%.3f\n",
  3074.                     the_instruction->data.point_data.position.v[X],
  3075.                     the_instruction->data.point_data.position.v[Y],
  3076.                     the_instruction->data.point_data.position.v[Z]);
  3077.                 break;
  3078.             case ePed_instruc_xpoint:
  3079.                 fprintf(f, "\txpoint\n");
  3080.                 fprintf(f, "\t%.3f,%.3f,%.3f\n",
  3081.                     the_instruction->data.point_data.position.v[X],
  3082.                     the_instruction->data.point_data.position.v[Y],
  3083.                     the_instruction->data.point_data.position.v[Z]);
  3084.                 break;
  3085.             case ePed_instruc_bchoice:
  3086.                 fprintf(f, "\tbchoice\n");
  3087.                 fprintf(f, "%d", the_instruction->data.choice_data.number_of_choices);
  3088.                 for (k = 0, the_choice = the_instruction->data.choice_data.choices; k < the_instruction->data.choice_data.number_of_choices; k++, the_choice++) {
  3089.                     fprintf(f, "%d,%d,%d,", the_choice->danger_level, the_choice->percentage_chance, the_choice->marker_ref);
  3090.                 }
  3091.                 break;
  3092.             case ePed_instruc_fchoice:
  3093.                 fprintf(f, "\tfchoice\n");
  3094.                 fprintf(f, "%d", the_instruction->data.choice_data.number_of_choices);
  3095.                 for (k = 0, the_choice = the_instruction->data.choice_data.choices; k < the_instruction->data.choice_data.number_of_choices; k++, the_choice++) {
  3096.                     fprintf(f, "%d,%d,%d,", the_choice->danger_level, the_choice->percentage_chance, the_choice->marker_ref);
  3097.                 }
  3098.                 break;
  3099.             case ePed_instruc_dead:
  3100.                 fprintf(f, "\tdead\n");
  3101.                 fprintf(f, "%d", the_instruction->data.death_data.death_sequence);
  3102.                 break;
  3103.             case ePed_instruc_bmarker:
  3104.                 fprintf(f, "\tbmarker\n");
  3105.                 fprintf(f, "%d", the_instruction->data.marker_data.marker_ref);
  3106.                 break;
  3107.             case ePed_instruc_fmarker:
  3108.                 fprintf(f, "\tfmarker\n");
  3109.                 fprintf(f, "%d", the_instruction->data.marker_data.marker_ref);
  3110.                 break;
  3111.             case ePed_instruc_baction:
  3112.                 fprintf(f, "\tbaction\n");
  3113.                 fprintf(f, "%d", the_instruction->data.action_data.action_index);
  3114.                 break;
  3115.             case ePed_instruc_faction:
  3116.                 fprintf(f, "\tfaction\n");
  3117.                 fprintf(f, "%d", the_instruction->data.action_data.action_index);
  3118.                 break;
  3119.             case ePed_instruc_reverse:
  3120.                 fprintf(f, "\treverse\n");
  3121.                 break;
  3122.             }
  3123.         }
  3124.         fprintf(f, "\n\n");
  3125.     }
  3126.     fclose(f);
  3127. }
  3128.  
  3129. // IDA: void __cdecl AddPed()
  3130. void AddPed(void) {
  3131.     tPedestrian_instruction* instructions;
  3132.     FILE* g;
  3133.     tPath_name the_path;
  3134.     LOG_TRACE("()");
  3135.  
  3136.     PathCat(the_path, gApplication_path, "PEDESTRN.TXT");
  3137.     g = DRfopen(the_path, "rt");
  3138.     if (g == NULL) {
  3139.         FatalError(kFatalError_OpenPedestrianFile);
  3140.     }
  3141.     gPed_instrucs[gPed_instruc_count].type = ePed_instruc_reverse;
  3142.     gPed_instruc_count++;
  3143.     instructions = BrMemAllocate(gPed_instruc_count * sizeof(tPedestrian_instruction), kMem_ped_new_instruc);
  3144.     memcpy(instructions, gPed_instrucs, gPed_instruc_count * sizeof(tPedestrian_instruction));
  3145.     CreatePedestrian(g, instructions, gPed_instruc_count, gInit_ped_instruc, gPed_ref_num, 1);
  3146.     fclose(g);
  3147.     gPed_instruc_count = 0;
  3148.     WriteOutPeds();
  3149. }
  3150.  
  3151. // IDA: void __usercall NewPed(int pRef_num@<EAX>)
  3152. void NewPed(int pRef_num) {
  3153.     char s[255];
  3154.     LOG_TRACE("(%d)", pRef_num);
  3155.  
  3156.     if (pRef_num >= 0) {
  3157.         if (PDKeyDown(0)) {
  3158.             pRef_num += 100;
  3159.         }
  3160.         if (PDKeyDown(2)) {
  3161.             pRef_num += 20;
  3162.         }
  3163.         if (PDKeyDown(1)) {
  3164.             pRef_num += 10;
  3165.         }
  3166.     }
  3167.     if (gCurrent_ped_path_actor != NULL) {
  3168.         gCurrent_ped_path_actor->model->nvertices -= 4;
  3169.         gCurrent_ped_path_actor->model->nfaces -= 4;
  3170.         BrModelUpdate(gCurrent_ped_path_actor->model, BR_MODU_ALL);
  3171.         gCurrent_ped_path_actor = NULL;
  3172.     }
  3173.     if (gPed_instruc_count != 0) {
  3174.         AddPed();
  3175.     }
  3176.     if (pRef_num >= 0) {
  3177.         gPed_ref_num = pRef_num;
  3178.         gPed_instruc_count = 0;
  3179.         gInit_ped_instruc = 0;
  3180.         gNumber_of_pedestrians++;
  3181.         gTotal_peds++;
  3182.         sprintf(s, "New pedestrian, refnum = %d", pRef_num);
  3183.         NewTextHeadupSlot(4, 0, 2000, -1, s);
  3184.         if (pRef_num >= 100) {
  3185.             DropInitPedPoint();
  3186.             NewPed(-1);
  3187.         }
  3188.     }
  3189. }
  3190.  
  3191. // IDA: void __cdecl RemoveCurrentPedPath()
  3192. void RemoveCurrentPedPath(void) {
  3193.     LOG_TRACE("()");
  3194.  
  3195.     if (gCurrent_ped_path_actor != NULL) {
  3196.         BrModelRemove(gCurrent_ped_path_actor->model);
  3197.         BrModelFree(gCurrent_ped_path_actor->model);
  3198.         BrActorRemove(gCurrent_ped_path_actor);
  3199.         BrActorFree(gCurrent_ped_path_actor);
  3200.         gCurrent_ped_path_actor = NULL;
  3201.     }
  3202. }
  3203.  
  3204. // IDA: void __cdecl ScrubPedestrian()
  3205. void ScrubPedestrian(void) {
  3206.     LOG_TRACE("()");
  3207.  
  3208.     gPed_instruc_count = 0;
  3209.     gNumber_of_pedestrians--;
  3210.     gTotal_peds--;
  3211.     NewTextHeadupSlot(4, 0, 2000, -1, "Scrubbed pedestrian");
  3212.     RemoveCurrentPedPath();
  3213. }
  3214.  
  3215. // IDA: void __cdecl TogglePedDetect()
  3216. void TogglePedDetect(void) {
  3217.     LOG_TRACE("()");
  3218.  
  3219.     gDetect_peds = !gDetect_peds;
  3220.     if (gDetect_peds) {
  3221.         NewTextHeadupSlot(4, 0, 2000, -1, "Pedestrian are meat again");
  3222.     } else {
  3223.         NewTextHeadupSlot(4, 0, 2000, -1, "Pedestrians are invulnerable");
  3224.     }
  3225. }
  3226.  
  3227. // IDA: void __cdecl NewPed0()
  3228. void NewPed0(void) {
  3229.     LOG_TRACE("()");
  3230.  
  3231.     NewPed(0);
  3232. }
  3233.  
  3234. // IDA: void __cdecl NewPed1()
  3235. void NewPed1(void) {
  3236.     LOG_TRACE("()");
  3237.  
  3238.     NewPed(1);
  3239. }
  3240.  
  3241. // IDA: void __cdecl NewPed2()
  3242. void NewPed2(void) {
  3243.     LOG_TRACE("()");
  3244.  
  3245.     NewPed(2);
  3246. }
  3247.  
  3248. // IDA: void __cdecl NewPed3()
  3249. void NewPed3(void) {
  3250.     LOG_TRACE("()");
  3251.  
  3252.     NewPed(3);
  3253. }
  3254.  
  3255. // IDA: void __cdecl NewPed4()
  3256. void NewPed4(void) {
  3257.     LOG_TRACE("()");
  3258.  
  3259.     NewPed(4);
  3260. }
  3261.  
  3262. // IDA: void __cdecl NewPed5()
  3263. void NewPed5(void) {
  3264.     LOG_TRACE("()");
  3265.  
  3266.     NewPed(5);
  3267. }
  3268.  
  3269. // IDA: void __cdecl NewPed6()
  3270. void NewPed6(void) {
  3271.     LOG_TRACE("()");
  3272.  
  3273.     NewPed(6);
  3274. }
  3275.  
  3276. // IDA: void __cdecl NewPed7()
  3277. void NewPed7(void) {
  3278.     LOG_TRACE("()");
  3279.  
  3280.     NewPed(7);
  3281. }
  3282.  
  3283. // IDA: void __cdecl NewPed8()
  3284. void NewPed8(void) {
  3285.     LOG_TRACE("()");
  3286.  
  3287.     NewPed(8);
  3288. }
  3289.  
  3290. // IDA: void __cdecl NewPed9()
  3291. void NewPed9(void) {
  3292.     LOG_TRACE("()");
  3293.  
  3294.     NewPed(9);
  3295. }
  3296.  
  3297. // IDA: void __cdecl NewPed0B()
  3298. void NewPed0B(void) {
  3299.     LOG_TRACE("()");
  3300.  
  3301.     NewPed(61);
  3302. }
  3303.  
  3304. // IDA: void __cdecl NewPed1B()
  3305. void NewPed1B(void) {
  3306.     LOG_TRACE("()");
  3307.  
  3308.     NewPed(51);
  3309. }
  3310.  
  3311. // IDA: void __cdecl NewPed2B()
  3312. void NewPed2B(void) {
  3313.     LOG_TRACE("()");
  3314.  
  3315.     NewPed(52);
  3316. }
  3317.  
  3318. // IDA: void __cdecl NewPed3B()
  3319. void NewPed3B(void) {
  3320.     LOG_TRACE("()");
  3321.  
  3322.     NewPed(53);
  3323. }
  3324.  
  3325. // IDA: void __cdecl NewPed4B()
  3326. void NewPed4B(void) {
  3327.     LOG_TRACE("()");
  3328.  
  3329.     NewPed(54);
  3330. }
  3331.  
  3332. // IDA: void __cdecl NewPed5B()
  3333. void NewPed5B(void) {
  3334.     LOG_TRACE("()");
  3335.  
  3336.     NewPed(55);
  3337. }
  3338.  
  3339. // IDA: void __cdecl NewPed6B()
  3340. void NewPed6B(void) {
  3341.     LOG_TRACE("()");
  3342.  
  3343.     NewPed(56);
  3344. }
  3345.  
  3346. // IDA: void __cdecl NewPed7B()
  3347. void NewPed7B(void) {
  3348.     LOG_TRACE("()");
  3349.  
  3350.     NewPed(57);
  3351. }
  3352.  
  3353. // IDA: void __cdecl NewPed8B()
  3354. void NewPed8B(void) {
  3355.     LOG_TRACE("()");
  3356.  
  3357.     NewPed(58);
  3358. }
  3359.  
  3360. // IDA: void __cdecl NewPed9B()
  3361. void NewPed9B(void) {
  3362.     LOG_TRACE("()");
  3363.  
  3364.     NewPed(59);
  3365. }
  3366.  
  3367. // IDA: void __cdecl MungeShowPedPath()
  3368. void MungeShowPedPath(void) {
  3369.     LOG_TRACE("()");
  3370.  
  3371.     RemoveCurrentPedPath();
  3372.     gPed_instrucs[gPed_instruc_count] = gPed_instrucs[gPed_instruc_count - 1];
  3373.     gCurrent_ped_path_actor = BuildPedPaths(gPed_instrucs, gPed_instruc_count + 1, gInit_ped_instruc);
  3374. }
  3375.  
  3376. // IDA: void __cdecl DropPedPoint2()
  3377. void DropPedPoint2(void) {
  3378.     LOG_TRACE("()");
  3379.  
  3380.     gPed_instrucs[gPed_instruc_count].type = ePed_instruc_point;
  3381.     gPed_instrucs[gPed_instruc_count].data.point_data.irreversable = 0;
  3382.     gPed_instrucs[gPed_instruc_count].data.point_data.position = *gOur_pos;
  3383.     gPed_instruc_count++;
  3384.     MungeShowPedPath();
  3385. }
  3386.  
  3387. // IDA: void __cdecl DropPedPoint()
  3388. void DropPedPoint(void) {
  3389.     LOG_TRACE("()");
  3390.  
  3391. #if defined(DETHRACE_FIX_BUGS)
  3392.     if (gPath_actor == NULL) {
  3393.         return;
  3394.     }
  3395. #endif
  3396.     DropPedPoint2();
  3397.     NewTextHeadupSlot(4, 0, 2000, -1, "Dropped pedestrian point");
  3398. }
  3399.  
  3400. // IDA: void __cdecl DropInitPedPoint()
  3401. void DropInitPedPoint(void) {
  3402.     LOG_TRACE("()");
  3403.  
  3404. #if defined(DETHRACE_FIX_BUGS)
  3405.     if (gPath_actor == NULL) {
  3406.         return;
  3407.     }
  3408. #endif
  3409.     gInit_ped_instruc = gPed_instruc_count;
  3410.     DropPedPoint2();
  3411.     NewTextHeadupSlot(4, 0, 2000, -1, "Dropped initial pedestrian point");
  3412. }
  3413.  
  3414. // IDA: void __cdecl DropPedPointAir2()
  3415. void DropPedPointAir2(void) {
  3416.     LOG_TRACE("()");
  3417.  
  3418.     gPed_instrucs[gPed_instruc_count].type = ePed_instruc_point;
  3419.     gPed_instrucs[gPed_instruc_count].data.point_data.irreversable = 0;
  3420.     gPed_instrucs[gPed_instruc_count].data.point_data.position = *gOur_pos;
  3421.     gPed_instrucs[gPed_instruc_count].data.point_data.position.v[Y] += 1000.4f;
  3422.     gPed_instruc_count++;
  3423.     MungeShowPedPath();
  3424. }
  3425.  
  3426. // IDA: void __cdecl DropPedPointAir()
  3427. void DropPedPointAir(void) {
  3428.     LOG_TRACE("()");
  3429.  
  3430. #if defined(DETHRACE_FIX_BUGS)
  3431.     if (gPath_actor == NULL) {
  3432.         return;
  3433.     }
  3434. #endif
  3435.     DropPedPointAir2();
  3436.     NewTextHeadupSlot(4, 0, 2000, -1, "Dropped auto-y pedestrian point");
  3437. }
  3438.  
  3439. // IDA: void __cdecl DropInitPedPointAir()
  3440. void DropInitPedPointAir(void) {
  3441.     LOG_TRACE("()");
  3442.  
  3443. #if defined(DETHRACE_FIX_BUGS)
  3444.     if (gPath_actor == NULL) {
  3445.         return;
  3446.     }
  3447. #endif
  3448.     gInit_ped_instruc = gPed_instruc_count;
  3449.     DropPedPointAir2();
  3450.     NewTextHeadupSlot(4, 0, 2000, -1, "Dropped initial auto-y pedestrian point");
  3451. }
  3452.  
  3453. // IDA: br_uint_32 __cdecl KillActorsModel(br_actor *pActor, void *pArg)
  3454. br_uintptr_t KillActorsModel(br_actor* pActor, void* pArg) {
  3455.     LOG_TRACE("(%p, %p)", pActor, pArg);
  3456.  
  3457.     if (pActor->model != NULL) {
  3458.         BrModelRemove(pActor->model);
  3459.         BrModelFree(pActor->model);
  3460.     }
  3461.     return 0;
  3462. }
  3463.  
  3464. // IDA: void __cdecl DisposePedPaths()
  3465. void DisposePedPaths(void) {
  3466.     LOG_TRACE("()");
  3467.  
  3468.     if (gPath_actor != NULL) {
  3469.         DRActorEnumRecurse(gPath_actor, KillActorsModel, NULL);
  3470.         BrActorRemove(gPath_actor);
  3471.         BrActorFree(gPath_actor);
  3472.         BrMaterialRemove(gPath_mat_normal);
  3473.         BrMaterialFree(gPath_mat_normal);
  3474.         BrMaterialRemove(gPath_mat_calc);
  3475.         BrMaterialFree(gPath_mat_calc);
  3476.         gPath_actor = NULL;
  3477.     }
  3478. }
  3479.  
  3480. // IDA: void __usercall GetPedPos(int *pPed_index@<EAX>, int *pPoint_index@<EDX>)
  3481. void GetPedPos(int* pPed_index, int* pPoint_index) {
  3482.     int i;
  3483.     int j;
  3484.     //int point_count; // Pierre-Marie Baty -- unused variable
  3485.     br_vector3 the_point;
  3486.     //br_vector3 last_point; // Pierre-Marie Baty -- unused variable
  3487.     br_scalar min_distance;
  3488.     br_scalar the_distance;
  3489.     LOG_TRACE("(%p, %p)", pPed_index, pPoint_index);
  3490.  
  3491.     min_distance = BR_SCALAR_MAX;
  3492.     for (i = 0; i < gPed_count; i++) {
  3493.         for (j = 0; j < gPedestrian_array[i].number_of_instructions; j++) {
  3494.             if (gPedestrian_array[i].instruction_list[j].type == ePed_instruc_point || gPedestrian_array[i].instruction_list[j].type == ePed_instruc_xpoint) {
  3495.                 the_point = gPedestrian_array[i].instruction_list[j].data.point_data.position;
  3496.                 if (the_point.v[Y] >= 500.f) {
  3497.                     the_point.v[Y] -= 999.6f;
  3498.                     the_point.v[Y] = FindYVerticallyBelow2(&the_point);
  3499.                     if (the_point.v[Y] < -100.f) {
  3500.                         the_point.v[Y] = 1000.f;
  3501.                         the_point.v[Y] = FindYVerticallyBelow2(&the_point);
  3502.                     }
  3503.                 }
  3504.                 the_distance = Vector3DistanceSquared(&the_point, gOur_pos);
  3505.                 if (the_distance < min_distance) {
  3506.                     *pPed_index = i;
  3507.                     *pPoint_index = j;
  3508.                     min_distance = the_distance;
  3509.                 }
  3510.             }
  3511.             // last_point = the_point;
  3512.         }
  3513.     }
  3514. }
  3515.  
  3516. // IDA: void __cdecl ShowPedPos()
  3517. void ShowPedPos(void) {
  3518.     int min_ped;
  3519.     int min_point;
  3520.     char s[255];
  3521.     LOG_TRACE("()");
  3522.  
  3523.     GetPedPos(&min_ped, &min_point);
  3524.     sprintf(s, "Nearest pedestrian is #%d, point #%d", min_ped + 1, min_point + 1);
  3525.     NewTextHeadupSlot(4, 0, 3000, -1, s);
  3526. }
  3527.  
  3528. // IDA: void __cdecl ShowPedPaths()
  3529. void ShowPedPaths(void) {
  3530.     int i;
  3531.     //br_model* the_model; // Pierre-Marie Baty -- unused variable
  3532.     LOG_TRACE("()");
  3533.  
  3534.     if (gPath_actor == NULL) {
  3535.         gPath_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
  3536.         BrActorAdd(gNon_track_actor, gPath_actor);
  3537.  
  3538.         gPath_mat_normal = BrMaterialAllocate(NULL);
  3539.         gPath_mat_normal->index_base = 3;
  3540.         gPath_mat_normal->index_range = 4;
  3541.         gPath_mat_normal->flags |= BR_MATF_TWO_SIDED;
  3542.         BrMaterialAdd(gPath_mat_normal);
  3543.  
  3544.         gPath_mat_calc = BrMaterialAllocate(NULL);
  3545.         gPath_mat_calc->index_base = 93;
  3546.         gPath_mat_calc->index_range = 4;
  3547.         gPath_mat_calc->flags |= BR_MATF_TWO_SIDED;
  3548.         BrMaterialAdd(gPath_mat_calc);
  3549.  
  3550.         gInit_pos_mat_calc = BrMaterialAllocate(NULL);
  3551.         gInit_pos_mat_calc->index_base = 51;
  3552.         gInit_pos_mat_calc->index_range = 4;
  3553.         gInit_pos_mat_calc->flags |= BR_MATF_TWO_SIDED;
  3554.         BrMaterialAdd(gInit_pos_mat_calc);
  3555.  
  3556.         for (i = 0; i < gPed_count; i++) {
  3557.             BuildPedPaths(gPedestrian_array[i].instruction_list,
  3558.                 gPedestrian_array[i].number_of_instructions,
  3559.                 gPedestrian_array[i].first_instruction);
  3560.         }
  3561.     }
  3562.     if (gPath_actor->render_style == BR_RSTYLE_FACES) {
  3563.         gPath_actor->render_style = BR_RSTYLE_NONE;
  3564.     } else {
  3565.         gPath_actor->render_style = BR_RSTYLE_FACES;
  3566.     }
  3567. }
  3568.  
  3569. // IDA: void __cdecl PullPedPoint()
  3570. void PullPedPoint(void) {
  3571.     int the_ped;
  3572.     int the_point;
  3573.     LOG_TRACE("()");
  3574.  
  3575.     if (gPed_instruc_count == 0) {
  3576.         GetPedPos(&the_ped, &the_point);
  3577.         gPedestrian_array[the_ped].instruction_list[the_point].data.point_data.position = *gOur_pos;
  3578.         WriteOutPeds();
  3579.         DisposePedPaths();
  3580.         ShowPedPaths();
  3581.     }
  3582. }
  3583.  
  3584. // IDA: void __cdecl PullPedPointAir()
  3585. void PullPedPointAir(void) {
  3586.     int the_ped;
  3587.     int the_point;
  3588.     LOG_TRACE("()");
  3589.  
  3590.     if (gPed_instruc_count == 0) {
  3591.         GetPedPos(&the_ped, &the_point);
  3592.         gPedestrian_array[the_ped].instruction_list[the_point].data.point_data.position = *gOur_pos;
  3593.         gPedestrian_array[the_ped].instruction_list[the_point].data.point_data.position.v[Y] += 1000.4f;
  3594.         WriteOutPeds();
  3595.         DisposePedPaths();
  3596.         ShowPedPaths();
  3597.     }
  3598. }
  3599.  
  3600. // IDA: void __cdecl DeletePedPath()
  3601. void DeletePedPath(void) {
  3602.     int the_ped;
  3603.     int the_point;
  3604.     int i;
  3605.     LOG_TRACE("()");
  3606.  
  3607.     GetPedPos(&the_ped, &the_point);
  3608.     for (i = the_ped; i < gPed_count - 1; i++) {
  3609.         gPedestrian_array[i] = gPedestrian_array[i + 1];
  3610.     }
  3611.     gPed_count--;
  3612.     WriteOutPeds();
  3613.     DisposePedPaths();
  3614.     ShowPedPaths();
  3615. }
  3616.  
  3617. // IDA: void __cdecl DeletePedPoint()
  3618. void DeletePedPoint(void) {
  3619.     LOG_TRACE("()");
  3620.  
  3621.     if (gPed_instruc_count == 0) {
  3622.         return;
  3623.     }
  3624.     if (gPed_instruc_count == 1) {
  3625.         ScrubPedestrian();
  3626.     } else {
  3627.         if (gInit_ped_instruc == gPed_instruc_count) {
  3628.             gInit_ped_instruc--;
  3629.         }
  3630.         gPed_instruc_count--;
  3631.         MungeShowPedPath();
  3632.     }
  3633. }
  3634.  
  3635. // IDA: void __cdecl DisposePedestrians()
  3636. void DisposePedestrians(void) {
  3637.     int i;
  3638.     int j;
  3639.     tPedestrian_data* the_pedestrian;
  3640.     LOG_TRACE("()");
  3641.  
  3642.     for (i = 0; i < COUNT_OF(gPed_gibs); i++) {
  3643.         PossibleService();
  3644.         BrModelRemove(gPed_gibs[i].actor->model);
  3645.         BrModelFree(gPed_gibs[i].actor->model);
  3646.         gPed_gibs[i].actor->model = NULL;
  3647.         if (gPed_gibs[i].size >= 0) {
  3648.             BrActorRemove(gPed_gibs[i].actor);
  3649.         }
  3650.         BrActorFree(gPed_gibs[i].actor);
  3651.     }
  3652.     for (i = 0; i < COUNT_OF(gPed_gib_materials); i++) {
  3653.         for (j = 0; j < gPed_size_counts[i]; j++) {
  3654.             BrMapRemove(gPed_gib_materials[i].materials[j]->colour_map);
  3655.             BrPixelmapFree(gPed_gib_materials[i].materials[j]->colour_map);
  3656.             gPed_gib_materials[i].materials[j]->colour_map = NULL;
  3657.             BrMaterialRemove(gPed_gib_materials[i].materials[j]);
  3658.             BrMaterialFree(gPed_gib_materials[i].materials[j]);
  3659.         }
  3660.     }
  3661.  
  3662.     // AddPed->CreatePedestrian needs the gPedestrian array.
  3663.     if (gPed_instruc_count != 0) {
  3664.         AddPed();
  3665.     }
  3666.  
  3667.     for (i = 0; i < gPed_count; i++) {
  3668.         the_pedestrian = &gPedestrian_array[i];
  3669.         PossibleService();
  3670.         BrActorRemove(the_pedestrian->actor);
  3671.         BrActorFree(the_pedestrian->actor);
  3672.         BrMemFree(the_pedestrian->instruction_list);
  3673.         if (!the_pedestrian->cloned) {
  3674.             BrMemFree(the_pedestrian->action_list);
  3675.             BrMemFree(the_pedestrian->sequences);
  3676.         }
  3677.     }
  3678.     ClearOutStorageSpace(&gPedestrians_storage_space);
  3679.     BrMemFree(gPedestrian_array);
  3680.     BrTableRemove(gProx_ray_shade_table);
  3681.     BrPixelmapFree(gProx_ray_shade_table);
  3682.     DisposePedPaths();
  3683. }
  3684.  
  3685. // IDA: void __cdecl DoPedReport()
  3686. void DoPedReport(void) {
  3687.     FILE* f;
  3688.     tPath_name the_path;
  3689.     time_t the_bloody_time;
  3690.     int i;
  3691.     int j;
  3692.     int count;
  3693.     int last_ref_num;
  3694.     int ped_count;     // added by dethrace
  3695.     int powerup_count; // added by dethrace
  3696.     char s[256];       // added by dethrace
  3697.     LOG_TRACE("()");
  3698.  
  3699.     powerup_count = 0;
  3700.     ped_count = 0;
  3701.     PathCat(the_path, gApplication_path, "PEDINFO.TXT");
  3702.     f = fopen(the_path, "at");
  3703.     time(&the_bloody_time);
  3704.     fprintf(f, "PEDESTRIAN REPORT FOR '%s' ON %s\n\n", gCurrent_race.name, ctime(&the_bloody_time));
  3705.     fprintf(f, "RefNum   Count\n===============================\n");
  3706.     last_ref_num = -1;
  3707.     for (i = 0; i < gPed_count; i++) {
  3708.         if (last_ref_num < gPedestrian_array[i].ref_number) {
  3709.             last_ref_num = gPedestrian_array[i].ref_number;
  3710.         }
  3711.     }
  3712.     for (i = 0; i <= last_ref_num; i++) {
  3713.         if (i == 100) {
  3714.             fprintf(f, "\n");
  3715.         }
  3716.         count = 0;
  3717.         for (j = 0; j < gPed_count; j++) {
  3718.             if (gPedestrian_array[j].ref_number == j) {
  3719.                 count++;
  3720.             }
  3721.         }
  3722.         if (count != 0) {
  3723.             if (i < 100) {
  3724.                 s[0] = '\0';
  3725.                 ped_count += count;
  3726.             } else {
  3727.                 GetPowerupMessage(i - 100, s);
  3728.                 powerup_count += count;
  3729.             }
  3730.             fprintf(f, "%6d    %5d      %s\n", i, count, s);
  3731.         }
  3732.     }
  3733.     fprintf(f, "\n\nSUMMARY:\n\n");
  3734.     fprintf(f, "Peds:     %5d\n", ped_count);
  3735.     fprintf(f, "Powerups: %5d\n", powerup_count);
  3736.     fprintf(f, "\n\n\n\n");
  3737.     fclose(f);
  3738. }
  3739.  
  3740. // IDA: void __usercall RenderProximityRays(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>, tU32 pTime)
  3741. void RenderProximityRays(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_actor* pCamera, br_matrix34* pCamera_to_world, tU32 pTime) {
  3742.     int i;
  3743.     float seed;
  3744.     tU32 the_time;
  3745.     br_vector3 car_pos;
  3746.     br_vector3 ped_pos;
  3747.     br_vector3 car_pos_cam;
  3748.     br_vector3 ped_pos_cam;
  3749.     br_vector3 car_add;
  3750.     br_vector3 car_add_c;
  3751.     br_vector3 ped_add;
  3752.     br_vector3 ray;
  3753.     br_vector3 r1;
  3754.     br_vector3 from_pos;
  3755.     br_vector3 to_pos;
  3756.     br_model* car_model;
  3757.     br_scalar distance;
  3758.     br_scalar t;
  3759.     LOG_TRACE("(%p, %p, %p, %p, %d)", pRender_screen, pDepth_buffer, pCamera, pCamera_to_world, pTime);
  3760.  
  3761.     the_time = GetTotalTime();
  3762.     StartPipingSession(ePipe_chunk_prox_ray);
  3763.     for (i = 0; i < COUNT_OF(gProximity_rays); i++) {
  3764.         if (gProximity_rays[i].start_time == 0) {
  3765.             continue;
  3766.         }
  3767.         if (the_time - gProximity_rays[i].start_time < 500) {
  3768.             AddProxRayToPipingSession(i,
  3769.                 gProximity_rays[i].car,
  3770.                 GET_PEDESTRIAN_INDEX(gProximity_rays[i].ped),
  3771.                 gProximity_rays[i].start_time);
  3772.             car_model = gProximity_rays[i].car->car_model_actors[gProximity_rays[i].car->principal_car_actor].actor->model;
  3773.  
  3774.             BrVector3Set(&car_add_c, 0.f, (car_model->bounds.max.v[Y] - car_model->bounds.min.v[Y]) / -5.f, 0.f);
  3775.             BrMatrix34ApplyV(&car_add, &car_add_c, &gProximity_rays[i].car->car_master_actor->t.t.mat);
  3776.             BrVector3Add(&car_pos, &gProximity_rays[i].car->pos, &car_add);
  3777.             DRMatrix34TApplyP(&car_pos_cam, &car_pos, &gCamera_to_world);
  3778.  
  3779.             BrVector3Set(&ped_add, 0.f, gProximity_rays[i].ped->actor->t.t.mat.m[1][1] / 2.f, 0.f);
  3780.             BrVector3Add(&ped_pos, &gProximity_rays[i].ped->pos, &ped_add);
  3781.             DRMatrix34TApplyP(&ped_pos_cam, &ped_pos, &gCamera_to_world);
  3782.  
  3783.             BrVector3Sub(&r1, &ped_pos_cam, &car_pos_cam);
  3784.             distance = BrVector3Length(&r1);
  3785.             BrVector3Normalise(&r1, &r1);
  3786.  
  3787.             from_pos = car_pos_cam;
  3788.  
  3789.             seed = the_time + ped_pos.v[X] + ped_pos.v[Y] + ped_pos.v[Z] + car_pos.v[X] + car_pos.v[Y] + car_pos.v[Z];
  3790.             srand(seed);
  3791.  
  3792.             t = 0.f;
  3793.             do {
  3794.                 BrVector3Scale(&ray, &r1, t);
  3795.                 BrVector3Add(&to_pos, &ray, &car_pos_cam);
  3796.                 to_pos.v[X] += SRandomPosNeg(0.1f);
  3797.                 to_pos.v[Y] += SRandomPosNeg(0.1f);
  3798.                 to_pos.v[Z] += SRandomPosNeg(0.1f);
  3799.                 DrawLine3D(&to_pos, &from_pos, pRender_screen, pDepth_buffer, gProx_ray_shade_table);
  3800.                 from_pos = to_pos;
  3801.                 t += 0.05f;
  3802.             } while (t < distance);
  3803.             DrawLine3D(&ped_pos_cam, &from_pos, pRender_screen, pDepth_buffer, gProx_ray_shade_table);
  3804.         } else {
  3805.             gProximity_rays[i].start_time = 0;
  3806.         }
  3807.     }
  3808.     EndPipingSession();
  3809. }
  3810.  
  3811. // IDA: void __usercall AdjustProxRay(int pRay_index@<EAX>, tU16 pCar_ID@<EDX>, tU16 pPed_index@<EBX>, tU32 pTime@<ECX>)
  3812. void AdjustProxRay(int pRay_index, tU16 pCar_ID, tU16 pPed_index, tU32 pTime) {
  3813.     LOG_TRACE("(%d, %d, %d, %d)", pRay_index, pCar_ID, pPed_index, pTime);
  3814.  
  3815.     if ((pCar_ID & 0xff00) == 0) {
  3816.         gProximity_rays[pRay_index].car = &gProgram_state.current_car;
  3817.     } else {
  3818.         gProximity_rays[pRay_index].car = GetCarSpec(pCar_ID >> 8, pCar_ID & 0xff);
  3819.     }
  3820.     gProximity_rays[pRay_index].ped = &gPedestrian_array[pPed_index];
  3821.     gProximity_rays[pRay_index].start_time = pTime;
  3822. }
  3823.  
  3824. // IDA: void __usercall ReceivedPedestrian(tNet_contents *pContents@<EAX>, tNet_message *pMessage@<EDX>, tU32 pReceive_time@<EBX>)
  3825. void ReceivedPedestrian(tNet_contents* pContents, tNet_message* pMessage, tU32 pReceive_time) {
  3826.     tPedestrian_data* the_pedestrian;
  3827.     //tNet_game_player_info* sender; // Pierre-Marie Baty -- unused variable
  3828.     tNet_game_player_info* murderer;
  3829.     int modified_action;
  3830.     int modified_action_2;
  3831.     int action;
  3832.     int instruction;
  3833.     //int dead; // Pierre-Marie Baty -- unused variable
  3834.     tPedestrian_sequence* the_sequence;
  3835.     LOG_TRACE("(%p, %p, %d)", pContents, pMessage, pReceive_time);
  3836.  
  3837.     if (pContents->data.pedestrian.index >= 0 && pContents->data.pedestrian.index < gPed_count) {
  3838.         the_pedestrian = &gPedestrian_array[pContents->data.pedestrian.index];
  3839.         action = (pContents->data.pedestrian.action_instruction & 0xf) - 1;
  3840.         if (action < 0) {
  3841.             action = 0;
  3842.         } else if (action >= the_pedestrian->number_of_actions) {
  3843.             action = the_pedestrian->number_of_actions - 1;
  3844.         }
  3845.         instruction = pContents->data.pedestrian.action_instruction >> 4;
  3846.         if (instruction < 0) {
  3847.             instruction = 0;
  3848.         } else if (instruction >= the_pedestrian->number_of_instructions) {
  3849.             instruction = the_pedestrian->number_of_instructions - 1;
  3850.         }
  3851.         if (pContents->data.pedestrian.flags & 0x8) {
  3852.             murderer = NetPlayerFromID(pContents->data.pedestrian.murderer);
  3853.             modified_action = action;
  3854.             if (action == the_pedestrian->fatal_ground_impact_action) {
  3855.                 modified_action = the_pedestrian->fatal_car_impact_action;
  3856.             }
  3857.             if (the_pedestrian->reverse_frames) {
  3858.                 modified_action_2 = 0;
  3859.             } else {
  3860.                 modified_action_2 = the_pedestrian->current_action;
  3861.                 if (modified_action_2 == the_pedestrian->fatal_ground_impact_action) {
  3862.                     modified_action_2 = the_pedestrian->fatal_car_impact_action;
  3863.                 }
  3864.             }
  3865.             if (modified_action != modified_action_2
  3866.                 && modified_action == the_pedestrian->fatal_car_impact_action
  3867.                 && the_pedestrian->ref_number < 100
  3868.                 && gNet_mode == eNet_mode_host
  3869.                 && gCurrent_net_game->type == eNet_game_type_carnage
  3870.                 && murderer != NULL
  3871.                 && the_pedestrian->murderer == -1) {
  3872.                 the_pedestrian->reverse_frames = 0;
  3873.                 murderer->score++;
  3874.                 gProgram_state.peds_killed++;
  3875.                 the_pedestrian->murderer = murderer->ID;
  3876.             }
  3877.         }
  3878.         if ((!the_pedestrian->active || gWait_for_it) && the_pedestrian->hit_points != -100) {
  3879.             if (pContents->data.pedestrian.flags & 0x2) {
  3880.                 the_pedestrian->mid_air = 1;
  3881.             } else {
  3882.                 the_pedestrian->mid_air = 0;
  3883.             }
  3884.             if (pContents->data.pedestrian.flags & 0x4) {
  3885.                 the_pedestrian->instruction_direction = -1;
  3886.             } else {
  3887.                 the_pedestrian->instruction_direction = 1;
  3888.             }
  3889.             if (the_pedestrian->current_action != action
  3890.                 && the_pedestrian->current_action != the_pedestrian->non_fatal_car_impact_action
  3891.                 && the_pedestrian->current_action != the_pedestrian->fatal_ground_impact_action) {
  3892.                 gPed_sound_disable = 1;
  3893.                 ChangeActionTo(the_pedestrian, action, 0);
  3894.                 gPed_sound_disable = 0;
  3895.             }
  3896.             if (pContents->data.pedestrian.flags & 0x10) {
  3897.                 the_pedestrian->hit_points = -100;
  3898.             } else {
  3899.                 if (pContents->data.pedestrian.flags & 0x8) {
  3900.                     if (the_pedestrian->hit_points > 0) {
  3901.                         the_pedestrian->current_sequence = 0;
  3902.                         the_sequence = &the_pedestrian->sequences[the_pedestrian->action_list[the_pedestrian->current_action].sequences[0].sequence_index];
  3903.                         the_pedestrian->current_frame = the_sequence->number_of_frames - 1;
  3904.                         the_pedestrian->done_initial = 0;
  3905.                         the_pedestrian->colour_map = the_sequence->frames[the_pedestrian->current_frame].pixelmap;
  3906.                     }
  3907.                     the_pedestrian->hit_points = -10;
  3908.                 } else {
  3909.                     the_pedestrian->hit_points = 0;
  3910.                 }
  3911.             }
  3912.             if (the_pedestrian->current_instruction != instruction) {
  3913.                 the_pedestrian->current_instruction = instruction;
  3914.                 if (the_pedestrian->current_action != the_pedestrian->fatal_car_impact_action) {
  3915.                     PedestrianNextInstruction(the_pedestrian, 0.f, 1, 0);
  3916.                 }
  3917.             }
  3918.             the_pedestrian->current_speed = pContents->data.pedestrian.speed;
  3919.             BrVector3Copy(&the_pedestrian->pos, &pContents->data.pedestrian.pos);
  3920.             BrVector3Copy(&the_pedestrian->actor->t.t.translate.t, &pContents->data.pedestrian.pos);
  3921.             if (pContents->data.pedestrian.flags & 0x20) {
  3922.                 BrVector3Copy(&the_pedestrian->to_pos, &pContents->data.pedestrian.to_pos);
  3923.             }
  3924.         } else if (the_pedestrian->current_action == the_pedestrian->fatal_car_impact_action
  3925.             || action != the_pedestrian->fatal_car_impact_action
  3926.             || the_pedestrian->reverse_frames) {
  3927.             if (the_pedestrian->action_list[the_pedestrian->current_action].danger_level < the_pedestrian->action_list[action].danger_level) {
  3928.                 ChangeActionTo(the_pedestrian, action, 0);
  3929.             }
  3930.         } else {
  3931.             the_pedestrian->fate = NetCarFromPlayerID(pContents->data.pedestrian.murderer);
  3932.         }
  3933.         if (pContents->data.pedestrian.flags & 0x40
  3934.             && the_pedestrian->ref_number >= 100
  3935.             && pContents->data.pedestrian.respawn_time_or_spin_period
  3936.             && the_pedestrian->respawn_time == 0) {
  3937.             the_pedestrian->respawn_time = pContents->data.pedestrian.respawn_time_or_spin_period;
  3938.         }
  3939.     }
  3940. }
  3941.  
  3942. // IDA: void __usercall SendAllPedestrianPositions(tPlayer_ID pPlayer@<EAX>)
  3943. void SendAllPedestrianPositions(tPlayer_ID pPlayer) {
  3944.     int i;
  3945.     tPedestrian_data* the_pedestrian;
  3946.     //tNet_contents* the_contents; // Pierre-Marie Baty -- unused variable
  3947.     LOG_TRACE("(%d)", pPlayer);
  3948.  
  3949.     gSend_peds = 1;
  3950.     for (i = 0; i < gPed_count; i++) {
  3951.         the_pedestrian = &gPedestrian_array[i];
  3952.         if (the_pedestrian->munged) {
  3953.             SendPedestrian(the_pedestrian, i);
  3954.         }
  3955.     }
  3956. }
  3957.