Subversion Repositories Games.Carmageddon

Rev

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

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