#include "datatypes_unfiltered.h" #include "globals_unfiltered.h" #include "source_unfiltered.h" void __cdecl lego::front::Advisor_Initialise(char *gameName,LegoCamera *cameraMain,Viewport *viewMain) { globs::advisorGlobs.positionName[0] = "Advisor_Objective"; globs::advisorGlobs.positionName[1] = "Advisor_ObjectiveAcheived"; globs::advisorGlobs.positionName[2] = "Advisor_ObjectiveFailed"; globs::advisorGlobs.positionName[3] = "Advisor_IconPoint_Normal"; globs::advisorGlobs.positionName[4] = "Advisor_IconPoint_BackButton"; globs::advisorGlobs.positionName[5] = "Advisor_IconPoint_TopButtons"; globs::advisorGlobs.positionName[6] = "Advisor_PanelPoint_RadarToggle"; globs::advisorGlobs.positionName[7] = "Advisor_PanelPoint_RadarTaggedObjectView"; globs::advisorGlobs.positionName[8] = "Advisor_PanelPoint_RadarZoomIn"; globs::advisorGlobs.positionName[9] = "Advisor_PanelPoint_RadarZoomOut"; globs::advisorGlobs.positionName[10] = "Advisor_PanelPoint_RadarMapView"; globs::advisorGlobs.positionName[11] = "Advisor_PanelPoint_InfoDockGoto"; globs::advisorGlobs.positionName[12] = "Advisor_PanelPoint_InfoDockClose"; globs::advisorGlobs.positionName[13] = "Advisor_PanelPoint_TopPanelInfo"; globs::advisorGlobs.positionName[14] = "Advisor_PanelPoint_TopPanelOptions"; globs::advisorGlobs.positionName[15] = "Advisor_PanelPoint_TopPanelPriorities"; globs::advisorGlobs.positionName[16] = "Advisor_PanelPoint_TopPanelCallToArms"; globs::advisorGlobs.positionName[17] = "Advisor_PanelPoint_TopPanelGoBack"; globs::advisorGlobs.positionName[18] = "Advisor_PanelPoint_ControlZoomIn"; globs::advisorGlobs.positionName[19] = "Advisor_PanelPoint_ControlZoomOut"; globs::advisorGlobs.positionName[20] = "Advisor_TalkInGame"; globs::advisorGlobs.animName[0] = "Advisor_Anim_PointToMap"; globs::advisorGlobs.animName[1] = "Advisor_Anim_Point_N"; globs::advisorGlobs.animName[2] = "Advisor_Anim_Point_NE"; globs::advisorGlobs.animName[3] = "Advisor_Anim_Point_E"; globs::advisorGlobs.animName[4] = "Advisor_Anim_Point_SE"; globs::advisorGlobs.animName[5] = "Advisor_Anim_Point_S"; globs::advisorGlobs.animName[6] = "Advisor_Anim_Point_SW"; globs::advisorGlobs.animName[7] = "Advisor_Anim_Point_W"; globs::advisorGlobs.animName[8] = "Advisor_Anim_Point_NW"; globs::advisorGlobs.animName[9] = "Advisor_Anim_Point_Up"; globs::advisorGlobs.animName[10] = "Advisor_Anim_Talk_Top"; globs::advisorGlobs.cameraCont = cameraMain->contCam; globs::advisorGlobs.viewMain = viewMain; globs::advisorGlobs.lightCont = gfx::Container_MakeLight(cameraMain->contCam,D3DRMLIGHT_DIRECTIONAL,1.0,1.0,1.0); gfx::Container_SetOrientation (globs::advisorGlobs.lightCont,cameraMain->contCam,0.0,0.0,-1.0,0.0,1.0,0.0); gfx::Container_Hide(globs::advisorGlobs.lightCont,TRUE); globs::advisorGlobs.flags = ADVISOR_GLOB_FLAG_NONE; return; } // Hard stop on the advisor animation, immediately hides. void __cdecl lego::front::Advisor_Stop(void) { Container *animCont; animCont = globs::advisorGlobs.anims [globs::advisorGlobs.positions[globs::advisorGlobs.currType].animType].cont; if (animCont != NULL) { gfx::Container_Hide(animCont,TRUE); } globs::advisorGlobs.flags &= ~ADVISOR_GLOB_FLAG_ANIMATING; gfx::Container_Hide(globs::advisorGlobs.lightCont,TRUE); return; } // param_unused: 200.0f is passed from Lego_Initialise void __cdecl lego::front::Advisor_InitViewport(float param_unused) { // It seems there used to be more functionality here, but it's been gutted. lego::view::Viewport_GetBackClip(globs::advisorGlobs.viewMain); lego::view::Viewport_GetFrontClip(globs::advisorGlobs.viewMain); globs::advisorGlobs.viewZ = 0.96; return; } // sqrt(((a.x - b.x)*(a.x - b.x)) + ((a.y - b.y)*(a.y - b.y))) float10 __cdecl lego::math::Maths_Vector2DDistance(Point2F *a,Point2F *b) { float10 fVar1; float10 fVar2; fVar1 = (float10)a->y - (float10)b->y; fVar2 = (float10)a->x - (float10)b->x; return SQRT(fVar2 * fVar2 + fVar1 * (float10)(float)fVar1); } // ,, // NOTE last two parameters can be set to any value if the anim is not made to loop e.g. 0,0 // // Advisor_Anim_Point_Up Mini-Figures\Captain\NEW_Captain_Point_CALL_T_ARMS,1.04,4.0 // Advisor_Anim_Talk_Top Mini-Figures\Captain\NEW_Captain_Point_QTalk,1.04,2.4 void __cdecl lego::front::Advisor_LoadAnims(Config *config,char *gameName) { char *keyPath; char *value; Container *cont; char **pAnimName; AdvisorAnimData *pAnim; float10 fVar1; char *stringParts [3]; char reduceName [64]; pAnim = globs::advisorGlobs.anims; pAnimName = globs::advisorGlobs.animName; do { keyPath = cfg::Config_BuildStringID(gameName,"Advisor",*pAnimName,0); value = cfg::Config_GetTempStringValue(config,keyPath); if (value == NULL) { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEANIMATION) == MAIN_FLAG_NONE) { std::sprintf(reduceName,"!%s",*pAnimName); keyPath = cfg::Config_BuildStringID(gameName,"Advisor",*pAnimName,0); value = cfg::Config_GetTempStringValue(config,keyPath); } if (value != NULL) goto LAB_004012f0; } else { LAB_004012f0: // BAD BAD BAD BAD! Using Util_Tokenise on TempStringValue (should not be modified) util::Util_Tokenise(value,stringParts,","); cont = gfx::Container_Load(globs::advisorGlobs.cameraCont,stringParts[0],"LWS",TRUE); pAnim->cont = cont; if (cont != NULL) { gfx::Container_SetOrientation(cont,globs::advisorGlobs.cameraCont,0.0,0.0,1.0,0.0,1.0,0.0); gfx::Container_Hide(pAnim->cont,TRUE); } fVar1 = std::atof(stringParts[1]); pAnim->loopStartTime = (float)(fVar1 * (float10)25.0); fVar1 = std::atof(stringParts[2]); pAnim->loopEndTime = (float)(fVar1 * (float10)25.0); } pAnimName = pAnimName + 1; pAnim = pAnim + 1; if ((char **)((int)globs::advisorGlobs.animName + 0x2b) < pAnimName) { return; } } while( true ); } BOOL __cdecl lego::front::Advisor_GetAdvisorType(char *advisorName,Advisor_Type *out_advisorType) { int cmp; char **pPositionName; int i; i = 0; pPositionName = (char **)&globs::advisorGlobs; do { cmp = std::_stricmp(*pPositionName,advisorName); if (cmp == 0) { *out_advisorType = i; return TRUE; } pPositionName = (char **)((int)pPositionName + 4); // index++ i += Advisor_ObjectiveAcheived; // index < ADVISOR__COUNT (21) } while (pPositionName < globs::advisorGlobs.positions); return FALSE; } // out_vector = { (a.y * b.z) - (a.z * b.y), // (a.z * b.x) - (a.x * b.z), // (a.x * b.y) - (a.y * b.x) } Vector3F * __cdecl lego::math::Maths_Vector3DCrossProduct(Vector3F *out_vector,Vector3F *a,Vector3F *b) { out_vector->x = b->z * a->y - a->z * b->y; out_vector->y = a->z * b->x - b->z * a->x; out_vector->z = b->y * a->x - a->y * b->x; return out_vector; } BOOL __cdecl lego::front::Advisor_GetAnimType(char *animName,Advisor_Anim *out_animType) { int cmp; char **pAnimName; int i; i = 0; pAnimName = globs::advisorGlobs.animName; do { cmp = std::_stricmp(*pAnimName,animName); if (cmp == 0) { *out_animType = i; return TRUE; } pAnimName = pAnimName + 1; // index++ i += Advisor_Anim_Point_N; // index < ADVISORANIM__COUNT (11) } while (pAnimName < globs::advisorGlobs.anims); return FALSE; } // out_vector = a + b Vector3F * __cdecl lego::math::Maths_Vector3DAdd(Vector3F *out_vector,Vector3F *a,Vector3F *b) { out_vector->x = b->x + a->x; out_vector->y = a->y + b->y; out_vector->z = a->z + b->z; return out_vector; } // ,,,,, // // Advisor_IconPoint_TopButtons Advisor_Anim_Point_NE,NULL,SFX_NULL,-25,25,NULL // Advisor_PanelPoint_RadarToggle Advisor_Anim_Point_N,NULL,SFX_NULL,220,65,Panel_Radar void __cdecl lego::front::Advisor_LoadPositions(Config *config,char *gameName,int screenWidth,int screenHeight) { char *arrayID; Config *prop; BOOL BVar1; int cmp; float10 fVar2; Panel_Type panelType; Text_Type textType; Advisor_Anim animType; float x; float y; SFX_ID sfxID; Advisor_Type advisorIndex; char *parts [6]; char arrayName [128]; std::sprintf(arrayName,"AdvisorPositions%ix%i",screenWidth,screenHeight); arrayID = cfg::Config_BuildStringID(gameName,arrayName,0); for (prop = cfg::Config_FindArray(config,arrayID); prop != NULL; prop = cfg::Config_GetNextItem(prop)) { // TEXT__COUNT (26) treated as NULL textType = Text_Type_Count; // PANEL__COUNT (12) treated as NULL panelType = Panel_Type_Count; BVar1 = Advisor_GetAdvisorType(prop->key,&advisorIndex); if (BVar1 != 0) { // BAD BAD BAD! Even more using Util_Tokenise with an immutable string!! util::Util_Tokenise(prop->value,parts,","); BVar1 = Advisor_GetAnimType(parts[0],&animType); if ((BVar1 != 0) && (((cmp = std::_stricmp("NULL",parts[1]), cmp == 0 || (BVar1 = Text_GetTextType(parts[1],&textType), BVar1 != 0)) && (BVar1 = snd::SFX_GetType(parts[2],&sfxID), BVar1 != 0)))) { fVar2 = std::atof(parts[3]); x = (float)fVar2; fVar2 = std::atof(parts[4]); y = (float)fVar2; cmp = std::_stricmp("NULL",parts[5]); if ((cmp == 0) || (BVar1 = Panel_GetPanelType(parts[5],&panelType), BVar1 != 0)) { Advisor_AddPosition(advisorIndex,animType,textType,sfxID,panelType,x,y); } } } } return; } // out_vector = a - b Vector3F * __cdecl lego::math::Maths_Vector3DSubtract(Vector3F *out_vector,Vector3F *a,Vector3F *b) { out_vector->x = a->x - b->x; out_vector->y = a->y - b->y; out_vector->z = a->z - b->z; return out_vector; } // out_vector = a * scalar Vector3F * __cdecl lego::math::Maths_Vector3DScale(Vector3F *out_vector,Vector3F *a,float scalar) { out_vector->x = scalar * a->x; out_vector->y = a->y * scalar; out_vector->z = a->z * scalar; return out_vector; } // ref_vector = ref_vector * (1.0 / modulus(ref_vector)) // REFERENCE: modulus(ref_vector) -> sqrt(dot_product(ref_vector, ref_vector)) Vector3F * __cdecl lego::math::Maths_Vector3DNormalize(Vector3F *ref_vector) { float fVar1; // Vector3_Modulus (without 1.0 / _) fVar1 = 1.0 / SQRT(ref_vector->x * ref_vector->x + ref_vector->z * ref_vector->z + ref_vector->y * ref_vector->y); ref_vector->x = fVar1 * ref_vector->x; ref_vector->y = fVar1 * ref_vector->y; ref_vector->z = fVar1 * ref_vector->z; return ref_vector; } void __cdecl lego::front::Advisor_AddPosition (Advisor_Type advisorType,Advisor_Anim animType,Text_Type textType,SFX_ID sfxID, Panel_Type panelType,float x,float y) { AdvisorFlags *pAFlags; globs::advisorGlobs.positions[advisorType].flags = ADVISOR_FLAG_USED; globs::advisorGlobs.positions[advisorType].animType = animType; globs::advisorGlobs.positions[advisorType].textType = textType; globs::advisorGlobs.positions[advisorType].sfxID = sfxID; globs::advisorGlobs.positions[advisorType].x = x; globs::advisorGlobs.positions[advisorType].y = y; globs::advisorGlobs.positions[advisorType].origX = x; globs::advisorGlobs.positions[advisorType].origY = y; globs::advisorGlobs.positions[advisorType].panelType = panelType; // NULL panel if (panelType == Panel_Type_Count) { pAFlags = &globs::advisorGlobs.positions[advisorType].flags; *pAFlags = *pAFlags | ADVISOR_FLAG_NOPANEL; } // non-NULL text if (textType != Text_Type_Count) { pAFlags = &globs::advisorGlobs.positions[advisorType].flags; *pAFlags = *pAFlags | ADVISOR_FLAG_HASTEXT; } return; } void __cdecl lego::front::Advisor_SetParameters(Advisor_Type advisorType,Panel_Type panelType,float x,float y) { AdvisorFlags aflags; globs::advisorGlobs.positions[advisorType].x = x; globs::advisorGlobs.positions[advisorType].y = y; globs::advisorGlobs.positions[advisorType].panelType = panelType; aflags = globs::advisorGlobs.positions[advisorType].flags; // NULL panel if (panelType == Panel_Type_Count) { globs::advisorGlobs.positions[advisorType].flags = aflags | ADVISOR_FLAG_NOPANEL; return; } globs::advisorGlobs.positions[advisorType].flags = aflags & ~ADVISOR_FLAG_NOPANEL; return; } void __cdecl lego::front::Advisor_GetOrigPos(Advisor_Type advisorType,float *out_origX,float *out_origY) { *out_origX = globs::advisorGlobs.positions[advisorType].origX; *out_origY = globs::advisorGlobs.positions[advisorType].origY; return; } BOOL __cdecl lego::front::Advisor_Start(Advisor_Type advisorType,BOOL loop) { if ((((globs::advisorGlobs.positions[advisorType].flags & ADVISOR_FLAG_USED) != ADVISOR_FLAG_NONE) && (globs::legoGlobs.viewMode != ViewMode_FP)) && ((globs::advisorGlobs.flags & ADVISOR_GLOB_FLAG_ANIMATING) == ADVISOR_GLOB_FLAG_NONE)) { globs::advisorGlobs.currType = advisorType; Advisor_PlaySFX(advisorType); if (loop != 0) { globs::advisorGlobs.flags = globs::advisorGlobs.flags | (ADVISOR_GLOB_FLAG_ANIMATING|ADVISOR_GLOB_FLAG_LOOPING); return TRUE; } globs::advisorGlobs.flags = globs::advisorGlobs.flags & ~ADVISOR_GLOB_FLAG_LOOPING | ADVISOR_GLOB_FLAG_ANIMATING; return TRUE; } return FALSE; } void __cdecl lego::front::Advisor_PlaySFX(Advisor_Type advisorType) { Container *animCont; animCont = globs::advisorGlobs.anims[globs::advisorGlobs.positions[advisorType].animType].cont; if (animCont != NULL) { gfx::Container_Hide(animCont,FALSE); gfx::Container_SetAnimationTime(animCont,0.0); snd::SFX_Random_PlaySoundNormal(globs::advisorGlobs.positions[advisorType].sfxID,FALSE); snd::SFX_AddToQueue(SFX_CaptainSlide,SoundMode_Once); } return; } void __cdecl lego::front::Advisor_Update(float elapsed) { BOOL BVar1; Advisor_Type advisorType; Container *animCont; advisorType = globs::advisorGlobs.currType; animCont = globs::advisorGlobs.anims [globs::advisorGlobs.positions[globs::advisorGlobs.currType].animType].cont; if (animCont != NULL) { if (((globs::advisorGlobs.flags & ADVISOR_GLOB_FLAG_ANIMATING) != ADVISOR_GLOB_FLAG_NONE) && (globs::legoGlobs.viewMode != ViewMode_FP)) { if ((globs::advisorGlobs.positions[globs::advisorGlobs.currType].flags & ADVISOR_FLAG_HASTEXT) != ADVISOR_FLAG_NONE) { Text_DisplayMessage(globs::advisorGlobs.positions[globs::advisorGlobs.currType].textType, TRUE,FALSE); } gfx::Container_Hide(animCont,FALSE); gfx::Container_Hide(globs::advisorGlobs.lightCont,FALSE); gfx::Container_Light_SetEnableContainer(globs::advisorGlobs.lightCont,animCont); Advisor_ViewportTransform(advisorType); BVar1 = Advisor_MoveAnimation(globs::advisorGlobs.positions[advisorType].animType,elapsed); if (BVar1 != 0) { return; } // Animation has ended. globs::advisorGlobs.flags &= ~ADVISOR_GLOB_FLAG_ANIMATING; } gfx::Container_Hide(animCont,TRUE); } gfx::Container_Hide(globs::advisorGlobs.lightCont,TRUE); return; } // Called by Advisor_Update, returns false when the animation has finished (and is not looping). BOOL __cdecl lego::front::Advisor_MoveAnimation(Advisor_Anim animType,float elapsed) { float10 overrun; Container *animCont; animCont = globs::advisorGlobs.anims[animType].cont; overrun = gfx::Container_MoveAnimation(animCont,elapsed); if (((byte)globs::advisorGlobs.flags & ADVISOR_GLOB_FLAG_LOOPING) == 0) { if ((ushort)((ushort)(overrun < (float10)0.0) << 8 | (ushort)(overrun == (float10)0.0) << 0xe) == 0) { // Not looping, end of animation. return FALSE; } } else { // While looping, wrap the animation if we've finished, or if we overrun our // loopEndTime. if ((ushort)((ushort)(overrun < (float10)0.0) << 8 | (ushort)(overrun == (float10)0.0) << 0xe) == 0) { gfx::Container_SetAnimationTime (animCont,(float)((float10)globs::advisorGlobs.anims[animType].loopStartTime + overrun)); return TRUE; } overrun = gfx::Container_GetAnimationTime(animCont); if ((float10)globs::advisorGlobs.anims[animType].loopEndTime <= overrun) { gfx::Container_SetAnimationTime (animCont,(float)((overrun - (float10)globs::advisorGlobs.anims[animType].loopEndTime) + (float10)globs::advisorGlobs.anims[animType].loopStartTime)); return TRUE; } } return TRUE; } // Ends the advisor loop while allowing the final animation cycle can finish. void __cdecl lego::front::Advisor_End(void) { globs::advisorGlobs.flags = globs::advisorGlobs.flags & ~ADVISOR_GLOB_FLAG_LOOPING; return; } void __cdecl lego::front::Advisor_ViewportTransform(Advisor_Type advisorType) { Container *cont; float y; Vector3F vector; Vector4F transform4d; Advisor_Type advisorType_00; advisorType_00 = advisorType; cont = globs::advisorGlobs.anims[globs::advisorGlobs.positions[advisorType].animType].cont; if ((globs::advisorGlobs.positions[advisorType].flags & ADVISOR_FLAG_NOPANEL) == ADVISOR_FLAG_NONE ) { // output -> x, y (get panel position?) Panel_GetPosition(globs::advisorGlobs.positions[advisorType].panelType,(float *)&advisorType,&y) ; } else { advisorType = Advisor_Objective; y = 0.0; } transform4d.x = globs::advisorGlobs.positions[advisorType_00].x + (float)advisorType; transform4d.z = globs::advisorGlobs.viewZ; transform4d.y = globs::advisorGlobs.positions[advisorType_00].y + y; transform4d.w = 1.0; lego::view::Viewport_InverseTransform(globs::advisorGlobs.viewMain,&vector,&transform4d); gfx::Container_SetPosition(cont,NULL,vector.x,vector.y,vector.z); return; } ProgrammerMode __cdecl lego::main::Main_ProgrammerMode(void) { return globs::mainGlobs.programmerLevel; } char * __cdecl lego::main::Main_GetStartLevel(void) { return (char *)(-(uint)((globs::mainGlobs.flags & MAIN_FLAG_STARTLEVEL) != MAIN_FLAG_NONE) & 0x506f8c); } BOOL __cdecl lego::front::Advisor_IsAnimating(void) { return globs::advisorGlobs.flags & ADVISOR_GLOB_FLAG_ANIMATING; } int __cdecl lego::main::appWidth(void) { return globs::mainGlobs.appWidth; } int __cdecl lego::main::appHeight(void) { return globs::mainGlobs.appHeight; } uint __cdecl lego::image::Font_GetStringWidth(Font *font,char *msg,...) { Font_VGetStringInfo(font,(uint *)&font,NULL,msg,&stack0x0000000c); return (uint)font; } void __cdecl lego::image::Font_GetStringInfo(Font *font,uint *out_width,uint *out_lineCount,char *msg,...) { Font_VGetStringInfo(font,out_width,out_lineCount,msg,&stack0x00000014); return; } BOOL __cdecl lego::ai::AIPriority_GetType(char *aiPriorityName,AI_Priority *out_priorityType) { int iVar1; char **ppcVar2; AI_Priority AVar3; AVar3 = AI_Priority_Crystal; ppcVar2 = globs::aiGlobs.priorityName; do { iVar1 = std::_stricmp(aiPriorityName,*ppcVar2); if (iVar1 == 0) { *out_priorityType = AVar3; return TRUE; } ppcVar2 = ppcVar2 + 1; AVar3 += AI_Priority_Ore; } while (ppcVar2 < globs::aiGlobs.priorityValues); return FALSE; } void __cdecl lego::ai::AITask_Initialise(void) { int iVar1; AITask_Globs *pAVar2; int *piVar3; pAVar2 = &globs::aiGlobs; for (iVar1 = 0xc; iVar1 != 0; iVar1 += -1) { pAVar2->listSet[0] = NULL; pAVar2 = (AITask_Globs *)(pAVar2->listSet + 1); } globs::aiGlobs.aitaskName[0] = "AITask_Type_Goto"; globs::aiGlobs.aitaskName[1] = "AITask_Type_Follow"; globs::aiGlobs.aitaskName[2] = "AITask_Type_FollowAttack"; globs::aiGlobs.aitaskName[3] = "AITask_Type_Collect"; globs::aiGlobs.aitaskName[4] = "AITask_Type_Gather"; globs::aiGlobs.aitaskName[12] = "AITask_Type_Clear"; globs::aiGlobs.aitaskName[5] = "AITask_Type_Deposit"; globs::aiGlobs.aitaskName[6] = "AITask_Type_Dump"; globs::aiGlobs.aitaskName[7] = "AITask_Type_Request"; globs::aiGlobs.aitaskName[10] = "AITask_Type_Repair"; globs::aiGlobs.aitaskName[8] = "AITask_Type_Dig"; globs::aiGlobs.aitaskName[9] = "AITask_Type_Dynamite"; globs::aiGlobs.aitaskName[11] = "AITask_Type_Reinforce"; globs::aiGlobs.aitaskName[13] = "AITask_Type_Wait"; globs::aiGlobs.aitaskName[14] = "AITask_Type_AnimationWait"; globs::aiGlobs.aitaskName[15] = "AITask_Type_ElecFence"; globs::aiGlobs.aitaskName[16] = "AITask_Type_Eat"; globs::aiGlobs.aitaskName[17] = "AITask_Type_GotoEat"; globs::aiGlobs.aitaskName[18] = "AITask_Type_FindDriver"; globs::aiGlobs.aitaskName[19] = "AITask_Type_GetTool"; globs::aiGlobs.aitaskName[20] = "AITask_Type_BirdScarer"; globs::aiGlobs.aitaskName[21] = "AITask_Type_Upgrade"; globs::aiGlobs.aitaskName[22] = "AITask_Type_BuildPath"; globs::aiGlobs.aitaskName[23] = "AITask_Type_Train"; globs::aiGlobs.aitaskName[24] = "AITask_Type_Depart"; globs::aiGlobs.aitaskName[25] = "AITask_Type_AttackPath"; globs::aiGlobs.aitaskName[26] = "AITask_Type_AttackRockMonster"; globs::aiGlobs.aitaskName[27] = "AITask_Type_Recharge"; globs::aiGlobs.aitaskName[28] = "AITask_Type_Dock"; globs::aiGlobs.aitaskName[29] = "AITask_Type_AttackObject"; globs::aiGlobs.aitaskName[30] = "AITask_Type_FindLoad"; globs::aiGlobs.priorityName[0] = "AI_Priority_Crystal"; globs::aiGlobs.priorityName[1] = "AI_Priority_Ore"; globs::aiGlobs.priorityName[2] = "AI_Priority_DefaultCollect"; globs::aiGlobs.priorityName[3] = "AI_Priority_Destruction"; globs::aiGlobs.priorityName[4] = "AI_Priority_Construction"; globs::aiGlobs.priorityName[5] = "AI_Priority_Request"; globs::aiGlobs.priorityName[6] = "AI_Priority_Reinforce"; globs::aiGlobs.priorityName[7] = "AI_Priority_Repair"; globs::aiGlobs.priorityName[8] = "AI_Priority_Clearing"; globs::aiGlobs.priorityName[9] = "AI_Priority_Storage"; globs::aiGlobs.priorityName[10] = "AI_Priority_Refining"; globs::aiGlobs.priorityName[11] = "AI_Priority_HealthLow"; globs::aiGlobs.priorityName[12] = "AI_Priority_GetIn"; globs::aiGlobs.priorityName[13] = "AI_Priority_Upgrade"; globs::aiGlobs.priorityName[14] = "AI_Priority_BuildPath"; globs::aiGlobs.priorityName[15] = "AI_Priority_AttackRockMonster"; globs::aiGlobs.priorityName[16] = "AI_Priority_Barrier"; globs::aiGlobs.priorityName[17] = "AI_Priority_FindLoad"; globs::aiGlobs.priorityName[18] = "AI_Priority_Recharge"; globs::aiGlobs.priorityName[19] = "AI_Priority_UpgradeBuilding"; globs::aiGlobs.priorityName[20] = "AI_Priority_Gather"; globs::aiGlobs.priorityName[21] = "AI_Priority_Steal"; globs::aiGlobs.priorityName[22] = "AI_Priority_Punch"; globs::aiGlobs.priorityName[23] = "AI_Priority_Depart"; globs::aiGlobs.priorityName[24] = "AI_Priority_AttackPath"; globs::aiGlobs.priorityName[26] = "AI_Priority_Congregate"; globs::aiGlobs.priorityName[25] = "AI_Priority_AttackObject"; piVar3 = globs::aiGlobs.priorityValues; for (iVar1 = 0x1b; iVar1 != 0; iVar1 += -1) { *piVar3 = 0x31; piVar3 = piVar3 + 1; } globs::aiGlobs.freeList = NULL; globs::aiGlobs.listCount = 0; globs::aiGlobs.priorityValues[0] = 0x37; globs::aiGlobs.priorityValues[3] = 0x28; globs::aiGlobs.priorityValues[4] = 0x3c; globs::aiGlobs.priorityValues[5] = 0x14; globs::aiGlobs.priorityValues[6] = 0x46; globs::aiGlobs.priorityValues[8] = 0x14; globs::aiGlobs.priorityValues[9] = 5; globs::aiGlobs.priorityValues[10] = 0xf; globs::aiGlobs.priorityValues[15] = 0x38; globs::aiGlobs.priorityValues[19] = 99; globs::aiGlobs.priorityValues[20] = 0x31; globs::aiGlobs.priorityValues[21] = 0x5a; globs::aiGlobs.priorityValues[22] = 0x31; globs::aiGlobs.priorityValues[23] = 0; globs::aiGlobs.priorityValues[24] = 0x14; globs::aiGlobs.priorityValues[25] = 0x1e; globs::aiGlobs.priorityValues[26] = 99; globs::aiGlobs.flags = AITASK_GLOB_FLAG_INITIALISED; return; } void __cdecl lego::ai::AITask_FUN_00401f40(AITask_Type taskType,LegoObject *liveObj,Point2I *opt_blockPos) { AITask **ppAVar1; AITask *pAVar2; pAVar2 = globs::aiGlobs.pendingTaskList; if (globs::aiGlobs.pendingTaskList != NULL) { do { if (pAVar2->taskType == taskType) { if ((liveObj != NULL) && (liveObj == pAVar2->targetObject)) { pAVar2->flags = pAVar2->flags | AITASK_FLAG_MAXIMUMPRIORITY; } if (((opt_blockPos != NULL) && (opt_blockPos->x == (pAVar2->blockPos).x)) && (opt_blockPos->y == (pAVar2->blockPos).y)) { pAVar2->flags = pAVar2->flags | AITASK_FLAG_MAXIMUMPRIORITY; } } ppAVar1 = &pAVar2->next; pAVar2 = *ppAVar1; } while (*ppAVar1 != NULL); } return; } void __cdecl lego::ai::AITask_SetPriorityType(AITask *aiTask,AI_Priority priorityType) { int iVar1; if ((aiTask->flags & (AITASK_FLAG_MAXIMUMPRIORITY|AITASK_FLAG_MANUALYSELECTED)) == AITASK_FLAG_NONE) { iVar1 = globs::aiGlobs.priorityValues[priorityType]; aiTask->priorityType = priorityType; aiTask->priorityValue = iVar1; return; } aiTask->priorityValue = 99; aiTask->priorityType = priorityType; return; } void __cdecl lego::ai::AITask_Game_SetPriorityValue(AI_Priority priorityType,int aiTaskValue) { globs::aiGlobs.priorityValues[priorityType] = aiTaskValue; return; } void __cdecl lego::ai::AITask_Game_SetPriorityOff(AI_Priority priorityType,BOOL off) { globs::aiGlobs.disabledPriorities[priorityType] = off; return; } BOOL __cdecl lego::ai::AITask_Game_IsPriorityOff(AI_Priority priorityType) { return globs::aiGlobs.disabledPriorities[priorityType]; } void __cdecl lego::ai::AITask_Shutdown(void) { AITask_Globs *pAVar1; pAVar1 = &globs::aiGlobs; do { if (pAVar1->listSet[0] != NULL) { io::Mem_Free(pAVar1->listSet[0]); } pAVar1 = (AITask_Globs *)(pAVar1->listSet + 1); } while (pAVar1 < (AITask_Globs *)&globs::aiGlobs.freeList); globs::aiGlobs.freeList = NULL; globs::aiGlobs.flags = AITASK_GLOB_FLAG_NONE; return; } // First call in Level_Free is false, which performs most cleanup and sets the cleanup flag. // Second call in Level_Free is true, which simply unsets this flag. void __cdecl lego::ai::AITask_CleanupLevel(BOOL end) { int iVar1; uint (*paauVar2) [15] [16]; BOOL *pBVar3; if (end != 0) { globs::aiGlobs.flags = globs::aiGlobs.flags & ~AITASK_GLOB_FLAG_REMOVING; return; } AITask_RunThroughLists(AITask_Callback_Remove,NULL); globs::aiGlobs.flags |= AITASK_GLOB_FLAG_REMOVING; globs::aiGlobs.pendingTaskList = NULL; globs::aiGlobs.creatureTaskList = NULL; paauVar2 = globs::aiGlobs.requestObjCounts; for (iVar1 = 0x12c0; iVar1 != 0; iVar1 += -1) { (*paauVar2)[0] = 0; paauVar2 = (uint (*) [15] [16])(*paauVar2 + 1); } pBVar3 = globs::aiGlobs.disabledPriorities; for (iVar1 = 0x1b; iVar1 != 0; iVar1 += -1) { *pBVar3 = 0; pBVar3 = pBVar3 + 1; } return; } void __cdecl lego::ai::AITask_Game_SetNoGather(BOOL noGather) { AITask *pAVar1; if (noGather == 0) { AITask_DoGather_Count(0); } pAVar1 = AITask_Create(AITask_Type_Depart); AITask_SetPriorityType(pAVar1,AI_Priority_Depart); pAVar1->flags = pAVar1->flags | AITASK_FLAG_DUPLICATE; pAVar1->next = globs::aiGlobs.creatureTaskList; globs::aiGlobs.creatureTaskList = pAVar1; pAVar1 = AITask_Create(AITask_Type_Recharge); AITask_InitTask_1(pAVar1,AI_Priority_Crystal); pAVar1->flags = pAVar1->flags & ~AITASK_FLAG_REALLOCATE | (AITASK_FLAG_DUPLICATE|AITASK_FLAG_CARRYTASK); return; } BOOL __cdecl lego::ai::AITask_Callback_Remove(AITask *aiTask) { AITask_Remove(aiTask,TRUE); return 0; } void __cdecl lego::util::free2(undefined *param_1) { io::Mem_Free(param_1); return; } void __cdecl lego::ai::AITask_UpdateAll(float elapsedGame) { float fVar1; int iVar2; int iVar3; AITask *aiTask; iVar3 = globs::aiGlobs.priorityValues[1]; if (globs::aiGlobs.priorityValues[1] <= globs::aiGlobs.priorityValues[0]) { iVar3 = globs::aiGlobs.priorityValues[0]; } iVar2 = globs::aiGlobs.priorityValues[4]; if ((globs::aiGlobs.priorityValues[4] < iVar3) && (iVar2 = globs::aiGlobs.priorityValues[0], globs::aiGlobs.priorityValues[0] < globs::aiGlobs.priorityValues[1])) { iVar2 = globs::aiGlobs.priorityValues[1]; } globs::aiGlobs.priorityValues[16] = iVar2 + 1; if ((globs::aiGlobs.flags & AITASK_GLOB_FLAG_DISABLEUPDATES) == AITASK_GLOB_FLAG_NONE) { AITask_RunThroughLists(AITask_Callback_UpdateTask,&elapsedGame); for (aiTask = globs::aiGlobs.pendingTaskList; aiTask != NULL; aiTask = aiTask->next) { if (((aiTask->taskType == AITask_Type_Repair) && ((aiTask->flags & AITASK_FLAG_UPGRADEBUILDING) == AITASK_FLAG_NONE)) && ((fVar1 = aiTask->targetObject->health, (ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) != 0 || (100.0 <= aiTask->targetObject->health)))) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; } } AITask_FUN_00402240(&globs::aiGlobs.pendingTaskList); AITask_FUN_00402240(&globs::aiGlobs.creatureTaskList); globs::aiGlobs.freeUnitCount = 0; globs::aiGlobs.freeCreatureCount = 0; game::LegoObject_RunThroughListsSkipUpgradeParts(AITask_Callback_UpdateObject,&elapsedGame); AITask_FUN_00405b40(); AITask_FUN_00405880(); } return; } void __cdecl lego::ai::AITask_FUN_00402240(AITask **ref_aiTask) { AITask **ppAVar1; AITask *pAVar2; AITask *pAVar3; AITaskFlags AVar4; bool bVar5; AITask **ppAVar6; BOOL BVar7; int iVar8; int iVar9; int iVar10; AITask *pAVar11; uint number; int *piVar12; AITask *local_4dc; int local_4d0 [5]; undefined4 local_4bc; undefined4 local_4b8; undefined4 local_4b4; AITask *local_4b0 [300]; local_4dc = NULL; pAVar2 = *ref_aiTask; pAVar11 = NULL; while (pAVar3 = pAVar11, pAVar11 = pAVar2, pAVar11 != NULL) { pAVar2 = pAVar11->next; if ((*(byte *)&pAVar11->flags & 0x20) != 0) { if (pAVar3 == NULL) { *ref_aiTask = pAVar2; AITask_Remove(pAVar11,FALSE); pAVar11 = pAVar3; } else { pAVar3->next = pAVar2; AITask_Remove(pAVar11,FALSE); pAVar11 = pAVar3; } } } number = 0; pAVar2 = local_4dc; if (*ref_aiTask != NULL) { ppAVar6 = local_4b0; pAVar11 = *ref_aiTask; do { pAVar3 = pAVar11->next; pAVar2 = pAVar11; if (number == 300) break; *ppAVar6 = pAVar11; ppAVar6 = ppAVar6 + 1; number += 1; if ((globs::aiGlobs.disabledPriorities[pAVar11->priorityType] == 0) || ((pAVar11->flags & AITASK_FLAG_MAXIMUMPRIORITY) != AITASK_FLAG_NONE)) { AVar4 = pAVar11->flags; pAVar11->flags = AVar4 & ~AITASK_FLAG_DISABLED; if ((AVar4 & (AITASK_FLAG_MAXIMUMPRIORITY|AITASK_FLAG_MANUALYSELECTED)) == AITASK_FLAG_NONE) { pAVar11->priorityValue = globs::aiGlobs.priorityValues[pAVar11->priorityType]; } else { pAVar11->priorityValue = 99; } } else { pAVar11->flags = pAVar11->flags | AITASK_FLAG_DISABLED; } if (pAVar11->taskType == AITask_Type_Dig) { if ((*(byte *)&pAVar11->flags & 8) == 0) { BVar7 = game::Level_Block_IsNotWallOrGround((pAVar11->blockPos).x,(pAVar11->blockPos).y); if (BVar7 != 0) { pAVar11->priorityValue = 0; } } else { local_4d0[0] = 0; local_4d0[1] = 0; local_4d0[2] = 0; local_4b4 = 0; local_4d0[3] = 0xffffffff; local_4d0[4] = 0xffffffff; local_4bc = 0xffffffff; local_4b8 = 0xffffffff; bVar5 = false; piVar12 = local_4d0; iVar10 = 4; do { BVar7 = game::Level_Block_IsWall (*piVar12 + (pAVar11->blockPos).x,piVar12[1] + (pAVar11->blockPos).y); if (BVar7 != 0) { bVar5 = true; } piVar12 = piVar12 + 2; iVar10 += -1; } while (iVar10 != 0); if (bVar5) { if (pAVar11->priorityValue == 0) { pAVar11->timeIn = (float)&DAT_42c80000; } } else { pAVar11->priorityValue = 0; } } } pAVar11 = pAVar3; pAVar2 = local_4dc; } while (pAVar3 != NULL); } local_4dc = pAVar2; if (number != 0) { std::qsort(local_4b0,number,4,AITask_QSortCompare); iVar10 = number - 1; iVar9 = 0; if (iVar10 != 0) { ppAVar6 = local_4b0; iVar8 = iVar10; do { pAVar2 = *ppAVar6; ppAVar1 = ppAVar6 + 1; ppAVar6 = ppAVar6 + 1; iVar8 += -1; pAVar2->next = *ppAVar1; iVar9 = iVar10; } while (iVar8 != 0); } local_4b0[iVar9]->next = local_4dc; *ref_aiTask = local_4b0[0]; } return; } void __cdecl lego::ai::AITask_DoDig_AtBlockPos(Point2I *blockPos,BOOL param_2,BOOL param_3) { AITaskFlags AVar1; Lego_Level *pLVar2; BOOL BVar3; AITask *aiTask; int iVar4; pLVar2 = lrr::Lego_GetLevel(); BVar3 = game::Level_Block_IsImmovable(blockPos); if (BVar3 == 0) { BVar3 = game::Level_Block_IsLava(blockPos); if (BVar3 == 0) { BVar3 = game::Level_Block_IsSurveyed(blockPos->x,blockPos->y); if (BVar3 != 0) { aiTask = AITask_Create(AITask_Type_Dig); (aiTask->blockPos).x = blockPos->x; (aiTask->blockPos).y = blockPos->y; if (param_2 != 0) { aiTask->flags = aiTask->flags | AITASK_FLAG_DIGCONNECTION; } AITask_UnkInitRouting_FUN_00402530(aiTask,1); AITask_InitTask_1(aiTask,AI_Priority_Destruction); AVar1 = aiTask->flags; aiTask->flags = AVar1 | AITASK_FLAG_NOTIMELIMIT; if (param_3 != 0) { aiTask->flags = AVar1 | (AITASK_FLAG_NOTIMELIMIT|AITASK_FLAG_MANUALYSELECTED); } if (param_2 == 0) { lego::map::Map3D_SetBlockHighlight(pLVar2->map,blockPos->x,blockPos->y,WALLHIGHLIGHT_DIG); iVar4 = pLVar2->width * blockPos->y + blockPos->x; pLVar2->blocks[iVar4].flags1 = pLVar2->blocks[iVar4].flags1 | BLOCK1_DIGREQUEST; } } } } return; } void __cdecl lego::ai::AITask_UnkInitRouting_FUN_00402530(AITask *aiTask,BOOL dropCarried) { uint *out_unitsCount; LegoObject **out_unitsList; BOOL BVar1; uint i; BVar1 = game::Message_AnyUnitSelected(); if (BVar1 != 0) { out_unitsCount = &aiTask->unitListCount; out_unitsList = (LegoObject **)&aiTask->unitList; aiTask->flags = aiTask->flags | (AITASK_FLAG_DUPLICATE|AITASK_FLAG_IMMEDIATESELECTION); game::Message_CopySelectedUnits((LegoObject ***)out_unitsList,out_unitsCount); i = 0; if (*out_unitsCount != 0) { do { game::LegoObject_Route_End(*(LegoObject **)((int)*out_unitsList + i * 4),FALSE); if (dropCarried != 0) { game::LegoObject_DropCarriedObject (*(LegoObject **)((int)((*out_unitsList)->routeCurve).points + i * 4 + -0x34), FALSE); } i += 1; } while (i < *out_unitsCount); } } return; } void __cdecl lego::ai::AITask_DoAttackRockMonster_Target(LegoObject *targetObj) { BOOL BVar1; AITask *aiTask; lrr::Lego_GetLevel(); if (targetObj != NULL) { BVar1 = game::LegoObject_CanShootObject(targetObj); if (BVar1 != 0) { aiTask = AITask_Create(AITask_Type_AttackRockMonster); AITask_InitTask_1(aiTask,AI_Priority_AttackRockMonster); aiTask->targetObject = targetObj; aiTask->flags = aiTask->flags & ~AITASK_FLAG_REALLOCATE | (AITASK_FLAG_DUPLICATE|AITASK_FLAG_PAUSEDDUPLICATION); } } return; } void __cdecl lego::ai::AITask_LiveObject_FUN_004025f0(LegoObject *liveObj) { BOOL BVar1; if ((liveObj->carryingThisObject == NULL) && ((liveObj->flags4 & LIVEOBJ4_USEDBYCONSTRUCTION) == LIVEOBJ4_NONE)) { BVar1 = AITask_RunThroughLists(AITask_IsCollectAndSameTarget,liveObj); if (BVar1 == 0) { AITask_DoCollect(liveObj,0.0); } } return; } BOOL __cdecl lego::ai::AITask_IsCollectAndSameTarget(AITask *aiTask,LegoObject *liveObj) { if ((aiTask->taskType == AITask_Type_Collect) && (aiTask->targetObject == liveObj)) { return 1; } return 0; } void __cdecl lego::ai::AITask_DoCollect(LegoObject *liveObj,float param_2) { LegoObject_Type LVar1; AITask *aiTask; AI_Priority priorityType; priorityType = AI_Priority_DefaultCollect; aiTask = AITask_Create(AITask_Type_Collect); aiTask->targetObject = liveObj; aiTask->timeIn = param_2; LVar1 = liveObj->type; if (LVar1 == LegoObject_PowerCrystal) { priorityType = -(uint)((liveObj->flags3 & LIVEOBJ3_POWEROFF) != LIVEOBJ3_NONE) & 0x12; } else { if (LVar1 == LegoObject_Ore) { priorityType = AI_Priority_Ore; } else { if (LVar1 == LegoObject_Barrier) { priorityType = AI_Priority_Barrier; } else { if (LVar1 == LegoObject_Dynamite) { aiTask->trainFlags = 8; priorityType = AI_Priority_Destruction; } } } } AITask_InitTask_1(aiTask,priorityType); AITask_DoCollect_Target(liveObj); return; } void __cdecl lego::ai::AITask_DoBuildPath_AtPosition(Point2I *blockPos) { BOOL BVar1; uint uVar2; AITask *aiTask; BVar1 = game::Level_Block_IsPath(blockPos); if (BVar1 == 0) { uVar2 = game::Level_Block_GetRubbleLayers(blockPos); if (uVar2 == 0) { BVar1 = game::Dependencies_Object_FUN_0040add0(LegoObject_Path,0,0); if (BVar1 != 0) { aiTask = AITask_Create(AITask_Type_BuildPath); (aiTask->blockPos).x = blockPos->x; (aiTask->blockPos).y = blockPos->y; AITask_InitTask_1(aiTask,AI_Priority_BuildPath); } } } return; } void __cdecl lego::ai::AITask_DoGather_Count(int count) { AITask *aiTask; bool bVar1; bVar1 = count == 0; if (bVar1) { count = 1; } if (true) { do { aiTask = AITask_Create(AITask_Type_Gather); AITask_SetPriorityType(aiTask,AI_Priority_Gather); if (bVar1) { aiTask->flags = aiTask->flags | AITASK_FLAG_DUPLICATE; } AITask_Init_2_NoPriority(aiTask); count += -1; } while (count != 0); } return; } void __cdecl lego::ai::AITask_DoCollect_Target(LegoObject *targetObj) { AITask *aiTask; if (targetObj->type == LegoObject_PowerCrystal) { aiTask = AITask_Create(AITask_Type_Collect); aiTask->targetObject = targetObj; AITask_SetPriorityType(aiTask,AI_Priority_Steal); AITask_Init_2_NoPriority(aiTask); aiTask->flags = aiTask->flags | AITASK_FLAG_CREATUREREALLOCATE; } return; } void __cdecl lego::ai::AITask_DoTrain_Target (LegoObject *targetObj,LegoObject_AbilityFlags trainFlags,BOOL param_3) { BOOL BVar1; AITask *aiTask; AI_Priority priorityType; BVar1 = game::LegoObject_HasTraining(targetObj,trainFlags); if (BVar1 == 0) { return; } aiTask = AITask_Create(AITask_Type_Train); aiTask->targetObject = targetObj; aiTask->trainFlags = trainFlags; if (false) { switchD_004027fb_caseD_3: priorityType = AI_Priority_Upgrade; } else { switch(trainFlags) { case ABILITY_FLAG_PILOT: case ABILITY_FLAG_SAILOR: case ABILITY_FLAG_DRIVER: priorityType = AI_Priority_GetIn; break; default: goto switchD_004027fb_caseD_3; case ABILITY_FLAG_DYNAMITE: priorityType = AI_Priority_Destruction; break; case ABILITY_FLAG_REPAIR: priorityType = AI_Priority_Repair; break; case ABILITY_FLAG_SCANNER: priorityType = AI_Priority_Construction; } } if (param_3 != 0) { AITask_UnkInitRouting_FUN_00402530(aiTask,1); } AITask_InitTask_1(aiTask,priorityType); aiTask->flags = aiTask->flags & ~AITASK_FLAG_DUPLICATE; return; } void __cdecl lego::ai::AITask_DoFindDriver_Target(LegoObject *targetObj) { AITask *aiTask; StatsFlags3 SVar1; StatsFlags1 SVar2; if ((*(byte *)&targetObj->flags2 & LIVEOBJ2_UNK_10) == 0) { aiTask = AITask_Create(AITask_Type_FindDriver); aiTask->targetObject = targetObj; targetObj->flags2 = targetObj->flags2 | LIVEOBJ2_UNK_10; SVar1 = stats::StatsObject_GetStatsFlags3(targetObj); if ((SVar1 & STATS3_NEEDSPILOT) == STATS3_NONE) { SVar2 = stats::StatsObject_GetStatsFlags1(targetObj); if ((SVar2 & STATS1_CROSSLAND) == STATS1_NONE) { SVar2 = stats::StatsObject_GetStatsFlags1(targetObj); if ((SVar2 & STATS1_CROSSWATER) != STATS1_NONE) { aiTask->trainFlags = LegoObject_AbilityType_Driver; } } else { SVar2 = stats::StatsObject_GetStatsFlags1(targetObj); if ((SVar2 & STATS1_CROSSWATER) == STATS1_NONE) { aiTask->trainFlags = LegoObject_AbilityType_Repair; } else { aiTask->trainFlags = LegoObject_AbilityType_Sailor; } } } else { aiTask->trainFlags = LegoObject_AbilityType_Sailor; } SVar1 = stats::StatsObject_GetStatsFlags3(targetObj); if (((SVar1 & STATS3_TAKECARRYINGDRIVERS) != STATS3_NONE) && ((targetObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE)) { aiTask->flags = aiTask->flags | AITASK_FLAG_ACCEPTCARRYING; } AITask_UnkInitRouting_FUN_00402530(aiTask,~aiTask->flags >> 0x14 & 1); aiTask->flags = aiTask->flags & ~AITASK_FLAG_DUPLICATE; AITask_InitTask_1(aiTask,AI_Priority_GetIn); } return; } BOOL __cdecl lego::ai::AITask_RemoveAttackPathReferences(Point2I *blockPos) { BOOL BVar1; Point2I *local_8; undefined4 local_4; // Uses struct size 8, but function only references first field (Point2I* blockPos). local_8 = blockPos; local_4 = 0; BVar1 = AITask_RunThroughLists(AITask_Callback_RemoveAttackPathReference,&local_8); return BVar1; } // param_2 is a Search struct (const Point2I* blockPos, undefined4 unused_4) BOOL __cdecl lego::ai::AITask_Callback_RemoveAttackPathReference(AITask *aiTask,Point2I **pBlockPos) { if (((aiTask->taskType == AITask_Type_AttackPath) && ((*pBlockPos)->x == (aiTask->blockPos).x)) && ((*pBlockPos)->y == (aiTask->blockPos).y)) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; } return 0; } // Removes all `AttackRockMonster` type tasks whose object_10 references match the specified object. void __cdecl lego::ai::AITask_RemoveAttackRockMonsterReferences(LegoObject *targetObj) { AITask_RunThroughLists(AITask_Callback_RemoveAttackRockMonsterReference,targetObj); return; } // Removes the `AttackRockMonster` type task if its object_10 reference match the specified object. BOOL __cdecl lego::ai::AITask_Callback_RemoveAttackRockMonsterReference(AITask *aiTask,LegoObject *targetObj) { if ((aiTask->taskType == AITask_Type_AttackRockMonster) && (aiTask->targetObject == targetObj)) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; } return 0; } void __cdecl lego::ai::AITask_RemoveDigReferences(Point2I *blockPos,BOOL digConnection) { Lego_Level *level; SearchAITaskDeselect_8 search; level = lrr::Lego_GetLevel(); search.blockPos = blockPos; search.digConnection = digConnection; AITask_RunThroughLists(AITask_Callback_RemoveWallReference,&search); lego::map::Map3D_ClearBlockHighlight(level->map,blockPos->x,blockPos->y); return; } BOOL __cdecl lego::ai::AITask_RemoveReinforceReferences(Point2I *blockPos) { BOOL BVar1; Point2I *local_8; undefined4 local_4; local_8 = blockPos; local_4 = 0; BVar1 = AITask_RunThroughLists(AITask_Callback_RemoveReinforceReference,&local_8); return BVar1; } BOOL __cdecl lego::ai::AITask_DelayOrRemoveClearReferences(Point2I *blockPos,BOOL delay) { BOOL BVar1; Point2I *local_8; undefined4 local_4; local_4 = 0; local_8 = blockPos; if (delay != 0) { BVar1 = AITask_RunThroughLists(AITask_Callback_DelayClearReference,&local_8); return BVar1; } BVar1 = AITask_RunThroughLists(AITask_Callback_RemoveClearReference,&local_8); return BVar1; } // DATA: SearchAITaskDeselect_8* // struct SearchAITaskDeselect_8 { // const Point2I* blockPos; // bool32 digConnection; // }; BOOL __cdecl lego::ai::AITask_Callback_RemoveWallReference(AITask *aiTask,SearchAITaskDeselect_8 *search) { bool bVar1; AITask_Type taskType; // switch (aiTask->taskType) { // case AITask_Type_Dig: // // `search->digConnection XNOR (flags & 0x8)` If both or true, or both are // false... // bVar1 = ((bool)search->digConnection == (bool)(aiTask->flags & // FLAG_DIGCONNECTION)); // break; // case AITask_Type_Dynamite: // case AITask_Type_Reinforce: // bVar1 = true; // break; // default: // bVar1 = false; // break; // } bVar1 = false; taskType = aiTask->taskType; if (taskType == AITask_Type_Dig) { // `search->param_2 XNOR (flags & 0x8)` If both or true, or both are false... if (search->digConnection != 0) { if ((*(byte *)&aiTask->flags & AITASK_FLAG_DIGCONNECTION) != 0) goto LAB_00402b16; if (search->digConnection != 0) goto LAB_00402b1b; } if ((*(byte *)&aiTask->flags & AITASK_FLAG_DIGCONNECTION) != 0) goto LAB_00402b1b; } else { if ((taskType != AITask_Type_Dynamite) && (taskType != AITask_Type_Reinforce)) goto LAB_00402b1b; } LAB_00402b16: bVar1 = true; LAB_00402b1b: if (((bVar1) && (search->blockPos->x == (aiTask->blockPos).x)) && (search->blockPos->y == (aiTask->blockPos).y)) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; game::Level_Block_SetBusy(search->blockPos,FALSE); } return 0; } // param_2 is a Search struct (const Point2I* blockPos, undefined4 field_4) BOOL __cdecl lego::ai::AITask_Callback_RemoveReinforceReference(AITask *aiTask,Point2I **pBlockPos) { Map3D *map; int bx; int by; if (((aiTask->taskType == AITask_Type_Reinforce) && ((*pBlockPos)->x == (aiTask->blockPos).x)) && ((*pBlockPos)->y == (aiTask->blockPos).y)) { by = (aiTask->blockPos).y; aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; bx = (aiTask->blockPos).x; map = lrr::Lego_GetMap(); lego::map::Map3D_ClearBlockHighlight(map,bx,by); } return 0; } // param_2 is a Search struct (const Point2I* blockPos, undefined4 field_4) BOOL __cdecl lego::ai::AITask_Callback_RemoveClearReference(AITask *aiTask,Point2I **pBlockPos) { if (((aiTask->taskType == AITask_Type_Clear) && ((*pBlockPos)->x == (aiTask->blockPos).x)) && ((*pBlockPos)->y == (aiTask->blockPos).y)) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; } return 0; } // Resets the float_18 timer on the task to 500.0f (20 seconds)? // param_2 is a Search struct (const Point2I* blockPos, undefined4 field_4) BOOL __cdecl lego::ai::AITask_Callback_DelayClearReference(AITask *aiTask,Point2I **pBlockPos) { if (((aiTask->taskType == AITask_Type_Clear) && ((*pBlockPos)->x == (aiTask->blockPos).x)) && ((*pBlockPos)->y == (aiTask->blockPos).y)) { aiTask->timeIn = 500.0; } return 0; } void __cdecl lego::ai::AITask_RemoveGetToolReferences(AITask *aiTask) { AITask *aiTaskLink; AITask **pAITaskLinkNext; if (aiTask->taskType == AITask_Type_GetTool) { if (aiTask->getToolTask != NULL) { // FIXME: This is USELESS USELESS USELESS USELESS! Passing the address of this // function's parameter on the stack when it's trying to compare against // field aiTask_58!!! // // Now for the real treat. THIS FUNCTION DOES NOTHING ANYWAY. // The callback returns true if the fields match, but outside of that. // ABSOLUTELY NOTHING is done with the result. AITask_RunThroughLists(AITask_Callback_FindGetToolReference,&aiTask); return; } } else { if ((aiTask->getToolTask != NULL) && (aiTaskLink = globs::aiGlobs.pendingTaskList, globs::aiGlobs.pendingTaskList != NULL)) { do { if ((aiTaskLink->taskType == AITask_Type_GetTool) && (aiTask->getToolTask == aiTaskLink)) { aiTaskLink->flags = aiTaskLink->flags | AITASK_FLAG_REMOVING; } pAITaskLinkNext = &aiTaskLink->next; aiTaskLink = *pAITaskLinkNext; } while (*pAITaskLinkNext != NULL); } } return; } BOOL __cdecl lego::ai::AITask_Callback_FindGetToolReference(AITask *aiTask,AITask *otherTask) { return (uint)(aiTask->getToolTask == otherTask); } BOOL __cdecl lego::ai::AITask_DoDynamite_AtBlockPos(Point2I *blockPos,BOOL noRoutingUnk) { AITaskFlags AVar1; BOOL BVar2; AITask *aiTask; Map3D *map; int bx; int by; WallHighlightType highlightType; if ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].terrain != Lego_SurfaceType8_Immovable) { BVar2 = game::Level_Block_IsWall(blockPos->x,blockPos->y); if (BVar2 != 0) { BVar2 = game::Level_Block_IsBusy(blockPos); if (BVar2 == 0) { aiTask = AITask_Create(AITask_Type_Dynamite); (aiTask->blockPos).x = blockPos->x; AVar1 = aiTask->flags; (aiTask->blockPos).y = blockPos->y; aiTask->objType = LegoObject_Dynamite; aiTask->objID = 0xffffffff; aiTask->objLevel = 0; aiTask->flags = AVar1 | AITASK_FLAG_CARRYTASK; if (noRoutingUnk == 0) { AITask_UnkInitRouting_FUN_00402530(aiTask,TRUE); } AITask_InitTask_1(aiTask,AI_Priority_Destruction); AITask_PlaceRequestObject(blockPos,LegoObject_Dynamite,0,0); game::Level_Block_SetBusy(blockPos,TRUE); by = blockPos->y; bx = blockPos->x; highlightType = WALLHIGHLIGHT_DYNAMITE; map = lrr::Lego_GetMap(); lego::map::Map3D_SetBlockHighlight(map,bx,by,highlightType); return TRUE; } } } return 0; } void __cdecl lego::ai::AITask_DoBirdScarer_AtPosition(Point2I *blockPos) { AITaskFlags AVar1; BOOL BVar2; AITask *aiTask; BVar2 = game::Level_Block_IsGround(blockPos->x,blockPos->y); if (BVar2 != 0) { aiTask = AITask_Create(AITask_Type_BirdScarer); AVar1 = aiTask->flags; (aiTask->blockPos).x = blockPos->x; (aiTask->blockPos).y = blockPos->y; aiTask->objType = LegoObject_OohScary; aiTask->objID = 0xffffffff; aiTask->objLevel = 0; aiTask->flags = AVar1 | AITASK_FLAG_CARRYTASK; AITask_UnkInitRouting_FUN_00402530(aiTask,TRUE); AITask_InitTask_1(aiTask,AI_Priority_Destruction); AITask_PlaceRequestObject(blockPos,LegoObject_OohScary,0,0); } return; } void __cdecl lego::ai::AITask_DoFindLoad(LegoObject *targetObj) { StatsFlags3 SVar1; AITask *aiTask; SVar1 = stats::StatsObject_GetStatsFlags3(targetObj); if ((((SVar1 & STATS3_CARRYVEHICLES) != STATS3_NONE) && ((targetObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE)) && ((targetObj->flags4 & LIVEOBJ4_UNK_10000) == LIVEOBJ4_NONE)) { aiTask = AITask_Create(AITask_Type_FindLoad); aiTask->targetObject = targetObj; targetObj->flags4 = targetObj->flags4 | LIVEOBJ4_UNK_10000; AITask_InitTask_1(aiTask,AI_Priority_FindLoad); aiTask->flags = aiTask->flags & ~AITASK_FLAG_DUPLICATE | (AITASK_FLAG_REALLOCATE|AITASK_FLAG_ACCEPTCARRYING); } return; } void __cdecl lego::ai::AITask_DoRepair_Target(LegoObject *targetObj,BOOL condition) { AITask *aiTask; aiTask = AITask_Create(AITask_Type_Repair); aiTask->targetObject = targetObj; aiTask->trainFlags = 0x10; if (condition != 0) { aiTask->flags = aiTask->flags | AITASK_FLAG_UPGRADEBUILDING; } AITask_InitTask_1(aiTask,(-(uint)(condition != 0) & 0xc) + AI_Priority_Repair); return; } void __cdecl lego::ai::AITask_QueueGotoEat_Target(LegoObject *liveObj,LegoObject *targetObj) { AITask *newAITask; AITask *tail; newAITask = AITask_Create(AITask_Type_GotoEat); newAITask->targetObject = targetObj; tail = AITask_GetObjectTaskListTail(liveObj); if (tail != NULL) { tail->next = newAITask; return; } liveObj->aiTask = newAITask; return; } void __cdecl lego::ai::AITask_DoElecFence(Point2I *blockPos) { AITaskFlags AVar1; AITask *aiTask; aiTask = AITask_Create(AITask_Type_ElecFence); AVar1 = aiTask->flags; (aiTask->blockPos).x = blockPos->x; (aiTask->blockPos).y = blockPos->y; aiTask->objType = LegoObject_ElectricFence; aiTask->objID = 0xffffffff; aiTask->objLevel = 0; aiTask->flags = AVar1 | AITASK_FLAG_CARRYTASK; AITask_UnkInitRouting_FUN_00402530(aiTask,1); AITask_InitTask_1(aiTask,AI_Priority_Construction); AITask_PlaceRequestObject(blockPos,LegoObject_ElectricFence,0,0); game::Level_Block_SetFenceRequest(blockPos->x,blockPos->y,TRUE); return; } void __cdecl lego::ai::AITask_DoReinforce_AtBlockPos(Point2I *blockPos) { BOOL BVar1; AITask *aiTask; Map3D *map; int bx; int by; WallHighlightType highlightType; BVar1 = game::Level_Block_IsWall(blockPos->x,blockPos->y); if (BVar1 != 0) { BVar1 = game::Level_Block_IsReinforced(blockPos->x,blockPos->y); if (BVar1 == 0) { aiTask = AITask_Create(AITask_Type_Reinforce); (aiTask->blockPos).x = blockPos->x; (aiTask->blockPos).y = blockPos->y; AITask_UnkInitRouting_FUN_00402530(aiTask,TRUE); AITask_InitTask_1(aiTask,AI_Priority_Reinforce); by = blockPos->y; bx = blockPos->x; highlightType = WALLHIGHLIGHT_REINFORCE; map = lrr::Lego_GetMap(); lego::map::Map3D_SetBlockHighlight(map,bx,by,highlightType); } } return; } void __cdecl lego::ai::AITask_DoClear_AtPosition(Point2I *blockPos,Message_Type completeAction) { AITask *aiTask; aiTask = AITask_Create(AITask_Type_Clear); (aiTask->blockPos).x = blockPos->x; (aiTask->blockPos).y = blockPos->y; aiTask->completeAction = completeAction; AITask_InitTask_1(aiTask,AI_Priority_Clearing); return; } void __cdecl lego::ai::AITask_DoGetTool_FromTask(AITask *aiTask) { BOOL BVar1; AITask *newAITask; LegoObject **unitList; uint uVar2; int iVar3; LegoObject *unit; AITask *aiTask_00; aiTask_00 = aiTask; BVar1 = stats::Stats_FindToolFromTaskType(aiTask->taskType,(LegoObject_ToolType *)&aiTask); if (BVar1 != 0) { aiTask_00->flags = aiTask_00->flags | AITASK_FLAG_WAITINGFORTOOL; newAITask = AITask_Create(AITask_Type_GetTool); if ((aiTask_00->flags & AITASK_FLAG_IMMEDIATESELECTION) != AITASK_FLAG_NONE) { unitList = (LegoObject **)io::Mem_Alloc(aiTask_00->unitListCount << 2); newAITask->unitList = unitList; unit = (LegoObject *)aiTask_00->unitList; for (uVar2 = aiTask_00->unitListCount & 0x3fffffff; uVar2 != 0; uVar2 -= 1) { *unitList = *(LegoObject **)unit; unit = (LegoObject *)((int)unit + 4); unitList = unitList + 1; } for (iVar3 = 0; iVar3 != 0; iVar3 += -1) { *(undefined *)unitList = *(undefined *)unit; unit = (LegoObject *)((int)unit + 1); unitList = (LegoObject **)((int)unitList + 1); } newAITask->unitListCount = aiTask_00->unitListCount; newAITask->flags = newAITask->flags | AITASK_FLAG_IMMEDIATESELECTION; } newAITask->flags = newAITask->flags | AITASK_FLAG_REALLOCATE; newAITask->toolType = (LegoObject_ToolType)aiTask; newAITask->getToolTask = aiTask_00; aiTask_00->getToolTask = newAITask; AITask_InitTask_1(newAITask,aiTask_00->priorityType); } return; } BOOL __cdecl lego::ai::AITask_DoGetTool(LegoObject_ToolType toolType) { AITask *aiTask; aiTask = AITask_Create(AITask_Type_GetTool); aiTask->toolType = toolType; aiTask->getToolTask = NULL; AITask_UnkInitRouting_FUN_00402530(aiTask,1); aiTask->flags = aiTask->flags & ~AITASK_FLAG_DUPLICATE | AITASK_FLAG_REALLOCATE; AITask_InitTask_1(aiTask,AI_Priority_DefaultCollect); return 1; } BOOL __cdecl lego::ai::AITask_Game_SelectedUnits_UnkEquippedTool_FUN_00403110(LegoObject_ToolType toolType) { BOOL BVar1; uint numSelected; LegoObject **pUnit; uint i; BVar1 = game::Message_AnyUnitSelected(); if (BVar1 == 0) { i = 0; if (globs::aiGlobs.freeUnitCount != 0) { pUnit = globs::aiGlobs.freeUnitList; while ((*pUnit == NULL || (BVar1 = game::LegoObject_HasToolEquipped(*pUnit,toolType), BVar1 == 0))) { i += 1; pUnit = pUnit + 1; if (globs::aiGlobs.freeUnitCount <= i) { return 0; } } return 1; } } else { numSelected = game::Message_GetNumSelectedUnits(); pUnit = game::Message_GetSelectedUnits(); i = 0; if (numSelected != 0) { do { BVar1 = game::LegoObject_HasToolEquipped(*pUnit,toolType); if (BVar1 != 0) { return TRUE; } i += 1; pUnit = pUnit + 1; } while (i < numSelected); return 0; } } return 0; } // If reevalTasks is true, then `AITask_ReevaluateObjectTasks` is called, void __cdecl lego::ai::AITask_QueueGotoBlock_Group (LegoObject **unitList,uint unitCount,Point2I *blockPos,BOOL reevalTasks) { LegoObject *liveObj; AITask *newAITask; StatsFlags1 sflags1; AITask *tail; if ((unitCount != 0) && (unitCount != 0)) { do { newAITask = AITask_Create(AITask_Type_Goto); (newAITask->blockPos).x = blockPos->x; (newAITask->blockPos).y = blockPos->y; newAITask->flags = AITASK_FLAG_VOLATILE; liveObj = *unitList; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) || (liveObj->driveObject != NULL)) && ((liveObj->carryingThisObject == NULL && ((*(byte *)&liveObj->flags3 & LIVEOBJ3_CANYESSIR) != 0)))) { if (reevalTasks != 0) { AITask_ReevaluateObjectTasks(liveObj); } tail = AITask_GetObjectTaskListTail(liveObj); if (tail == NULL) { liveObj->aiTask = newAITask; } else { tail->next = newAITask; } } unitList = unitList + 1; unitCount -= 1; } while (unitCount != 0); } return; } void __cdecl lego::ai::AITask_DoUpgrade(LegoObject *liveObj,uint newObjLevel) { AITask *newAITask; AITask *tail; LegoObject *foundObj; Point2F local_8; foundObj = NULL; if ((liveObj->type == LegoObject_MiniFigure) && ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE)) { game::LegoObject_GetPosition(liveObj,&local_8.x,&local_8.y); foundObj = game::Level_GetBuildingAtPosition(&local_8); } else { if (liveObj->type == LegoObject_Vehicle) { foundObj = (LegoObject *)game::LegoObject_Search_FUN_00438eb0(liveObj); } } if (foundObj != NULL) { newAITask = AITask_Create(AITask_Type_Upgrade); newAITask->targetObject = foundObj; newAITask->objLevel = newObjLevel; AITask_ReevaluateObjectTasks(liveObj); tail = AITask_GetObjectTaskListTail(liveObj); if (tail != NULL) { tail->next = newAITask; return; } liveObj->aiTask = newAITask; } return; } void __cdecl lego::ai::AITask_DoDock(LegoObject *liveObj) { AITask *pAVar1; AITask *pAVar2; pAVar1 = AITask_Create(AITask_Type_Dock); pAVar2 = AITask_GetObjectTaskListTail(liveObj); if (pAVar2 != NULL) { pAVar2->next = pAVar1; return; } liveObj->aiTask = pAVar1; return; } void __cdecl lego::ai::AITask_DoGoto_Congregate(Point2I *blockPos) { AITaskFlags AVar1; AITask *aiTask; aiTask = AITask_Create(AITask_Type_Goto); (aiTask->blockPos).x = blockPos->x; AVar1 = aiTask->flags; (aiTask->blockPos).y = blockPos->y; aiTask->flags = AVar1 & ~AITASK_FLAG_REALLOCATE | AITASK_FLAG_DUPLICATE; AITask_SetPriorityType(aiTask,AI_Priority_Congregate); AITask_Init_2_NoPriority(aiTask); return; } void __cdecl lego::ai::AITask_StopGoto_Congregate(Point2I *blockPos) { AITask *pAVar1; AITask *aiTask; AITask *pAVar2; pAVar1 = globs::aiGlobs.creatureTaskList; pAVar2 = NULL; if (globs::aiGlobs.creatureTaskList != NULL) { do { aiTask = pAVar1; pAVar1 = aiTask->next; if (((aiTask->taskType == AITask_Type_Goto) && ((aiTask->blockPos).x == blockPos->x)) && ((aiTask->blockPos).y == blockPos->y)) { if (pAVar2 == NULL) { globs::aiGlobs.creatureTaskList = pAVar1; AITask_Remove(aiTask,FALSE); return; } pAVar2->next = pAVar1; AITask_Remove(aiTask,FALSE); return; } pAVar2 = aiTask; } while (pAVar1 != NULL); } return; } void __cdecl lego::ai::AITask_DoAttackObject(LegoObject *liveObj) { AITask *aiTask; aiTask = AITask_Create(AITask_Type_AttackObject); aiTask->targetObject = liveObj; AITask_SetPriorityType(aiTask,AI_Priority_AttackObject); AITask_Init_2_NoPriority(aiTask); aiTask->flags = aiTask->flags | AITASK_FLAG_DUPLICATE; return; } void __cdecl lego::ai::AITask_DoAttackPath(Point2I *blockPos) { AITask *aiTask; aiTask = AITask_Create(AITask_Type_AttackPath); (aiTask->blockPos).x = blockPos->x; (aiTask->blockPos).y = blockPos->y; AITask_SetPriorityType(aiTask,AI_Priority_AttackPath); AITask_Init_2_NoPriority(aiTask); return; } void __cdecl lego::ai::AITask_DoRepair(LegoObject *liveObj) { AITask *aiTask; aiTask = AITask_Create(AITask_Type_Repair); aiTask->targetObject = liveObj; AITask_SetPriorityType(aiTask,AI_Priority_Punch); AITask_Init_2_NoPriority(aiTask); aiTask->flags = aiTask->flags | AITASK_FLAG_DUPLICATE; return; } void __cdecl lego::ai::AITask_StopRepairForObject(LegoObject *liveObj) { AITask *aiTask; AITask *newTaskList; AITask *pAVar1; AITask *taskNext; newTaskList = NULL; aiTask = globs::aiGlobs.creatureTaskList; if (globs::aiGlobs.creatureTaskList != NULL) { do { taskNext = aiTask->next; pAVar1 = aiTask; if ((aiTask->taskType == AITask_Type_Repair) && (liveObj == aiTask->targetObject)) { pAVar1 = newTaskList; if (newTaskList == NULL) { globs::aiGlobs.creatureTaskList = taskNext; AITask_Remove(aiTask,FALSE); } else { newTaskList->next = taskNext; AITask_Remove(aiTask,FALSE); } } aiTask = taskNext; newTaskList = pAVar1; } while (taskNext != NULL); } return; } void __cdecl lego::ai::AITask_Game_PTL_GotoOrRMGoto (LegoObject *liveObj,Point2I *blockPos,AITask *opt_referrerTask) { AITask *newAITask; AITask *tail; newAITask = AITask_Create(AITask_Type_Goto); (newAITask->blockPos).x = blockPos->x; (newAITask->blockPos).y = blockPos->y; newAITask->referrerTask = opt_referrerTask; tail = AITask_GetObjectTaskListTail(liveObj); if (tail != NULL) { tail->next = newAITask; return; } liveObj->aiTask = newAITask; front::Bubble_ShowBubble(liveObj); return; } void __cdecl lego::ai::AITask_QueueDepositInObject(LegoObject *liveObj,LegoObject *targetObj) { AITask *newAITask; AITask *tail; if ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { newAITask = AITask_Create(AITask_Type_Deposit); newAITask->targetObject = targetObj; tail = AITask_GetObjectTaskListTail(liveObj); if (tail != NULL) { tail->next = newAITask; return; } liveObj->aiTask = newAITask; } return; } void __cdecl lego::ai::AITask_PushFollowObject_Group(LegoObject **unitList,uint unitCount,LegoObject *targetObj) { LegoObject *liveObj; AITask *newAITask; AITask *tail; if ((unitCount != 0) && (unitCount != 0)) { do { newAITask = AITask_Create(AITask_Type_Follow); newAITask->targetObject = targetObj; newAITask->time = 0.0; liveObj = *unitList; AITask_ReevaluateObjectTasks(liveObj); tail = AITask_GetObjectTaskListTail(liveObj); if (tail == NULL) { liveObj->aiTask = newAITask; } else { tail->next = newAITask; } unitList = unitList + 1; unitCount -= 1; } while (unitCount != 0); } return; } void __cdecl lego::ai::AITask_Game_PTL_FollowAttack(LegoObject *liveObj,LegoObject *targetObj) { AITask *pAVar1; AITask *pAVar2; pAVar1 = AITask_Create(AITask_Type_FollowAttack); pAVar1->targetObject = targetObj; pAVar1->time = 0.0; pAVar2 = AITask_GetObjectTaskListTail(liveObj); if (pAVar2 != NULL) { pAVar2->next = pAVar1; return; } liveObj->aiTask = pAVar1; return; } // Sets flags 0x20 for all aiTasks with the same constructionHandle and meeting object requirements // (or checkObjType is false). void __cdecl lego::ai::AITask_Construction_FUN_00403630 (uint constructHandle,BOOL checkObjType,LegoObject_Type objType,LegoObject_ID objID) { AITask *aiTask; AITask **pNext; aiTask = globs::aiGlobs.pendingTaskList; if (globs::aiGlobs.pendingTaskList != NULL) { do { if (((aiTask->taskType == AITask_Type_Request) && (aiTask->constructHandle == constructHandle) ) && ((checkObjType == FALSE || ((objType == aiTask->objType && (objID == aiTask->objID))) ))) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; } pNext = &aiTask->next; aiTask = *pNext; } while (*pNext != NULL); } return; } void __cdecl lego::ai::AITask_DoRequest_ObjectType (LegoObject_Type objType,LegoObject_ID objID,uint objLevel,Point2I *blockPos,uint param_5, Point2F *pointFloat,BOOL param_7) { int iVar1; AITask *aiTask; float10 fVar2; aiTask = AITask_Create(AITask_Type_Request); aiTask->objType = objType; aiTask->objID = objID; aiTask->objLevel = objLevel; (aiTask->blockPos).x = blockPos->x; iVar1 = blockPos->y; aiTask->constructHandle = param_5; (aiTask->blockPos).y = iVar1; if (pointFloat == NULL) { fVar2 = math::Maths_RandRange(0.4,0.6); (aiTask->blockOffset).x = (float)fVar2; fVar2 = math::Maths_RandRange(0.4,0.6); (aiTask->blockOffset).y = (float)fVar2; } else { (aiTask->blockOffset).x = pointFloat->x; (aiTask->blockOffset).y = pointFloat->y; } if (param_7 != 0) { aiTask->flags = aiTask->flags | AITASK_FLAG_FACEOUT; } aiTask->targetObject = NULL; aiTask->time = 0.0; AITask_InitTask_1(aiTask,AI_Priority_Request); aiTask->flags = aiTask->flags | AITASK_FLAG_CARRYTASK; AITask_PlaceRequestObject(blockPos,objType,objID,objLevel); return; } void __cdecl lego::ai::AITask_PlaceRequestObject (Point2I *blockPos,LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { LegoObject *pLVar1; LegoObject *liveObj; uint uVar2; pLVar1 = game::LegoObject_FUN_00438d20(blockPos,objType,objID,objLevel); if (pLVar1 == NULL) { if (((objID != 0) && (objType == LegoObject_Ore)) && (pLVar1 = game::LegoObject_FUN_00438d20(blockPos,LegoObject_Ore,0,objLevel), pLVar1 != NULL)) { liveObj = game::LegoObject_FindResourceProcessingBuilding(NULL,blockPos,LegoObject_Ore,0); uVar2 = stats::StatsObject_GetMaxCarry(liveObj); if (uVar2 == 0) { return; } do { game::LegoObject_SpawnCarryableObject(pLVar1,LegoObject_Ore,0,objLevel); uVar2 -= 1; } while (uVar2 != 0); return; } } else { pLVar1 = game::LegoObject_SpawnCarryableObject(pLVar1,objType,objID,objLevel); if (pLVar1 != NULL) { return; } } globs::aiGlobs.requestObjCounts[objType][objID][objLevel] = globs::aiGlobs.requestObjCounts[objType][objID][objLevel] + 1; return; } AITask * __cdecl lego::ai::AITask_DoDeposit_ObjectType (LegoObject *liveObj,LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { AITask *aiTask; aiTask = AITask_Create(AITask_Type_Deposit); aiTask->targetObject = liveObj; aiTask->time = 0.0; aiTask->objType = objType; aiTask->objID = objID; aiTask->objLevel = objLevel; AITask_InitTask_1(aiTask,AI_Priority_Refining); aiTask->flags = aiTask->flags & ~AITASK_FLAG_REALLOCATE | (AITASK_FLAG_DUPLICATE|AITASK_FLAG_NOTIMELIMIT|AITASK_FLAG_CARRYTASK); return aiTask; } void __cdecl lego::ai::AITask_DoRequestObjectCallbacks(LegoObject *liveObj) { BOOL BVar1; LegoObject *pLVar2; LegoObject_ID objID; LegoObject_Type objType; uint objLevel; uint (*paauVar3) [15] [16]; int local_8; uint local_4; objType = LegoObject_None; paauVar3 = globs::aiGlobs.requestObjCounts; do { objID = 0; do { objLevel = 0; do { local_8 = 0; local_4 = 0; if ((*paauVar3)[0] != 0) { do { BVar1 = AITask_FUN_00404e40(objType,objID,objLevel); if ((BVar1 == 0) || (pLVar2 = game::LegoObject_SpawnCarryableObject(liveObj,objType,objID,objLevel), pLVar2 != NULL)) { local_8 += 1; } local_4 += 1; } while (local_4 < (*paauVar3)[0]); } objLevel += 1; (*paauVar3)[0] = (*paauVar3)[0] - local_8; paauVar3 = (uint (*) [15] [16])(*paauVar3 + 1); } while (objLevel < 0x10); objID += 1; } while (objID < 0xf); objType += LegoObject_Vehicle; } while (paauVar3 <= (uint (*) [15] [16])((int)globs::aiGlobs.requestObjCounts[0x13][0xe] + 0x3f)) ; return; } void __cdecl lego::ai::AITask_LiveObject_FUN_004038d0(LegoObject *liveObj) { AITask *aiTask; aiTask = AITask_DoDeposit_ObjectType(liveObj,LegoObject_None,0xffffffff,0); AITask_SetPriorityType(aiTask,AI_Priority_Storage); AITask_DoRequestObjectCallbacks(liveObj); return; } void __cdecl lego::ai::AITask_DoGotoEat(LegoObject *liveObj) { AITask *aiTask; aiTask = AITask_Create(AITask_Type_GotoEat); aiTask->targetObject = liveObj; aiTask->time = 0.0; AITask_InitTask_1(aiTask,AI_Priority_Crystal); aiTask->flags = aiTask->flags & ~AITASK_FLAG_REALLOCATE | (AITASK_FLAG_DUPLICATE|AITASK_FLAG_NOTIMELIMIT); return; } BOOL __cdecl lego::ai::AITask_LiveObject_FUN_00403940(LegoObject *liveObj) { BOOL BVar1; BVar1 = AITask_RunThroughLists(AITask_Callback_FUN_00403960,liveObj); return BVar1; } BOOL __cdecl lego::ai::AITask_Callback_FUN_00403960(AITask *aiTask,LegoObject *liveObj) { if ((aiTask->taskType == AITask_Type_Deposit) && (liveObj == aiTask->targetObject)) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; } return 0; } // Removes all tasks whose targetObject references match the specified object. void __cdecl lego::ai::AITask_RemoveTargetObjectReferences(LegoObject *targetObj) { AITask *aiTask; AITaskFlags aflags; AITask *taskNext; if (((byte)globs::aiGlobs.flags & AITASK_GLOB_FLAG_UNK_2) == 0) { aiTask = targetObj->aiTask; while (aiTask != NULL) { aflags = aiTask->flags; taskNext = aiTask->next; if (((aflags & AITASK_FLAG_REALLOCATE) == AITASK_FLAG_NONE) || ((aflags & AITASK_FLAG_REMOVING) != AITASK_FLAG_NONE)) { if (((aflags & AITASK_FLAG_CREATUREREALLOCATE) == AITASK_FLAG_NONE) || ((aflags & AITASK_FLAG_REMOVING) != AITASK_FLAG_NONE)) { AITask_Remove(aiTask,FALSE); aiTask = taskNext; } else { AITask_Init_2_NoPriority(aiTask); aiTask = taskNext; } } else { AITask_InitTask_1(aiTask,aiTask->priorityType); aiTask = taskNext; } } targetObj->aiTask = NULL; AITask_RunThroughLists(AITask_Callback_RemoveTargetObjectReference,targetObj); } return; } // Removes the task if its object_10 reference match the specified object. BOOL __cdecl lego::ai::AITask_Callback_RemoveTargetObjectReference(AITask *aiTask,LegoObject *targetObj) { if (targetObj == aiTask->targetObject) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; } return 0; } void __cdecl lego::ai::AITask_Route_End(LegoObject *liveObj,BOOL completed) { AITask *objTask; objTask = liveObj->aiTask; if (objTask != NULL) { if (completed == 0) { objTask->flags = objTask->flags & ~AITASK_FLAG_PERFORMING; } else { if (objTask->taskType == AITask_Type_Goto) { AITask_LiveObject_FUN_00404110(liveObj); if (liveObj->type == LegoObject_RockMonster) { game::Message_PostEvent(Message_RockMonsterGotoComplete,liveObj,0,NULL); return; } } } } return; } void __cdecl lego::ai::AITask_LiveObject_FUN_00403a70(LegoObject *liveObj) { AITaskFlags *pAFlags; if (liveObj->aiTask != NULL) { pAFlags = &liveObj->aiTask->flags; *pAFlags = *pAFlags & ~AITASK_FLAG_PERFORMING; } return; } void __cdecl lego::ai::AITask_VariousGatherTasks_FUN_00403a90(LegoObject *liveObj) { LegoObject *carriedObj; uint uVar1; LegoObject **ppLVar2; if ((((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && ((liveObj->flags1 & LIVEOBJ1_STORING) == LIVEOBJ1_NONE)) && (uVar1 = 0, liveObj->numCarriedObjects != 0)) { ppLVar2 = liveObj->carriedObjects; do { carriedObj = *ppLVar2; AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Deposit,carriedObj); AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Dump,carriedObj); AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Dynamite,carriedObj); AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_ElecFence,carriedObj); AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Request,carriedObj); AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Gather,NULL); AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_BirdScarer,carriedObj); uVar1 += 1; ppLVar2 = ppLVar2 + 1; } while (uVar1 < liveObj->numCarriedObjects); } return; } void __cdecl lego::ai::AITask_LiveObject_FUN_00403b30 (LegoObject *holderObj,AITask_Type taskType,LegoObject *carriedObj) { AITask **ppAVar1; AITask_Type AVar2; Map3D *map; AITask *pAVar3; AITask *aiTask; int bx; int by; if (((byte)globs::aiGlobs.flags & 2) != 0) { return; } pAVar3 = NULL; aiTask = holderObj->aiTask; if (aiTask == NULL) { return; } while (taskType != aiTask->taskType) { ppAVar1 = &aiTask->next; pAVar3 = aiTask; aiTask = *ppAVar1; if (*ppAVar1 == NULL) { return; } } AVar2 = aiTask->taskType; if (AVar2 == AITask_Type_Deposit) { LAB_00403b90: if (AVar2 == AITask_Type_Request) goto LAB_00403b95; } else { if (AVar2 != AITask_Type_Request) { if ((((AVar2 != AITask_Type_Dump) && (AVar2 != AITask_Type_Collect)) && (AVar2 != AITask_Type_Dynamite)) && ((AVar2 != AITask_Type_ElecFence && (AVar2 != AITask_Type_BirdScarer)))) goto LAB_00403c01; goto LAB_00403b90; } LAB_00403b95: AITask_DoRequest_ObjectType (aiTask->objType,aiTask->objID,aiTask->objLevel,&aiTask->blockPos, aiTask->constructHandle,&aiTask->blockOffset,aiTask->flags & AITASK_FLAG_FACEOUT); } if (aiTask->taskType == AITask_Type_Dynamite) { game::Level_Block_SetBusy(&aiTask->blockPos,FALSE); by = (aiTask->blockPos).y; bx = (aiTask->blockPos).x; map = lrr::Lego_GetMap(); lego::map::Map3D_ClearBlockHighlight(map,bx,by); } AITask_DoCollect(carriedObj,150.0); AITask_DoCollect_Target(carriedObj); LAB_00403c01: if (pAVar3 == NULL) { holderObj->aiTask = aiTask->next; AITask_Remove(aiTask,FALSE); return; } pAVar3->next = aiTask->next; AITask_Remove(aiTask,FALSE); return; } void __cdecl lego::ai::AITask_LiveObject_SetAITaskUnk (LegoObject *liveObj,AITask_Type taskType,LegoObject *liveObj2,BOOL param_4) { Point2I *blockPos; AITask *pAVar1; LegoObject *argument2; BOOL BVar2; BlockFlags1 BVar3; AITask *aiTask; AITask *pAVar4; AITask_Type AVar5; LegoObject *liveObj_00; bool shouldPlaceResource; liveObj_00 = liveObj; if (((byte)globs::aiGlobs.flags & AITASK_GLOB_FLAG_REMOVING) == 0) { if ((taskType == AITask_Type_Collect) && (argument2 = game::LegoObject_FindResourceProcessingBuilding (liveObj,NULL,liveObj2->type,liveObj2->objLevel), argument2 != NULL)) { game::Message_PostEvent(Message_CollectCrystalComplete,liveObj,argument2,NULL); } pAVar1 = liveObj->aiTask; pAVar4 = NULL; if (liveObj->aiTask != NULL) { LAB_00403c9a: // Linked list while loop. // while (aiTask != nullptr) { ...; aiTask = aiTask->next; } aiTask = pAVar1; if (taskType != aiTask->taskType) goto code_r0x00403ca4; liveObj = NULL; shouldPlaceResource = false; if (param_4 != 0) { if (pAVar4 == NULL) { liveObj_00->aiTask = aiTask->next; } else { pAVar4->next = aiTask->next; } } if (aiTask->taskType == AITask_Type_Request) { AVar5 = aiTask->constructHandle; shouldPlaceResource = true; liveObj = liveObj2; BVar2 = game::Construction_Zone_NeedsMoreOfResource(AVar5,liveObj2->type,liveObj2->id); if (BVar2 == 0) { AITask_Construction_FUN_00403630(AVar5,TRUE,liveObj2->type,liveObj2->id); shouldPlaceResource = false; } } else { AVar5 = taskType; if (aiTask->taskType == AITask_Type_Clear) { if (liveObj_00->type == LegoObject_Vehicle) { // Instantly clear all but 1 rubble layers. For loop simply loops until number of layers // is 1. // (then the function below handles the final clearing) for (BVar3 = (globs::legoGlobs.currLevel)->blocks [(aiTask->blockPos).y * (globs::legoGlobs.currLevel)->width + (aiTask->blockPos).x].flags1 & BLOCK1_RUBBLE_FULL; BVar3 != BLOCK1_NONE; BVar3 += ~BLOCK1_NONE) { game::Level_Block_ClearRubbleLayer(&aiTask->blockPos); game::Message_PostEvent(aiTask->completeAction,0,0,&aiTask->blockPos); // BVar3 -= 1; } } blockPos = &aiTask->blockPos; game::Level_Block_ClearRubbleLayer(blockPos); game::Message_PostEvent(aiTask->completeAction,0,0,blockPos); game::Level_Block_SetBusyFloor(blockPos,FALSE); game::Level_Block_SetDozerClearing(blockPos,FALSE); } else { if (taskType == AITask_Type_Train) { game::LegoObject_TrainMiniFigure_instantunk(liveObj_00,aiTask->trainFlags); front::Text_DisplayMessage(Text_ManTrained,TRUE,FALSE); } } } if (param_4 != 0) { AITask_Remove(aiTask,FALSE); } if (shouldPlaceResource) { game::Construction_Zone_PlaceResource(AVar5,liveObj); } } LAB_00403dfc: if (taskType == AITask_Type_Collect) { AITask_RemoveCollectReferences(liveObj2); } } return; code_r0x00403ca4: pAVar1 = aiTask->next; pAVar4 = aiTask; if (aiTask->next == NULL) goto LAB_00403dfc; goto LAB_00403c9a; } BOOL __cdecl lego::ai::AITask_RemoveCollectReferences(LegoObject *targetObj) { BOOL BVar1; BVar1 = AITask_RunThroughLists(AITask_Callback_RemoveCollectReference,targetObj); return BVar1; } BOOL __cdecl lego::ai::AITask_Callback_RemoveCollectReference(AITask *aiTask,LegoObject *targetObj) { if ((aiTask->taskType == AITask_Type_Collect) && (aiTask->targetObject == targetObj)) { aiTask->flags = aiTask->flags | AITASK_FLAG_REMOVING; } return 0; } void __cdecl lego::ai::AITask_DoAnimationWait(LegoObject *liveObj) { AITask *newAITask; if ((liveObj->aiTask == NULL) || (liveObj->aiTask->taskType != AITask_Type_AnimationWait)) { newAITask = AITask_Create(AITask_Type_AnimationWait); newAITask->next = liveObj->aiTask; liveObj->aiTask = newAITask; } return; } void __cdecl lego::ai::AITask_LiveObject_Unk_UpdateAITask_AnimationWait(LegoObject *liveObj) { if ((liveObj->aiTask != NULL) && (liveObj->aiTask->taskType == AITask_Type_AnimationWait)) { AITask_LiveObject_FUN_00404110(liveObj); } return; } int __cdecl lego::ai::AITask_QSortCompare(AITask **task_a,AITask **task_b) { AITask *pAVar1; AITask *pAVar2; AITaskFlags AVar3; AITaskFlags AVar4; pAVar1 = *task_a; pAVar2 = *task_b; AVar3 = pAVar1->flags & AITASK_FLAG_IMMEDIATESELECTION; if ((AVar3 != AITASK_FLAG_NONE) && ((pAVar2->flags & AITASK_FLAG_IMMEDIATESELECTION) == AITASK_FLAG_NONE)) { return 0xffffffff; } AVar4 = pAVar2->flags & AITASK_FLAG_IMMEDIATESELECTION; if (AVar4 == AITASK_FLAG_NONE) { if (AVar3 == AITASK_FLAG_NONE) goto LAB_00403f0c; } else { if (AVar3 == AITASK_FLAG_NONE) { return 1; } } if (AVar4 != AITASK_FLAG_NONE) { if (pAVar2->creationTime < pAVar1->creationTime) { return 0xffffffff; } if (pAVar1->creationTime < pAVar2->creationTime) { return 1; } } LAB_00403f0c: if (pAVar1->priorityValue < 0) { pAVar1->priorityValue = 0; } if (pAVar2->priorityValue < 0) { pAVar2->priorityValue = 0; } if (99 < pAVar1->priorityValue) { pAVar1->priorityValue = 99; } if (99 < pAVar2->priorityValue) { pAVar2->priorityValue = 99; } if (pAVar2->priorityValue < pAVar1->priorityValue) { return 0xffffffff; } return (uint)(pAVar1->priorityValue < pAVar2->priorityValue); } AITask * __cdecl lego::ai::AITask_InitTask_1(AITask *aiTask,AI_Priority priorityType) { // Prepend to linked list. aiTask->next = globs::aiGlobs.pendingTaskList; globs::aiGlobs.pendingTaskList = aiTask; aiTask->time = 1500.0; aiTask->flags = aiTask->flags & ~AITASK_FLAG_PERFORMING | AITASK_FLAG_REALLOCATE; aiTask->priorityValue = globs::aiGlobs.priorityValues[priorityType]; aiTask->priorityType = priorityType; return aiTask; } void __cdecl lego::ai::AITask_Init_2_NoPriority(AITask *aiTask) { // Prepend to linked list. aiTask->next = globs::aiGlobs.creatureTaskList; globs::aiGlobs.creatureTaskList = aiTask; aiTask->time = 1500.0; aiTask->flags = aiTask->flags & ~(AITASK_FLAG_PERFORMING|AITASK_FLAG_REALLOCATE); return; } void __cdecl lego::ai::AITask_Game_UnkLiveObjectHandleDynamite(LegoObject *liveObj) { // if (!(aiGlobs.flags & (AITASK_GLOB_FLAG_REMOVING|AITASK_GLOB_FLAG_UPDATINGOBJECT))) if (((byte)globs::aiGlobs.flags & 6) == 0) { AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Goto,NULL); if (((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && (liveObj->carriedObjects[0]->type == LegoObject_Dynamite)) { AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Dynamite,liveObj->carriedObjects[0]); } AITask_ReevaluateObjectTasks(liveObj); AITask_RemoveAssignedToObjectReferences(liveObj); } return; } // Seems to clean up existing tasks with certain flags, in the object's task list. void __cdecl lego::ai::AITask_ReevaluateObjectTasks(LegoObject *liveObj) { AITaskFlags aflags; AITask *foundTask; AITask *objTask; AITask *objTaskNext; foundTask = NULL; objTaskNext = liveObj->aiTask; while (objTask = objTaskNext, objTask != NULL) { aflags = objTask->flags; objTaskNext = objTask->next; if ((aflags & AITASK_FLAG_VOLATILE) == AITASK_FLAG_NONE) { // Is this some logic for dropping certain tasks and putting it back in the pool for // other object's to take on? if (((aflags & AITASK_FLAG_REALLOCATE) == AITASK_FLAG_NONE) || ((aflags & AITASK_FLAG_REMOVING) != AITASK_FLAG_NONE)) { if (((aflags & AITASK_FLAG_CREATUREREALLOCATE) == AITASK_FLAG_NONE) || ((aflags & AITASK_FLAG_REMOVING) != AITASK_FLAG_NONE)) { if (foundTask == NULL) { objTask->next = NULL; foundTask = objTask; } else { // Assign as SECOND task in liveObj linked task list. (Is this intended to not append // more than 1?) foundTask->next = objTask; // Note: `objTask->next = NULL` won't force a break in the while loop, since we stored // objTaskNext earlier. objTask->next = NULL; } } else { // Prepend to linked list. objTask->next = globs::aiGlobs.creatureTaskList; globs::aiGlobs.creatureTaskList = objTask; } } else { // Prepend to linked list. objTask->next = globs::aiGlobs.pendingTaskList; globs::aiGlobs.pendingTaskList = objTask; } } else { AITask_Remove(objTask,FALSE); } } liveObj->aiTask = foundTask; return; } // Returns the last task in the object's linked list of tasks. // Or null if the object has no tasks. AITask * __cdecl lego::ai::AITask_GetObjectTaskListTail(LegoObject *liveObj) { AITask *task; AITask *taskNext; task = liveObj->aiTask; if (task != NULL) { for (taskNext = task->next; taskNext != NULL; taskNext = taskNext->next) { task = taskNext; } } return task; } BOOL __cdecl lego::ai::AITask_LiveObject_IsCurrentTaskType(LegoObject *liveObj,AITask_Type taskType) { AITask *pAVar1; pAVar1 = liveObj->aiTask; if (pAVar1 == NULL) { return (BOOL)NULL; } do { if (taskType == pAVar1->taskType) { return (BOOL)(AITask *)0x1; } pAVar1 = pAVar1->next; } while (pAVar1 != NULL); return (BOOL)pAVar1; } void __cdecl lego::ai::AITask_LiveObject_FUN_00404110(LegoObject *liveObj) { AITaskFlags aflags; AITask *objTask; objTask = liveObj->aiTask; if (objTask != NULL) { liveObj->aiTask = objTask->next; aflags = objTask->flags; if (((aflags & AITASK_FLAG_REALLOCATE) != AITASK_FLAG_NONE) && ((aflags & AITASK_FLAG_REMOVING) == AITASK_FLAG_NONE)) { // Prepend to linked list. objTask->next = globs::aiGlobs.pendingTaskList; globs::aiGlobs.pendingTaskList = objTask; return; } if (((aflags & AITASK_FLAG_CREATUREREALLOCATE) != AITASK_FLAG_NONE) && ((aflags & AITASK_FLAG_REMOVING) == AITASK_FLAG_NONE)) { // Prepend to linked list. objTask->next = globs::aiGlobs.creatureTaskList; globs::aiGlobs.creatureTaskList = objTask; return; } AITask_Remove(objTask,FALSE); } return; } // Called during AITask_UpdateAll, to update two count-down timers for all tasks. BOOL __cdecl lego::ai::AITask_Callback_UpdateTask(AITask *aiTask,float *pElapsedGame) { if ((*(byte *)&aiTask->flags & AITASK_FLAG_NOTIMELIMIT) == 0) { aiTask->time = aiTask->time - *pElapsedGame; } aiTask->timeIn = aiTask->timeIn - *pElapsedGame; return 0; } BOOL __cdecl lego::ai::AITask_Callback_UpdateObject(LegoObject *liveObj,float *pElapsedGame) { float fVar1; LegoObject *pLVar2; bool bVar3; bool bVar4; LegoObject *liveObj_00; float *pfVar5; BOOL BVar6; TutorialFlags tflags; StatsFlags1 sflags1; Map3D *map; AITask *pAVar7; float fVar8; uint uVar9; LegoObject *aiTask; float10 fVar10; uint bx; Vector3F *out_vertPoses; void *local_6c; void *local_68; undefined local_64 [4]; Point2I local_60; float local_58; VehicleModel *vehicle; Point2I local_50; Point2I local_48; float local_40; float local_3c; Point2I local_38; Vector3F local_30 [2]; float local_18; float local_14; LegoObject *targetObj; AITaskFlags aflags; LegoObject_Type objType; AITask_Type taskType; liveObj_00 = liveObj; globs::aiGlobs.flags |= AITASK_GLOB_FLAG_UPDATINGOBJECT; if (((((((liveObj->flags3 & LIVEOBJ3_AITASK_UNK_400000) == LIVEOBJ3_NONE) || ((ushort)((ushort)(liveObj->health < 0.0) << 8 | (ushort)(liveObj->health == 0.0) << 0xe) != 0)) || (BVar6 = lrr::Lego_IsFPObject(liveObj), pfVar5 = pElapsedGame, BVar6 != 0)) || ((liveObj->driveObject != NULL && (liveObj->type == LegoObject_MiniFigure)))) || (liveObj->carryingThisObject != NULL)) || (((liveObj->flags2 & (LIVEOBJ2_PUSHED|LIVEOBJ2_FROZEN)) != LIVEOBJ2_NONE || ((liveObj->flags1 & LIVEOBJ1_RUNNINGAWAY) != LIVEOBJ1_NONE)))) goto LAB_00404c90; pAVar7 = liveObj->aiTask; local_6c = NULL; if (pAVar7 == NULL) { local_60.x = 0; local_60.y = 0; liveObj->aiTimer_338 = *pElapsedGame + liveObj->aiTimer_338; game::LegoObject_GetBlockPos(liveObj,&local_38.x,&local_38.y); if (((liveObj->aiTimer_338 == *pfVar5) || ((*(byte *)&liveObj->flags4 & 0xc0) != 0)) || (BVar6 = game::LegoObject_FUN_004439d0(liveObj,&local_38,&local_60,0), BVar6 == 0)) { if ((ushort)((ushort)(liveObj->aiTimer_338 < 250.0) << 8 | (ushort)(liveObj->aiTimer_338 == 250.0) << 0xe) == 0) { if ((liveObj->type == LegoObject_MiniFigure) && (BVar6 = lrr::Lego_IsFPObject(liveObj), BVar6 == 0)) { game::LegoObject_TryWaiting(liveObj); } liveObj->aiTimer_338 = 0.0; } else { liveObj = NULL; aiTask = (LegoObject *)globs::aiGlobs.pendingTaskList; pLVar2 = (LegoObject *)globs::aiGlobs.pendingTaskList; if (globs::aiGlobs.pendingTaskList == NULL) { LAB_00404c21: if (aiTask != NULL) { AITask_FUN_00406290((AITask *)aiTask,(AITask *)liveObj,liveObj_00); goto LAB_00404c90; } } else { do { aiTask = pLVar2; fVar8 = (aiTask->routeCurve).points[5].x; if ((((((uint)fVar8 & 0x80000) == 0) && ((((uint)fVar8 & 0x100000) != 0 || ((BVar6 = game::LegoObject_VehicleMaxCarryChecksTime_FUN_00439c80(liveObj_00), BVar6 == 0 && (fVar8 = (aiTask->routeCurve).points[5].x, ((uint)fVar8 & 0x400) == 0)))))) && ((((uint)fVar8 & 0x100) != 0 || (BVar6 = game::Message_IsUnitSelected(liveObj_00,NULL), BVar6 == 0)))) && ((((uint)(aiTask->routeCurve).points[5].x & 0x100) == 0 || (BVar6 = game::Message_FindIndexOfObject ((LegoObject **)(aiTask->routeCurve).points[1].y, (uint)(aiTask->routeCurve).points[2].x,liveObj_00,NULL), BVar6 != 0)))) { local_58 = (float)((Point2I *)&aiTask->customName)->x; vehicle = aiTask->vehicle; BVar6 = AITask_FUN_00404ef0((AITask *)aiTask,liveObj_00,NULL,&local_58,&pElapsedGame,1 ,1); if ((BVar6 != 0) && (pElapsedGame == NULL)) { if (((uint)(aiTask->routeCurve).points[5].x & 0x100000) != 0) goto LAB_00404c21; game::LegoObject_GetBlockPos(liveObj_00,&local_50.x,&local_50.y); objType = aiTask->type; if ((((objType == LegoObject_UpgradePart) || (objType == LegoObject_ElectricFence)) || (objType == 0x17)) || ((objType == 0x15 || ((objType == LegoObject_Dynamite && ((*(byte *)&(aiTask->routeCurve).points[5].x & 8) == 0)))))) { if (((local_58 == (float)local_50.x) && (uVar9 = (int)vehicle - local_50.y >> 0x1f, ((int)vehicle - local_50.y ^ uVar9) - uVar9 == 1)) || ((vehicle == (VehicleModel *)local_50.y && (uVar9 = (int)local_58 - local_50.x >> 0x1f, ((int)local_58 - local_50.x ^ uVar9) - uVar9 == 1)))) goto LAB_00404c21; } else { if ((local_58 == (float)local_50.x) && (vehicle == (VehicleModel *)local_50.y)) goto LAB_00404c21; } } } if ((((((uint)(aiTask->routeCurve).points[5].x & 0x400) != 0) && (BVar6 = game::LegoObject_VehicleMaxCarryChecksTime_FUN_00439c80(liveObj_00), BVar6 != 0)) && ((liveObj_00->flags3 & LIVEOBJ3_SELECTED) == LIVEOBJ3_NONE)) && (liveObj_00->type != LegoObject_RockMonster)) { pLVar2 = liveObj_00->carriedObjects[0]; if ((pLVar2->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE) { if ((aiTask->upgradePart == NULL) || (((pLVar2->objLevel == aiTask->routeBlocksTotal && ((aiTask->routeBlocks == (RoutingBlock *)0xffffffff || ((RoutingBlock *)pLVar2->id == aiTask->routeBlocks)))) && ((Upgrade_PartModel *)pLVar2->type == aiTask->upgradePart)))) { objType = aiTask->type; bVar3 = false; bVar4 = false; if (((objType == LegoObject_Ore) || (objType == LegoObject_Barrier)) || ((objType == LegoObject_Path || (objType == LegoObject_Type_Count)))) { LAB_00404b3f: bVar3 = true; } else { if (objType == LegoObject_Boulder) { if ((LegoObject *)aiTask->miniFigure == NULL) goto LAB_00404b3f; BVar6 = game::LegoObject_IsActive((LegoObject *)aiTask->miniFigure,0); if (BVar6 != 0) { BVar6 = game::LegoObject_TryDepositCarried (liveObj_00,(LegoObject *)aiTask->miniFigure); if (BVar6 != 0) goto LAB_00404c21; bVar4 = true; } } } if (bVar3) { if (aiTask->type == LegoObject_Barrier) { BVar6 = game::LiveObject_FUN_00431ba0 (liveObj_00,(Point2I *)&aiTask->customName,&local_48,1); if (BVar6 == 0) { bVar4 = true; } } else { local_48.x = ((Point2I *)&aiTask->customName)->x; local_48.y = (int)aiTask->vehicle; } if (!bVar4) { game::LegoObject_GetBlockPos(liveObj_00,(int *)&local_40,(int *)&local_3c); BVar6 = game::LegoObject_Route_ScoreNoCallback_FUN_00440ef0 (liveObj_00,(uint)local_40,(uint)local_3c,local_48.x, local_48.y,&local_6c,&local_68,local_64); if (BVar6 == 0) { bVar4 = true; goto LAB_00404bc6; } io::Mem_Free(local_6c); io::Mem_Free(local_68); goto LAB_00404c21; } } else { LAB_00404bc6: if (!bVar4) goto LAB_00404bd1; } aiTask->building = (BuildingModel *)0x42960000; } } else { if (aiTask->type == 0x1b) goto LAB_00404c21; } } LAB_00404bd1: if ((((uint)(aiTask->routeCurve).points[5].x & 0x100) != 0) && (BVar6 = game::Message_FindIndexOfObject ((LegoObject **)(aiTask->routeCurve).points[1].y, (uint)(aiTask->routeCurve).points[2].x,liveObj_00,NULL), BVar6 != 0)) { aiTask = NULL; goto LAB_00404c21; } pLVar2 = (LegoObject *)(aiTask->routeCurve).points[5].y; liveObj = aiTask; } while (pLVar2 != NULL); } BVar6 = game::LegoObject_VehicleMaxCarryChecksTime_FUN_00439c80(liveObj_00); if (BVar6 == 0) { if (globs::aiGlobs.freeUnitCount < 0x32) { globs::aiGlobs.freeUnitList[globs::aiGlobs.freeUnitCount] = liveObj_00; globs::aiGlobs.freeUnitCount += 1; } if (((globs::aiGlobs.freeCreatureCount < 0x32) && (liveObj_00->type == LegoObject_RockMonster)) && ((liveObj_00->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE)) { globs::aiGlobs.freeCreatureList[globs::aiGlobs.freeCreatureCount] = liveObj_00; globs::aiGlobs.freeCreatureCount += 1; } } } } else { if ((local_60.x != 0) && (local_60.y != 0)) { pAVar7 = AITask_Create(AITask_Type_Goto); liveObj->aiTask = pAVar7; (pAVar7->blockPos).x = local_60.x; (pAVar7->blockPos).y = local_60.y; } } goto LAB_00404c90; } liveObj->aiTimer_338 = 0.0; aflags = pAVar7->flags; if ((aflags & AITASK_FLAG_REMOVING) != AITASK_FLAG_NONE) { AITask_LiveObject_FUN_00404110(liveObj); game::LegoObject_Route_End(liveObj,FALSE); goto LAB_00404c90; } taskType = pAVar7->taskType; if ((taskType == AITask_Type_Wait) && ((ushort)((ushort)(pAVar7->time < 0.0) << 8 | (ushort)(pAVar7->time == 0.0) << 0xe) != 0)) { AITask_LiveObject_FUN_00404110(liveObj); } else { if (taskType == AITask_Type_Follow) { if ((ushort)((ushort)(pAVar7->time < 0.0) << 8 | (ushort)(pAVar7->time == 0.0) << 0xe) != 0) { game::LegoObject_GetBlockPos(liveObj,&local_48.x,&local_48.y); game::LegoObject_GetBlockPos(pAVar7->targetObject,&local_50.x,&local_50.y); if ((local_48.x == local_50.x) && (local_48.y == local_50.y)) goto LAB_0040441c; LAB_004043f4: AITask_LiveObject_FUN_00404d30(liveObj,&local_50,NULL); pAVar7->time = 50.0; } } else { if (taskType == AITask_Type_FollowAttack) { if ((ushort)((ushort)(pAVar7->time < 0.0) << 8 | (ushort)(pAVar7->time == 0.0) << 0xe) != 0) { fVar8 = pAVar7->targetObject->health; fVar1 = pAVar7->targetObject->stats->PainThreshold; if ((ushort)((ushort)(fVar8 < fVar1) << 8 | (ushort)(fVar8 == fVar1) << 0xe) == 0) { game::LegoObject_GetPosition(liveObj,(float *)&local_48,(float *)&local_48.y); game::LegoObject_GetPosition(pAVar7->targetObject,&local_58,(float *)&vehicle); fVar8 = SQRT(((float)local_48.y - (float)vehicle) * ((float)local_48.y - (float)vehicle) + ((float)local_48.x - local_58) * ((float)local_48.x - local_58)); if ((ushort)((ushort)(fVar8 < 130.0) << 8 | (ushort)(fVar8 == 130.0) << 0xe) == 0) { game::LegoObject_GetBlockPos(liveObj,&local_60.x,&local_60.y); game::LegoObject_GetBlockPos(pAVar7->targetObject,&local_50.x,&local_50.y); if ((local_60.x != local_50.x) || (local_60.y != local_50.y)) goto LAB_004043f4; } else { BVar6 = game::LegoObject_FireBeamWeaponAtObject (liveObj,pAVar7->targetObject,Weapon_KnownType_Pusher); if (BVar6 == 0) { pAVar7->time = 25.0; goto LAB_004047ed; } } LAB_0040441c: pAVar7->time = 50.0; } else { pAVar7->flags = aflags | AITASK_FLAG_REMOVING; } } } else { if (((aflags & AITASK_FLAG_PERFORMING) == AITASK_FLAG_NONE) && ((liveObj->flags3 & LIVEOBJ3_SELECTED) == LIVEOBJ3_NONE)) { BVar6 = 1; if (true) { switch(taskType) { case AITask_Type_Goto: game::LegoObject_GetBlockPos(liveObj,&local_48.x,&local_48.y); if ((local_48.x == (pAVar7->blockPos).x) && ((VehicleModel *)local_48.y == (VehicleModel *)(pAVar7->blockPos).y)) { BVar6 = 1; AITask_LiveObject_FUN_00404110(liveObj); } else { uVar9 = (pAVar7->blockPos).y; bx = (pAVar7->blockPos).x; out_vertPoses = local_30; map = lrr::Lego_GetMap(); lego::map::Map3D_GetBlockVertexPositions(map,bx,uVar9,out_vertPoses); fVar10 = math::Maths_RandRange(local_30[0].x - -6.0,local_18 - 6.0); local_40 = (float)fVar10; fVar10 = math::Maths_RandRange(local_14 - -6.0,local_30[0].y - 6.0); local_3c = (float)fVar10; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); BVar6 = AITask_LiveObject_FUN_00404d30 (liveObj,&pAVar7->blockPos, (float *)(-(uint)((sflags1 & STATS1_ROUTEAVOIDANCE) != STATS1_NONE) & (uint)&local_40)); } break; case AITask_Type_Collect: BVar6 = game::LegoObject_TryCollectObject(liveObj,pAVar7->targetObject); break; case AITask_Type_Gather: BVar6 = game::LegoObject_PTL_GatherRock(liveObj); break; case AITask_Type_Deposit: BVar6 = game::LegoObject_TryDepositCarried(liveObj,pAVar7->targetObject); break; case AITask_Type_Dump: BVar6 = game::LegoObject_TryRequestOrDumpCarried (liveObj,&pAVar7->blockPos,&pAVar7->blockOffset,TRUE, aflags & AITASK_FLAG_FACEOUT); break; case AITask_Type_Request: BVar6 = game::LegoObject_TryRequestOrDumpCarried (liveObj,&pAVar7->blockPos,&pAVar7->blockOffset,TRUE, aflags & AITASK_FLAG_FACEOUT); break; case AITask_Type_Dig: if ((((aflags & AITASK_FLAG_DIGCONNECTION) != AITASK_FLAG_NONE) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_SINGLEWIDTHDIG) != STATS1_NONE)) || ((*(byte *)&pAVar7->flags & 8) == 0)) { BVar6 = game::LegoObject_RouteToDig_FUN_00447100 (liveObj,(pAVar7->blockPos).x,(pAVar7->blockPos).y, pAVar7->flags & AITASK_FLAG_DIGCONNECTION); } break; case AITask_Type_Dynamite: BVar6 = game::LegoObject_TryDynamite_FUN_00448ac0(liveObj,&pAVar7->blockPos); break; case AITask_Type_Repair: BVar6 = game::LegoObject_TryRepairDrainObject (liveObj,pAVar7->targetObject,TRUE, aflags & AITASK_FLAG_UPGRADEBUILDING); break; case AITask_Type_Reinforce: BVar6 = game::LegoObject_TryReinforceBlock(liveObj,&pAVar7->blockPos); break; case AITask_Type_Clear: BVar6 = game::LegoObject_TryClear_FUN_00449570(liveObj,&pAVar7->blockPos); break; case AITask_Type_ElecFence: BVar6 = game::LegoObject_TryElecFence_FUN_00448d20(liveObj,&pAVar7->blockPos); break; case AITask_Type_Eat: BVar6 = game::LegoObject_TryGoEat_FUN_00449d80(liveObj,pAVar7->targetObject); break; case AITask_Type_GotoEat: BVar6 = game::LegoObject_TryGoEat_FUN_00449d80(liveObj,pAVar7->targetObject); break; case AITask_Type_FindDriver: BVar6 = game::LegoObject_TryFindDriver_FUN_00440690(liveObj,pAVar7->targetObject); break; case AITask_Type_GetTool: BVar6 = game::LegoObject_DoGetTool(liveObj,pAVar7->toolType); front::Bubble_ResetObjectBubbleImage(liveObj); break; case AITask_Type_BirdScarer: BVar6 = game::LegoObject_PlaceCarriedBirdScarerAt(liveObj,&pAVar7->blockPos); break; case AITask_Type_Upgrade: BVar6 = game::LegoObject_TryUpgrade_FUN_00448f50 (liveObj,pAVar7->targetObject,pAVar7->objLevel); break; case AITask_Type_BuildPath: BVar6 = game::LegoObject_TryBuildPath_FUN_00448f10(liveObj); break; case AITask_Type_Train: BVar6 = game::LegoObject_TryTrain_FUN_00449170(liveObj,pAVar7->targetObject,FALSE); break; case AITask_Type_Depart: BVar6 = game::LegoObject_TryDepart_FUN_004499c0(liveObj); break; case AITask_Type_AttackPath: BVar6 = game::LegoObject_TryAttackPath_FUN_004498d0(liveObj,&pAVar7->blockPos); break; case AITask_Type_AttackRockMonster: targetObj = pAVar7->targetObject; if ((targetObj == NULL) || (targetObj->freezeObject == NULL)) { LAB_0040469f: BVar6 = game::LegoObject_TryAttackRockMonster_FUN_004496f0 (liveObj,pAVar7->targetObject); } else { if ((targetObj->flags2 & LIVEOBJ2_FROZEN) == LIVEOBJ2_NONE) { tflags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((tflags == TUTORIAL_NONE) || (pAVar7->targetObject->stats->PainThreshold <= pAVar7->targetObject->health)) goto LAB_0040469f; BVar6 = 0; } else { BVar6 = 0; } } break; case AITask_Type_Recharge: BVar6 = game::LegoObject_TryRechargeCarried(liveObj); break; case AITask_Type_Dock: BVar6 = game::LegoObject_TryDock_FUN_004402b0(liveObj); break; case AITask_Type_AttackObject: BVar6 = game::LegoObject_TryAttackObject_FUN_004497e0(liveObj,pAVar7->targetObject); break; case AITask_Type_FindLoad: BVar6 = game::LegoObject_TryFindLoad_FUN_00440130(liveObj,pAVar7->targetObject); } } if (BVar6 == 0) { local_6c = (void *)0x1; } else { pAVar7->flags = pAVar7->flags | AITASK_FLAG_PERFORMING; } } } } } LAB_004047ed: if (local_6c != NULL) { if ((pAVar7->taskType == AITask_Type_Dig) && ((*(byte *)&pAVar7->flags & AITASK_FLAG_DIGCONNECTION) != 0)) { // = 100.0f; (4 seconds) pAVar7->timeIn = (float)&DAT_42c80000; } if (((*(byte *)&pAVar7->flags & AITASK_FLAG_REALLOCATE) != 0) && (pAVar7->time < 0.0)) { pAVar7->time = 1500.0; } AITask_LiveObject_FUN_00404110(liveObj); } LAB_00404c90: globs::aiGlobs.flags = globs::aiGlobs.flags & ~AITASK_GLOB_FLAG_UPDATINGOBJECT; return 0; } BOOL __cdecl lego::ai::AITask_LiveObject_FUN_00404d30(LegoObject *in_liveObj,Point2I *blockPos2,float *param_3) { LegoObject *liveObj; BOOL BVar1; uint *local_10; uint count; LegoObject_Type local_8; uint local_4; liveObj = in_liveObj; game::LegoObject_GetBlockPos(in_liveObj,(int *)&local_8,(int *)&local_4); if ((local_8 == blockPos2->x) && (local_4 == blockPos2->y)) { in_liveObj = (LegoObject *)&local_8; local_10 = &local_4; count = 1; } else { BVar1 = game::LegoObject_Route_ScoreNoCallback_FUN_00440ef0 (liveObj,local_8,local_4,blockPos2->x,blockPos2->y,&in_liveObj,&local_10, &count); if (BVar1 == 0) { return 0; } } game::LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj,count,(int *)in_liveObj,(int *)local_10,(Point2F *)param_3); if (in_liveObj != (LegoObject *)&local_8) { io::Mem_Free(in_liveObj); io::Mem_Free(local_10); } return TRUE; } BOOL __cdecl lego::ai::AITask_LiveObject_FUN_00404e00(LegoObject *liveObj) { BOOL BVar1; if ((liveObj->type == LegoObject_PowerCrystal) && ((liveObj->flags3 & LIVEOBJ3_POWEROFF) != LIVEOBJ3_NONE)) { BVar1 = game::LegoObject_FindNearestRechargeSeam(liveObj,NULL); return BVar1; } BVar1 = AITask_FUN_00404e40(liveObj->type,liveObj->id,liveObj->objLevel); return BVar1; } BOOL __cdecl lego::ai::AITask_FUN_00404e40(LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { BOOL BVar1; LegoObject_Type local_c; LegoObject_ID local_8; uint local_4; local_c = objType; local_8 = objID; local_4 = objLevel; BVar1 = AITask_RunThroughLists(AITask_Callback_FUN_00404e80,&local_c); return BVar1; } BOOL __cdecl lego::ai::AITask_Callback_FUN_00404e80(AITask *aiTask,int *param_2) { AITask_Type AVar1; BOOL BVar2; AVar1 = aiTask->taskType; if (AVar1 != AITask_Type_Deposit) { if (((AVar1 != AITask_Type_Request) && (AVar1 != AITask_Type_Dynamite)) && (AVar1 != AITask_Type_ElecFence)) { return 0; } if (((AVar1 != AITask_Type_Deposit) && (aiTask->targetObject != NULL)) && (BVar2 = game::LegoObject_IsActive(aiTask->targetObject,FALSE), BVar2 == 0)) { return 0; } } if ((aiTask->objType != LegoObject_None) && (((*param_2 != aiTask->objType || ((aiTask->objID != 0xffffffff && (param_2[1] != aiTask->objID)))) || (param_2[2] != aiTask->objLevel)))) { return 0; } return TRUE; } BOOL __cdecl lego::ai::AITask_FUN_00404ef0 (AITask *aiTask,LegoObject *liveObj_2,float *param_3,float *param_4,undefined4 *param_5, int param_6,int param_7) { Point2I *blockPos; AITask_Type AVar1; LegoObject_Type LVar2; LegoObject_AbilityFlags LVar3; StatsFlags1 SVar4; BOOL BVar5; Container *pCVar6; StatsFlags3 SVar7; Map3D *pMVar8; uint uVar9; LegoObject *pLVar10; BOOL BVar11; float10 fVar12; float fVar13; uint uVar14; float by; float *pfVar15; Vector3F local_18; Vector3F local_c; if (param_5 != NULL) { *param_5 = 0; } if (((aiTask->taskType != AITask_Type_Collect) || (aiTask->targetObject->type != LegoObject_Dynamite)) && ((ushort)((ushort)(aiTask->timeIn < 0.0) << 8 | (ushort)(aiTask->timeIn == 0.0) << 0xe) == 0)) { return 0; } SVar4 = stats::StatsObject_GetStatsFlags1(liveObj_2); if (((SVar4 & STATS1_CANBEDRIVEN) != STATS1_NONE) && (liveObj_2->driveObject == NULL)) { return 0; } if ((liveObj_2->flags1 & LIVEOBJ1_RUNNINGAWAY) != LIVEOBJ1_NONE) { return 0; } if ((liveObj_2->flags4 & 0x400) != LIVEOBJ4_NONE) { return 0; } if (((((byte)globs::legoGlobs.flags2 & 1) != 0) && (BVar5 = game::LegoObject_MiniFigureHasBeamEquipped2(liveObj_2), BVar5 != 0)) && (aiTask->taskType != AITask_Type_AttackRockMonster)) { return 0; } AVar1 = aiTask->taskType; if (AVar1 == AITask_Type_AttackRockMonster) { BVar5 = game::LegoObject_MiniFigureHasBeamEquipped(liveObj_2); if (BVar5 == 0) { return 0; } BVar5 = tools::Weapon_LegoObject_WithinAwarenessRange(liveObj_2,aiTask->targetObject); if (BVar5 == 0) { return 0; } BVar5 = tools::Weapon_LegoObject_SeeThroughWalls_FUN_00471c20(liveObj_2,aiTask->targetObject); if (BVar5 != 0) { return 0; } BVar5 = game::LegoObject_IsActive(aiTask->targetObject,TRUE); if (BVar5 == 0) { return 0; } if (((byte)globs::legoGlobs.flags2 & GAME2_CALLTOARMS) == 0) { return 0; } if (param_3 != NULL) { game::LegoObject_GetPosition(aiTask->targetObject,param_3,param_3 + 1); } if (param_4 != NULL) { game::LegoObject_GetBlockPos(aiTask->targetObject,(int *)param_4,(int *)(param_4 + 1)); return 1; } } else { if (AVar1 == AITask_Type_FindLoad) { pCVar6 = game::LegoObject_GetDepositNull(aiTask->targetObject); if ((pCVar6 == NULL) || (SVar7 = stats::StatsObject_GetStatsFlags3(liveObj_2), (SVar7 & STATS3_VEHICLECANBECARRIED) == STATS3_NONE)) { return 0; } gfx::Container_GetPosition(pCVar6,NULL,&local_18); if (param_3 != NULL) { *param_3 = local_18.x; param_3[1] = local_18.y; } if (param_4 != NULL) { pfVar15 = param_4 + 1; pMVar8 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ (pMVar8,local_18.x,local_18.y,(int *)param_4,(int *)pfVar15); return 1; } } else { if (AVar1 == AITask_Type_Collect) { if ((*(byte *)&liveObj_2->flags3 & 0x40) == 0) { return 0; } BVar5 = game::LegoObject_FUN_00439e90(liveObj_2,aiTask->targetObject,1); if (BVar5 == 0) { return 0; } if ((liveObj_2->type == LegoObject_Vehicle) && (uVar9 = stats::StatsObject_GetMaxCarry(liveObj_2), uVar9 == 0)) { return 0; } pLVar10 = aiTask->targetObject; LVar2 = pLVar10->type; if (((LVar2 == LegoObject_Dynamite) && ((*(byte *)&liveObj_2->abilityFlags & 8) == 0)) && (param_7 != 0)) { return 0; } if ((liveObj_2->type == LegoObject_RockMonster) && (LVar2 != LegoObject_PowerCrystal)) { return 0; } if (liveObj_2->type == LegoObject_Vehicle) { if (LVar2 == LegoObject_Barrier) { return 0; } if (true) { if ((LVar2 == LegoObject_PowerCrystal) && ((pLVar10->flags3 & LIVEOBJ3_POWEROFF) != LIVEOBJ3_NONE)) { return 0; } if (((true) && ((liveObj_2->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) && (liveObj_2->carriedObjects[0]->type == LegoObject_ElectricFence)) { return 0; } } } BVar5 = AITask_LiveObject_FUN_00404e00(pLVar10); if (BVar5 == 0) { return 0; } BVar5 = game::LegoObject_FUN_00439e40(liveObj_2,aiTask->targetObject); if (BVar5 == 0) { return 0; } if (param_3 != NULL) { game::LegoObject_GetPosition(aiTask->targetObject,param_3,param_3 + 1); } if (param_4 != NULL) { game::LegoObject_GetBlockPos(aiTask->targetObject,(int *)param_4,(int *)(param_4 + 1)); return 1; } } else { if (((AVar1 == AITask_Type_Dig) || (AVar1 == AITask_Type_Goto)) || ((AVar1 == AITask_Type_Reinforce || (AVar1 == AITask_Type_Clear)))) { BVar5 = 1; if (AVar1 == AITask_Type_Dig) { BVar5 = game::LiveObject_BlockCheck_FUN_004326a0 (liveObj_2,(aiTask->blockPos).x,(aiTask->blockPos).y, aiTask->flags & AITASK_FLAG_DIGCONNECTION,1); } if (((param_6 != 0) && (AVar1 = aiTask->taskType, AVar1 != AITask_Type_Goto)) && ((AVar1 != AITask_Type_Dynamite && (BVar11 = game::LegoObject_TaskHasTool_FUN_0044b780(liveObj_2,AVar1), BVar11 == 0)))) { return 0; } if ((aiTask->taskType == AITask_Type_Reinforce) && (liveObj_2->type != LegoObject_MiniFigure)) { return 0; } if ((aiTask->taskType == AITask_Type_Clear) && (SVar4 = stats::StatsObject_GetStatsFlags1(liveObj_2), (SVar4 & STATS1_CANCLEARRUBBLE) == STATS1_NONE)) { return 0; } if (aiTask->taskType == AITask_Type_Dig) { if ((*(byte *)&liveObj_2->flags3 & 2) == 0) { return 0; } if (BVar5 == 0) { return 0; } if (((*(byte *)&aiTask->flags & 8) != 0) && (SVar4 = stats::StatsObject_GetStatsFlags1(liveObj_2), (SVar4 & STATS1_SINGLEWIDTHDIG) == STATS1_NONE)) { return 0; } } if (param_3 != NULL) { uVar9 = (aiTask->blockPos).y; pfVar15 = param_3 + 1; uVar14 = (aiTask->blockPos).x; pMVar8 = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(pMVar8,uVar14,uVar9,param_3,pfVar15); } if (param_4 != NULL) { *param_4 = (float)(aiTask->blockPos).x; param_4[1] = (float)(aiTask->blockPos).y; } } else { if (AVar1 == AITask_Type_Repair) { if ((param_6 != 0) && (BVar5 = game::LegoObject_TaskHasTool_FUN_0044b780(liveObj_2,AITask_Type_Repair), BVar5 == 0)) { return 0; } if (((param_7 != 0) && ((*(byte *)&liveObj_2->abilityFlags & 0x10) == 0)) && ((aiTask->flags & AITASK_FLAG_UPGRADEBUILDING) == AITASK_FLAG_NONE)) { return 0; } if (liveObj_2->type != LegoObject_MiniFigure) { return 0; } if (param_3 != NULL) { game::LegoObject_GetPosition(aiTask->targetObject,param_3,param_3 + 1); if (param_4 == NULL) { return 1; } game::LegoObject_GetBlockPos(aiTask->targetObject,(int *)param_4,(int *)(param_4 + 1)) ; return 1; } } else { if (AVar1 == AITask_Type_GotoEat) { BVar5 = game::LegoObject_IsActive(aiTask->targetObject,0); if (BVar5 == 0) { return 0; } if (((liveObj_2->type == LegoObject_MiniFigure) && ((liveObj_2->flags2 & LIVEOBJ2_UNK_800) == LIVEOBJ2_NONE)) && (fVar13 = liveObj_2->health * 0.01 * globs::legoGlobs.MinEnergyForEat, (ushort)((ushort)(liveObj_2->energy < fVar13) << 8 | (ushort)(liveObj_2->energy == fVar13) << 0xe) != 0)) { if ((liveObj_2->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { return 1; } return 0; } return 0; } if (AVar1 == AITask_Type_FindDriver) { if ((((liveObj_2->type != LegoObject_MiniFigure) || (liveObj_2->aiTask != NULL)) || (liveObj_2->driveObject != NULL)) || (((aiTask->trainFlags & liveObj_2->abilityFlags) == ABILITY_FLAG_NONE && (param_7 != 0)))) { return 0; } SVar4 = stats::StatsObject_GetStatsFlags1(aiTask->targetObject); if ((SVar4 & STATS1_CROSSLAND) == STATS1_NONE) { if ((((*(byte *)&aiTask->targetObject->flags4 & 0x40) != 0) && (pLVar10 = aiTask->targetObject->routeToObject, pLVar10 != NULL)) && ((pLVar10->type == LegoObject_Building && (pCVar6 = gfx::Building_GetEntranceNull(pLVar10->building), pCVar6 != NULL)))) { gfx::Container_GetPosition(pCVar6,NULL,&local_c); if (param_3 != NULL) { *param_3 = local_c.x; param_3[1] = local_c.y; } if (param_4 == NULL) { return 1; } pfVar15 = param_4 + 1; pMVar8 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ (pMVar8,local_c.x,local_c.y,(int *)param_4,(int *)pfVar15); return 1; } BVar5 = game::LegoObject_CheckUnkGetInAtLand_FUN_0043a100 (aiTask->targetObject,(Point2I *)&local_18); if (BVar5 == 0) { return 0; } if (param_3 != NULL) { pfVar15 = param_3 + 1; fVar13 = local_18.x; by = local_18.y; pMVar8 = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(pMVar8,(uint)fVar13,(uint)by,param_3,pfVar15); } if (param_4 == NULL) { return 1; } *param_4 = local_18.x; param_4[1] = local_18.y; return 1; } if (param_3 != NULL) { game::LegoObject_GetPosition(aiTask->targetObject,param_3,param_3 + 1); if (param_4 == NULL) { return 1; } game::LegoObject_GetBlockPos (aiTask->targetObject,(int *)param_4,(int *)(param_4 + 1)); return 1; } } else { if (AVar1 == AITask_Type_Upgrade) { if (liveObj_2->type != LegoObject_Vehicle) { return 0; } if (liveObj_2->driveObject != NULL) { pCVar6 = game::LegoObject_GetDepositNull(aiTask->targetObject); gfx::Container_GetPosition(pCVar6,NULL,&local_c); if (param_3 != NULL) { *param_3 = local_c.x; param_3[1] = local_c.y; } if (param_4 == NULL) { return 1; } pfVar15 = param_4 + 1; pMVar8 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ (pMVar8,local_c.x,local_c.y,(int *)param_4,(int *)pfVar15); return 1; } return 0; } if (AVar1 != AITask_Type_Train) { if (AVar1 != AITask_Type_BuildPath) { if (AVar1 == AITask_Type_GetTool) { if (((liveObj_2->type == LegoObject_MiniFigure) && (uVar9 = stats::StatsObject_GetNumOfToolsCanCarry(liveObj_2), uVar9 != 0)) && (BVar5 = game::LegoObject_HasToolEquipped(liveObj_2,aiTask->toolType), BVar5 == 0)) { game::LegoObject_GetPosition(liveObj_2,&local_18.x,&local_18.y); pLVar10 = game::Level_GetBuildingAtPosition((Point2F *)&local_18); if (pLVar10 != NULL) { if (param_3 == NULL) { return 1; } game::LegoObject_GetPosition(pLVar10,param_3,param_3 + 1); return 1; } } return 0; } if (param_5 == NULL) { return 1; } *param_5 = 1; return 1; } if (liveObj_2->type != LegoObject_MiniFigure) { return 0; } blockPos = &aiTask->blockPos; BVar5 = game::Level_IsBuildPathBoolUnk_true(blockPos); if (BVar5 != 0) { if (param_3 != NULL) { uVar9 = (aiTask->blockPos).y; pfVar15 = param_3 + 1; uVar14 = blockPos->x; pMVar8 = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(pMVar8,uVar14,uVar9,param_3,pfVar15); } if (param_4 == NULL) { return 1; } *param_4 = (float)blockPos->x; param_4[1] = (float)(aiTask->blockPos).y; return 1; } return 0; } if (liveObj_2->type != LegoObject_MiniFigure) { return 0; } LVar3 = liveObj_2->abilityFlags; if (((LVar3 & ABILITY_FLAG_PILOT) != ABILITY_FLAG_NONE) && (aiTask->trainFlags == LegoObject_AbilityType_Sailor)) { return 0; } if (((LVar3 & ABILITY_FLAG_SAILOR) != ABILITY_FLAG_NONE) && (aiTask->trainFlags == LegoObject_AbilityType_Driver)) { return 0; } if (((LVar3 & ABILITY_FLAG_DRIVER) != ABILITY_FLAG_NONE) && (aiTask->trainFlags == LegoObject_AbilityType_Repair)) { return 0; } if (((LVar3 & ABILITY_FLAG_DYNAMITE) != ABILITY_FLAG_NONE) && (aiTask->trainFlags == 8)) { return 0; } if (((LVar3 & ABILITY_FLAG_REPAIR) != ABILITY_FLAG_NONE) && (aiTask->trainFlags == 0x10)) { return 0; } if (((LVar3 & ABILITY_FLAG_SCANNER) != ABILITY_FLAG_NONE) && (aiTask->trainFlags == 0x20)) { return 0; } fVar12 = lrr::Lego_GetTrainTime(); if ((ushort)((ushort)(fVar12 < (float10)liveObj_2->elapsedTime1) << 8 | (ushort)(fVar12 == (float10)liveObj_2->elapsedTime1) << 0xe) == 0) { return 0; } if (param_3 != NULL) { game::LegoObject_GetPosition(aiTask->targetObject,param_3,param_3 + 1); } } } if (param_4 != NULL) { game::LegoObject_GetBlockPos(aiTask->targetObject,(int *)param_4,(int *)(param_4 + 1)); return 1; } } } } } return 1; } void __cdecl lego::ai::AITask_FUN_00405880(void) { LegoObject *liveObj; AITask_Type AVar1; float fVar2; float fVar3; bool bVar4; BOOL BVar5; uint uVar6; int iVar7; StatsFlags2 SVar8; AITask *pAVar9; uint uVar10; AITask *aiTask; float10 fVar11; LegoObject **local_24; AITask *local_1c; float local_18; float local_14; float local_10; float local_c; int local_8; int local_4; local_1c = NULL; pAVar9 = globs::aiGlobs.creatureTaskList; if (globs::aiGlobs.creatureTaskList != NULL) { do { aiTask = pAVar9; if ((ushort)((ushort)(aiTask->timeIn < 0.0) << 8 | (ushort)(aiTask->timeIn == 0.0) << 0xe) != 0) { bVar4 = false; uVar10 = 0; if (globs::aiGlobs.freeCreatureCount != 0) { local_24 = globs::aiGlobs.freeCreatureList; do { liveObj = *local_24; game::LegoObject_GetPosition(liveObj,&local_18,&local_14); game::LegoObject_GetBlockPos(liveObj,&local_8,&local_4); fVar11 = stats::StatsObject_GetPainThreshold(liveObj); if (fVar11 < (float10)liveObj->health) { AVar1 = aiTask->taskType; if (AVar1 == AITask_Type_Gather) { BVar5 = game::LegoObject_IsRockMonsterCanGather(liveObj); if ((BVar5 != 0) && (uVar6 = game::LegoObject_GetObjectsBuilt(LegoObject_Building,0), uVar6 != 0)) { bVar4 = true; } } else { if (AVar1 == AITask_Type_Repair) { SVar8 = stats::StatsObject_GetStatsFlags2(liveObj); if (((SVar8 & STATS2_DRAINPOWER) == STATS2_NONE) || ((BVar5 = game::LegoObject_IsActive(aiTask->targetObject,FALSE), BVar5 != 0 && (SVar8 = stats::StatsObject_GetStatsFlags2(aiTask->targetObject), (SVar8 & STATS2_SELFPOWERED) == STATS2_NONE)))) { game::LegoObject_GetPosition(aiTask->targetObject,&local_10,&local_c); fVar3 = local_18 - local_10; fVar2 = local_14 - local_c; fVar11 = stats::StatsObject_GetAttackRadius(liveObj); if ((float10)SQRT(fVar2 * fVar2 + fVar3 * fVar3) < fVar11) { bVar4 = true; SVar8 = stats::StatsObject_GetStatsFlags2(liveObj); if ((SVar8 & STATS2_DRAINPOWER) == STATS2_NONE) { aiTask->timeIn = 750.0; } } } } else { if (AVar1 == AITask_Type_Collect) { iVar7 = game::LegoObject_CheckCanSteal(liveObj); joined_r0x00405a76: if (iVar7 != 0) { bVar4 = true; aiTask->timeIn = 250.0; } } else { if (AVar1 == AITask_Type_AttackPath) { SVar8 = stats::StatsObject_GetStatsFlags2(liveObj); if ((SVar8 & STATS2_ATTACKPATHS) != STATS2_NONE) { bVar4 = true; } } else { if (AVar1 == AITask_Type_Goto) { BVar5 = game::LegoObject_IsRockMonsterCanGather(liveObj); if ((BVar5 != 0) && (((aiTask->blockPos).x != local_8 || ((aiTask->blockPos).y != local_4)))) { bVar4 = true; } } else { if (AVar1 == AITask_Type_AttackObject) { iVar7 = game::LegoObject_IsRockMonsterCanGather(liveObj); goto joined_r0x00405a76; } } } } } } } if ((aiTask->taskType == AITask_Type_Depart) && ((BVar5 = game::LegoObject_IsRockMonsterCanGather(liveObj), BVar5 != 0 || (SVar8 = stats::StatsObject_GetStatsFlags2(liveObj), (SVar8 & STATS2_USEHOLES) != STATS2_NONE)))) { bVar4 = true; } if (bVar4) { iVar7 = globs::aiGlobs.freeCreatureCount - 1; globs::aiGlobs.freeCreatureCount = globs::aiGlobs.freeCreatureCount - 1; globs::aiGlobs.freeCreatureList[uVar10] = globs::aiGlobs.freeCreatureList[iVar7]; if ((*(byte *)&aiTask->flags & 0x40) == 0) { if (local_1c == NULL) { globs::aiGlobs.creatureTaskList = aiTask->next; } else { local_1c->next = aiTask->next; } aiTask->next = NULL; liveObj->aiTask = aiTask; } else { pAVar9 = AITask_Clone(aiTask); liveObj->aiTask = pAVar9; } break; } uVar10 += 1; local_24 = local_24 + 1; } while (uVar10 < globs::aiGlobs.freeCreatureCount); } } pAVar9 = aiTask->next; local_1c = aiTask; } while (aiTask->next != NULL); } return; } void __cdecl lego::ai::AITask_FUN_00405b40(void) { bool bVar1; int iVar2; BOOL BVar3; Map3D *map; BOOL BVar4; uint uVar5; LegoObject *pLVar6; LegoObject *pLVar7; LegoObject **ppLVar8; AITask *aiTask; float fVar9; float fVar10; Point2I *pPVar11; uint *out_bx; int *piVar12; uint *out_by; LegoObject *local_94; LegoObject *local_90; LegoObject **local_8c; Message_Type local_88; uint local_84; Point2I local_80; Message_Type local_78; float local_74; float local_70; Point2I local_6c; uint local_64; uint local_60; uint local_5c; int local_58; int local_54; AITask *taskLast; float local_4c; float local_48; float local_44; float local_40; float local_3c; void *local_38; int local_34; void *local_30; Point2F local_2c; Point2I local_24; float local_18; undefined local_14 [4]; Point2I local_10; Point2F local_8; AITask *taskNext; AITask_Type taskType; taskLast = NULL; local_44 = 99999.0; taskNext = globs::aiGlobs.pendingTaskList; if (globs::aiGlobs.pendingTaskList != NULL) { do { aiTask = taskNext; if (((ushort)((ushort)(aiTask->timeIn < 0.0) << 8 | (ushort)(aiTask->timeIn == 0.0) << 0xe) != 0) && ((aiTask->flags & (AITASK_FLAG_CARRYTASK|AITASK_FLAG_DISABLED)) == AITASK_FLAG_NONE )) { pLVar6 = NULL; local_90 = NULL; local_84 = 0; if (globs::aiGlobs.freeUnitCount != 0) { local_8c = globs::aiGlobs.freeUnitList; pLVar7 = pLVar6; do { pLVar6 = *local_8c; if (pLVar6 != NULL) { if ((aiTask->flags & AITASK_FLAG_IMMEDIATESELECTION) == AITASK_FLAG_NONE) { BVar3 = game::Message_IsUnitSelected(pLVar6,NULL); pLVar7 = local_90; if (BVar3 == 0) { if ((aiTask->flags & AITASK_FLAG_IMMEDIATESELECTION) != AITASK_FLAG_NONE) goto LAB_00405bda; goto LAB_00405bf5; } } else { LAB_00405bda: BVar3 = game::Message_FindIndexOfObject ((LegoObject **)aiTask->unitList,aiTask->unitListCount,pLVar6,NULL ); pLVar7 = local_90; if (BVar3 != 0) { LAB_00405bf5: game::LegoObject_GetPosition(pLVar6,&local_4c,&local_48); BVar3 = AITask_FUN_00404ef0(aiTask,pLVar6,&local_74,NULL,&local_34,1,1); if (BVar3 != 0) { piVar12 = &local_6c.y; pPVar11 = &local_6c; fVar9 = local_74; fVar10 = local_70; map = lrr::Lego_GetMap(); BVar4 = lego::map::Map3D_WorldToBlockPos_NoZ (map,fVar9,fVar10,&pPVar11->x,piVar12); if (BVar4 != 0) { out_by = &local_60; out_bx = &local_64; fVar9 = local_4c; fVar10 = local_48; map = lrr::Lego_GetMap(); BVar4 = lego::map::Map3D_WorldToBlockPos_NoZ (map,fVar9,fVar10,(int *)out_bx,(int *)out_by); if (BVar4 != 0) { taskType = aiTask->taskType; local_94 = (LegoObject *)0x1; if ((((((taskType == AITask_Type_Dig) && ((*(byte *)&aiTask->flags & AITASK_FLAG_DIGCONNECTION) == 0)) || (taskType == AITask_Type_Repair)) || ((taskType == AITask_Type_Reinforce || (taskType == AITask_Type_Train)) )) || (taskType == AITask_Type_GetTool)) && (((local_64 != local_6c.x || (uVar5 = (int)(local_60 - local_6c.y) >> 0x1f, (local_60 - local_6c.y ^ uVar5) - uVar5 != 1)) && ((local_60 != local_6c.y || (uVar5 = (int)(local_64 - local_6c.x) >> 0x1f, (local_64 - local_6c.x ^ uVar5) - uVar5 != 1)))))) { local_24.x = local_6c.x; local_24.y = local_6c.y; BVar4 = game::LiveObject_FUN_00431ba0(local_90,&local_24,&local_6c,1); if (BVar4 == 0) { // = NULL; local_94 = (LegoObject *)BVar4; } } if (local_94 != NULL) { BVar3 = game::LegoObject_Route_ScoreNoCallback_FUN_00440ef0 (pLVar6,local_64,local_60,local_6c.x,local_6c.y, &local_30,&local_38,local_14); if (BVar3 == 0) { aiTask->timeIn = 75.0; } else { io::Mem_Free(local_30); io::Mem_Free(local_38); } } } } } if (local_34 != 0) { local_5c = local_84; local_40 = local_74; local_3c = local_70; break; } pLVar7 = local_90; if (BVar3 != 0) { local_18 = local_70 - local_48; fVar9 = SQRT(local_18 * local_18 + (local_74 - local_4c) * (local_74 - local_4c) ); game::LegoObject_GetFaceDirection(pLVar6,&local_8); if ((local_90 == NULL) || (fVar9 < local_44)) { local_5c = local_84; local_40 = local_74; local_3c = local_70; pLVar7 = pLVar6; local_90 = pLVar6; local_44 = fVar9; } } } } } pLVar6 = pLVar7; local_84 += 1; local_8c = local_8c + 1; pLVar7 = pLVar6; } while (local_84 < globs::aiGlobs.freeUnitCount); } if (pLVar6 == NULL) { if (((aiTask->flags & AITASK_FLAG_WAITINGFORTOOL) == AITASK_FLAG_NONE) && (uVar5 = 0, globs::aiGlobs.freeUnitCount != 0)) { ppLVar8 = globs::aiGlobs.freeUnitList; do { pLVar6 = *ppLVar8; if (pLVar6 != NULL) { if ((aiTask->flags & AITASK_FLAG_IMMEDIATESELECTION) == AITASK_FLAG_NONE) { BVar3 = game::Message_IsUnitSelected(pLVar6,NULL); if (BVar3 == 0) { if ((aiTask->flags & AITASK_FLAG_IMMEDIATESELECTION) != AITASK_FLAG_NONE) goto LAB_004060b6; goto LAB_004060cd; } } else { LAB_004060b6: BVar3 = game::Message_FindIndexOfObject ((LegoObject **)aiTask->unitList,aiTask->unitListCount,pLVar6, NULL); if (BVar3 != 0) { LAB_004060cd: BVar3 = AITask_FUN_00404ef0(aiTask,pLVar6,NULL,NULL,NULL,0,1); if (BVar3 != 0) { AITask_DoGetTool_FromTask(aiTask); break; } } } } uVar5 += 1; ppLVar8 = ppLVar8 + 1; } while (uVar5 < globs::aiGlobs.freeUnitCount); } if (((aiTask->taskType != AITask_Type_Train) && (aiTask->trainFlags != LegoObject_AbilityType_Pilot)) && ((aiTask->flags & AITASK_FLAG_WAITINGFORTRAIN) == AITASK_FLAG_NONE)) { uVar5 = 0; local_94 = NULL; bVar1 = false; if (globs::aiGlobs.freeUnitCount != 0) { ppLVar8 = globs::aiGlobs.freeUnitList; do { pLVar6 = *ppLVar8; if (pLVar6 != NULL) { if ((aiTask->flags & AITASK_FLAG_IMMEDIATESELECTION) == AITASK_FLAG_NONE) { BVar3 = game::Message_IsUnitSelected(pLVar6,NULL); if (BVar3 == 0) { if ((aiTask->flags & AITASK_FLAG_IMMEDIATESELECTION) != AITASK_FLAG_NONE) goto LAB_0040615f; goto LAB_00406176; } } else { LAB_0040615f: BVar3 = game::Message_FindIndexOfObject ((LegoObject **)aiTask->unitList,aiTask->unitListCount,pLVar6, NULL); if (BVar3 != 0) { LAB_00406176: BVar3 = AITask_FUN_00404ef0(aiTask,pLVar6,&local_2c.x,NULL,NULL,0,0); if ((BVar3 != 0) && (BVar3 = AITask_FUN_00404ef0(aiTask,pLVar6,&local_2c.x,NULL,NULL,0,1), local_94 = pLVar6, BVar3 != 0)) { bVar1 = true; break; } } } } uVar5 += 1; ppLVar8 = ppLVar8 + 1; } while (uVar5 < globs::aiGlobs.freeUnitCount); } if (((local_94 != NULL) && (!bVar1)) && (pLVar6 = (LegoObject *) game::LegoObject_Search_FUN_00439110(NULL,&local_2c,aiTask->trainFlags), pLVar6 != NULL)) { AITask_DoTrain_Target (pLVar6,aiTask->trainFlags,(uint)(aiTask->trainFlags != ABILITY_FLAG_REPAIR) ); aiTask->flags = aiTask->flags | AITASK_FLAG_WAITINGFORTRAIN; } } } else { bVar1 = true; game::LegoObject_GetBlockPos(pLVar6,&local_58,&local_54); piVar12 = &local_80.y; pPVar11 = &local_80; fVar9 = local_40; fVar10 = local_3c; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar9,fVar10,&pPVar11->x,piVar12); taskType = aiTask->taskType; if (((((taskType == AITask_Type_Clear) || (taskType == AITask_Type_Collect)) || (taskType == AITask_Type_BuildPath)) || (taskType == AITask_Type_Upgrade)) && ((local_58 != local_80.x || (local_54 != local_80.y)))) { if (aiTask->assignedToObject == NULL) { if (true) { switch(taskType) { case AITask_Type_Collect: local_78 = Message_CollectCrystal; break; case AITask_Type_Clear: local_78 = Message_Clear; break; case AITask_Type_Upgrade: local_78 = Message_Upgrade; break; case AITask_Type_BuildPath: local_78 = Message_BuildPath; } } game::Message_PostEvent(local_78,pLVar6,aiTask,&local_80); if ((aiTask->flags & AITASK_FLAG_IMMEDIATESELECTION) == AITASK_FLAG_NONE) { aiTask->assignedToObject = pLVar6; } if ((aiTask->taskType == AITask_Type_Clear) && (pLVar6->type == LegoObject_Vehicle)) { AITask_DelayOrRemoveClearReferences(&aiTask->blockPos,TRUE); aiTask->timeIn = 0.0; } } LAB_00406042: bVar1 = false; } else { if ((((taskType == AITask_Type_Dig) && ((*(byte *)&aiTask->flags & AITASK_FLAG_DIGCONNECTION) == 0)) || (((taskType == AITask_Type_Repair || (taskType == AITask_Type_Reinforce)) || ((taskType == AITask_Type_Train || (taskType == AITask_Type_GetTool)))))) && (((local_58 != local_80.x || (uVar5 = local_54 - local_80.y >> 0x1f, (local_54 - local_80.y ^ uVar5) - uVar5 != 1)) && ((local_54 != local_80.y || (uVar5 = local_58 - local_80.x >> 0x1f, (local_58 - local_80.x ^ uVar5) - uVar5 != 1)))))) { if (aiTask->assignedToObject == NULL) { if (true) { switch(taskType) { case AITask_Type_Dig: local_88 = Message_Dig; break; case AITask_Type_Repair: local_88 = Message_Repair; break; case AITask_Type_Reinforce: local_88 = Message_Reinforce; break; case AITask_Type_GetTool: local_88 = Message_CollectTool; break; case AITask_Type_Train: local_88 = Message_Train; } } BVar3 = game::LiveObject_FUN_00431ba0(pLVar6,&local_80,&local_10,TRUE); if (BVar3 == 0) { aiTask->priorityValue = aiTask->priorityValue + -1; } else { game::Message_PostEvent(local_88,pLVar6,aiTask,&local_10); if ((aiTask->flags & AITASK_FLAG_IMMEDIATESELECTION) == AITASK_FLAG_NONE) { aiTask->assignedToObject = pLVar6; } } } goto LAB_00406042; } } if (bVar1) { AITask_FUN_00406290(aiTask,taskLast,pLVar6); } iVar2 = globs::aiGlobs.freeUnitCount - 1; globs::aiGlobs.freeUnitCount = globs::aiGlobs.freeUnitCount - 1; globs::aiGlobs.freeUnitList[local_5c] = globs::aiGlobs.freeUnitList[iVar2]; } } taskNext = aiTask->next; taskLast = aiTask; } while (aiTask->next != NULL); } return; } void __cdecl lego::ai::AITask_FUN_00406290(AITask *aiTask1,AITask *aiTask2,LegoObject *liveObj) { AITask *newAITask; if ((*(byte *)&aiTask1->flags & AITASK_FLAG_DUPLICATE) == 0) { if (aiTask2 == NULL) { globs::aiGlobs.pendingTaskList = aiTask1->next; } else { aiTask2->next = aiTask1->next; } aiTask1->next = NULL; liveObj->aiTask = aiTask1; } else { newAITask = AITask_Clone(aiTask1); liveObj->aiTask = newAITask; if ((aiTask1->flags & AITASK_FLAG_PAUSEDDUPLICATION) != AITASK_FLAG_NONE) { // 1 second aiTask1->timeIn = 25.0; } } AITask_RemoveAssignedToObjectReferences(liveObj); front::Bubble_ShowBubble(liveObj); return; } // Removes references to assignedToObject. // But only from the `aiGlobs.pendingTaskList` linked list. void __cdecl lego::ai::AITask_RemoveAssignedToObjectReferences(LegoObject *assignedToObj) { AITask *task; AITask **pNext; task = globs::aiGlobs.pendingTaskList; if (globs::aiGlobs.pendingTaskList != NULL) { do { if (task->assignedToObject == assignedToObj) { task->assignedToObject = NULL; } pNext = &task->next; task = *pNext; } while (*pNext != NULL); } return; } AITask * __cdecl lego::ai::AITask_Clone(AITask *aiTask) { AITask *newAITask; int iVar1; AITask *pAVar2; AITask *nextFree; newAITask = AITask_Create(aiTask->taskType); nextFree = newAITask->nextFree; pAVar2 = newAITask; // std::memcpy(newAITask, aiTask, sizeof(AITask)); // aka // ListSet::MemCopy(newAITask, aiTask); // which preserves the nextFree field. for (iVar1 = 0x1a; iVar1 != 0; iVar1 += -1) { pAVar2->taskType = aiTask->taskType; aiTask = (AITask *)&aiTask->referrerTask; pAVar2 = (AITask *)&pAVar2->referrerTask; } newAITask->nextFree = nextFree; newAITask->flags = newAITask->flags | AITASK_FLAG_CLONED; newAITask->next = NULL; return newAITask; } AITask * __cdecl lego::ai::AITask_Create(AITask_Type taskType) { AITask *pAVar1; uint uVar2; int iVar3; AITask *pAVar4; if (globs::aiGlobs.freeList == NULL) { AITask_AddList(); } pAVar1 = globs::aiGlobs.freeList; pAVar4 = globs::aiGlobs.freeList; globs::aiGlobs.freeList = (globs::aiGlobs.freeList)->nextFree; for (iVar3 = 0x1a; iVar3 != 0; iVar3 += -1) { pAVar4->taskType = AITask_Type_Goto; pAVar4 = (AITask *)&pAVar4->referrerTask; } pAVar1->nextFree = pAVar1; uVar2 = main::Main_GetTime(); pAVar1->creationTime = uVar2; pAVar1->taskType = taskType; return pAVar1; } // levelCleanup is only true when called by `AITask_Callback_Remove`. void __cdecl lego::ai::AITask_Remove(AITask *aiTask,BOOL levelCleanup) { if (levelCleanup == 0) { // Extra removal behaviour that should NOT be called during level cleanup. AITask_RemoveGetToolReferences(aiTask); } if ((aiTask->unitList != NULL) && ((aiTask->flags & AITASK_FLAG_CLONED) == AITASK_FLAG_NONE)) { io::Mem_Free(aiTask->unitList); } aiTask->nextFree = globs::aiGlobs.freeList; globs::aiGlobs.freeList = aiTask; return; } void __cdecl lego::ai::AITask_AddList(void) { AITask *pAVar1; AITask *pAVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::aiGlobs.listCount & 0x1f); pAVar2 = (AITask *)io::Mem_Alloc(uVar4 * 0x68); globs::aiGlobs.listSet[globs::aiGlobs.listCount] = pAVar2; pAVar2 = globs::aiGlobs.listSet[globs::aiGlobs.listCount]; if (pAVar2 != NULL) { globs::aiGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pAVar1 = pAVar2; do { pAVar1->nextFree = pAVar1 + 1; iVar3 += -1; pAVar1 = pAVar1 + 1; } while (iVar3 != 0); } pAVar2[uVar4 - 1].nextFree = globs::aiGlobs.freeList; globs::aiGlobs.freeList = pAVar2; } return; } BOOL __cdecl lego::ai::AITask_RunThroughLists(AITask_RunThroughListsCallback callback,void *data) { AITask *aiTask; BOOL BVar1; int itemOffset; AITask **pAITaskList; uint count; uint itemIndex; uint listIndex; listIndex = 0; if (globs::aiGlobs.listCount == 0) { return 0; } pAITaskList = (AITask **)&globs::aiGlobs; do { if (*pAITaskList != NULL) { itemIndex = 0; count = 1 << ((byte)listIndex & 0x1f); if (count != 0) { itemOffset = 0; do { aiTask = (AITask *)((int)&(*pAITaskList)->taskType + itemOffset); if (((aiTask != NULL) && (aiTask->nextFree == aiTask)) && (BVar1 = (*callback)(aiTask,data), BVar1 != 0)) { return TRUE; } itemIndex += 1; itemOffset += 0x68; } while (itemIndex < count); } } listIndex += 1; pAITaskList = pAITaskList + 1; if (globs::aiGlobs.listCount <= listIndex) { return FALSE; } } while( true ); } IDirectDraw4 * __cdecl lego::ddraw::DirectDraw(void) { return globs::directDrawGlobs.lpDirectDraw; } IDirectDrawSurface4 * __cdecl lego::ddraw::DirectDraw_bSurf(void) { return globs::directDrawGlobs.bSurf; } void __cdecl lego::math::BezierCurve_Curve (Point2F *out_r,Point2F *p0,Point2F *p1,Point2F *p2,Point2F *p3,float t) { float xVar0; float xVar2; float yVar1; float yVar2; float p3__y; float p2__y; float t2; float xVar1; float yVar0; xVar0 = p1->x * 3.0 + p0->x; t2 = t * t; xVar1 = (xVar0 - p0->x) * 3.0; xVar2 = ((p2->x - p3->x * 3.0) - xVar0) * 3.0 - xVar1; p3__y = p3->y; yVar0 = p1->y * 3.0 + p0->y; p2__y = p2->y; out_r->x = xVar1 * t + xVar2 * t2 + (((p2->x - p0->x) - xVar1) - xVar2) * t2 * t + p0->x; yVar1 = (yVar0 - p0->y) * 3.0; yVar2 = ((p2__y - p3__y * 3.0) - yVar0) * 3.0 - yVar1; out_r->y = yVar2 * t2 + yVar1 * t + (((p2->y - p0->y) - yVar1) - yVar2) * t2 * t + p0->y; return; } // sqrt(((a.x-b.x)*(a.x-b.x)) + ((a.y-b.y)*(a.y-b.y))) float10 __cdecl lego::math::BezierCurve_Vector2DDistance(Point2F *a,Point2F *b) { float10 diff_x; float10 diff_y; diff_x = (float10)a->x - (float10)b->x; diff_y = (float10)a->y - (float10)b->y; return SQRT(diff_y * diff_y + diff_x * (float10)(float)diff_x); } // ref_point = norm(ref_point) * newLength // NOTE: Unlike `Maths_Vector2DSetLength`, this function modifies the input point. Point2F * __cdecl lego::math::BezierCurve_Vector2DChangeLength(Point2F *ref_r,float newLength) { float m; m = SQRT(ref_r->x * ref_r->x + ref_r->y * ref_r->y) / newLength; ref_r->x = ref_r->x / m; ref_r->y = ref_r->y / m; return ref_r; } float10 __cdecl lego::math::BezierCurve_UpdateDistances(BezierCurve *curve) { BezierCurve *pBVar1; uint index; float *pDistance; float10 dist; float totalDist; index = 1; totalDist = 0.0; curve->distances[0] = 0.0; if (1 < curve->count) { pDistance = curve->distances; pBVar1 = curve; do { pDistance = pDistance + 1; dist = BezierCurve_Vector2DDistance(pBVar1->points,pBVar1->points + 1); *pDistance = (float)dist; index += 1; totalDist = (float)(dist + (float10)totalDist); pBVar1 = (BezierCurve *)&pBVar1->points[0].y; } while (index < curve->count); } return (float10)totalDist; } void __cdecl lego::math::BezierCurve_BuildPoints (BezierCurve *curve,Point2F *p0,Point2F *p1,Point2F *p2,Point2F *p3,uint count) { uint index; Point2F *curPoint; if (49 < count) { count = 50; } index = 1; curve->count = count; curve->points[0].x = p0->x; curve->points[0].y = p0->y; if (1 < count) { curPoint = curve->points; do { curPoint = curPoint + 1; BezierCurve_Curve(curPoint,p0,p1,p2,p3, (float)(ulonglong)index * (1.0 / (float)(ulonglong)(count - 1))); index += 1; } while (index < count); } return; } uint __cdecl lego::math::BezierCurve_Interpolate(BezierCurve *curve,float currentDist,Point2F *out_r) { float fVar1; float fVar2; uint index; float *pDistance; float endDist; uint count; float delta; endDist = 0.0; count = curve->count; index = 1; if (1 < count) { pDistance = curve->distances; do { pDistance = pDistance + 1; endDist = endDist + *pDistance; if (currentDist < endDist) break; index += 1; } while (index < count); } if (index < count) { // This assignment has no effect out_r->x = curve->points[index - 1].x; out_r->y = curve->points[index - 1].y; fVar1 = curve->points[index].y; fVar2 = curve->points[index - 1].y; delta = (currentDist - (endDist - curve->distances[index])) / curve->distances[index]; out_r->x = (curve->points[index].x - curve->points[index - 1].x) * delta + curve->points[index - 1].x; out_r->y = (fVar1 - fVar2) * delta + curve->points[index - 1].y; return index; } out_r->x = curve->points[index - 1].x; out_r->y = curve->points[index - 1].y; return index; } BOOL __cdecl lego::gfx::Creature_IsCameraFlipDir(CreatureModel *creature) { return (uint)(creature->cameraFlipDir == BOOL3_TRUE); } BOOL __cdecl lego::gfx::Creature_Load (CreatureModel *creature,LegoObject_ID objID,Container *root,char *filename,char *gameName ) { char cVar1; Config *prop; Container *pCVar2; char *pcVar3; BoolTri BVar4; MeshLOD *pMVar5; uint uVar6; uint uVar7; char **ppcVar8; int iVar9; undefined4 *puVar10; char *pcVar11; undefined4 *puVar12; BOOL result; char *stringParts [100]; char buffName [1024]; char buffPath [1024]; uVar6 = 0xffffffff; pcVar3 = filename; do { pcVar11 = pcVar3; if (uVar6 == 0) break; uVar6 -= 1; pcVar11 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar11; } while (cVar1 != '\0'); uVar6 = ~uVar6; puVar10 = (undefined4 *)(pcVar11 + -uVar6); puVar12 = (undefined4 *)buffName; for (uVar7 = uVar6 >> 2; uVar7 != 0; uVar7 -= 1) { *puVar12 = *puVar10; puVar10 = puVar10 + 1; puVar12 = puVar12 + 1; } result = 0; for (uVar6 &= 3; uVar6 != 0; uVar6 -= 1) { *(undefined *)puVar12 = *(undefined *)puVar10; puVar10 = (undefined4 *)((int)puVar10 + 1); puVar12 = (undefined4 *)((int)puVar12 + 1); } uVar6 = util::Util_Tokenise(buffName,stringParts,"\\"); if (1 < uVar6) { ppcVar8 = stringParts; iVar9 = uVar6 - 1; do { ppcVar8 = ppcVar8 + 1; iVar9 += -1; (*ppcVar8)[-1] = '\\'; } while (iVar9 != 0); } std::sprintf(buffPath,"%s\\%s.%s",buffName,stringParts[uVar6 - 1],"ae"); prop = cfg::Config_Load(buffPath); if (prop != NULL) { pCVar2 = Container_Load(root,filename,"ACT",TRUE); creature->contAct = pCVar2; if (pCVar2 != NULL) { pcVar3 = cfg::Config_BuildStringID(gameName,"CameraNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); creature->cameraNullName = pcVar3; if (pcVar3 == NULL) { creature->cameraNullFrames = 0; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"CameraNullFrames",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 == NULL) { pcVar3 = ____EMPTYSTR__; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"CameraNullFrames",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); } uVar6 = std::atoi(pcVar3); creature->cameraNullFrames = uVar6; pcVar3 = cfg::Config_BuildStringID(gameName,"CameraFlipDir",0); BVar4 = cfg::Config_GetBoolValue(prop,pcVar3); creature->cameraFlipDir = BVar4; } pcVar3 = cfg::Config_BuildStringID(gameName,"DrillNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); creature->drillNullName = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"FootStepNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); creature->footStepNullName = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"CarryNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); creature->carryNullName = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"ThrowNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); creature->throwNullName = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"DepositNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); creature->depositNullName = pcVar3; creature->objID = objID; pMVar5 = game::LegoObject_LoadMeshLOD(prop,gameName,filename,LOD_MediumPoly,1); creature->polyMedium = pMVar5; pMVar5 = game::LegoObject_LoadMeshLOD(prop,gameName,filename,LOD_HighPoly,1); creature->polyHigh = pMVar5; pMVar5 = game::LegoObject_LoadMeshLOD (prop,gameName,filename,LOD_FPPoly,creature->cameraNullFrames); creature->polyFP = pMVar5; creature->flags = CREATURE_FLAG_SOURCE; result = 1; } cfg::Config_Free(prop); } return result; } void __cdecl lego::gfx::Creature_SwapPolyMedium(CreatureModel *creature,BOOL swap) { MeshLOD_SwapTarget(creature->polyMedium,creature->contAct,(uint)(swap == 0),0); return; } void __cdecl lego::gfx::Creature_SwapPolyHigh(CreatureModel *creature,BOOL swap) { MeshLOD_SwapTarget(creature->polyHigh,creature->contAct,(uint)(swap == 0),0); return; } void __cdecl lego::gfx::Creature_SwapPolyFP(CreatureModel *creature,BOOL swap,uint cameraNo) { MeshLOD_SwapTarget(creature->polyFP,creature->contAct,(uint)(swap == 0),cameraNo); return; } void __cdecl lego::gfx::Object_Hide(BasicObjectModel *basicObjData,BOOL hide) { Container_Hide(basicObjData->contAct,hide); return; } void __cdecl lego::gfx::Creature_Clone(CreatureModel *srcCreature,CreatureModel *destCreature) { MeshLOD *meshLOD; Container *contAct; int iVar1; CreatureModel *pCVar2; CreatureModel *pCVar3; pCVar2 = srcCreature; pCVar3 = destCreature; for (iVar1 = 0x1d; iVar1 != 0; iVar1 += -1) { pCVar3->objID = pCVar2->objID; pCVar2 = (CreatureModel *)&pCVar2->contAct; pCVar3 = (CreatureModel *)&pCVar3->contAct; } destCreature->flags = destCreature->flags & 0xfffffffe; meshLOD = MeshLOD_Clone(srcCreature->polyMedium); destCreature->polyMedium = meshLOD; meshLOD = MeshLOD_Clone(srcCreature->polyHigh); destCreature->polyHigh = meshLOD; meshLOD = MeshLOD_Clone(srcCreature->polyFP); destCreature->polyFP = meshLOD; contAct = Container_Clone(srcCreature->contAct); destCreature->contAct = contAct; return; } void __cdecl lego::gfx::Creature_SetAnimationTime(CreatureModel *creature,float time) { Container_SetAnimationTime(creature->contAct,time); return; } float10 __cdecl lego::gfx::Creature_MoveAnimation(CreatureModel *creature,float elapsed,uint repeatCount) { float fVar1; uint uVar2; float10 fVar3; fVar3 = Container_MoveAnimation(creature->contAct,elapsed); fVar1 = (float)fVar3; if ((1 < repeatCount) && (fVar1 != 0.0)) { uVar2 = Container_GetAnimationFrames(creature->contAct); return (float10)fVar1 - (float10)(ulonglong)(uVar2 * (repeatCount - 1)); } return (float10)fVar1; } float10 __cdecl lego::gfx::Creature_GetAnimationTime(CreatureModel *creature) { float10 fVar1; fVar1 = Container_GetAnimationTime(creature->contAct); return fVar1; } void __cdecl lego::gfx::Creature_SetOrientation(CreatureModel *creature,float xDir,float yDir) { Container_SetOrientation(creature->contAct,NULL,xDir,yDir,0.0,0.0,0.0,-1.0); return; } void __cdecl lego::gfx::Creature_SetPosition (CreatureModel *creature,float xPos,float yPos,GetWorldZCallback zCallback,Map3D *map) { float10 zPos; zPos = (*zCallback)(xPos,yPos,map); Container_SetPosition(creature->contAct,NULL,xPos,yPos,(float)zPos); return; } Container * __cdecl lego::gfx::Object_GetActivityContainer(BasicObjectModel *basicObjData) { return basicObjData->contAct; } BOOL __cdecl lego::gfx::Creature_SetActivity(CreatureModel *creature,char *activityName,float elapsed) { uint i; BOOL success; Container **pNull; MeshLOD_RemoveTargets(creature->polyMedium); MeshLOD_RemoveTargets(creature->polyHigh); MeshLOD_RemoveTargets(creature->polyFP); i = 0; creature->drillNull = NULL; creature->footStepNull = NULL; creature->carryNull = NULL; creature->throwNull = NULL; creature->depositNull = NULL; if (creature->cameraNullFrames != 0) { pNull = creature->cameraNulls; do { *pNull = NULL; i += 1; pNull = pNull + 1; } while (i < creature->cameraNullFrames); } success = Container_SetActivity(creature->contAct,activityName); Container_SetAnimationTime(creature->contAct,elapsed); return success; } void __cdecl lego::gfx::Creature_Remove(CreatureModel *creature) { MeshLOD_Free(creature->polyMedium); MeshLOD_Free(creature->polyHigh); MeshLOD_Free(creature->polyFP); if ((*(byte *)&creature->flags & 1) != 0) { if (creature->drillNullName != NULL) { io::Mem_Free(creature->drillNullName); } if (creature->footStepNullName != NULL) { io::Mem_Free(creature->footStepNullName); } if (creature->cameraNullName != NULL) { io::Mem_Free(creature->cameraNullName); } if (creature->carryNullName != NULL) { io::Mem_Free(creature->carryNullName); } if (creature->throwNullName != NULL) { io::Mem_Free(creature->throwNullName); } } Container_Remove(creature->contAct); return; } Container * __cdecl lego::gfx::Object_FindNull(BasicObjectModel *basicObjData,char *name,uint frameNo) { char *partName; Container *cont; partName = Container_FormatPartName(basicObjData->contAct,name,(int *)&frameNo); cont = Container_SearchTree(basicObjData->contAct,partName,Container_SearchMode_FirstMatch,NULL); return cont; } Container * __cdecl lego::gfx::Creature_GetCameraNull(CreatureModel *creature,int cameraIndex) { Container *pCVar1; pCVar1 = (Container *)creature->cameraNullName; if (pCVar1 != NULL) { if (creature->cameraNulls[cameraIndex] == NULL) { pCVar1 = Object_FindNull((BasicObjectModel *)creature,(char *)pCVar1,cameraIndex); creature->cameraNulls[cameraIndex] = pCVar1; } pCVar1 = creature->cameraNulls[cameraIndex]; } return pCVar1; } Container * __cdecl lego::gfx::Creature_GetDrillNull(CreatureModel *creature) { Container *cont; cont = creature->drillNull; if (cont == NULL) { if (creature->drillNullName != NULL) { cont = Object_FindNull((BasicObjectModel *)creature,creature->drillNullName,0); creature->drillNull = cont; return cont; } cont = NULL; } return cont; } Container * __cdecl lego::gfx::Creature_GetCarryNull(CreatureModel *creature) { Container *cont; if (creature->carryNullName == NULL) { cont = NULL; } else { cont = creature->carryNull; if (cont == NULL) { cont = Object_FindNull((BasicObjectModel *)creature,creature->carryNullName,0); creature->carryNull = cont; return cont; } } return cont; } Container * __cdecl lego::gfx::Creature_GetDepositNull(CreatureModel *creature) { Container *cont; if (creature->depositNullName == NULL) { cont = NULL; } else { cont = creature->depositNull; if (cont == NULL) { cont = Object_FindNull((BasicObjectModel *)creature,creature->depositNullName,0); creature->depositNull = cont; return cont; } } return cont; } // Checks if the model has a throw null, and performs initialisation for the null if not found. // // A more correct name would be Creature_HasThrowNull, but the fact that this performs // initialisation is still awkward to convey. BOOL __cdecl lego::gfx::Creature_CheckThrowNull(CreatureModel *creature) { Container *contNull; float10 fVar1; if ((creature->throwNull == NULL) && (creature->throwNullName != NULL)) { contNull = Object_FindNull((BasicObjectModel *)creature,creature->throwNullName,0); creature->throwNull = contNull; } if (creature->throwNull != NULL) { fVar1 = Container_GetZXRatio(creature->throwNull); if (fVar1 != (float10)1.0) { return TRUE; } } return 0; } float10 __cdecl lego::gfx::Creature_GetTransCoef(CreatureModel *creature) { float10 fVar1; fVar1 = Container_GetTransCoef(creature->contAct); return fVar1; } void __cdecl lego::front::Bubble_Initialise(void) { globs::bubbleGlobs.bubbleName[0] = "Bubble_CantDo"; globs::bubbleGlobs.bubbleName[1] = "Bubble_Idle"; globs::bubbleGlobs.bubbleName[2] = "Bubble_CollectCrystal"; globs::bubbleGlobs.bubbleName[3] = "Bubble_CollectOre"; globs::bubbleGlobs.bubbleName[4] = "Bubble_CollectStud"; globs::bubbleGlobs.bubbleName[5] = "Bubble_CollectDynamite"; globs::bubbleGlobs.bubbleName[6] = "Bubble_CollectBarrier"; globs::bubbleGlobs.bubbleName[7] = "Bubble_CollectElecFence"; globs::bubbleGlobs.bubbleName[8] = "Bubble_CollectDrill"; globs::bubbleGlobs.bubbleName[9] = "Bubble_CollectSpade"; globs::bubbleGlobs.bubbleName[10] = "Bubble_CollectHammer"; globs::bubbleGlobs.bubbleName[11] = "Bubble_CollectSpanner"; globs::bubbleGlobs.bubbleName[12] = "Bubble_CollectLaser"; globs::bubbleGlobs.bubbleName[13] = "Bubble_CollectPusher"; globs::bubbleGlobs.bubbleName[14] = "Bubble_CollectFreezer"; globs::bubbleGlobs.bubbleName[15] = "Bubble_CollectBirdScarer"; globs::bubbleGlobs.bubbleName[16] = "Bubble_CarryCrystal"; globs::bubbleGlobs.bubbleName[17] = "Bubble_CarryOre"; globs::bubbleGlobs.bubbleName[18] = "Bubble_CarryStud"; globs::bubbleGlobs.bubbleName[19] = "Bubble_CarryDynamite"; globs::bubbleGlobs.bubbleName[20] = "Bubble_CarryBarrier"; globs::bubbleGlobs.bubbleName[21] = "Bubble_CarryElecFence"; globs::bubbleGlobs.bubbleName[22] = "Bubble_Goto"; globs::bubbleGlobs.bubbleName[23] = "Bubble_Dynamite"; globs::bubbleGlobs.bubbleName[24] = "Bubble_Reinforce"; globs::bubbleGlobs.bubbleName[25] = "Bubble_Drill"; globs::bubbleGlobs.bubbleName[26] = "Bubble_Repair"; globs::bubbleGlobs.bubbleName[27] = "Bubble_Dig"; globs::bubbleGlobs.bubbleName[28] = "Bubble_Flee"; globs::bubbleGlobs.bubbleName[29] = "Bubble_PowerOff"; globs::bubbleGlobs.bubbleName[30] = "Bubble_CallToArms"; globs::bubbleGlobs.bubbleName[31] = "Bubble_ElecFence"; globs::bubbleGlobs.bubbleName[32] = "Bubble_Eat"; globs::bubbleGlobs.bubbleName[33] = "Bubble_Drive"; globs::bubbleGlobs.bubbleName[34] = "Bubble_Upgrade"; globs::bubbleGlobs.bubbleName[35] = "Bubble_BuildPath"; globs::bubbleGlobs.bubbleName[36] = "Bubble_Train"; globs::bubbleGlobs.bubbleName[37] = "Bubble_Recharge"; globs::bubbleGlobs.bubbleName[38] = "Bubble_Request"; return; } void __cdecl lego::front::Bubble_LoadBubbles(Config *config) { char cVar1; char *arrayID; Config *prop; Bubble_Type bubbleType; Image *image; int iVar2; char *bubbleName; char *pcVar3; bool noReduce; arrayID = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Bubbles",0); prop = cfg::Config_FindArray(config,arrayID); do { if (prop == NULL) { return; } bubbleName = prop->key; noReduce = true; if (bubbleName != NULL) { // std::strlen(bubbleName) (except the result is negative for some reason) iVar2 = -1; pcVar3 = bubbleName; do { if (iVar2 == 0) break; iVar2 += -1; cVar1 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar1 != '\0'); // if (std::strlen(bubbleName) != 0 && bubbleName[0] != '!') if ((iVar2 != -2) && (*bubbleName == '!')) { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEIMAGES) == MAIN_FLAG_NONE) { bubbleName = bubbleName + 1; } else { noReduce = false; } } } if (noReduce) { bubbleType = Bubble_GetBubbleType(bubbleName); image = lego::image::Image_LoadBMPScaled(prop->value,0,0); globs::bubbleGlobs.bubbleImage[bubbleType] = image; if (image != NULL) { lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); } } prop = cfg::Config_GetNextItem(prop); } while( true ); } Bubble_Type __cdecl lego::front::Bubble_GetBubbleType(char *bubbleName) { Bubble_Type BVar1; char **ppcVar2; Bubble_Type BVar3; BVar3 = Bubble_CantDo; ppcVar2 = globs::bubbleGlobs.bubbleName; do { BVar1 = std::_stricmp(*ppcVar2,bubbleName); if (BVar1 == Bubble_CantDo) { return BVar3; } ppcVar2 = ppcVar2 + 1; BVar3 += Bubble_Idle; } while ((int)ppcVar2 < 0x55899c); return BVar1; } void __cdecl lego::front::Bubble_ToggleObjectUIsAlwaysVisible(void) { globs::bubbleGlobs.alwaysVisible = (uint)(globs::bubbleGlobs.alwaysVisible == 0); return; } BOOL __cdecl lego::front::Bubble_GetObjectUIsAlwaysVisible(void) { return globs::bubbleGlobs.alwaysVisible; } void __cdecl lego::front::Bubble_ResetObjectBubbleImage(LegoObject *liveObj) { if (globs::bubbleGlobs.alwaysVisible != 0) { liveObj->bubbleTimer = 0.0; Bubble_EvaluateObjectBubbleImage(liveObj,&liveObj->bubbleImage); } return; } // Remove references from the bubble tables that match the specified object. void __cdecl lego::front::Bubble_RemoveObjectReferences(LegoObject *liveObj) { Bubble *bubble; bubble = globs::bubbleGlobs.healthBarList; do { if (liveObj == bubble->object) { bubble->object = NULL; } bubble = bubble + 1; } while (bubble < globs::bubbleGlobs.bubbleList); bubble = globs::bubbleGlobs.bubbleList; do { if (liveObj == bubble->object) { bubble->object = NULL; } bubble = bubble + 1; } while (bubble < globs::bubbleGlobs.powerOffList); bubble = globs::bubbleGlobs.powerOffList; do { if (liveObj == bubble->object) { bubble->object = NULL; } bubble = bubble + 1; } while (bubble < globs::bubbleGlobs.callToArmsList); bubble = globs::bubbleGlobs.callToArmsList; do { if (liveObj == bubble->object) { bubble->object = NULL; } bubble = bubble + 1; } while (bubble < (Bubble *)&DAT_00558d54); return; } void __cdecl lego::front::Bubble_ShowPowerOff(LegoObject *liveObj) { Bubble *bubble; int i; if (liveObj->type == LegoObject_Building) { i = 0; bubble = globs::bubbleGlobs.powerOffList; do { if (liveObj == bubble->object) break; bubble = bubble + 1; i += 1; } while (bubble < globs::bubbleGlobs.callToArmsList); if (i == 0x14) { bubble = globs::bubbleGlobs.powerOffList; while (bubble->object != NULL) { bubble = bubble + 1; if ((Bubble *)((int)&globs::bubbleGlobs.powerOffList[0x13].remainingTimer + 3) < bubble) { return; } } bubble->object = liveObj; } } return; } void __cdecl lego::front::Bubble_ShowBubble(LegoObject *liveObj) { int i; Bubble *bubble; Bubble *bubble_; if (liveObj->type == LegoObject_MiniFigure) { i = 0; bubble_ = globs::bubbleGlobs.bubbleList; do { bubble = bubble_; if (liveObj == bubble->object) break; i += 1; bubble_ = bubble + 1; } while (bubble + 1 < globs::bubbleGlobs.powerOffList); if (i == 0x14) { i = 0; bubble_ = globs::bubbleGlobs.bubbleList; do { bubble = bubble_; if (bubble->object == NULL) { bubble->object = liveObj; break; } i += 1; bubble_ = bubble + 1; } while (bubble + 1 < globs::bubbleGlobs.powerOffList); if (i == 0x14) { return; } } bubble->remainingTimer = 12.5; } return; } void __cdecl lego::front::Bubble_ShowCallToArms(LegoObject *liveObj) { int i; Bubble *bubble; Bubble *bubble_; if (liveObj->type == LegoObject_MiniFigure) { i = 0; bubble_ = globs::bubbleGlobs.callToArmsList; do { bubble = bubble_; if (liveObj == bubble->object) break; i += 1; bubble_ = bubble + 1; } while (bubble + 1 < (Bubble *)&DAT_00558d54); if (i == 50) { i = 0; bubble_ = globs::bubbleGlobs.callToArmsList; do { bubble = bubble_; if (bubble->object == NULL) { bubble->object = liveObj; break; } i += 1; bubble_ = bubble + 1; } while (bubble + 1 < (Bubble *)&DAT_00558d54); if (i == 50) { return; } } bubble->remainingTimer = 2250000.0; } return; } void __cdecl lego::front::Bubble_SetCallToArmsTimer(LegoObject *liveObj,float timer) { float *pBubbleRemainingTimer; if (liveObj->type == LegoObject_MiniFigure) { pBubbleRemainingTimer = &globs::bubbleGlobs.callToArmsList[0].remainingTimer; do { if (pBubbleRemainingTimer[-1] != 0.0) { *pBubbleRemainingTimer = timer; } pBubbleRemainingTimer = pBubbleRemainingTimer + 2; } while (pBubbleRemainingTimer < null_ARRAY_00558d58); } return; } void __cdecl lego::front::Bubble_ShowHealthBar(LegoObject *liveObj) { StatsFlags3 sflags3; int i; Bubble *bubble; Bubble *bubble_; sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if ((sflags3 & STATS3_SHOWHEALTHBAR) != STATS3_NONE) { i = 0; bubble_ = globs::bubbleGlobs.healthBarList; do { bubble = bubble_; if (liveObj == bubble->object) break; i += 1; bubble_ = bubble + 1; } while (bubble + 1 < globs::bubbleGlobs.bubbleList); if (i == 0x14) { i = 0; bubble_ = globs::bubbleGlobs.healthBarList; do { bubble = bubble_; if (bubble->object == NULL) { bubble->object = liveObj; break; } i += 1; bubble_ = bubble + 1; } while (bubble + 1 < globs::bubbleGlobs.bubbleList); if (i == 0x14) { return; } } bubble->remainingTimer = 37.5; } return; } void __cdecl lego::front::Bubble_DrawAllObjInfos(float elapsedAbs) { float fVar1; Image *pIVar2; BOOL BVar3; Container *pCVar4; int iVar5; Bubble *bubbleData; float10 fVar6; longlong lVar7; Container *pCVar8; Vector3F *pVVar9; Point2F local_14; Vector3F local_c; LegoObject *liveObj; if ((globs::bubbleGlobs.alwaysVisible != 0) && (BVar3 = lrr::Lego_IsFirstPersonView(), BVar3 == 0) ) { game::LegoObject_RunThroughListsSkipUpgradeParts(Bubble_Callback_DrawObjInfo,&elapsedAbs); } bubbleData = globs::bubbleGlobs.healthBarList; do { liveObj = bubbleData->object; if (liveObj != NULL) { if ((((liveObj->type != LegoObject_MiniFigure) || (globs::bubbleGlobs.alwaysVisible == 0)) && (BVar3 = lrr::Lego_IsFirstPersonView(), BVar3 == 0)) && ((liveObj->flags1 & (LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE)) { pVVar9 = &local_c; pCVar8 = NULL; pCVar4 = game::LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(pCVar4,pCVar8,pVVar9); fVar6 = stats::StatsObject_GetCollHeight(liveObj); local_c.z = (float)((float10)local_c.z - fVar6); lego::view::Viewport_WorldToScreen(globs::legoGlobs.viewMain,&local_14,&local_c); lVar7 = __ftol((float10)local_14.y); iVar5 = (int)lVar7; lVar7 = __ftol((float10)local_14.x); ObjInfo_DrawHealthBar(liveObj,(int)lVar7,iVar5); } fVar1 = bubbleData->remainingTimer - elapsedAbs; bubbleData->remainingTimer = fVar1; if (fVar1 < 0.0) { bubbleData->object = NULL; } } bubbleData = bubbleData + 1; } while (bubbleData < globs::bubbleGlobs.bubbleList); BVar3 = lrr::Lego_IsFirstPersonView(); if (BVar3 == 0) { if (12.5 <= globs::s_Bubble_PowerOffFlashTimer) { if (25.0 <= globs::s_Bubble_PowerOffFlashTimer) { globs::s_Bubble_PowerOffFlashTimer = globs::s_Bubble_PowerOffFlashTimer - 25.0; } } else { bubbleData = globs::bubbleGlobs.powerOffList; do { pIVar2 = globs::bubbleGlobs.bubbleImage[29]; liveObj = bubbleData->object; if (liveObj != NULL) { if ((liveObj->flags3 & LIVEOBJ3_HASPOWER) == LIVEOBJ3_NONE) { pVVar9 = &local_c; pCVar8 = NULL; pCVar4 = game::LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(pCVar4,pCVar8,pVVar9); fVar6 = stats::StatsObject_GetCollHeight(liveObj); local_c.z = (float)((float10)local_c.z - fVar6); lego::view::Viewport_WorldToScreen(globs::legoGlobs.viewMain,&local_14,&local_c); local_14.y = local_14.y - (float)pIVar2->height; local_14.x = local_14.x - (float)pIVar2->width * 0.5; lego::image::Image_DisplayScaled(pIVar2,NULL,&local_14,NULL); } else { bubbleData->object = NULL; } } bubbleData = bubbleData + 1; } while (bubbleData < globs::bubbleGlobs.callToArmsList); } globs::s_Bubble_PowerOffFlashTimer = globs::s_Bubble_PowerOffFlashTimer + elapsedAbs; } bubbleData = globs::bubbleGlobs.bubbleList; do { liveObj = bubbleData->object; if (liveObj != NULL) { if (((liveObj->type != LegoObject_MiniFigure) || (globs::bubbleGlobs.alwaysVisible == 0)) && (((liveObj->flags1 & (LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE && (BVar3 = lrr::Lego_IsFirstPersonView(), BVar3 == 0)))) { local_14.x = 0.0; Bubble_UpdateAndGetBubbleImage(liveObj,elapsedAbs,(Image **)&local_14,&local_c); pIVar2 = (Image *)local_14.x; if (((Image *)local_14.x != NULL) && ((Image *)local_14.x != globs::bubbleGlobs.bubbleImage[1])) { lVar7 = __ftol((float10)local_c.y); iVar5 = (int)lVar7; lVar7 = __ftol((float10)local_c.x); ObjInfo_DrawBubbleImage(pIVar2,(int)lVar7,iVar5); } } fVar1 = bubbleData->remainingTimer - elapsedAbs; bubbleData->remainingTimer = fVar1; if (fVar1 < 0.0) { bubbleData->object = NULL; } } bubbleData = bubbleData + 1; } while (bubbleData < globs::bubbleGlobs.powerOffList); bubbleData = globs::bubbleGlobs.callToArmsList; do { liveObj = bubbleData->object; if (liveObj != NULL) { if (((globs::bubbleGlobs.alwaysVisible == 0) && ((liveObj->flags1 & (LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE)) && (BVar3 = lrr::Lego_IsFirstPersonView(), BVar3 == 0)) { local_14.x = 0.0; Bubble_UpdateAndGetBubbleImage(liveObj,elapsedAbs,(Image **)&local_14,&local_c); pIVar2 = (Image *)local_14.x; if ((Image *)local_14.x != NULL) { lVar7 = __ftol((float10)local_c.y); iVar5 = (int)lVar7; lVar7 = __ftol((float10)local_c.x); ObjInfo_DrawBubbleImage(pIVar2,(int)lVar7,iVar5); } } if ((ushort)((ushort)(bubbleData->remainingTimer < 0.0) << 8 | (ushort)(bubbleData->remainingTimer == 0.0) << 0xe) != 0) { bubbleData->object = NULL; } } bubbleData = bubbleData + 1; } while (bubbleData < (Bubble *)&DAT_00558d54); return; } void __cdecl lego::front::Bubble_UpdateAndGetBubbleImage (LegoObject *liveObj,float elapsedAbs,Image **out_bubbleImage,Point2F *out_screenPt) { float fVar1; Container *cont; float10 fVar2; Container *opt_ref; Vector3F *out_pos; Vector3F local_c; out_pos = &local_c; opt_ref = NULL; cont = game::LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(cont,opt_ref,out_pos); fVar2 = stats::StatsObject_GetCollHeight(liveObj); local_c.z = (float)((float10)local_c.z - fVar2); lego::view::Viewport_WorldToScreen(globs::legoGlobs.viewMain,out_screenPt,&local_c); fVar1 = liveObj->bubbleTimer - elapsedAbs; liveObj->bubbleTimer = fVar1; if ((ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) == 0) { *out_bubbleImage = liveObj->bubbleImage; } else { Bubble_EvaluateObjectBubbleImage(liveObj,out_bubbleImage); } if (*out_bubbleImage == NULL) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[1]; } return; } BOOL __cdecl lego::front::Bubble_Callback_DrawObjInfo(LegoObject *liveObj,float *pElapsedAbs) { float *image; int iVar1; longlong lVar2; float elapsedAbs; float local_4; elapsedAbs = *pElapsedAbs; if ((liveObj->type == LegoObject_MiniFigure) && ((liveObj->flags1 & (LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE)) { pElapsedAbs = NULL; Bubble_UpdateAndGetBubbleImage(liveObj,elapsedAbs,(Image **)&pElapsedAbs,&elapsedAbs); lVar2 = __ftol((float10)local_4); iVar1 = (int)lVar2; lVar2 = __ftol((float10)elapsedAbs); ObjInfo_DrawHealthBar(liveObj,(int)lVar2,iVar1); lVar2 = __ftol((float10)local_4); iVar1 = (int)lVar2; lVar2 = __ftol((float10)elapsedAbs); ObjInfo_DrawHungerImage(liveObj,(int)lVar2,iVar1); image = pElapsedAbs; if ((Image *)pElapsedAbs != NULL) { lVar2 = __ftol((float10)local_4); iVar1 = (int)lVar2; lVar2 = __ftol((float10)elapsedAbs); ObjInfo_DrawBubbleImage((Image *)image,(int)lVar2,iVar1); } } return FALSE; } void __cdecl lego::front::Bubble_EvaluateObjectBubbleImage(LegoObject *liveObj,Image **out_bubbleImage) { AITask *aiTask; LegoObject *carriedObj; AITask *nextTask; LegoObject_Type objType; AITask_Type taskType; LegoObject_ToolType toolType; aiTask = liveObj->aiTask; if ((*(byte *)&liveObj->flags4 & 0x20) != 0) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[30]; return; } if ((liveObj->flags1 & LIVEOBJ1_RUNNINGAWAY) != LIVEOBJ1_NONE) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[28]; return; } if ((liveObj->flags1 & LIVEOBJ1_CANTDO) != LIVEOBJ1_NONE) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[0]; return; } if (aiTask != NULL) { taskType = aiTask->taskType; while ((taskType == AITask_Type_AnimationWait && (nextTask = aiTask->next, nextTask != NULL))) { taskType = nextTask->taskType; aiTask = nextTask; } if (true) { switch(aiTask->taskType) { case AITask_Type_Goto: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[22]; return; case AITask_Type_Collect: objType = aiTask->targetObject->type; if (objType == LegoObject_PowerCrystal) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[2]; return; } if (objType == LegoObject_Ore) { if (aiTask->targetObject->id == 0) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[3]; return; } *out_bubbleImage = globs::bubbleGlobs.bubbleImage[4]; return; } if (objType == LegoObject_Dynamite) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[5]; return; } if (objType == LegoObject_Barrier) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[6]; return; } if (objType == LegoObject_ElectricFence) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[7]; return; } break; case AITask_Type_Deposit: carriedObj = liveObj->carriedObjects[0]; if (carriedObj != NULL) { objType = carriedObj->type; if (objType == LegoObject_PowerCrystal) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[16]; return; } if (objType == LegoObject_Ore) { if (carriedObj->id == 0) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[17]; return; } *out_bubbleImage = globs::bubbleGlobs.bubbleImage[18]; return; } if (objType == LegoObject_Dynamite) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[19]; return; } if (objType == LegoObject_Barrier) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[20]; return; } if (objType == LegoObject_ElectricFence) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[21]; return; } } break; case AITask_Type_Request: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[38]; break; case AITask_Type_Dig: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[25]; return; case AITask_Type_Dynamite: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[23]; return; case AITask_Type_Repair: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[26]; return; case AITask_Type_Reinforce: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[24]; return; case AITask_Type_Clear: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[27]; return; case AITask_Type_ElecFence: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[31]; return; case AITask_Type_Eat: case AITask_Type_GotoEat: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[32]; return; case AITask_Type_FindDriver: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[33]; return; case AITask_Type_GetTool: toolType = aiTask->toolType; if (toolType == LegoObject_ToolType_Drill) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[8]; return; } if (toolType == LegoObject_ToolType_Spade) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[9]; return; } if (toolType == LegoObject_ToolType_Hammer) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[10]; return; } if (toolType == LegoObject_ToolType_Spanner) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[11]; return; } if (toolType == LegoObject_ToolType_Laser) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[12]; return; } if (toolType == LegoObject_ToolType_PusherGun) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[13]; return; } if (toolType == LegoObject_ToolType_FreezerGun) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[14]; return; } if (toolType == LegoObject_ToolType_BirdScarer) { *out_bubbleImage = globs::bubbleGlobs.bubbleImage[15]; return; } break; case AITask_Type_Upgrade: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[34]; return; case AITask_Type_BuildPath: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[35]; return; case AITask_Type_Train: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[36]; return; case AITask_Type_Recharge: *out_bubbleImage = globs::bubbleGlobs.bubbleImage[37]; return; } } } return; } BOOL __cdecl lego::gfx::Building_Load (BuildingModel *building,LegoObject_ID objID,Container *root,char *filename,char *gameName ) { char cVar1; Container *pCVar2; Config *prop; char *pcVar3; Point2I *pPVar4; char *pcVar5; int iVar6; uint uVar7; uint uVar8; char **ppcVar9; undefined4 *puVar10; BuildingModel *pBVar11; undefined4 *puVar12; float10 fVar13; char **local_99c; int local_998; char *stringParts [100]; char buffName [1024]; char buffPath [1024]; pBVar11 = building; for (iVar6 = 0x53; iVar6 != 0; iVar6 += -1) { pBVar11->objID = 0; pBVar11 = (BuildingModel *)&pBVar11->contAct; } pCVar2 = Container_Load(root,filename,"ACT",TRUE); building->contAct = pCVar2; if (pCVar2 == NULL) { return 0; } uVar7 = 0xffffffff; do { pcVar3 = filename; if (uVar7 == 0) break; uVar7 -= 1; pcVar3 = filename + 1; cVar1 = *filename; filename = pcVar3; } while (cVar1 != '\0'); uVar7 = ~uVar7; puVar10 = (undefined4 *)(pcVar3 + -uVar7); puVar12 = (undefined4 *)buffName; for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar12 = *puVar10; puVar10 = puVar10 + 1; puVar12 = puVar12 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar12 = *(undefined *)puVar10; puVar10 = (undefined4 *)((int)puVar10 + 1); puVar12 = (undefined4 *)((int)puVar12 + 1); } uVar7 = util::Util_Tokenise(buffName,stringParts,"\\"); if (1 < uVar7) { ppcVar9 = stringParts; iVar6 = uVar7 - 1; do { ppcVar9 = ppcVar9 + 1; iVar6 += -1; (*ppcVar9)[-1] = '\\'; } while (iVar6 != 0); } std::sprintf(buffPath,"%s\\%s.%s",buffName,stringParts[uVar7 - 1],"ae"); prop = cfg::Config_Load(buffPath); if (prop != NULL) { pcVar3 = cfg::Config_BuildStringID(gameName,"CarryNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); building->carryNullName = pcVar3; if (pcVar3 == NULL) { building->carryNullFrames = 0; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"CarryNullFrames",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 == NULL) { uVar7 = std::atoi(____EMPTYSTR__); building->carryNullFrames = uVar7; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"CarryNullFrames",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); uVar7 = std::atoi(pcVar3); building->carryNullFrames = uVar7; } } pcVar3 = cfg::Config_BuildStringID(gameName,"CameraNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); building->cameraNullName = pcVar3; if (pcVar3 == NULL) { building->cameraNullFrames = 0; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"CameraNullFrames",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 == NULL) { uVar7 = std::atoi(____EMPTYSTR__); building->cameraNullFrames = uVar7; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"CameraNullFrames",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); uVar7 = std::atoi(pcVar3); building->cameraNullFrames = uVar7; } } pcVar3 = cfg::Config_BuildStringID(gameName,"ToolNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); building->toolNullName = pcVar3; if (pcVar3 == NULL) { building->toolNullFrames = 0; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"ToolNullFrames",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 == NULL) { uVar7 = std::atoi(____EMPTYSTR__); building->toolNullFrames = uVar7; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"ToolNullFrames",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); uVar7 = std::atoi(pcVar3); building->toolNullFrames = uVar7; } } pcVar3 = cfg::Config_BuildStringID(gameName,"DepositNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); building->depositNullName = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"FireNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); building->fireNullName = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"EntranceNullName",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); building->entranceNullName = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"yPivot",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); building->yPivot = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"xPivot",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); building->xPivot = pcVar3; pcVar3 = cfg::Config_BuildStringID(gameName,"PivotMaxZ",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 == NULL) { (building->weapons).pivotMaxZ = 1.0; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"PivotMaxZ",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 == NULL) { fVar13 = std::atof(____EMPTYSTR__); (building->weapons).pivotMaxZ = (float)fVar13; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"PivotMaxZ",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); fVar13 = std::atof(pcVar3); (building->weapons).pivotMaxZ = (float)fVar13; } } pcVar3 = cfg::Config_BuildStringID(gameName,"PivotMinZ",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 == NULL) { (building->weapons).pivotMinZ = -1.0; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"PivotMinZ",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 == NULL) { fVar13 = std::atof(____EMPTYSTR__); (building->weapons).pivotMinZ = (float)fVar13; } else { pcVar3 = cfg::Config_BuildStringID(gameName,"PivotMinZ",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); fVar13 = std::atof(pcVar3); (building->weapons).pivotMinZ = (float)fVar13; } } Upgrade_Load(&building->upgrades,prop,gameName); pPVar4 = (Point2I *)io::Mem_Alloc(0x50); building->shapePoints = pPVar4; building->shapeCount = 1; pPVar4->y = 0; building->shapePoints->x = 0; pcVar3 = cfg::Config_BuildStringID(gameName,"Shape",0); pcVar3 = cfg::Config_GetStringValue(prop,pcVar3); if (pcVar3 != NULL) { local_998 = util::Util_Tokenise(pcVar3,stringParts,":"); if (local_998 != 0) { local_99c = stringParts; do { uVar7 = building->shapeCount; pPVar4 = building->shapePoints; pcVar5 = *local_99c; building->shapeCount = uVar7 + 1; iVar6 = std::atoi(pcVar5); pPVar4[uVar7].x = iVar6; pcVar5 = std::strstr(pcVar5,","); iVar6 = std::atoi(pcVar5 + 1); pPVar4[uVar7].y = iVar6; local_99c = local_99c + 1; local_998 += -1; } while (local_998 != 0); } io::Mem_Free(pcVar3); } pcVar3 = cfg::Config_BuildStringID(gameName,"PowerLevelScene",0); pcVar3 = cfg::Config_GetTempStringValue(prop,pcVar3); if (pcVar3 != NULL) { std::sprintf(buffPath,"%s\\%s",buffName,pcVar3); pCVar2 = Container_Load(root,buffPath,"LWS",TRUE); building->contPowerLevel = pCVar2; } cfg::Config_Free(prop); } Container_Hide(building->contAct,TRUE); building->objID = objID; building->flags = BUILDING_FLAG_NONE; return TRUE; } void __cdecl lego::gfx::Building_ChangePowerLevel(BuildingModel *building,BOOL increment) { float timer; if (increment == FALSE) { timer = (building->powerLevel - 0.1) * 10.0 * 0.1111111; } else { timer = building->powerLevel - (1.0 - building->powerLevel) * -0.1; } building->powerLevel = timer; if (building->powerLevel < 0.0) { building->powerLevel = 0.0; } building->flags = building->flags | BUILDING_FLAG_UPDATEPOWERLEVEL; return; } Point2I * __cdecl lego::gfx::Building_GetShapePoints(BuildingModel *building,uint *optout_shapeCount) { if (optout_shapeCount != NULL) { *optout_shapeCount = building->shapeCount; } return building->shapePoints; } void __cdecl lego::gfx::Object_SetOwnerObject(BasicObjectModel *basicObjData,LegoObject *liveObj) { Container_SetUserData(basicObjData->contAct,liveObj); return; } void __cdecl lego::gfx::Building_SetUpgradeActivity(BuildingModel *building,char *activityName) { int *opt_instance; Upgrade_PartInfo *pUVar1; Container **ppCVar2; Container *partChildCont; char *partName; Container *partParentCont; WeaponsModel *pWVar3; int i; Upgrade_PartModel *upgradePart; uint j; int zero; uint locIndex; Upgrade_PartInfo *locPartInfo; Upgrade_PartModel *locUpgrade; BuildingModel *building_00; uint index; LegoObject *upgradeObjs; building_00 = building; i = 3; upgradeObjs = (building->upgrades).firstObject; ppCVar2 = (building->weapons).yPivotNulls; pWVar3 = &building->weapons; do { ppCVar2[0x1a] = NULL; *ppCVar2 = NULL; ppCVar2[-3] = NULL; pWVar3->fireNullPairs[0] = NULL; ppCVar2 = ppCVar2 + 1; i += -1; pWVar3->fireNullPairs[1] = NULL; pWVar3 = (WeaponsModel *)pWVar3->fireNullPairs[1]; } while (i != 0); (building->weapons).count = 0; do { if (upgradeObjs == NULL) { return; } upgradePart = upgradeObjs->upgradePart; pUVar1 = upgradePart->partInfo; locPartInfo = pUVar1; locUpgrade = upgradePart; partParentCont = Object_FindNull((BasicObjectModel *)building_00,pUVar1->nullObjectName,pUVar1->nullFrameNo) ; partChildCont = Object_GetActivityContainer((BasicObjectModel *)upgradePart); Container_SetParent(partChildCont,partParentCont); Container_ClearTransform(partChildCont); if (activityName == NULL) { Container_SetActivity(upgradePart->cont,globs::objectGlobs.activityName[0]); } else { Upgrade_Part_SetActivity(upgradePart,activityName); } if (pUVar1->weaponName != NULL) { index = (building_00->weapons).count; zero = 0; (building_00->weapons).fireNullPairFrames[index] = 0; j = 0; opt_instance = (building_00->weapons).fireNullPairFrames + index; building = (BuildingModel *)(building_00->weapons).fireNullPairs[index]; locIndex = index; do { // fireNullPairs[index][j] = nullptr; building->objID = 0; partName = Container_FormatPartName (building_00->contAct,building_00->fireNullName,opt_instance); partParentCont = Container_SearchTree(partChildCont,partName,Container_SearchMode_FirstMatch,NULL); (building_00->weapons).fireNullPairs[index][*opt_instance] = partParentCont; partParentCont = (building_00->weapons).fireNullPairs[index][*opt_instance]; *opt_instance = *opt_instance + 1; if (partParentCont == NULL) break; j += 1; building = (BuildingModel *)&building->contAct; } while (j < 2); partName = Container_FormatPartName(building_00->contAct,building_00->xPivot,&zero); partParentCont = Container_SearchTree(partChildCont,partName,Container_SearchMode_FirstMatch,NULL); index = locIndex; (building_00->weapons).xPivotNulls[locIndex] = partParentCont; partName = Container_FormatPartName(building_00->contAct,building_00->yPivot,&zero); partParentCont = Container_SearchTree(partChildCont,partName,Container_SearchMode_FirstMatch,NULL); (building_00->weapons).yPivotNulls[index] = partParentCont; (building_00->weapons).parts[index] = locPartInfo; (building_00->weapons).count = (building_00->weapons).count + 1; upgradePart = locUpgrade; } upgradeObjs = upgradePart->nextObject; } while( true ); } BOOL __cdecl lego::gfx::Building_SetActivity(BuildingModel *building,char *activityName,float elapsed) { uint i; BOOL success; Container **pNull; i = 0; if (building->carryNullFrames != 0) { pNull = building->carryNulls; do { *pNull = NULL; i += 1; pNull = pNull + 1; } while (i < building->carryNullFrames); } i = 0; if (building->cameraNullFrames != 0) { pNull = building->cameraNulls; do { *pNull = NULL; i += 1; pNull = pNull + 1; } while (i < building->cameraNullFrames); } building->depositNull = NULL; building->entranceNull = NULL; success = Container_SetActivity(building->contAct,activityName); Container_SetAnimationTime(building->contAct,elapsed); Building_SetUpgradeActivity(building,activityName); return success; } Container * __cdecl lego::gfx::Building_GetCameraNull(BuildingModel *building,uint frameNo) { Container *cont; // NOTE: cont here is `char* partName` cont = (Container *)building->cameraNullName; if (cont != NULL) { if (building->cameraNulls[frameNo] == NULL) { cont = Object_FindNull((BasicObjectModel *)building,(char *)cont,frameNo); building->cameraNulls[frameNo] = cont; } cont = building->cameraNulls[frameNo]; } return cont; } void __cdecl lego::gfx::Building_Clone(BuildingModel *srcBuilding,BuildingModel *destBuilding) { Container *contAct; int iVar1; BuildingModel *pBVar2; BuildingModel *pBVar3; pBVar2 = srcBuilding; pBVar3 = destBuilding; for (iVar1 = 0x53; iVar1 != 0; iVar1 += -1) { pBVar3->objID = pBVar2->objID; pBVar2 = (BuildingModel *)&pBVar2->contAct; pBVar3 = (BuildingModel *)&pBVar3->contAct; } destBuilding->flags = destBuilding->flags & ~BUILDING_FLAG_SOURCE; contAct = Container_Clone(srcBuilding->contAct); destBuilding->contAct = contAct; if (srcBuilding->contPowerLevel != NULL) { contAct = Container_Clone(srcBuilding->contPowerLevel); destBuilding->contPowerLevel = contAct; } return; } void __cdecl lego::gfx::Building_Hide(BuildingModel *building,BOOL hide) { Container_Hide(building->contAct,hide); if (building->contPowerLevel != NULL) { Container_Hide(building->contPowerLevel,hide); } return; } BOOL __cdecl lego::gfx::Object_IsHidden(BasicObjectModel *basicObjData) { BOOL BVar1; BVar1 = Container_IsHidden(basicObjData->contAct); return BVar1; } void __cdecl lego::gfx::Building_SetOrientation(BuildingModel *building,float xDir,float yDir) { Container_SetOrientation(building->contAct,NULL,xDir,yDir,0.0,0.0,0.0,-1.0); if (building->contPowerLevel != NULL) { Container_SetOrientation(building->contPowerLevel,NULL,xDir,yDir,0.0,0.0,0.0,-1.0); } return; } void __cdecl lego::gfx::Building_SetPosition (BuildingModel *building,float xPos,float yPos,GetWorldZCallback zCallback,Map3D *map) { float10 zPos; zPos = (*zCallback)(xPos,yPos,map); Container_SetPosition(building->contAct,NULL,xPos,yPos,(float)zPos); if (building->contPowerLevel != NULL) { Container_SetPosition(building->contPowerLevel,NULL,xPos,yPos,(float)zPos); } return; } Container * __cdecl lego::gfx::Building_GetCarryNull(BuildingModel *building,uint frameNo) { Container *cont; if (building->carryNullName == NULL) { return NULL; } if (building->carryNulls[frameNo] != NULL) { return building->carryNulls[frameNo]; } cont = Object_FindNull((BasicObjectModel *)building,building->carryNullName,frameNo); building->carryNulls[frameNo] = cont; return cont; } Container * __cdecl lego::gfx::Building_GetDepositNull(BuildingModel *building) { Container *cont; if (building->depositNullName == NULL) { cont = NULL; } else { cont = building->depositNull; if (cont == NULL) { cont = Object_FindNull((BasicObjectModel *)building,building->depositNullName,0); building->depositNull = cont; return cont; } } return cont; } Container * __cdecl lego::gfx::Building_GetEntranceNull(BuildingModel *building) { Container *cont; if (building->entranceNullName == NULL) { cont = NULL; } else { cont = building->entranceNull; if (cont == NULL) { cont = Object_FindNull((BasicObjectModel *)building,building->entranceNullName,0); building->entranceNull = cont; return cont; } } return cont; } Container * __cdecl lego::gfx::Building_GetToolNull(BuildingModel *building,uint frameNo) { Container *cont; if (building->toolNullName == NULL) { return NULL; } if (building->toolNulls[frameNo] != NULL) { return building->toolNulls[frameNo]; } cont = Object_FindNull((BasicObjectModel *)building,building->toolNullName,frameNo); building->toolNulls[frameNo] = cont; return cont; } uint __cdecl lego::gfx::Building_GetCarryNullFrames(BuildingModel *building) { return building->carryNullFrames; } float10 __cdecl lego::gfx::Building_MoveAnimation(BuildingModel *building,float elapsed,uint repeatCount) { BuildingModel *pBVar1; uint animFrames; float10 fVar2; BuildingModel *building_00; building_00 = building; fVar2 = Container_MoveAnimation(building->contAct,elapsed); pBVar1 = (BuildingModel *)(float)fVar2; if ((1 < repeatCount) && ((float)pBVar1 != 0.0)) { animFrames = Container_GetAnimationFrames(building->contAct); pBVar1 = (BuildingModel *)((float)pBVar1 - (float)(ulonglong)(animFrames * (repeatCount - 1))); } building = pBVar1; if ((*(byte *)&building_00->flags & 2) != 0) { if (building_00->contPowerLevel != NULL) { animFrames = Container_GetAnimationFrames(building_00->contPowerLevel); Container_SetAnimationTime (building_00->contPowerLevel,(float)(ulonglong)animFrames * building_00->powerLevel) ; } building_00->flags = building_00->flags & ~BUILDING_FLAG_UPDATEPOWERLEVEL; } return (float10)(float)building; } float10 __cdecl lego::gfx::Building_GetTransCoef(BuildingModel *building) { return (float10)0.0; } void __cdecl lego::gfx::Building_Remove(BuildingModel *building) { // Set level to -1 to forcefully remove all upgrade model parts. Building_SetUpgradeLevel(building,0xffffffff); if (building->contPowerLevel != NULL) { Container_Remove(building->contPowerLevel); } Container_Remove(building->contAct); return; } // When `current` is true, the function returns whether the object can currently get this upgrade. // (AKA, has the object not gotten the upgrade yet? And does it support the upgrade type?) // Otherwise the function returns whether the object type supports the upgrade at all. BOOL __cdecl lego::gfx::Building_CanUpgradeType (BuildingModel *building,LegoObject_UpgradeType upgradeType,BOOL current) { uint mask; mask = 1 << ((byte)upgradeType & 0x1f); if ((current != 0) && (((building->upgrades).levelFlags & mask) != 0)) { return 0; } return (building->upgrades).levelFlags & mask; } void __cdecl lego::gfx::Building_SetUpgradeLevel(BuildingModel *building,uint objLevel) { Upgrade_SetUpgradeLevel(&building->upgrades,objLevel); Building_SetUpgradeActivity(building,NULL); return; } float10 __cdecl lego::math::Collision_DistanceToLine(Point2F *point,Point2F *start,Point2F *end) { float fVar1; float fVar2; float fVar3; float10 fVar4; float10 fVar5; float10 length; float norm_y; float norm_x; float diff1_x; float diff1_y; float diff2_x; float diff2_y; // param_1 seems to be an origin point, while param_2 and param_3 are both possible // destination points. fVar1 = end->x - start->x; fVar3 = end->y - start->y; fVar4 = (float10)point->x - (float10)end->x; fVar5 = (float10)point->y - (float10)end->y; diff1_x = (float)fVar4; diff1_y = (float)fVar5; length = SQRT(fVar5 * (float10)diff1_y + fVar4 * (float10)diff1_x); fVar2 = 1.0 / SQRT(fVar3 * fVar3 + fVar1 * fVar1); norm_x = fVar2 * fVar1; norm_y = fVar2 * fVar3; if ((float10)(float)((float10)1.0 / length) * (float10)diff1_y * (float10)norm_y + ((float10)1.0 / length) * (float10)diff1_x * (float10)norm_x < (float10)0.0) { diff2_x = point->x - start->x; diff2_y = point->y - start->y; fVar2 = SQRT(diff2_y * diff2_y + diff2_x * diff2_x); fVar1 = (1.0 / fVar2) * diff2_y * norm_y + (1.0 / fVar2) * diff2_x * norm_x; if ((ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) != 0) { return (float10)fVar2; } fVar4 = std::acos((float10)fVar1); fVar4 = (float10)fsin(fVar4); length = fVar4 * (float10)fVar2; } return length; } // Does not return 0 when point is inside polygon, only the distance to the outline. float10 __cdecl lego::math::Collision_DistanceToPolyOutline (Point2F *point,Point2F *fromList,Point2F *toList,uint count) { Point2F *pPVar1; int iVar2; int iVar3; float10 fVar4; float10 value; // minValue = fVar4 = Collision_DistanceToLine(point,fromList,toList); pPVar1 = (Point2F *)(float)fVar4; if (1 < count) { iVar3 = (int)toList - (int)fromList; iVar2 = count - 1; toList = (Point2F *)(float)fVar4; do { fromList = fromList + 1; value = Collision_DistanceToLine(point,fromList,(Point2F *)(iVar3 + (int)fromList)); // if (value < minValue) minValue = value; if (value < (float10)(float)toList) { toList = (Point2F *)(float)value; } iVar2 += -1; pPVar1 = toList; } while (iVar2 != 0); } toList = pPVar1; return (float10)(float)toList; } Point2F * __cdecl lego::math::Collision_PointOnLine(Point2F *start,Point2F *end,Point2F *point,Point2F *result) { float fVar1; float fVar2; float dot; float ray_x; float ray_y; float length; fVar2 = end->x - start->x; fVar1 = end->y - start->y; length = 1.0 / SQRT(fVar1 * fVar1 + fVar2 * fVar2); ray_x = length * fVar2; ray_y = length * fVar1; dot = (point->y - start->y) * ray_y + (point->x - start->x) * ray_x; result->x = dot * ray_x + start->x; result->y = dot * ray_y + start->y; return result; } Point2F * __cdecl lego::math::Collision_PointOnLineRay(Point2F *start,Point2F *ray,Point2F *point,Point2F *result) { float fVar1; float fVar2; float dot; float ray_x; float ray_y; float length; fVar1 = ray->y; fVar2 = ray->x; length = 1.0 / SQRT(fVar1 * fVar1 + fVar2 * fVar2); ray_x = length * fVar2; ray_y = length * fVar1; dot = (point->y - start->y) * ray_y + (point->x - start->x) * ray_x; result->x = dot * ray_x + start->x; result->y = dot * ray_y + start->y; return result; } // Would have looked up the baseName in a list of up to 5 names, and returned the index (or // buildingBaseCount on failure). // No building bases are ever defined, so the function will always return 0 (aka buildingBaseCount). uint __cdecl lego::game::Construction_GetBuildingBase(char *baseName) { byte bVar1; byte *pbVar2; int iVar3; uint i; byte *pbVar4; byte **pName; bool bVar5; i = 0; if (globs::constructionGlobs.buildingBaseCount == 0) { return 0; } pName = (byte **)globs::constructionGlobs.buildingBaseName; do { pbVar2 = *pName; pbVar4 = (byte *)baseName; do { bVar1 = *pbVar2; bVar5 = bVar1 < *pbVar4; if (bVar1 != *pbVar4) { LAB_00408bee: iVar3 = (1 - (uint)bVar5) - (uint)(bVar5 != 0); goto LAB_00408bf3; } if (bVar1 == 0) break; bVar1 = pbVar2[1]; bVar5 = bVar1 < pbVar4[1]; if (bVar1 != pbVar4[1]) goto LAB_00408bee; pbVar2 = pbVar2 + 2; pbVar4 = pbVar4 + 2; } while (bVar1 != 0); iVar3 = 0; LAB_00408bf3: if (iVar3 == 0) { return i; } i += 1; pName = pName + 1; if (globs::constructionGlobs.buildingBaseCount <= i) { return globs::constructionGlobs.buildingBaseCount; } } while( true ); } void __cdecl lego::game::Construction_Zone_PlaceResource(uint constructHandle,LegoObject *placedObj) { Construction_Zone *construct; construct = Construction_Zone_FindByHandleOrAtBlock(NULL,&constructHandle); if (construct == NULL) { if (placedObj->type == LegoObject_PowerCrystal) { Message_PostEvent(Message_GenerateCrystalComplete,placedObj,0,NULL); return; } Message_PostEvent(Message_GenerateOreComplete,placedObj,0,NULL); } else { if (placedObj != NULL) { placedObj->flags4 = placedObj->flags4 | LIVEOBJ4_USEDBYCONSTRUCTION; construct->placedObjects[construct->placedCount2] = placedObj; construct->placedCount2 = construct->placedCount2 + 1; construct->placedCount = construct->placedCount + 1; } if (construct->requestCount == construct->placedCount) { // Unused float field, may have been timer for construction delay. construct->float_28 = 125.0; construct->flags = construct->flags | CONSTRUCTION_FLAG_READY; return; } } return; } BOOL __cdecl lego::game::Construction_Zone_NeedsMoreOfResource (uint constructHandle,LegoObject_Type objType,LegoObject_ID objID) { Construction_Zone *construct; uint placed; LegoObject_Type constructObjType; uint cost; LegoObject_ID objID_00; LegoObject_Type objType_00; construct = Construction_Zone_FindByHandleOrAtBlock(NULL,&constructHandle); objID_00 = objID; objType_00 = objType; if (construct != NULL) { placed = Construction_Zone_CountOfResourcePlaced(construct,objType,objID); // constructObjType = ((construct->flags & CONSTRUCTION_FLAG_LAYPATH) ? LegoObject_Path // : LegoObject_Building); constructObjType = (-(uint)((construct->flags & CONSTRUCTION_FLAG_LAYPATH) != CONSTRUCTION_FLAG_NONE) & 0xb) + LegoObject_Building; if (objType_00 == LegoObject_PowerCrystal) { cost = stats::Stats_GetCostCrystal(constructObjType,construct->objID,0); } else { if (objType_00 != LegoObject_Ore) { return 1; } if (objID_00 == 0) { cost = stats::Stats_GetCostOre(constructObjType,construct->objID,0); } else { cost = stats::Stats_GetCostRefinedOre(constructObjType,construct->objID,0); } } if (placed < cost) { return TRUE; } } return FALSE; } uint __cdecl lego::game::Construction_Zone_CountOfResourcePlaced (Construction_Zone *construct,LegoObject_Type objType,LegoObject_ID objID) { uint objCount; LegoObject **pPlacedObj; uint placedCount; objCount = 0; // count of the list field placedCount = construct->placedCount; if (placedCount != 0) { // a ptr list field pPlacedObj = construct->placedObjects; do { if ((objType == (*pPlacedObj)->type) && (objID == (*pPlacedObj)->id)) { objCount += 1; } pPlacedObj = pPlacedObj + 1; placedCount -= 1; } while (placedCount != 0); } return objCount; } void __cdecl lego::game::Construction_Zone_RequestResource (Point2I *originBlockPos,LegoObject_Type objType,LegoObject_ID objID,uint objLevel, uint count) { Construction_Zone *construct; construct = Construction_Zone_FindByHandleOrAtBlock(originBlockPos,NULL); if ((objType == LegoObject_Ore) && (objID == LegoObject_ID_ProcessedOre)) { construct->flags = construct->flags | CONSTRUCTION_FLAG_USESTUDS; } if (count != 0) { do { construct->requestCount = construct->requestCount + 1; ai::AITask_DoRequest_ObjectType (objType,objID,objLevel,originBlockPos,construct->handleValue,NULL,FALSE); count -= 1; } while (count != 0); } return; } void __cdecl lego::game::Construction_Zone_RequestBarriers (Point2I *originBlockPos,Point2I *shapeBlocks,uint shapeCount) { Point2I *pPVar1; Construction_Zone *construct; Map3D *map; Point2I *pPVar2; uint j; int *pShapeBlock_0_y; Point2I *pPVar3; Point2I *pShapeBlock_0; Point2I *pShapeBlock_1; float10 blockSize; uint i; Point2I DIRECTIONS [4]; Point2F local_20; float local_18; float local_14; float local_10; float local_c; float local_8; float local_4; bool innerConnection; construct = Construction_Zone_FindByHandleOrAtBlock(originBlockPos,NULL); map = lrr::Lego_GetMap(); blockSize = lego::map::Map3D_BlockSize(map); DIRECTIONS[1].x = 1; DIRECTIONS[2].y = 1; DIRECTIONS[0].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].y = 0; i = 0; local_20.x = 0.5; local_14 = 0.5; local_10 = 0.5; local_4 = 0.5; local_c = (float)((float10)8.8 / blockSize); local_20.y = 1.0 - local_c; if (shapeCount != 0) { pShapeBlock_0_y = &shapeBlocks->y; pShapeBlock_1 = shapeBlocks + 1; pShapeBlock_0 = shapeBlocks; local_18 = local_20.y; local_8 = local_c; do { if (((i == shapeCount - 1) || (pShapeBlock_0->x != pShapeBlock_1->x)) || (*pShapeBlock_0_y != pShapeBlock_1->y)) { // dir = 0; originBlockPos = NULL; do { innerConnection = false; j = 0; pPVar2 = shapeBlocks; pPVar1 = shapeBlocks; do { pPVar3 = pPVar1 + 1; if (((j == shapeCount - 1) || (pPVar2->x != pPVar3->x)) || (pPVar2->y != pPVar1[1].y)) { if ((pPVar2->x == *(int *)((int)&originBlockPos->x + (int)&DIRECTIONS[0].x) + pShapeBlock_0->x) && (pPVar2->y == *pShapeBlock_0_y + *(int *)((int)((int)register0x00000010 + -0x3c) + (int)originBlockPos))) { innerConnection = true; } } else { j += 1; pPVar3 = pPVar1 + 2; pPVar2 = pPVar2 + 1; } j += 1; pPVar2 = pPVar2 + 1; pPVar1 = pPVar3; } while (j < shapeCount); if (!innerConnection) { // This side of the current block is not connected to another construction tile, so we // should place a barrier. ai::AITask_DoRequest_ObjectType (LegoObject_Barrier,0,0,pShapeBlock_0,construct->handleValue, (Point2F *)((int)&originBlockPos->x + (int)&local_20.x),TRUE); construct->requestCount = construct->requestCount + 1; } originBlockPos = originBlockPos + 1; // } while (dir < 4); } while (originBlockPos < (Point2I *)&DAT_00000020); } else { // Skip one shape block i += 1; pShapeBlock_1 = pShapeBlock_1 + 1; pShapeBlock_0 = pShapeBlock_0 + 1; pShapeBlock_0_y = pShapeBlock_0_y + 2; } i += 1; pShapeBlock_1 = pShapeBlock_1 + 1; pShapeBlock_0 = pShapeBlock_0 + 1; pShapeBlock_0_y = pShapeBlock_0_y + 2; } while (i < shapeCount); } return; } // Checks if a construction zone origin exists at the specified block position. BOOL __cdecl lego::game::Construction_Zone_ExistsAtBlock(Point2I *originBlockPos) { Construction_Zone *construct; construct = Construction_Zone_FindByHandleOrAtBlock(originBlockPos,NULL); return (uint)(construct != NULL); } // `originBlockPos` or `constructHandle` must be non-null. `originBlockPos` has priority. Construction_Zone * __cdecl lego::game::Construction_Zone_FindByHandleOrAtBlock (Point2I *optor_originBlockPos,uint *optor_constructHandle) { Construction_Zone *construct; Construction_Zone **pNextConstruct; construct = globs::constructionGlobs.constructList; if (globs::constructionGlobs.constructList != NULL) { do { if (optor_originBlockPos == NULL) { if ((optor_constructHandle != NULL) && (*optor_constructHandle == construct->handleValue)) { return construct; } } else { if ((optor_originBlockPos->x == (construct->originBlockPos).x) && (optor_originBlockPos->y == (construct->originBlockPos).y)) { return construct; } } pNextConstruct = &construct->next; construct = *pNextConstruct; } while (*pNextConstruct != NULL); } return NULL; } void __cdecl lego::game::Construction_Zone_CompletePath(Point2I *originBlockPos) { Construction_Zone *construct; construct = Construction_Zone_FindByHandleOrAtBlock(originBlockPos,NULL); if (construct != NULL) { front::Interface_BackToMain_IfSelectedGroundOrConstruction_IsBlockPos(originBlockPos); Construction_Zone_ConsumePlacedResources(construct); Construction_Zone_Free(construct); } return; } void __cdecl lego::game::Construction_Zone_CancelPath(Point2I *originBlockPos) { Construction_Zone *construct; uint i; LegoObject **pPlacedObj; LiveFlags4 *pLFlags4; LegoObject *placedObj; construct = Construction_Zone_FindByHandleOrAtBlock(originBlockPos,NULL); Level_Block_SetLayedPath(originBlockPos,FALSE); // Mark all placed resources as unreserved again and request collection. i = 0; if (construct->placedCount2 != 0) { pPlacedObj = construct->placedObjects; do { placedObj = *pPlacedObj; pLFlags4 = &placedObj->flags4; *pLFlags4 = *pLFlags4 & ~LIVEOBJ4_USEDBYCONSTRUCTION; ai::AITask_DoCollect(placedObj,0.0); i += 1; pPlacedObj = pPlacedObj + 1; } while (i < construct->placedCount2); } front::Interface_BackToMain_IfSelectedGroundOrConstruction_IsBlockPos(originBlockPos); ai::AITask_Construction_FUN_00403630(construct->handleValue,FALSE,LegoObject_None,0); Construction_Zone_Free(construct); return; } void __cdecl lego::game::Construction_UpdateAll(float elapsedGame) { BOOL BVar1; Construction_Zone *construction; Construction_ZoneFlags cflags; Construction_Zone *next; construction = globs::constructionGlobs.constructList; if (globs::constructionGlobs.constructList != NULL) { do { cflags = construction->flags; next = construction->next; if (((cflags & CONSTRUCTION_FLAG_LAYPATH) == CONSTRUCTION_FLAG_NONE) || ((cflags & CONSTRUCTION_FLAG_REQUESTED) != CONSTRUCTION_FLAG_NONE)) { if ((cflags & CONSTRUCTION_FLAG_READY) != CONSTRUCTION_FLAG_NONE) { if ((cflags & CONSTRUCTION_FLAG_LAYPATH) == CONSTRUCTION_FLAG_NONE) { BVar1 = Construction_Zone_NoForeignObjectsInside(construction); if (BVar1 != 0) { Construction_Zone_ConsumePlacedResources(construction); Construction_Zone_CompleteBuilding(construction,TRUE); Construction_Zone_Free(construction); } } else { ai::AITask_DoBuildPath_AtPosition(&construction->originBlockPos); construction->flags = construction->flags & ~CONSTRUCTION_FLAG_READY; } } } else { Construction_Zone_RequestPathResources(construction); } construction = next; } while (next != NULL); } return; } BOOL __cdecl lego::game::Construction_Zone_NoForeignObjectsInside(Construction_Zone *construction) { BOOL hasForeignObj; hasForeignObj = LegoObject_RunThroughListsSkipUpgradeParts (Construction_Zone_ObjectCallback_IsForeignObjectInside,construction); return (uint)(hasForeignObj == 0); } BOOL __cdecl lego::game::Construction_Zone_ObjectCallback_IsForeignObjectInside (LegoObject *liveObj,Construction_Zone *data) { uint i; LegoObject **pPlacedObj; Point2I blockPos; uint count; LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); if (((data->originBlockPos).x == blockPos.x) && ((data->originBlockPos).y == blockPos.y)) { count = data->placedCount2; i = 0; if (count != 0) { pPlacedObj = data->placedObjects; do { if (liveObj == *pPlacedObj) break; i += 1; pPlacedObj = pPlacedObj + 1; } while (i < count); } // Object is not tracked by construction, must be foreign object. if (i == count) { return TRUE; } } return FALSE; } // Starts a construction zone for laying down a Power Path. BOOL __cdecl lego::game::Construction_Zone_StartPath(Point2I *originBlockPos) { BOOL isPath; Construction_Zone *construct; isPath = Level_Block_IsPath(originBlockPos); if (isPath == 0) { construct = Construction_Zone_Create(originBlockPos); Level_Block_SetLayedPath(originBlockPos,TRUE); construct->flags = construct->flags | CONSTRUCTION_FLAG_LAYPATH; front::Interface_BackToMain_IfSelectedGroundOrConstruction_IsBlockPos(originBlockPos); return TRUE; } return FALSE; } Construction_Zone * __cdecl lego::game::Construction_Zone_Create(Point2I *originBlockPos) { Construction_Zone *construct; int iVar1; Construction_Zone *pCVar2; construct = (Construction_Zone *)io::Mem_Alloc(0xd4); pCVar2 = construct; for (iVar1 = 0x35; iVar1 != 0; iVar1 += -1) { pCVar2->objID = 0; pCVar2 = (Construction_Zone *)&pCVar2->direction; } construct->placedCount = 0; construct->requestCount = 0; construct->handleValue = globs::constructionGlobs.nextHandleValue; globs::constructionGlobs.nextHandleValue += 1; (construct->originBlockPos).x = originBlockPos->x; (construct->originBlockPos).y = originBlockPos->y; construct->next = globs::constructionGlobs.constructList; globs::constructionGlobs.constructList = construct; return construct; } void __cdecl lego::game::Construction_PowerGrid_PowerAdjacentBlocks(Point2I *blockPos) { BOOL BVar1; Point2I *pBlockOffPos; int dir; Point2I DIRECTIONS [4]; Point2I *pBlockOffPos_; // const Point2I DIRECTIONS[4] = { // { 0, -1 }, // { 1, 0 }, // { 0, 1 }, // { -1, 0 }, // }; // // initialised to ((int*)local_20)[-2] dir = 4; pBlockOffPos_ = (Point2I *)&stack0xffffffd8; do { pBlockOffPos = pBlockOffPos_ + 1; pBlockOffPos->x = pBlockOffPos->x + blockPos->x; pBlockOffPos_[1].y = pBlockOffPos_[1].y + blockPos->y; BVar1 = Level_Block_IsPath(pBlockOffPos); if (BVar1 == 0) { BVar1 = Level_Block_IsSolidBuilding(pBlockOffPos->x,pBlockOffPos_[1].y,TRUE); if (BVar1 != 0) goto LAB_00409350; } else { LAB_00409350: // if (Level_Block_IsPath() or Level_Block_IsSolidBuilding()) BVar1 = Level_Block_IsPowered(pBlockOffPos); if (BVar1 == 0) { // Add to list, and mark as visited, so that we don't get stuck in an infinite loop. Level_PowerGrid_AddPoweredBlock(pBlockOffPos); Construction_PowerGrid_PowerAdjacentBlocks(pBlockOffPos); } } dir += -1; pBlockOffPos_ = pBlockOffPos; if (dir == 0) { return; } } while( true ); } // Returns false if a building cannot be powered. BOOL __cdecl lego::game::Construction_PowerGrid_DrainAdjacentBlocks(Point2I *blockPos,int crystalDrainedAmount) { BOOL result; result = Construction_PowerGrid_DrainAdjacentBlocks_Recurse(blockPos,crystalDrainedAmount); Level_PowerGrid_ClearDrainPowerBlocks(); return result; } BOOL __cdecl lego::game::Construction_PowerGrid_DrainAdjacentBlocks_Recurse (Point2I *blockPos,int crystalDrainedAmount) { BOOL BVar1; LegoObject *liveObj; Point2I *blockPos_00; uint i; Point2I DIRECTIONS [4]; i = 0; // const Point2I DIRECTIONS[4] = { // { 0, -1 }, // { 1, 0 }, // { 0, 1 }, // { -1, 0 }, // }; DIRECTIONS[0].x = 0; DIRECTIONS[0].y = -1; DIRECTIONS[1].x = 1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = 1; DIRECTIONS[3].x = -1; DIRECTIONS[3].y = 0; blockPos_00 = DIRECTIONS; do { blockPos_00->x = blockPos_00->x + blockPos->x; blockPos_00->y = blockPos_00->y + blockPos->y; BVar1 = Level_Block_IsGeneratePower(blockPos_00); // This condition does not check the temp drainpower flag, is it possible for this to be // hit more than once for the same tile? if (((BVar1 != 0) && (liveObj = LegoObject_FindPoweredBuildingAtBlockPos(blockPos_00), liveObj != NULL)) && (BVar1 = LegoObject_AddThisDrainedCrystals(liveObj,crystalDrainedAmount), BVar1 != 0)) { return 1; } BVar1 = Level_Block_IsPath(blockPos_00); if (((BVar1 != 0) || (BVar1 = Level_Block_IsSolidBuilding(blockPos_00->x,blockPos_00->y,TRUE), BVar1 != 0)) && (BVar1 = Level_PowerGrid_IsDrainPowerBlock(blockPos_00), BVar1 == 0)) { // Add to list, and mark as visited, so that we don't get stuck in an infinite loop. Level_PowerGrid_AddDrainPowerBlock(blockPos_00); BVar1 = Construction_PowerGrid_DrainAdjacentBlocks_Recurse(blockPos_00,crystalDrainedAmount); if (BVar1 != 0) { return TRUE; } } i += 1; blockPos_00 = blockPos_00 + 1; } while (i < 4); return FALSE; } // Internally used for Paths during `Construction_UpdateAll`. Does NOT use objID field. void __cdecl lego::game::Construction_Zone_RequestPathResources(Construction_Zone *construct) { Point2I *blockPos; BOOL BVar1; LegoObject *oreProcessingObj; uint crystalsCost; uint oreCost; uint studsCost; LegoObject_ID oreObjID; blockPos = &construct->originBlockPos; // This function always returns true. It's likely a preprocessor/removed debug setting. BVar1 = Level_IsBuildPathBoolUnk_true(blockPos); if (BVar1 != 0) { oreProcessingObj = LegoObject_FindResourceProcessingBuilding(NULL,blockPos,LegoObject_Ore,0); crystalsCost = stats::Stats_GetCostCrystal(LegoObject_Path,0,0); oreCost = stats::Stats_GetCostOre(LegoObject_Path,0,0); studsCost = stats::Stats_GetCostRefinedOre(LegoObject_Path,0,0); Construction_Zone_RequestResource(blockPos,LegoObject_PowerCrystal,0,0,crystalsCost); if ((oreProcessingObj == NULL) || (studsCost == 0)) { oreObjID = LegoObject_ID_Ore; } else { // An ore processing building exists, request studs instead of ore. oreObjID = LegoObject_ID_ProcessedOre; oreCost = studsCost; } Construction_Zone_RequestResource(blockPos,LegoObject_Ore,oreObjID,0,oreCost); construct->flags = construct->flags | CONSTRUCTION_FLAG_REQUESTED; } return; } void __cdecl lego::game::Construction_Zone_CancelBuilding(Point2I *originBlockPos) { Lego_Level *level; Construction_Zone *construct; int idx; uint i; LegoObject **pPlacedObj; uint count; LegoObject *placedObj; Point2I *shapePoints; level = globs::legoGlobs.currLevel; construct = Construction_Zone_FindByHandleOrAtBlock(originBlockPos,NULL); if ((construct != NULL) && (construct->requestCount != construct->placedCount)) { count = construct->shapeCount; i = 0; if (count != 0) { do { if (((i != count - 1) && (shapePoints = construct->shapeBlocks, shapePoints[i].x == shapePoints[i + 1].x)) && (shapePoints[i].y == shapePoints[i + 1].y)) { idx = shapePoints[i].y * level->width + shapePoints[i].x; level->blocks[idx].flags1 = level->blocks[idx].flags1 & ~BLOCK1_BUILDINGPATH; } idx = construct->shapeBlocks[i].y * level->width + construct->shapeBlocks[i].x; level->blocks[idx].flags1 = level->blocks[idx].flags1 & ~BLOCK1_FOUNDATION; level->blocks[construct->shapeBlocks[i].y * level->width + construct->shapeBlocks[i].x]. construct = NULL; Level_BlockUpdateSurface(level,construct->shapeBlocks[i].x,construct->shapeBlocks[i].y,0); front::Interface_BackToMain_IfSelectedGroundOrConstruction_IsBlockPos (construct->shapeBlocks + i); count = construct->shapeCount; i += 1; } while (i < count); } i = 0; if (construct->placedCount2 != 0) { pPlacedObj = construct->placedObjects; do { placedObj = *pPlacedObj; if (placedObj->type == LegoObject_Barrier) { placedObj->flags3 = placedObj->flags3 | LIVEOBJ3_REMOVING; (*pPlacedObj)->health = -1.0; } else { placedObj->flags4 = placedObj->flags4 & ~LIVEOBJ4_USEDBYCONSTRUCTION; ai::AITask_DoCollect(*pPlacedObj,0.0); } i += 1; pPlacedObj = pPlacedObj + 1; } while (i < construct->placedCount2); } ai::AITask_Construction_FUN_00403630(construct->handleValue,FALSE,LegoObject_None,0); Construction_Zone_Free(construct); } return; } // Starts a construction zone for a Building object. // Returns handle value to construction zone. uint __cdecl lego::game::Construction_Zone_StartBuilding (LegoObject_ID buildingObjID,Point2I *originBlockPos,Direction direction, Point2I *shapeBlocks,uint count) { bool bVar1; Lego_Level *level; Construction_Zone *construct; Point2I *pPVar2; Map3D *map; int idx; uint uVar3; Point2I *pPVar4; float mult_4_0; BlockFlags1 *bflags1; level = globs::legoGlobs.currLevel; construct = Construction_Zone_Create(originBlockPos); construct->objID = buildingObjID; construct->direction = direction; pPVar2 = (Point2I *)io::Mem_Alloc(count * 8); construct->shapeBlocks = pPVar2; pPVar4 = shapeBlocks; for (uVar3 = count * 8 >> 2; uVar3 != 0; uVar3 -= 1) { pPVar2->x = pPVar4->x; pPVar4 = (Point2I *)&pPVar4->y; pPVar2 = (Point2I *)&pPVar2->y; } mult_4_0 = 4.0; for (idx = 0; idx != 0; idx += -1) { *(undefined *)&pPVar2->x = *(undefined *)&pPVar4->x; pPVar4 = (Point2I *)((int)&pPVar4->x + 1); pPVar2 = (Point2I *)((int)&pPVar2->x + 1); } pPVar4 = construct->shapeBlocks; construct->shapeCount = count; uVar3 = count; map = lrr::Lego_GetMap(); lego::map::Map3D_FlattenShapeVertices(map,pPVar4,uVar3,mult_4_0); originBlockPos = NULL; if (count != 0) { pPVar4 = shapeBlocks + 1; do { if (((originBlockPos == (Point2I *)(count - 1)) || (shapeBlocks->x != pPVar4->x)) || (shapeBlocks->y != pPVar4->y)) { bVar1 = false; } else { bVar1 = true; bflags1 = &level->blocks[shapeBlocks->y * level->width + shapeBlocks->x].flags1; *bflags1 = *bflags1 | BLOCK1_BUILDINGPATH; level->blocks[shapeBlocks->y * level->width + shapeBlocks->x].construct = construct; } idx = shapeBlocks->y * level->width + shapeBlocks->x; level->blocks[idx].flags1 = level->blocks[idx].flags1 | BLOCK1_FOUNDATION; level->blocks[shapeBlocks->y * level->width + shapeBlocks->x].construct = construct; Level_BlockUpdateSurface(level,shapeBlocks->x,shapeBlocks->y,0); Construction_FlattenGround(shapeBlocks); front::Interface_BackToMain_IfSelectedGroundOrConstruction_IsBlockPos(shapeBlocks); pPVar2 = shapeBlocks; if (bVar1) { originBlockPos = (Point2I *)((int)&originBlockPos->x + 1); pPVar2 = shapeBlocks + 1; pPVar4 = pPVar4 + 1; } shapeBlocks = pPVar4; originBlockPos = (Point2I *)((int)&originBlockPos->x + 1); pPVar4 = shapeBlocks + 1; shapeBlocks = pPVar2 + 1; } while (originBlockPos < count); } return construct->handleValue; } void __cdecl lego::game::Construction_FlattenGround(Point2I *blockPos) { int i; Point2I ANGLES [8]; int *pAngle; // const Point2I ANGLES[8] = { // { -1, -1 }, // { 0, -1 }, // { 1, -1 }, // { 1, 0 }, // { 1, 1 }, // { 0, 1 }, // { -1, 1 }, // { -1, 0 }, // }; // // for (int i = 0; i < 8; i++) { // Level_Block_LowerDigVertices(globs::legoGlobs.level, // blockPos->x + ANGLES[i].x, // blockPos->y + ANGLES[i].y); // } i = 8; pAngle = (int *)&stack0xffffffb8; do { Level_Block_LowerRoofVertices (globs::legoGlobs.currLevel,blockPos->x + pAngle[2],pAngle[3] + blockPos->y); i += -1; pAngle = pAngle + 2; } while (i != 0); return; } void __cdecl lego::game::Construction_RemoveAll(void) { Construction_Zone *construct; Construction_Zone *next; construct = globs::constructionGlobs.constructList; if (globs::constructionGlobs.constructList != NULL) { do { next = construct->next; Construction_Zone_Free(construct); construct = next; } while (next != NULL); } return; } // Frees and removes the construction zone from the global list. void __cdecl lego::game::Construction_Zone_Free(Construction_Zone *construct) { Construction_Zone *pCVar1; Construction_Zone *pCVar2; Construction_Zone *pCVar3; pCVar1 = globs::constructionGlobs.constructList; pCVar3 = NULL; if (globs::constructionGlobs.constructList != NULL) { do { pCVar2 = pCVar1; if (pCVar2 == construct) { if (pCVar3 == NULL) { globs::constructionGlobs.constructList = pCVar2->next; } else { pCVar3->next = pCVar2->next; } break; } pCVar1 = pCVar2->next; pCVar3 = pCVar2; } while (pCVar2->next != NULL); } io::Mem_Free(construct->shapeBlocks); io::Mem_Free(construct); return; } void __cdecl lego::game::Construction_Zone_ConsumePlacedResources(Construction_Zone *construct) { uint i; LegoObject **pPlacedObj; LegoObject *placedObj; i = 0; if (construct->placedCount2 != 0) { pPlacedObj = construct->placedObjects; do { placedObj = *pPlacedObj; pPlacedObj = pPlacedObj + 1; placedObj->health = -1.0; i += 1; placedObj->flags3 = placedObj->flags3 | LIVEOBJ3_REMOVING; } while (i < construct->placedCount2); } return; } // Immediately spawns a Building object without the need of a construction zone. LegoObject * __cdecl lego::game::Construction_SpawnBuilding (LegoObject_ID objID,Point2I *originBlockPos,Direction direction,Point2I *shapeBlocks, uint shapeCount,BOOL teleportDown) { Map3D *map; LegoObject *liveObj; int iVar1; Construction_Zone *pCVar2; float mult_4_0; Construction_Zone local_construct; pCVar2 = &local_construct; for (iVar1 = 0x35; iVar1 != 0; iVar1 += -1) { pCVar2->objID = 0; pCVar2 = (Construction_Zone *)&pCVar2->direction; } local_construct.originBlockPos.x = originBlockPos->x; local_construct.originBlockPos.y = originBlockPos->y; local_construct.objID = objID; local_construct.direction = direction; mult_4_0 = 4.0; local_construct.shapeBlocks = shapeBlocks; local_construct.shapeCount = shapeCount; map = lrr::Lego_GetMap(); lego::map::Map3D_FlattenShapeVertices(map,shapeBlocks,shapeCount,mult_4_0); Construction_FlattenGround(originBlockPos); liveObj = Construction_Zone_CompleteBuilding(&local_construct,teleportDown); return liveObj; } LegoObject * __cdecl lego::game::Construction_Zone_CompleteBuilding(Construction_Zone *construct,BOOL teleportDown) { ulonglong uVar1; Map3D *map; LegoObject *liveObj; uint count; StatsFlags1 sflags1; StatsFlags2 sflags2; uint i; float xPos; uint bx; uint by; float *out_x; float *out_y; float yPos; Point2I *pShape; i = 0; xPos = 0.0; out_y = &yPos; xPos = (float)construct->direction; out_x = &xPos; by = (construct->originBlockPos).y; uVar1 = (ulonglong)(uint)xPos; bx = (construct->originBlockPos).x; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,by,out_x,out_y); // 1.570796f == (M_PI / 2.0f) liveObj = LegoObject_CreateInWorld (globs::legoGlobs.buildingData + construct->objID,LegoObject_Building, construct->objID,0,xPos,yPos,(float)uVar1 * 1.570796); if (teleportDown != 0) { LegoObject_TeleportDownBuilding(liveObj); front::Info_Send(Info_Constructed,NULL,liveObj,NULL); } count = construct->shapeCount; if (count != 0) { do { count = count - 1; if (i == count) { LAB_00409b4b: sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_TOOLSTORE) == STATS1_NONE) { front::Interface_BackToMain_IfSelectedGroundOrConstruction_IsBlockPos (construct->shapeBlocks + i); Level_Block_SetSolidBuilding(construct->shapeBlocks[i].x,construct->shapeBlocks[i].y); sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_GENERATEPOWER) != STATS2_NONE) { Level_Block_SetGeneratePower(construct->shapeBlocks + i); } Construction_DeselectAdjacentDig(construct->shapeBlocks + i); } else { Level_Block_SetToolStoreBuilding(construct->shapeBlocks + i); } ElectricFence_UpdateBlockConnections (construct->shapeBlocks[i].x,construct->shapeBlocks[i].y); } else { pShape = construct->shapeBlocks; if ((pShape[i].x != pShape[i + 1].x) || (pShape[i].y != pShape[i + 1].y)) goto LAB_00409b4b; Level_Block_SetPathBuilding(pShape[i].x,pShape[i].y); LegoObject_TryDock_AtBlockPos_FUN_004403f0(liveObj,construct->shapeBlocks + i); i += 1; } count = construct->shapeCount; i += 1; } while (i < count); } return liveObj; } // Calls `AITask_Block_DeselectDig` (@00402a10) for the 4 blocks surrounding blockPos. void __cdecl lego::game::Construction_DeselectAdjacentDig(Point2I *blockPos) { int dir; Point2I *pBlockOffPos; Point2I DIRECTIONS_I [4]; DIRECTIONS_I[0].x = 0; DIRECTIONS_I[0].y = -1; DIRECTIONS_I[1].x = 1; DIRECTIONS_I[1].y = 0; DIRECTIONS_I[2].x = 0; DIRECTIONS_I[2].y = 1; DIRECTIONS_I[3].x = -1; DIRECTIONS_I[3].y = 0; pBlockOffPos = DIRECTIONS_I; dir = 4; do { pBlockOffPos->x = pBlockOffPos->x + blockPos->x; pBlockOffPos->y = pBlockOffPos->y + blockPos->y; ai::AITask_RemoveDigReferences(pBlockOffPos,FALSE); pBlockOffPos = pBlockOffPos + 1; dir += -1; } while (dir != 0); return; } // Disables dropping resource costs for an object when teleported up. Generally used at the end of a // level. void __cdecl lego::game::Construction_DisableCryOreDrop(BOOL disabled) { globs::constructionGlobs.disableCryOreDrop = disabled; return; } // The process before directly removing a Building object. // - Unsets building tile flags. // - Disconnects efences. // - Spawns dust effects (based on flags4). // - Generates cryore drops for the build cost of the object. // etc... void __cdecl lego::game::Construction_CleanupBuildingFoundation(LegoObject *liveObj) { bool bVar1; Point2I *shapePoints; Point2I *shapeBlocks; Map3D *map; Point2I *pPVar2; Direction rotation; uint i; float10 fVar3; uint bx; uint by; Vector3F *out_x; float xPos; float *out_y; float yPos; uint shapeCount; Point2F faceDir; Point2I blockPos; Point2F worldPos; Vector3F effectWorldPos; Vector3F effectDir; Point2I *pShapeBlock; LegoObject_GetFaceDirection(liveObj,&faceDir); LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); LegoObject_GetPosition(liveObj,&worldPos.x,&worldPos.y); if (ABS(faceDir.x) <= ABS(faceDir.y)) { if ((ushort)((ushort)(faceDir.y < 0.0) << 8 | (ushort)(faceDir.y == 0.0) << 0xe) == 0) { rotation = DIRECTION_UP; } else { rotation = DIRECTION_DOWN; } } else { if ((ushort)((ushort)(faceDir.x < 0.0) << 8 | (ushort)(faceDir.x == 0.0) << 0xe) == 0) { rotation = DIRECTION_RIGHT; } else { rotation = DIRECTION_LEFT; } } shapePoints = gfx::Building_GetShapePoints (globs::legoGlobs.buildingData + liveObj->id,&shapeCount); shapeBlocks = gfx::SelectPlace_TransformShapePoints(&blockPos,shapePoints,shapeCount,rotation); i = 0; pShapeBlock = shapeBlocks; if (shapeCount != 0) { do { pPVar2 = pShapeBlock + 1; if (((i == shapeCount - 1) || (shapeBlocks->x != pPVar2->x)) || (shapeBlocks->y != pShapeBlock[1].y)) { bVar1 = false; } else { bVar1 = true; } Level_Block_UnsetBuildingTile(shapeBlocks); Level_Block_UnsetGeneratePower(shapeBlocks); if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_UNK_8) == 0) { by = shapeBlocks->y; out_y = &effectWorldPos.y; out_x = &effectWorldPos; bx = shapeBlocks->x; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,by,&out_x->x,out_y); xPos = effectWorldPos.x; yPos = effectWorldPos.y; map = lrr::Lego_GetMap(); fVar3 = lego::map::Map3D_GetWorldZ(map,xPos,yPos); effectWorldPos.z = (float)fVar3; math::Maths_Vector3DRandom(&effectDir); effectDir.z = 0.0; effect::Effect_Spawn_Particle(MISCOBJECT_PATHDUST,&effectWorldPos,&effectDir); ai::AITask_DoClearTypeAction(shapeBlocks,Message_ClearBuildingComplete); } ElectricFence_UpdateBlockConnections(shapeBlocks->x,shapeBlocks->y); if (bVar1) { i += 1; pPVar2 = pShapeBlock + 2; shapeBlocks = shapeBlocks + 1; } i += 1; shapeBlocks = shapeBlocks + 1; pShapeBlock = pPVar2; } while (i < shapeCount); } Construction_GenerateCryOreDrop(liveObj); return; } // Spawns the resource costs of an object (i.e. when a building is teleported up/destroyed). void __cdecl lego::game::Construction_GenerateCryOreDrop(LegoObject *liveObj) { uint oreCost; uint crystalsCost; Point2I blockPos; if ((liveObj->flags4 & LIVEOBJ4_CRYORECOSTDROPPED) == LIVEOBJ4_NONE) { LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); oreCost = stats::Stats_GetCostOre(LegoObject_Building,liveObj->id,liveObj->objLevel); crystalsCost = stats::Stats_GetCostCrystal(LegoObject_Building,liveObj->id,liveObj->objLevel); stats::Stats_GetCostRefinedOre(LegoObject_Building,liveObj->id,liveObj->objLevel); if (globs::constructionGlobs.disableCryOreDrop == 0) { for (; crystalsCost != 0; crystalsCost -= 1) { Level_GenerateCrystal(&blockPos,0,NULL,FALSE); } for (; oreCost != 0; oreCost -= 1) { Level_GenerateOre(&blockPos,0,NULL,FALSE); } } liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_CRYORECOSTDROPPED; } return; } // A wrapper around `LegoObject_Remove` for use with Building objects. void __cdecl lego::game::Construction_RemoveBuildingObject(LegoObject *liveObj) { bool bVar1; bool bVar2; bool bVar3; StatsFlags1 sflags1; Point2F local_8; bVar3 = false; bVar1 = false; bVar2 = false; LegoObject_GetPosition(liveObj,&local_8.x,&local_8.y); sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_SMALLTELEPORTER) != STATS1_NONE) && (globs::legoGlobs.placeDestSmallTeleporter == liveObj)) { bVar1 = true; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_BIGTELEPORTER) != STATS1_NONE) && (globs::legoGlobs.placeDestBigTeleporter == liveObj)) { bVar2 = true; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_WATERTELEPORTER) != STATS1_NONE) && (globs::legoGlobs.placeDestWaterTeleporter == liveObj)) { bVar3 = true; } if (bVar1) { globs::legoGlobs.placeDestSmallTeleporter = LegoObject_FindSmallTeleporter(&local_8); } if (bVar2) { globs::legoGlobs.placeDestBigTeleporter = LegoObject_FindBigTeleporter(&local_8); } if (bVar3) { globs::legoGlobs.placeDestWaterTeleporter = LegoObject_FindWaterTeleporter(&local_8); } LegoObject_Remove(liveObj); LegoObject_RequestPowerGridUpdate(); return; } void __cdecl lego::front::Credits_Play(char *textFile,Font *font,char *aviFile) { char *pcVar1; byte *memblock; Animation_t *anim; uint uVar2; uint uVar3; DWORD DVar4; uint lineWidth; BOOL BVar5; int iVar6; int iVar7; int startLineY; char **pLine; int iVar8; int lineY; int local_444; uint fileSize; uint scrollY; DWORD local_438; int lineCount; uint local_430; char *text; int local_428; BOOL finished; char **lines; int appCenterX; Animation_t *local_418; BOOL mslbLast; Rect2I animDestRect; char cconvBuff [1024]; lineCount = 0; scrollY = 0; finished = 0; local_438 = timeGetTime(); animDestRect.left = 0; animDestRect.top = 0; animDestRect.right = globs::mainGlobs.appWidth; animDestRect.bottom = globs::mainGlobs.appHeight; local_430 = lego::image::Font_GetHeight(font); iVar8 = globs::mainGlobs.appHeight / local_430 + 1; appCenterX = (int)globs::mainGlobs.appWidth / 2; local_428 = iVar8; std::sprintf(cconvBuff,"%s.cconv",textFile); memblock = io::File_LoadBinary(cconvBuff,&fileSize); if ((memblock != NULL) || (memblock = io::File_LoadBinary(textFile,&fileSize), memblock != NULL)) { text = (char *)io::Mem_ReAlloc(memblock,fileSize + 4); text[fileSize] = '\0'; anim = video::Animation_Load(aviFile); if (1 < (int)fileSize) { iVar6 = fileSize - 1; pcVar1 = text; do { if ((*pcVar1 == '\r') && (pcVar1[1] == '\n')) { lineCount += 1; } iVar6 += -1; pcVar1 = pcVar1 + 1; } while (iVar6 != 0); } lineCount += 1; local_418 = anim; lines = (char **)io::Mem_Alloc(lineCount * 4); util::Util_Tokenise(text,lines,"\r\n"); iVar6 = -iVar8; iVar7 = 0; local_444 = iVar6; do { // Is key pressed, or is left mouse button released? uVar2 = input::Input_AnyKeyPressed(); if ((uVar2 != 0) || ((globs::INPUT.mslb == 0 && (iVar7 != 0)))) { finished = 1; } mslbLast = globs::INPUT.mslb; video::Animation_Update(anim); // Loop animation after reaching the end. uVar2 = video::Animation_GetLength(anim); uVar3 = video::Animation_GetTime(anim); if (uVar2 <= uVar3) { video::Animation_SetTime(anim,0); } video::Animation_BlitToBackBuffer(anim,(RECT *)&animDestRect); // Update scrolling. DVar4 = timeGetTime(); iVar7 = iVar6; if (0x21 < DVar4 - local_438) { scrollY += 1; if (scrollY == local_430) { iVar7 = iVar6 + 1; scrollY = 0; local_444 = iVar7; if (iVar6 == lineCount) { iVar7 = -iVar8; local_444 = iVar7; } } uVar2 = local_438 + 0x21; local_438 = uVar2; DVar4 = timeGetTime(); if (uVar2 < DVar4) { local_438 = timeGetTime(); } } iVar6 = iVar7; if (iVar7 < lineCount) { startLineY = iVar7 * local_430; pLine = lines + iVar7; lineY = startLineY; do { iVar6 = local_444; anim = local_418; iVar8 = local_428; if (local_428 < iVar7 - local_444) break; if (-1 < iVar7) { lineWidth = lego::image::Font_GetStringWidth(font,"%s",*pLine); lego::image::Font_PrintF (font,appCenterX - (int)lineWidth / 2,(lineY - startLineY) - scrollY,"%s", *pLine); } iVar7 += 1; lineY += local_430; pLine = pLine + 1; anim = local_418; iVar8 = local_428; } while (iVar7 < lineCount); } snd::SFX_Update(1.0); BVar5 = video::Animation_IsOk(anim); if (BVar5 == 0) { main::Main_LoopUpdate(TRUE); Sleep(10); } else { main::Main_LoopUpdate(FALSE); } iVar7 = mslbLast; } while (finished == 0); if (anim != NULL) { video::Animation_Free(anim); } io::Mem_Free(lines); io::Mem_Free(text); } return; } void __cdecl lego::effect::DamageFont_Cleanup(void) { uint *puVar1; puVar1 = &globs::dmgfontGlobs.instanceTable[0].flags; do { if ((*puVar1 & 1) != 0) { *puVar1 = *puVar1 & 0xfffffffe; gfx::Container_Hide((Container *)puVar1[-7],TRUE); } puVar1 = puVar1 + 8; } while (puVar1 < globs::dependencyGlobs.table[0].numRequirements + 6); return; } void __cdecl lego::effect::DamageFont_LoadFrames(char *dirName,char *fileBaseName) { Container_Texture *pCVar1; uint uVar2; char filenameBuff [260]; char baseDirBuff [260]; uVar2 = 0; do { std::sprintf(baseDirBuff,"%s\\",dirName); if (fileBaseName == NULL) { std::sprintf(filenameBuff,"%i.bmp",uVar2); } else { std::sprintf(filenameBuff,"%s%i.bmp",fileBaseName); } if (uVar2 == 10) { globs::dmgfontGlobs.fontTextMinus = gfx::Mesh_LoadTexture(baseDirBuff,filenameBuff,NULL,NULL); } else { pCVar1 = gfx::Mesh_LoadTexture(baseDirBuff,filenameBuff,NULL,NULL); globs::dmgfontGlobs.fontTextDigitsTable[uVar2] = pCVar1; } uVar2 += 1; } while (uVar2 < 0xb); return; } void __cdecl lego::effect::DamageFont_DisplayDamage_OverLiveObject(LegoObject *liveObj,uint displayNumber) { BOOL BVar1; DamageFontData *healthFont; Container *pCVar2; Mesh *pMVar3; int iVar4; float10 fVar5; uint local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_18 = 0; local_14 = 2; local_10 = 1; local_c = 0; local_8 = 3; local_4 = 2; BVar1 = front::DamageFont_LiveObject_CheckCanShowDamage_Unk(liveObj); if ((((BVar1 != 0) && (displayNumber != 0)) && (displayNumber < 999)) && (healthFont = DamageFont_GetNextFree(), healthFont != NULL)) { healthFont->timerUp = 0.0; healthFont->float_10 = 0.0; healthFont->float_c = 0.0; fVar5 = stats::StatsObject_GetCollHeight(liveObj); healthFont->timerDown = (float)-fVar5; if (healthFont->ownerCont == NULL) { pCVar2 = game::LegoObject_GetActivityContainer(liveObj); pCVar2 = gfx::Container_Create(pCVar2); healthFont->ownerCont = pCVar2; pMVar3 = gfx::Mesh_CreateOnFrame (pCVar2->activityFrame,DamageFont_MeshRenderCallback,0x3000,healthFont, Mesh_Type_Norm); healthFont->mesh = pMVar3; iVar4 = 4; do { gfx::Mesh_AddGroup(healthFont->mesh,4,2,3,&local_18); iVar4 += -1; } while (iVar4 != 0); } else { pCVar2 = game::LegoObject_GetActivityContainer(liveObj); gfx::Container_SetParent(healthFont->ownerCont,pCVar2); gfx::Container_Hide(healthFont->ownerCont,0); } DamageFont_SetDisplayNumber(healthFont,displayNumber); } return; } DamageFontData * __cdecl lego::effect::DamageFont_GetNextFree(void) { DamageFontData *pDVar1; pDVar1 = globs::dmgfontGlobs.instanceTable; do { if ((*(byte *)&pDVar1->flags & 1) == 0) { pDVar1->flags = pDVar1->flags | 1; return pDVar1; } pDVar1 = pDVar1 + 1; } while (pDVar1 < (DamageFontData *)&DAT_004b9bc4); return NULL; } void __cdecl lego::effect::DamageFont_SetDisplayNumber(DamageFontData *healthFont,uint displayNumber) { uint uVar1; D3DRMGroupIndex DVar2; D3DRMGroupIndex groupID; Mesh *mesh; float r; float g; D3DRMGroupIndex local_4; DVar2 = D3DRMGROUP_0; local_4 = D3DRMGROUP_0; groupID = D3DRMGROUP_0; do { if (displayNumber < 5) { gfx::Mesh_SetGroupColour(healthFont->mesh,groupID,0.0,1.0,0.0,Mesh_Colour_Diffuse); mesh = healthFont->mesh; g = 1.0; r = 0.0; } else { if (displayNumber < 10) { gfx::Mesh_SetGroupColour(healthFont->mesh,groupID,1.0,1.0,0.0,Mesh_Colour_Diffuse); mesh = healthFont->mesh; g = 1.0; r = 1.0; } else { gfx::Mesh_SetGroupColour(healthFont->mesh,groupID,1.0,0.25,0.0,Mesh_Colour_Diffuse); mesh = healthFont->mesh; g = 0.25; r = 1.0; } } gfx::Mesh_SetGroupColour(mesh,groupID,r,g,0.0,Mesh_Colour_Emissive); groupID += 1; } while (groupID < 4); uVar1 = 1; if (displayNumber != 0) { do { DVar2 += 1; uVar1 *= 10; local_4 = DVar2; } while (uVar1 <= displayNumber); } DVar2 = D3DRMGROUP_0; if (local_4 != D3DRMGROUP_0) { do { gfx::Mesh_SetGroupTexture (healthFont->mesh,DVar2,globs::dmgfontGlobs.fontTextDigitsTable[displayNumber % 10]) ; gfx::Mesh_HideGroup(healthFont->mesh,DVar2,FALSE); displayNumber = (displayNumber - displayNumber % 10) / 10; DVar2 += 1; } while (DVar2 < local_4); } gfx::Mesh_SetGroupTexture(healthFont->mesh,DVar2,globs::dmgfontGlobs.fontTextMinus); for (DVar2 = local_4 + 1; DVar2 < 4; DVar2 += 1) { gfx::Mesh_HideGroup(healthFont->mesh,DVar2,TRUE); } healthFont->groupCount = local_4 + 1; return; } void __cdecl lego::effect::DamageFont_MeshRenderCallback(Mesh *mesh,DamageFontData *healthFont,Viewport *view) { float fVar1; float fVar2; float fVar3; float fVar4; Container *cont; Container *cont_00; D3DRMGroupIndex groupID; float local_88; Vector3F local_80; float local_74; float local_70; float local_6c; Vector3F local_68; Vector3F local_5c; float local_50; float local_4c; float local_48; float local_44; float local_40; float local_3c; float local_38; float local_34; float local_30; Point2F local_2c; undefined4 local_24; undefined4 local_20; undefined4 local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; Vector3F local_c; local_2c.x = 0.0; local_2c.y = 0.0; local_24 = 0x3f800000; local_20 = 0; local_1c = 0x3f800000; local_18 = 0x3f800000; local_14 = 0; local_10 = 0x3f800000; cont = lrr::Lego_GetCurrentViewLight(); fVar1 = healthFont->timerUp * 0.06666667; gfx::Container_SetOrientation(healthFont->ownerCont,NULL,0.0,0.0,1.0,0.0,1.0,0.0); cont_00 = lego::view::Viewport_GetCamera(view); gfx::Container_GetOrientation(cont_00,NULL,&local_68,&local_80); gfx::Container_GetPosition(cont,NULL,&local_c); fVar2 = local_80.y * local_68.z; fVar3 = local_80.z * local_68.y; fVar4 = local_80.z * local_68.x; local_68.z = local_80.x * local_68.z; local_68.y = local_80.x * local_68.y; local_68.x = local_80.y * local_68.x; local_6c = ((fVar1 + fVar1) - -1.0) * 3.0; local_80.x = local_6c * local_80.x; local_80.y = local_6c * local_80.y; local_88 = 1.0 - (float)(ulonglong)healthFont->groupCount * 0.5; local_80.z = local_6c * local_80.z; local_74 = local_6c * (fVar2 - fVar3); groupID = D3DRMGROUP_0; local_70 = local_6c * (fVar4 - local_68.z); local_6c = local_6c * (local_68.y - local_68.x); if (healthFont->groupCount != 0) { do { local_5c.x = healthFont->float_c - local_88 * local_74; local_5c.y = healthFont->float_10 - local_88 * local_70; local_5c.z = healthFont->timerDown - local_88 * local_6c; local_50 = local_74 + local_5c.x; local_4c = local_70 + local_5c.y; local_48 = local_6c + local_5c.z; local_38 = local_80.x + local_5c.x; local_34 = local_80.y + local_5c.y; local_44 = local_80.x + local_50; local_30 = local_80.z + local_5c.z; local_40 = local_80.y + local_4c; local_3c = local_80.z + local_48; gfx::Mesh_SetVertices_PointNormalAt(healthFont->mesh,groupID,0,4,&local_5c,&local_c,&local_2c) ; local_88 = local_88 - -1.0; groupID += 1; } while (groupID < healthFont->groupCount); } return; } void __cdecl lego::effect::DamageFont_UpdateAll(float elapsedAbs) { DamageFontData *healthFont; healthFont = globs::dmgfontGlobs.instanceTable; do { if ((*(byte *)&healthFont->flags & 1) != 0) { DamageFont_UpdateSingle(healthFont,elapsedAbs); } healthFont = healthFont + 1; } while (healthFont < (DamageFontData *)&DAT_004b9bc4); return; } void __cdecl lego::effect::DamageFont_UpdateSingle(DamageFontData *healthFont,float elapsedAbs) { float fVar1; D3DRMGroupIndex groupID; if (healthFont->timerUp < 15.0) { healthFont->float_c = healthFont->float_c + 0.0; groupID = D3DRMGROUP_0; healthFont->float_10 = healthFont->float_10 + 0.0; healthFont->timerDown = elapsedAbs * -1.0 + healthFont->timerDown; fVar1 = healthFont->timerUp; if (healthFont->groupCount != 0) { do { gfx::Mesh_SetGroupMaterialValues (healthFont->mesh,groupID,1.0 - fVar1 * 0.06666667,Mesh_Colour_Alpha); groupID += 1; } while (groupID < healthFont->groupCount); } healthFont->timerUp = elapsedAbs + healthFont->timerUp; return; } healthFont->flags = healthFont->flags & 0xfffffffe; gfx::Container_Hide(healthFont->ownerCont,TRUE); return; } BOOL __cdecl lego::front::DamageFont_LiveObject_CheckCanShowDamage_Unk(LegoObject *liveObj) { StatsFlags2 SVar1; SVar1 = stats::StatsObject_GetStatsFlags2(liveObj); if ((((SVar1 & STATS2_DONTSHOWDAMAGE) == STATS2_NONE) && (liveObj->type != LegoObject_Dynamite)) && (liveObj->type != LegoObject_OohScary)) { return TRUE; } return 0; } void __cdecl lego::debug::Dependencies_SetEnabled(BOOL on) { globs::dependencyGlobs.disabled = (uint)(on == 0); return; } void __cdecl lego::game::Dependencies_Reset_ClearAllLevelFlags_10c(void) { DependencyFlags *pFlags; int objLevel; DependencyFlags *pDVar1; int objIndex; pDVar1 = globs::dependencyGlobs.table[0].levelFlags; do { objIndex = 0xf; do { objLevel = 0x10; pFlags = pDVar1; do { objLevel += -1; *pFlags = *pFlags & ~(DEPENDENCY_FLAG_UNK_4|DEPENDENCY_FLAG_UNK_8|DEPENDENCY_FLAG_UNK_100); pFlags = pFlags + 1; } while (objLevel != 0); pDVar1 = pDVar1 + 0x31; objIndex += -1; } while (objIndex != 0); } while (pDVar1 < globs::effectGlobs.rockFallEffects[0].xBlockPosTable + 2); return; } void __cdecl lego::game::Dependencies_Initialise(Config *config,char *gameName) { char *pcVar1; Config *prop; int numParts; BOOL BVar2; int cmp; int objLevel; DependencyFlags *pFlags; uint uVar3; DependencyRequirement *pDVar4; int requireObjLevel; char **pRequirePart; uint size; int objIndex; int requireObjIndex; LegoObject_Type requireObjType; uint numRequired; char *targetParts [3]; char *requireObjParts [2]; char *requireParts [10]; pcVar1 = cfg::Config_BuildStringID(gameName,"Dependencies",0); for (prop = cfg::Config_FindArray(config,pcVar1); prop != NULL; prop = cfg::Config_GetNextItem(prop)) { numParts = util::Util_Tokenise(prop->key,targetParts,":"); BVar2 = lrr::Lego_GetObjectByName (targetParts[1],(LegoObject_Type *)&gameName,(LegoObject_ID *)&objIndex,NULL); if (BVar2 != 0) { cmp = std::_stricmp(targetParts[0],"HitOnceStay"); if (numParts == 3) { objLevel = std::atoi(targetParts[2]); stats::Stats_GetLevels((LegoObject_Type)gameName,objIndex); if (cmp == 0) { globs::dependencyGlobs.table[(int)gameName][objIndex].levelFlags[objLevel] = globs::dependencyGlobs.table[(int)gameName][objIndex].levelFlags[objLevel] | DEPENDENCY_FLAG_HITONCESTAY; } globs::dependencyGlobs.table[(int)gameName][objIndex].manualLevel = TRUE; } else { objLevel = 0; if (cmp == 0) { numParts = 0x10; pFlags = globs::dependencyGlobs.table[(int)gameName][objIndex].levelFlags; do { numParts += -1; *pFlags = *pFlags | DEPENDENCY_FLAG_HITONCESTAY; pFlags = pFlags + 1; } while (numParts != 0); } globs::dependencyGlobs.table[(int)gameName][objIndex].manualLevel = FALSE; } uVar3 = util::Util_Tokenise(prop->value,requireParts,","); numParts = objIndex; pcVar1 = gameName; size = uVar3 << 4; pDVar4 = (DependencyRequirement *)io::Mem_Alloc(size); globs::dependencyGlobs.table[(int)pcVar1][numParts].requirements[objLevel] = pDVar4; globs::dependencyGlobs.table[(int)pcVar1][numParts].numRequirements[objLevel] = uVar3; if (uVar3 != 0) { pRequirePart = requireParts; numRequired = uVar3; do { numParts = util::Util_Tokenise(*pRequirePart,requireObjParts,":"); BVar2 = lrr::Lego_GetObjectByName (requireObjParts[0],&requireObjType,(LegoObject_ID *)&requireObjIndex, NULL); if (BVar2 != 0) { // [objType][objIndex].requirements[objLevel][i].objType = requireObjType; // [objType][objIndex].requirements[objLevel][i].objIndex = requireObjIndex; *(LegoObject_Type *) ((int)&globs::dependencyGlobs.table[(int)gameName][objIndex].requirements[objLevel][-1] .objType + size) = requireObjType; *(int *)((int)globs::dependencyGlobs.table[(int)gameName][objIndex].requirements [objLevel] + (size - 0xc)) = requireObjIndex; if (numParts == 2) { requireObjLevel = std::atoi(requireObjParts[1]); stats::Stats_GetLevels(requireObjType,requireObjIndex); // [objType][objIndex].requirements[objLevel][i].objLevel = requireObjlevel; // [objType][objIndex].requirements[objLevel][i].hasLevel = TRUE; *(int *)((int)globs::dependencyGlobs.table[(int)gameName][objIndex].requirements [objLevel] + (size - 8)) = requireObjLevel; *(undefined4 *) ((int)globs::dependencyGlobs.table[(int)gameName][objIndex].requirements[objLevel] + (size - 4)) = TRUE; } else { // [objType][objIndex].requirements[objLevel][i].hasLevel = FALSE; *(undefined4 *) ((int)globs::dependencyGlobs.table[(int)gameName][objIndex].requirements[objLevel] + (size - 4)) = FALSE; } } pRequirePart = pRequirePart + 1; size -= 0x10; numRequired -= 1; } while (numRequired != 0); } } } Dependencies_Prepare_Unk(); return; } BOOL __cdecl lego::game::Dependencies_Object_FUN_0040add0 (LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { BOOL BVar1; int iVar2; LegoObject_Type LVar3; DependencyFlags dflags; DependencyFlags *pDFlags; if (globs::dependencyGlobs.disabled == 0) { pDFlags = globs::dependencyGlobs.table[objType][objID].levelFlags + objLevel; if ((*(byte *)(globs::dependencyGlobs.table[objType][objID].levelFlags + objLevel) & DEPENDENCY_FLAG_UNK_2) == 0) { Dependencies_Object_GetRequirements (objType,objID,objLevel,(DependencyRequirement **)&objID,&objType); LVar3 = LegoObject_None; if (objType != LegoObject_None) { iVar2 = 0; do { BVar1 = LegoObject_RunThroughListsSkipUpgradeParts (Dependencies_LiveObject_CallbackCheck_FUN_0040ae70, (void *)(objID + iVar2)); if (BVar1 == 0) { return FALSE; } LVar3 += LegoObject_Vehicle; iVar2 += 0x10; } while (LVar3 < objType); } dflags = *pDFlags; if ((dflags & DEPENDENCY_FLAG_HITONCESTAY) != DEPENDENCY_FLAG_NONE) { *pDFlags = dflags | DEPENDENCY_FLAG_UNK_2; } } } return TRUE; } BOOL __cdecl lego::game::Dependencies_LiveObject_CallbackCheck_FUN_0040ae70 (LegoObject *liveObj,LegoObject *otherObj) { BOOL BVar1; BVar1 = LegoObject_CanStoredObjectTypeBeSpawned(otherObj->type); if (BVar1 == 0) { if (otherObj->type != liveObj->type) { return 0; } if (otherObj->id != liveObj->id) { return 0; } if ((otherObj->vehicle != NULL) && ((char *)liveObj->objLevel < otherObj->customName)) { return 0; } } return TRUE; } void __cdecl lego::game::Dependencies_Object_GetRequirements (LegoObject_Type objType,LegoObject_ID objID,uint objLevel, DependencyRequirement **out_requirements,uint *out_count) { if (globs::dependencyGlobs.table[objType][objID].manualLevel != 0) { *out_requirements = globs::dependencyGlobs.table[objType][objID].requirements[objLevel]; *out_count = globs::dependencyGlobs.table[objType][objID].numRequirements[objLevel]; return; } *out_requirements = globs::dependencyGlobs.table[objType][objID].requirements[0]; *out_count = globs::dependencyGlobs.table[objType][objID].numRequirements[0]; return; } void __cdecl lego::game::Dependencies_Object_Unlock (LegoObject_Type objType,LegoObject_ID objID,uint objLevel,DependencyUnlocks *unlocks) { DependencyUnlocks *pDVar1; int objIndexOff; uint reqIdx; uint objIndex_00; LegoObject_Type objType_00; uint numRequirements; uint *local_8; uint local_4; pDVar1 = unlocks; local_8 = (uint *)&globs::dependencyGlobs.table[0].manualLevel; objType_00 = LegoObject_None; unlocks->count = 0; do { objIndex_00 = 0; do { if (*local_8 == 0) { Dependencies_Object_GetRequirements (objType_00,objIndex_00,0,(DependencyRequirement **)&unlocks,&numRequirements); reqIdx = 0; if (numRequirements != 0) { objIndexOff = 0; do { if (((*(LegoObject_Type *)((int)unlocks->objTypes + objIndexOff) == objType) && (*(LegoObject_ID *)((int)unlocks->objTypes + objIndexOff + 4) == objID)) && ((*(int *)((int)unlocks->objTypes + objIndexOff + 0xc) == 0 || (*(uint *)((int)unlocks->objTypes + objIndexOff + 8) == objLevel)))) { pDVar1->objTypes[pDVar1->count] = objType_00; pDVar1->objIDs[pDVar1->count] = objIndex_00; pDVar1->objHasLevels[pDVar1->count] = FALSE; pDVar1->count = pDVar1->count + 1; } reqIdx += 1; objIndexOff += 0x10; } while (reqIdx < numRequirements); } } else { reqIdx = 0; do { Dependencies_Object_GetRequirements (objType_00,objIndex_00,reqIdx,(DependencyRequirement **)&unlocks, &numRequirements); objIndexOff = 0; local_4 = 0; if (numRequirements != 0) { do { if (((*(LegoObject_Type *)((int)unlocks->objTypes + objIndexOff) == objType) && (*(LegoObject_ID *)((int)unlocks->objTypes + objIndexOff + 4) == objID)) && ((*(int *)((int)unlocks->objTypes + objIndexOff + 0xc) == 0 || (*(uint *)((int)unlocks->objTypes + objIndexOff + 8) == objLevel)))) { pDVar1->objTypes[pDVar1->count] = objType_00; pDVar1->objIDs[pDVar1->count] = objIndex_00; pDVar1->objLevels[pDVar1->count] = reqIdx; pDVar1->objHasLevels[pDVar1->count] = TRUE; pDVar1->count = pDVar1->count + 1; } objIndexOff += 0x10; local_4 += 1; } while (local_4 < numRequirements); } reqIdx += 1; } while (reqIdx < 0x10); } objIndex_00 += 1; local_8 = local_8 + 0x31; } while (objIndex_00 < 0xf); objType_00 += LegoObject_Vehicle; } while (local_8 < globs::effectGlobs.rockFallEffects[0].xBlockPosTable + 1); return; } void __cdecl lego::game::Dependencies_Prepare_Unk(void) { BOOL BVar1; DependencyFlags flags; LegoObject_ID objID; uint objTypeOff; uint objLevel; LegoObject_Type objType; DependencyFlags *pFlags; objTypeOff = 0; objType = LegoObject_None; do { objID = 0; do { objLevel = 0; do { if ((objLevel == 1) && (globs::dependencyGlobs.table[objID + objTypeOff].manualLevel != 0)) break; pFlags = globs::dependencyGlobs.table[objID + objTypeOff].levelFlags + objLevel; if ((*(byte *)(globs::dependencyGlobs.table[objID + objTypeOff].levelFlags + objLevel) & DEPENDENCY_FLAG_UNK_8) == 0) { BVar1 = Dependencies_Object_FUN_0040add0(objType,objID,objLevel); flags = *pFlags; if (BVar1 == 0) { if ((flags & DEPENDENCY_FLAG_UNK_4) != DEPENDENCY_FLAG_NONE) goto LAB_0040b14c; } else { if ((flags & DEPENDENCY_FLAG_UNK_4) == DEPENDENCY_FLAG_NONE) { flags |= DEPENDENCY_FLAG_UNK_4; } else { LAB_0040b14c: flags = flags & ~DEPENDENCY_FLAG_UNK_4 | DEPENDENCY_FLAG_UNK_8; } *pFlags = flags; } } objLevel += 1; } while (objLevel < 0x10); objID += 1; } while (objID < 0xf); objTypeOff += 0xf; objType += LegoObject_Vehicle; if (299 < objTypeOff) { return; } } while( true ); } BOOL __cdecl lego::game::Dependencies_Object_IsLevelFlag4 (LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { if (globs::dependencyGlobs.table[objType][objID].manualLevel != 0) { return globs::dependencyGlobs.table[objType][objID].levelFlags[objLevel] & DEPENDENCY_FLAG_UNK_4 ; } return globs::dependencyGlobs.table[objType][objID].levelFlags[0] & DEPENDENCY_FLAG_UNK_4; } void __cdecl lego::game::Dependencies_Object_AddLevelFlag_100 (LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { globs::dependencyGlobs.table[objType][objID].levelFlags[objLevel] = globs::dependencyGlobs.table[objType][objID].levelFlags[objLevel] | DEPENDENCY_FLAG_UNK_100; return; } BOOL __cdecl lego::game::Dependencies_Object_GetLevelFlag_100 (LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { return globs::dependencyGlobs.table[objType][objID].levelFlags[objLevel] & DEPENDENCY_FLAG_UNK_100 ; } Detail_TextureSet * __cdecl lego::map::Detail_LoadTextureSet(char *textureBaseName,uint width,uint height) { Detail_TextureSet *buffer; Container_Texture **gridSurfaces; Container_Texture *texture; uint y; uint x; int xyPtrOffset; int yPtrOffset; char buff [1024]; buffer = (Detail_TextureSet *)io::Mem_Alloc(0xc); y = 0; if (buffer != NULL) { gridSurfaces = (Container_Texture **)io::Mem_Alloc(height * width * 4); buffer->gridSurfaces = gridSurfaces; if (gridSurfaces == NULL) { io::Mem_Free(buffer); buffer = NULL; } else { (buffer->gridSize).width = width; (buffer->gridSize).height = height; if (height != 0) { yPtrOffset = 0; do { x = 0; xyPtrOffset = yPtrOffset; if (width != 0) { do { std::sprintf(buff,"%s%0.1x%0.1x.bmp",textureBaseName,x,y); texture = gfx::Container_LoadTexture2(buff,TRUE,NULL,NULL); x += 1; *(Container_Texture **)((int)buffer->gridSurfaces + xyPtrOffset) = texture; xyPtrOffset = xyPtrOffset + 4; } while (x < width); } y += 1; yPtrOffset += width * 4; } while (y < height); return buffer; } } } return buffer; } void __cdecl lego::map::Detail_FreeTextureSet(Detail_TextureSet *textureSet) { uint width; uint y; uint x; y = 0; if ((textureSet->gridSize).height != 0) { do { width = (textureSet->gridSize).width; x = 0; if (width != 0) { do { gfx::Container_FreeTexture(textureSet->gridSurfaces[y * width + x]); width = (textureSet->gridSize).width; x += 1; } while (x < width); } y += 1; } while (y < (uint)(textureSet->gridSize).height); } io::Mem_Free(textureSet->gridSurfaces); io::Mem_Free(textureSet); return; } // Something about calculating the distance/visibility of a wall from the viewport. I think. float10 __cdecl lego::map::Detail_FUN_0040b3a0 (Vector3F *vertPoses,Viewport *view,Point2F *viewportSize,BOOL param_4) { float *pVec3_Y; float *pVec4_Z; int i; Vector4F *pTransform; Vector3F *pVec3; float10 fVar1; float10 fVar2; float local_78; Vector3F local_70 [4]; Vector4F transforms [4]; local_78 = 1.0; // NOTE: For all comments in loops, assume i is incremented from 0 till 4. i = 4; pTransform = transforms; pVec3 = local_70; do { // Viewport_Transform(view, &transforms[i], &vertPoses[i]); lego::view::Viewport_Transform (view,pTransform,(Vector3F *)(((int)vertPoses - (int)local_70) + (int)pVec3)); i += -1; // The z field is never written to. This is effectively a Point2F array. pVec3->x = pTransform->x / pTransform->w; pVec3->y = pTransform->y / pTransform->w; pTransform = pTransform + 1; pVec3 = pVec3 + 1; } while (i != 0); if (param_4 == 0) { pVec4_Z = &transforms[0].z; pVec3_Y = &local_70[0].y; i = 4; do { // if ((pVec3->x >= 0.0f) || (pVec3->x > param_3->x) || // (pVec3->y >= 0.0f) || (pVec3->y > param_3->y) || // (transforms[i]->z > transforms[i]->w) || (transforms[i]->z < 0.0f)) // { // local_78 -= 0.25f; // } // // if (pVec3->x >= 0.0f) if (0.0 <= pVec3_Y[-1]) { // if (pVec3->y >= 0.0f) if (0.0 <= *pVec3_Y) { // if (pVec3->x > param_3->x) if ((ushort)((ushort)(pVec3_Y[-1] < viewportSize->x) << 8 | (ushort)(pVec3_Y[-1] == viewportSize->x) << 0xe) == 0) { local_78 = local_78 - 0.25; } else { // if (pVec3->y > param_3->y) if ((ushort)((ushort)(*pVec3_Y < viewportSize->y) << 8 | (ushort)(*pVec3_Y == viewportSize->y) << 0xe) == 0) { local_78 = local_78 - 0.25; } else { // if ((transforms[i]->z > transforms[i]->w) || (transforms[i]->z < 0.0f)) if (((ushort)((ushort)(*pVec4_Z < pVec4_Z[1]) << 8 | (ushort)(*pVec4_Z == pVec4_Z[1]) << 0xe) == 0) || (*pVec4_Z < 0.0)) { local_78 = local_78 - 0.25; } } } } else { local_78 = local_78 - 0.25; } } else { local_78 = local_78 - 0.25; } pVec3_Y = pVec3_Y + 3; pVec4_Z = pVec4_Z + 4; i += -1; } while (i != 0); } // if (local_78 <= 0.0) if ((ushort)((ushort)(local_78 < 0.0) << 8 | (ushort)(local_78 == 0.0) << 0xe) != 0) { return (float10)0.0; } // fVar1 = Maths_TriangleAreaZ(&local_70[2], &local_70[1], &local_70[0], FALSE); // fVar2 = Maths_TriangleAreaZ(&local_70[0], &local_70[3], &local_70[2], FALSE); fVar1 = math::Maths_TriangleAreaZ(local_70 + 2,local_70 + 1,local_70,FALSE); fVar2 = math::Maths_TriangleAreaZ(local_70,local_70 + 3,local_70 + 2,FALSE); return (fVar2 + (float10)(float)fVar1) * (float10)local_78; } Detail_Mesh * __cdecl lego::map::Detail_LoadMeshes (Container *cont,char *meshName_a,char *meshName_b,float blockSize, Detail_TextureSet *textureSet) { Detail_Mesh *detailMesh; Container *pCVar1; Vertex *out_retArray; float *pfVar2; int iVar3; float fVar4; Container *(*papCVar5) [100]; Detail_Mesh *pDVar6; uint uVar7; Container *(*papCVar8) [100]; if (meshName_b == NULL) { meshName_b = meshName_a; } detailMesh = (Detail_Mesh *)io::Mem_Alloc(0x340); if (detailMesh != NULL) { pCVar1 = gfx::Container_Load(cont,meshName_a,"LWO:NOTEXTURE",TRUE); detailMesh->promesh_ab[0] = pCVar1; if (pCVar1 != NULL) { pCVar1 = gfx::Container_Load(cont,meshName_b,"LWO:NOTEXTURE",TRUE); detailMesh->promesh_ab[1] = pCVar1; if (pCVar1 == NULL) { pCVar1 = gfx::Container_Load(cont,meshName_a,"LWO:NOTEXTURE",TRUE); detailMesh->promesh_ab[1] = pCVar1; } fVar4 = blockSize * 0.01; detailMesh->cloneCount = 0; detailMesh->BlockSize = blockSize; detailMesh->textureSet = textureSet; papCVar5 = detailMesh->clones_ab; // = 2 blockSize = 2.802597e-45; pDVar6 = detailMesh; do { gfx::Container_Mesh_Scale(pDVar6->promesh_ab[0],fVar4,fVar4,fVar4); gfx::Container_Mesh_SetPerspectiveCorrection(pDVar6->promesh_ab[0],D3DRMGROUP_0,TRUE); gfx::Container_Hide(pDVar6->promesh_ab[0],TRUE); papCVar8 = papCVar5; for (iVar3 = 100; iVar3 != 0; iVar3 += -1) { (*papCVar8)[0] = NULL; papCVar8 = (Container *(*) [100])(*papCVar8 + 1); } pDVar6 = (Detail_Mesh *)(pDVar6->promesh_ab + 1); papCVar5 = papCVar5[1]; blockSize = (float)((int)blockSize + -1); } while (blockSize != 0.0); uVar7 = 0; do { gfx::Container_Mesh_GetGroup (detailMesh->promesh_ab[uVar7],D3DRMGROUP_0,(uint *)&blockSize,NULL,NULL,NULL,NULL ); out_retArray = (Vertex *)io::Mem_Alloc((int)blockSize * 0x24); gfx::Container_Mesh_GetVertices (detailMesh->promesh_ab[uVar7],D3DRMGROUP_0,0,(uint)blockSize,out_retArray); fVar4 = 0.0; if (blockSize != 0.0) { pfVar2 = &out_retArray->tv; do { if (uVar7 != 0) { pfVar2[-1] = 1.0 - pfVar2[-1]; *pfVar2 = 1.0 - *pfVar2; } fVar4 = (float)((int)fVar4 + 1); pfVar2 = pfVar2 + 9; } while ((uint)fVar4 < (uint)blockSize); } gfx::Container_Mesh_SetVertices (detailMesh->promesh_ab[uVar7],D3DRMGROUP_0,0,(uint)blockSize,out_retArray); io::Mem_Free(out_retArray); uVar7 += 1; } while (uVar7 < 2); return detailMesh; } io::Mem_Free(detailMesh); } return NULL; } void __cdecl lego::map::Detail_FreeMesh(Detail_Mesh *detailMesh) { Detail_Mesh *pDVar1; int i; if (detailMesh != NULL) { Detail_RemoveMesh_FUN_0040b740(detailMesh); i = 2; pDVar1 = detailMesh; do { gfx::Container_Remove(pDVar1->promesh_ab[0]); pDVar1 = (Detail_Mesh *)(pDVar1->promesh_ab + 1); i += -1; } while (i != 0); io::Mem_Free(detailMesh); } return; } void __cdecl lego::map::Detail_RemoveMesh_FUN_0040b740(Detail_Mesh *detailMesh) { int iVar1; Container *(*papCVar2) [100]; int iVar3; detailMesh->cloneCount = 0; papCVar2 = detailMesh->clones_ab; iVar1 = 2; do { iVar3 = 100; do { if ((*papCVar2)[0] != NULL) { gfx::Container_Remove((*papCVar2)[0]); (*papCVar2)[0] = NULL; } papCVar2 = (Container *(*) [100])(*papCVar2 + 1); iVar3 += -1; } while (iVar3 != 0); iVar1 += -1; } while (iVar1 != 0); return; } Container_Texture * __cdecl lego::map::Detail_GetTexture(Detail_TextureSet *textureSet,SurfaceTexture coord_4X_0Y) { if (textureSet != NULL) { return textureSet->gridSurfaces [(coord_4X_0Y & 0xf) * (textureSet->gridSize).width + (uint)(coord_4X_0Y >> 4)]; } return NULL; } void __cdecl lego::map::Detail_FUN_0040b7b0 (Detail_Mesh *detailMesh,Vector3F *vectPoses4,SurfaceTexture texture,byte direction, float scaleZ,float brightness) { float blockSize; Container_Texture *contTexture; Container *cont; uint d2; Container **pContClone; uint i_; uint i; Container *contClones [2]; int VERT_INDEXES [4] [3]; uint d1; if (detailMesh != NULL) { blockSize = detailMesh->BlockSize; // VERT_INDEXES[direction][3] // // VERT_INDEXES = { // { 3, 0, 2 }, // { 0, 1, 3 }, // { 1, 2, 0 }, // { 2, 3, 1 }, // } VERT_INDEXES[0][2] = 2; VERT_INDEXES[2][1] = 2; VERT_INDEXES[3][0] = 2; VERT_INDEXES[0][0] = 3; VERT_INDEXES[1][2] = 3; VERT_INDEXES[3][1] = 3; VERT_INDEXES[0][1] = 0; VERT_INDEXES[1][0] = 0; VERT_INDEXES[1][1] = 1; VERT_INDEXES[2][0] = 1; VERT_INDEXES[2][2] = 0; VERT_INDEXES[3][2] = 1; contTexture = Detail_GetTexture(detailMesh->textureSet,texture); pContClone = contClones; i_ = 0; do { // Container_Clone(detailMesh->promesh_ab[(i/100)]) cont = gfx::Container_Clone (*(Container **)(((int)detailMesh - (int)contClones) + (int)pContClone)); // detailMesh->clones_ab[(i/100)][detailMesh->cloneCount] detailMesh->clones_ab[i_ + detailMesh->cloneCount] = cont; i = i_ + 100; *pContClone = detailMesh->clones_ab[i_ + detailMesh->cloneCount]; pContClone = pContClone + 1; i_ = i; } while (i < 200); d1 = (uint)direction; Detail_Sub1_Transform (contClones[0],blockSize,vectPoses4 + VERT_INDEXES[d1][0], vectPoses4 + VERT_INDEXES[d1][1],vectPoses4 + VERT_INDEXES[d1][2],scaleZ,brightness, contTexture,DETAIL_TRANSFORM_FLAG_NONE); // Rotate direction +180 degrees. d2 = d1 + 2 & 3; Detail_Sub1_Transform (contClones[1],blockSize,vectPoses4 + VERT_INDEXES[d2][0], vectPoses4 + VERT_INDEXES[d2][1],vectPoses4 + VERT_INDEXES[d2][2],scaleZ,brightness, contTexture,DETAIL_TRANSFORM_FLAG_NONE); detailMesh->cloneCount = detailMesh->cloneCount + 1; } return; } void __cdecl lego::map::Detail_Sub1_Transform (Container *cont,float blockSize,Vector3F *p1,Vector3F *p2,Vector3F *p3,float scaleZ, float brightness,Container_Texture *contTexture,Detail_TransformFlags transformFlags) { uint count; D3DRMGroupIndex count_; D3DRMGroupIndex groupID; Detail_Sub2_FUN_0040bac0(cont,blockSize,p1,p2,p3); gfx::Container_Hide(cont,FALSE); groupID = D3DRMGROUP_0; count = gfx::Container_Mesh_GetGroupCount(cont); if (count != 0) { do { gfx::Container_Mesh_SetTexture(cont,groupID,contTexture); groupID += 1; count_ = gfx::Container_Mesh_GetGroupCount(cont); } while (groupID < count_); } gfx::Container_AddTranslation(cont,Container_Combine_Before,-0.02,-0.02,0.0); gfx::Container_AddScale(cont,Container_Combine_Before,1.015,1.015,scaleZ); gfx::Container_SetColourAlpha(cont,brightness,brightness,brightness,1.0); if ((transformFlags & DETAIL_ROTATE_FLAG_X1_DEG90) != DETAIL_TRANSFORM_FLAG_NONE) { // rotate: x+1, degrees+90 gfx::Container_AddRotation(cont,Container_Combine_Before,1.0,0.0,0.0,1.570796); } if ((transformFlags & DETAIL_ROTATE_FLAG_X1_DEGM90) != DETAIL_TRANSFORM_FLAG_NONE) { // rotate: x+1, degrees-90 gfx::Container_AddRotation(cont,Container_Combine_Before,1.0,0.0,0.0,-1.570796); } if ((transformFlags & DETAIL_ROTATE_FLAG_Y1_DEG90) != DETAIL_TRANSFORM_FLAG_NONE) { // rotate: y+1, degrees+90 gfx::Container_AddRotation(cont,Container_Combine_Before,0.0,1.0,0.0,1.570796); } if ((transformFlags & DETAIL_ROTATE_FLAG_Y1_DEGM90) != DETAIL_TRANSFORM_FLAG_NONE) { // rotate: y+1, degrees-90 gfx::Container_AddRotation(cont,Container_Combine_Before,0.0,1.0,0.0,-1.570796); } if ((transformFlags & DETAIL_ROTATE_FLAG_Z1_DEG90) != DETAIL_TRANSFORM_FLAG_NONE) { // rotate: z+1, degrees+90 gfx::Container_AddRotation(cont,Container_Combine_Before,0.0,0.0,1.0,1.570796); } if ((transformFlags & DETAIL_ROTATE_FLAG_Z1_DEGM90) != DETAIL_TRANSFORM_FLAG_NONE) { // rotate: z+1, degrees-90 gfx::Container_AddRotation(cont,Container_Combine_Before,0.0,0.0,1.0,-1.570796); } if ((transformFlags & DETAIL_TRANSLATE_FLAG_YM10) != DETAIL_TRANSFORM_FLAG_NONE) { // translate after: y-10 gfx::Container_AddTranslation(cont,Container_Combine_After,0.0,-10.0,0.0); } if ((transformFlags & DETAIL_TRANSLATE_FLAG_Y10) != DETAIL_TRANSFORM_FLAG_NONE) { // translate after: y+10 gfx::Container_AddTranslation(cont,Container_Combine_After,0.0,10.0,0.0); } return; } void __cdecl lego::map::Detail_Sub2_FUN_0040bac0 (Container *cont,float blockSize,Vector3F *p1,Vector3F *p2,Vector3F *p3) { Vector3F newUp; Vector3F newDir; Matrix4F matrix; float lenUp; float lenDir; float newUp_x; float tempDir_x; float tempDir_y; float tempDir_z; // Maths_Vector3DSubtract(&newUp, p2, p1); // Maths_Vector3DCrossProduct(&newDir, Maths_Vector3DSubtract(&tempDir, p3, p2), // &newUp); // // Maths_Vector3DNormalize(newUp); // Maths_Vector3DNormalize(newDir); // // Gods98::Container_SetOrientation(cont, nullptr, -newDir.x, -newDir.y, -newDir.z, // newUp.x, newUp.y, newUp.z); newUp_x = p2->x - p1->x; newUp.y = p2->y - p1->y; newUp.z = p2->z - p1->z; tempDir_x = p3->x - p2->x; tempDir_y = p3->y - p2->y; tempDir_z = p3->z - p2->z; newDir.x = tempDir_z * newUp.y - tempDir_y * newUp.z; newDir.y = tempDir_x * newUp.z - tempDir_z * newUp_x; newDir.z = tempDir_y * newUp_x - tempDir_x * newUp.y; lenUp = 1.0 / SQRT(newUp.z * newUp.z + newUp.y * newUp.y + newUp_x * newUp_x); lenDir = 1.0 / SQRT(newDir.z * newDir.z + newDir.y * newDir.y + newDir.x * newDir.x); gfx::Container_SetOrientation (cont,NULL,-(lenDir * newDir.x),-(lenDir * newDir.y),-(lenDir * newDir.z), lenUp * newUp_x,lenUp * newUp.y,lenUp * newUp.z); gfx::Container_SetPosition(cont,NULL,p1->x,p1->y,p1->z); gfx::Container_InverseTransform(cont,&newUp,p2); gfx::Container_InverseTransform(cont,&newDir,p3); math::Detail_Matrix_FUN_0040bc90(&matrix,blockSize,blockSize,newUp.y,newDir.x,newDir.y); gfx::Container_AddTransform(cont,Container_Combine_Before,&matrix); return; } void __cdecl lego::math::Detail_Matrix_FUN_0040bc90 (Matrix4F *out_m,float blockWidth,float blockHeight,float invxP2_y,float invxP3_x, float invxP3_y) { // float val1 = (invxP3_x / blockWidth); // float val2 = (invxP3_y / blockWidth); // simplified // float val3 = (invxP2_y / blockHeight); // const Matrix4F m = {{ // { val1, val2, 0.0f, 0.0f }, // { 0.0f, val3, 0.0f, 0.0f }, // { 0.0f, 0.0f, 1.0f, 0.0f }, // { 0.0f, 0.0f, 0.0f, 1.0f }, // }}; out_m->values[3] = 0.0; out_m->values[2] = 0.0; out_m->values[1][3] = 0.0; out_m->values[1][2] = 0.0; out_m->values[1][0] = 0.0; out_m->values[2][3] = 0.0; out_m->values[2][1] = 0.0; out_m->values[2][0] = 0.0; out_m->values[3][2] = 0.0; out_m->values[3][1] = 0.0; out_m->values[3][0] = 0.0; out_m->values[3][3] = 1.0; out_m->values[2][2] = 1.0; out_m->values[0] = invxP3_x / blockWidth; out_m->values[1][1] = invxP2_y / blockHeight; out_m->values[1] = (invxP3_y / invxP3_x) * (invxP3_x / blockWidth); return; } void __cdecl lego::effect::Effect_StopAll(void) { uint *dummy; // This is an ungodly-lazy method that just sets an arbitrarily // large amount of passed time, thus forcing any sane animation // to finish. Effect_UpdateAll(10000.0,&dummy,&dummy); return; } // This CAN ONLY be used with a non-activity-based object type: // I.E. anything but Vehicles, MiniFigures, RockMonsters, Vehicles, or Upgrades. void __cdecl lego::effect::Effect_Spawn_BoulderExplode_AtObjectOther(LegoObject *liveObj) { Vector3F objPosition; gfx::Container_GetPosition(liveObj->other,NULL,&objPosition); Effect_Spawn_BoulderExplode(&objPosition); return; } void __cdecl lego::effect::Effect_Spawn_BoulderExplode(Vector3F *position) { Container **pCont; Lego_Level *level; int i; Container *cont; i = 0; pCont = globs::effectGlobs.boulderExplodeContTable; do { if (*pCont == NULL) { level = lrr::Lego_GetLevel(); cont = globs::legoGlobs.contBoulderExplode; // Hardcoded Ice boulder explode effect if (level->BoulderAnimation == TEXTURES_ICE) { cont = globs::legoGlobs.contBoulderExplodeIce; } cont = gfx::Container_Clone(cont); globs::effectGlobs.boulderExplodeContTable[i] = cont; gfx::Container_SetAnimationTime(cont,0.0); gfx::Container_SetPosition (globs::effectGlobs.boulderExplodeContTable[i],NULL,position->x,position->y, position->z); gfx::Container_SetOrientation (globs::effectGlobs.boulderExplodeContTable[i],NULL,0.0,1.0,0.0,0.0,0.0,-1.0); return; } pCont = pCont + 1; i += 1; } while (pCont < globs::effectGlobs.smashPathContTable); return; } // Must pass in non-null LiveObject* -OR- Vector3F* // in order to get a position. (LiveObject* has precedence) void __cdecl lego::effect::Effect_Spawn_SmashPath(LegoObject *optor_liveObj,Vector3F *optor_position) { Container *pCVar1; EffectElectricFenceBeam *pEVar2; Vector3F local_c; if (optor_liveObj == NULL) { local_c.x = optor_position->x; local_c.y = optor_position->y; local_c.z = optor_position->z; } else { pCVar1 = game::LegoObject_GetActivityContainer(optor_liveObj); gfx::Container_GetPosition(pCVar1,NULL,&local_c); } pEVar2 = (EffectElectricFenceBeam *)globs::effectGlobs.smashPathContTable; do { if (pEVar2->cont == NULL) { pCVar1 = gfx::Container_Clone(globs::legoGlobs.contSmashPath); pEVar2->cont = pCVar1; gfx::Container_SetAnimationTime(pCVar1,0.0); gfx::Container_SetPosition(pEVar2->cont,NULL,local_c.x,local_c.y,local_c.z); gfx::Container_SetOrientation(pEVar2->cont,NULL,0.0,1.0,0.0,0.0,0.0,-1.0); } pEVar2 = (EffectElectricFenceBeam *)pEVar2->contTable; } while (pEVar2 < globs::effectGlobs.efenceEffects); return; } BOOL __cdecl lego::effect::Effect_GetRockFallStyle(char *name,uint *out_index) { int cmp; uint i; char **pName; i = 0; if (globs::effectGlobs.rockFallStyleCount == 0) { return 0; } pName = globs::effectGlobs.rockFallStyleName; do { cmp = std::_stricmp(*pName,name); if (cmp == 0) { *out_index = i; return TRUE; } i += 1; pName = pName + 1; } while (i < globs::effectGlobs.rockFallStyleCount); return 0; } void __cdecl lego::effect::Effect_SetRockFallStyle(int rockFallStyleIndex) { globs::effectGlobs.rockFallStyleIndex = rockFallStyleIndex; return; } void __cdecl lego::effect::Effect_Load_RockFallStylesAll(Config *config,char *gameName,Container *root) { char cVar1; char *pcVar2; Config *prop; uint numParts; uint rockFallTypeIdx; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; undefined4 *puVar7; char *stringParts [10]; char buff [1024]; pcVar2 = cfg::Config_BuildStringID(gameName,"RockFallStyles",0); prop = cfg::Config_FindArray(config,pcVar2); do { if (prop == NULL) { return; } pcVar2 = util::Util_StrCpy(prop->key); globs::effectGlobs.rockFallStyleName[globs::effectGlobs.rockFallStyleCount] = pcVar2; // std::strcpy(buff, prop->value); uVar3 = 0xffffffff; pcVar2 = prop->value; do { pcVar6 = pcVar2; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); puVar7 = (undefined4 *)buff; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar7 = *puVar5; puVar5 = puVar5 + 1; puVar7 = puVar7 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } // This right here is where they fucked up... // We're passing stringParts[0] into Effect_Load_RockFallStyle, // And THAT string is being stored in a struct for later used. // AND THIS string is from a temporary buffer.... SO BAD! numParts = util::Util_Tokenise(buff,stringParts,","); uVar3 = 1; if (1 < numParts) { rockFallTypeIdx = 1; do { Effect_Load_RockFallStyle (root,stringParts[rockFallTypeIdx],globs::effectGlobs.rockFallStyleCount, rockFallTypeIdx - 1,stringParts[0]); uVar3 += 1; rockFallTypeIdx = uVar3 & 0xffff; } while (rockFallTypeIdx < numParts); } globs::effectGlobs.rockFallStyleCount += 1; prop = cfg::Config_GetNextItem(prop); } while( true ); } BOOL __cdecl lego::effect::Effect_Load_RockFallStyle (Container *root,char *filename,int rockFallStyle,int rockFallType,char *itemName) { int iVar1; EffectRockFall *pEVar2; char *pcVar3; Container *pCVar4; char *name; int iVar5; Container **ppCVar6; iVar1 = rockFallType + rockFallStyle * 3; pEVar2 = globs::effectGlobs.rockFallEffects + iVar1; pCVar4 = gfx::Container_Load(root,filename,"LWS",TRUE); pEVar2->cont = pCVar4; if (pCVar4 == NULL) { pCVar4 = gfx::Container_Load(root,filename,"ANIM",TRUE); pEVar2->cont = pCVar4; } if (pEVar2->cont != NULL) { gfx::Container_Hide(pEVar2->cont,TRUE); ppCVar6 = globs::effectGlobs.rockFallEffects[iVar1].contTable; iVar5 = 4; do { pCVar4 = gfx::Container_Clone(pEVar2->cont); *ppCVar6 = pCVar4; ppCVar6[0xc] = (Container *)TRUE; ppCVar6[0x24] = NULL; gfx::Container_Hide(*ppCVar6,TRUE); pcVar3 = itemName; ppCVar6 = ppCVar6 + 1; iVar5 += -1; } while (iVar5 != 0); name = gfx::Container_FormatPartName(pEVar2->cont,itemName,NULL); gfx::Container_SearchTree (pEVar2->cont,name,Container_SearchMode_MatchCount,(uint *)&rockFallStyle); globs::effectGlobs.rockFallEffects[iVar1].itemFrameCount = rockFallStyle; // itemName is a temporary buffer on the stack! // WTF ARE YOU DOING STORING HERE!?? globs::effectGlobs.rockFallEffects[iVar1].itemName = pcVar3; return TRUE; } return FALSE; } BOOL __cdecl lego::effect::Effect_Load_ElectricFenceBeam(Container *root,char *filename,BOOL longBeam) { Container *cont; int i; Container **ppCVar1; cont = gfx::Container_Load(root,filename,"LWS",TRUE); globs::effectGlobs.efenceEffects[longBeam].cont = cont; if (cont != NULL) { gfx::Container_Hide(cont,TRUE); ppCVar1 = globs::effectGlobs.efenceEffects[longBeam].contTable; i = 30; do { cont = gfx::Container_Clone(globs::effectGlobs.efenceEffects[longBeam].cont); // efenceEffects[isLongBeam].contTable[i] = TRUE; *ppCVar1 = cont; // efenceEffects[isLongBeam].finishedTable[i] = TRUE; ppCVar1[0x1e] = (Container *)TRUE; gfx::Container_Hide(*ppCVar1,TRUE); ppCVar1 = ppCVar1 + 1; i += -1; } while (i != 0); return TRUE; } return 0; } BOOL __cdecl lego::effect::Effect_Spawn_RockFall (RockFallType rockFallType,int bx,int by,float x,float y,float z,float dirX,float dirY) { int iVar1; int *piVar2; uint j; int i; i = rockFallType + globs::effectGlobs.rockFallStyleIndex * 3; j = 0; iVar1 = i * 0xa4; piVar2 = globs::effectGlobs.rockFallEffects[i].finishedTable; do { // if (rockFallEffects[i].finishedTable[j] != false) break; if (*piVar2 != 0) break; j += 1; piVar2 = piVar2 + 1; } while (j < 4); if (j < 4) { // Container_Hide(rockFallEffects[i].contTable[j], false); gfx::Container_Hide(*(Container **)(iVar1 + 0x4c81e4 + j * 4),FALSE); // Container_SetAnimationTime(rockFallEffects[i].contTable[j], 0.0f); gfx::Container_SetAnimationTime(*(Container **)(iVar1 + 0x4c81e4 + j * 4),0.0); // Container_SetPosition(rockFallEffects[i].contTable[j], NULL, x, y, z); gfx::Container_SetPosition(*(Container **)(iVar1 + 0x4c81e4 + j * 4),NULL,x,y,z); // Container_SetOrientation(rockFallEffects[i].contTable[j], NULL, dirX, dirY, 0.0f, // 0.0f, 0.0f, -1.0f); gfx::Container_SetOrientation (*(Container **)(iVar1 + 0x4c81e4 + j * 4),NULL,dirX,dirY,0.0,0.0,0.0,-1.0); // rockFallEffects[i].xBlockTable[j] = bx; // rockFallEffects[i].yBlockTable[j] = by; *(int *)(iVar1 + 0x4c81f4 + j * 4) = bx; *(int *)(iVar1 + 0x4c8204 + j * 4) = by; // rockFallEffects[i].finishedTable[j] = false; *(undefined4 *)(iVar1 + 0x4c8214 + j * 4) = 0; return TRUE; } return 0; } BOOL __cdecl lego::effect::Effect_ElectricFenceBeam_Spawn (BOOL longBeam,float xPos,float yPos,float zPos,float xDir,float yDir,float zDir) { int iVar1; int *piVar2; uint i; i = 0; iVar1 = longBeam * 0xf4; piVar2 = globs::effectGlobs.efenceEffects[longBeam].finishedTable; do { // if (efenceEffects[longBeam].finishedTable != false) break; if (*piVar2 != 0) break; i += 1; piVar2 = piVar2 + 1; } while (i < 30); if (i < 30) { // Container_Hide(efenceEffects[longBeam].contTable[i], false); gfx::Container_Hide(*(Container **)(iVar1 + 0x4c8bfc + i * 4),FALSE); // Container_SetAnimationTime(efenceEffects[longBeam].contTable[i], 0.0f); gfx::Container_SetAnimationTime(*(Container **)(iVar1 + 0x4c8bfc + i * 4),0.0); // Container_SetPosition(efenceEffects[longBeam].contTable[i], NULL, xPos, yPos, zPos); gfx::Container_SetPosition(*(Container **)(iVar1 + 0x4c8bfc + i * 4),NULL,xPos,yPos,zPos); // Container_SetOrientation(efenceEffects[longBeam].contTable[i], NULL, xDir, yDir, // zDir, 0.0f, 0.0f, -1.0f); gfx::Container_SetOrientation (*(Container **)(iVar1 + 0x4c8bfc + i * 4),NULL,xDir,yDir,zDir,0.0,0.0,-1.0); // efenceEffects[longBeam].finishedTable[i] = false; *(undefined4 *)(iVar1 + 0x4c8c74 + i * 4) = 0; return TRUE; } return 0; } // Returns number of finisher rockFall effects. uint __cdecl lego::effect::Effect_UpdateAll (float elapsedGame,uint **out_rockFallTypes,uint **out_rockFallSubtypes) { uint rockFallsFinished; uint rfType; int j; int *piVar1; ElectricFence_Block **ppEVar2; uint rfIndex; ElectricFence_Block **ppEVar3; float10 animTime; int idx; rockFallsFinished = 0; Effect_Update_Explosion(elapsedGame); Effect_Update_BoulderExplode(elapsedGame); Effect_Update_SmashPath(elapsedGame); Effect_Update_MiscEffectsAll(elapsedGame); rfType = 0; do { idx = rfType + globs::effectGlobs.rockFallStyleIndex * 3; if (globs::effectGlobs.rockFallEffects[idx].cont != NULL) { rfIndex = 0; piVar1 = globs::effectGlobs.rockFallEffects[idx].finishedTable; do { // if (rockFallEffects[idx].finishedTable[rfIndex] == false) if (*piVar1 == 0) { // Container_MoveAnimation(rockFallEffects[idx].contTable[rfIndex], elapsedGame); animTime = gfx::Container_MoveAnimation((Container *)piVar1[-0xc],elapsedGame); // if (animTime > 0.0f) if ((ushort)((ushort)(animTime < (float10)0.0) << 8 | (ushort)(animTime == (float10)0.0) << 0xe) == 0) { // Container_Hide(rockFallEffects[idx].contTable[rfIndex], true); gfx::Container_Hide((Container *)piVar1[-0xc],TRUE); // rockFallEffects[idx].finishedTable[rfIndex] = true; *piVar1 = 1; // rockFallEffects[idx].bitfieldTable_94[rfIndex] = 0; piVar1[0x18] = 0; globs::effectGlobs.rockFallCompletedTypes[rockFallsFinished] = rfType; globs::effectGlobs.rockFallCompletedIndexes[rockFallsFinished] = rfIndex; rockFallsFinished += 1; } } rfIndex += 1; piVar1 = piVar1 + 1; } while (rfIndex < 4); } rfType += 1; } while (rfType < 3); // i = 0; ppEVar3 = (ElectricFence_Block **)globs::effectGlobs.efenceEffects[0].finishedTable; *out_rockFallTypes = globs::effectGlobs.rockFallCompletedTypes; *out_rockFallSubtypes = globs::effectGlobs.rockFallCompletedIndexes; do { j = 30; ppEVar2 = ppEVar3; do { // if (efenceEffects[i].finishedTable[j] == false) if (*ppEVar2 == NULL) { // Container_MoveAnimation(efenceEffects[i].contTable[j], elapsedGame); animTime = gfx::Container_MoveAnimation((Container *)ppEVar2[-0x1e],elapsedGame); // if (animTime > 0.0f) if ((ushort)((ushort)(animTime < (float10)0.0) << 8 | (ushort)(animTime == (float10)0.0) << 0xe) == 0) { // Container_Hide(efenceEffects[i].contTable[j], true); gfx::Container_Hide((Container *)ppEVar2[-0x1e],TRUE); // efenceEffects[i].finishedTable[j] = true; *ppEVar2 = (ElectricFence_Block *)0x1; } } ppEVar2 = ppEVar2 + 1; j += -1; } while (j != 0); // i++; ppEVar3 = ppEVar3 + 0x3d; // while (i < 2); } while (ppEVar3 < globs::efenceGlobs.listSet + 0x17); return rockFallsFinished; } void __cdecl lego::effect::Effect_Update_BoulderExplode(float elapsedGame) { Container **pCont; float10 animTime; // i = 0; pCont = globs::effectGlobs.boulderExplodeContTable; do { if (*pCont != NULL) { animTime = gfx::Container_MoveAnimation(*pCont,elapsedGame); // if (animTime > 0.0f) if ((ushort)((ushort)(animTime < (float10)0.0) << 8 | (ushort)(animTime == (float10)0.0) << 0xe) == 0) { gfx::Container_Remove(*pCont); *pCont = NULL; } } pCont = pCont + 1; // while (i < 4); } while (pCont < globs::effectGlobs.smashPathContTable); return; } void __cdecl lego::effect::Effect_Update_SmashPath(float elapsedGame) { Container **pCont; float10 animTime; // i = 0; pCont = globs::effectGlobs.smashPathContTable; do { if (*pCont != NULL) { animTime = gfx::Container_MoveAnimation(*pCont,elapsedGame); // if (animTime > 0.0f) if ((ushort)((ushort)(animTime < (float10)0.0) << 8 | (ushort)(animTime == (float10)0.0) << 0xe) == 0) { gfx::Container_Remove(*pCont); *pCont = NULL; } } pCont = pCont + 1; // while (i < 4); } while (pCont < globs::effectGlobs.efenceEffects); return; } void __cdecl lego::effect::Effect_GetBlockPos_RockFall (RockFallType rockFallType,int index,uint *out_bx,uint *out_by) { int iVar1; iVar1 = (rockFallType + globs::effectGlobs.rockFallStyleIndex * 3) * 0xa4; *out_bx = *(uint *)(iVar1 + 0x4c81f4 + index * 4); *out_by = *(uint *)(iVar1 + 0x4c8204 + index * 4); return; } Container * __cdecl lego::effect::Effect_Unk_RockFall_FUN_0040c4e0(uint bx,uint by) { uint *puVar1; char *name; Container *pCVar2; uint uVar3; uint uVar4; EffectRockFall *pEVar5; uVar3 = 0; pEVar5 = globs::effectGlobs.rockFallEffects + globs::effectGlobs.rockFallStyleIndex * 3; do { if (pEVar5->cont != NULL) { uVar4 = 0; puVar1 = pEVar5->xBlockPosTable; do { if (((puVar1[8] == 0) && (bx == *puVar1)) && (by == puVar1[4])) { by = 0; if (pEVar5->itemFrameCount != 0) goto LAB_0040c546; goto LAB_0040c564; } uVar4 += 1; puVar1 = puVar1 + 1; } while (uVar4 < 4); } uVar3 += 1; pEVar5 = pEVar5 + 1; if (2 < uVar3) { return NULL; } } while( true ); while( true ) { by += 1; if ((uint)pEVar5->itemFrameCount <= by) break; LAB_0040c546: if ((pEVar5->bitfieldTable_94[uVar4] & 1 << ((byte)by & 0x1f)) == 0) break; } LAB_0040c564: if (by != pEVar5->itemFrameCount) { pEVar5->bitfieldTable_94[uVar4] = pEVar5->bitfieldTable_94[uVar4] | 1 << ((byte)by & 0x1f); name = gfx::Container_FormatPartName(pEVar5->contTable[uVar4],pEVar5->itemName,(int *)&by); pCVar2 = gfx::Container_SearchTree (pEVar5->contTable[uVar4],name,Container_SearchMode_FirstMatch,NULL); return pCVar2; } return NULL; } void __cdecl lego::effect::Effect_RemoveAll_BoulderExplode(void) { Container **ppCVar1; ppCVar1 = globs::effectGlobs.boulderExplodeContTable; do { if (*ppCVar1 != NULL) { gfx::Container_Remove(*ppCVar1); *ppCVar1 = NULL; } ppCVar1 = ppCVar1 + 1; } while (ppCVar1 < globs::effectGlobs.smashPathContTable); return; } void __cdecl lego::effect::Effect_RemoveAll_RockFall(void) { int iVar1; uint uVar2; Container **ppCVar3; int iVar4; uVar2 = 0; iVar1 = globs::effectGlobs.rockFallStyleIndex; do { iVar4 = uVar2 + iVar1 * 3; if (globs::effectGlobs.rockFallEffects[iVar4].cont != NULL) { ppCVar3 = globs::effectGlobs.rockFallEffects[iVar4].contTable; iVar4 = 4; do { gfx::Container_Remove(*ppCVar3); *ppCVar3 = NULL; ppCVar3 = ppCVar3 + 1; iVar4 += -1; iVar1 = globs::effectGlobs.rockFallStyleIndex; } while (iVar4 != 0); } uVar2 += 1; } while (uVar2 < 3); return; } void __cdecl lego::effect::Effect_Load_Explosion(Container *root,char *filename) { globs::effectGlobs.explosionCont = gfx::Container_Load(root,filename,"LWS",TRUE); gfx::Container_Hide(globs::effectGlobs.explosionCont,TRUE); return; } void __cdecl lego::effect::Effect_Spawn_Explosion(LegoObject *optor_liveObj,Point2F *optor_position) { Map3D *map; Container *pCVar1; float10 fVar2; float xPos; float yPos; Vector3F position; if (optor_liveObj == NULL) { position.x = optor_position->x; position.y = optor_position->y; } else { game::LegoObject_GetPosition(optor_liveObj,&position.x,&position.y); } xPos = position.x; yPos = position.y; map = lrr::Lego_GetMap(); fVar2 = lego::map::Map3D_GetWorldZ(map,xPos,yPos); position.z = (float)(fVar2 - (float10)1.0); if (globs::effectGlobs.explosionCount < 4) { pCVar1 = gfx::Container_Clone(globs::effectGlobs.explosionCont); globs::effectGlobs.explosionContTable[globs::effectGlobs.explosionCount] = pCVar1; pCVar1 = globs::effectGlobs.explosionContTable[globs::effectGlobs.explosionCount]; globs::effectGlobs.explosionCount += 1; gfx::Container_Hide(pCVar1,FALSE); gfx::Container_SetPosition(pCVar1,NULL,position.x,position.y,position.z); gfx::Container_SetOrientation(pCVar1,NULL,0.0,1.0,0.0,0.0,0.0,-1.0); gfx::Container_SetAnimationTime(pCVar1,0.0); } return; } void __cdecl lego::effect::Effect_Update_Explosion(float elapsedGame) { Container *cont; int iVar1; int iVar2; Container **ppCVar3; Container **ppCVar4; float10 fVar5; iVar2 = 0; if (0 < (int)globs::effectGlobs.explosionCount) { ppCVar3 = globs::effectGlobs.explosionContTable; do { cont = *ppCVar3; fVar5 = gfx::Container_MoveAnimation(cont,elapsedGame); ppCVar4 = ppCVar3; if (fVar5 != (float10)0.0) { gfx::Container_Remove(cont); iVar2 += -1; ppCVar4 = ppCVar3 + -1; iVar1 = globs::effectGlobs.explosionCount - 1; globs::effectGlobs.explosionCount = globs::effectGlobs.explosionCount - 1; *ppCVar3 = globs::effectGlobs.explosionContTable[iVar1]; } iVar2 += 1; ppCVar3 = ppCVar4 + 1; } while (iVar2 < (int)globs::effectGlobs.explosionCount); } return; } EffectMisc * __cdecl lego::effect::Effect_GetMiscEffectData(MiscEffectType miscEffectType) { switch(miscEffectType) { case MISCOBJECT_LAZERHIT: return &globs::effectGlobs.lazerHitEffect; case MISCOBJECT_PUSHERHIT: return &globs::effectGlobs.pusherHitEffect; case MISCOBJECT_FREEZERHIT: return &globs::effectGlobs.freezerHitEffect; case MISCOBJECT_PATHDUST: return &globs::effectGlobs.pathDustEffect; case MISCOBJECT_LAVAEROSIONSMOKE1: return globs::effectGlobs.lavaErosionSmokeEffects; case MISCOBJECT_LAVAEROSIONSMOKE2: return globs::effectGlobs.lavaErosionSmokeEffects + 1; case MISCOBJECT_LAVAEROSIONSMOKE3: return globs::effectGlobs.lavaErosionSmokeEffects + 2; case MISCOBJECT_LAVAEROSIONSMOKE4: return globs::effectGlobs.lavaErosionSmokeEffects + 3; case MISCOBJECT_BIRDSCARER: return &globs::effectGlobs.birdScarerEffect; case MISCOBJECT_UPGRADEEFFECT: return &globs::effectGlobs.upgradeEffect; default: return NULL; } } BOOL __cdecl lego::effect::Effect_Load_Misc(EffectMisc *effectMisc,Container *root,char *filename) { Container *pCVar1; if (filename == NULL) { return 0; } pCVar1 = gfx::Container_Load(root,filename,"LWS",TRUE); effectMisc->cont = pCVar1; if (pCVar1 == NULL) { pCVar1 = gfx::Container_Load(root,filename,"LWO",TRUE); effectMisc->cont = pCVar1; if (pCVar1 == NULL) { return 0; } } gfx::Container_Hide(effectMisc->cont,TRUE); return TRUE; } void __cdecl lego::effect::Effect_Initialise(Config *config,char *gameName,Container *root) { char *pcVar1; pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","LazerHit",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(&globs::effectGlobs.lazerHitEffect,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","PusherHit",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(&globs::effectGlobs.pusherHitEffect,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","FreezerHit",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(&globs::effectGlobs.freezerHitEffect,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","PathDust",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(&globs::effectGlobs.pathDustEffect,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","LavaErosionSmoke1",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(globs::effectGlobs.lavaErosionSmokeEffects,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","LavaErosionSmoke2",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(globs::effectGlobs.lavaErosionSmokeEffects + 1,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","LavaErosionSmoke3",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(globs::effectGlobs.lavaErosionSmokeEffects + 2,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","LavaErosionSmoke4",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(globs::effectGlobs.lavaErosionSmokeEffects + 3,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","BirdScarer",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(&globs::effectGlobs.birdScarerEffect,root,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"MiscObjects","UpgradeEffect",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); Effect_Load_Misc(&globs::effectGlobs.upgradeEffect,root,pcVar1); return; } void __cdecl lego::effect::Effect_Update_MiscEffect(EffectMisc *miscEffect,float elapsedGame) { Container *cont; uint uVar1; uint uVar2; EffectMisc *pEVar3; uint uVar4; float10 fVar5; Point2F local_14; Vector3F local_c; uVar4 = 0; pEVar3 = miscEffect; if (miscEffect->count != 0) { do { cont = pEVar3->contTable[0]; if ((miscEffect == &globs::effectGlobs.birdScarerEffect) && (globs::effectGlobs.birdScarerEffect.field_2c = elapsedGame + globs::effectGlobs.birdScarerEffect.field_2c, (ushort)((ushort)(globs::effectGlobs.birdScarerEffect.field_2c < 12.5) << 8 | (ushort)(globs::effectGlobs.birdScarerEffect.field_2c == 12.5) << 0xe) == 0)) { gfx::Container_GetPosition(cont,NULL,&local_c); local_14.x = local_c.x; local_14.y = local_c.y; game::LegoObject_DoBirdScarerRadiusCallbacks (NULL,&local_14,globs::legoGlobs.BirdScarerRadius); globs::effectGlobs.birdScarerEffect.field_2c = 0.0; } fVar5 = gfx::Container_MoveAnimation(cont,elapsedGame); if (fVar5 != (float10)0.0) { gfx::Container_Remove(cont); uVar1 = miscEffect->count; uVar2 = uVar1 - 1; miscEffect->count = uVar2; if (uVar4 == uVar2) { pEVar3->contTable[0] = NULL; } else { pEVar3->contTable[0] = miscEffect->contTable[uVar1 - 1]; } uVar4 -= 1; pEVar3 = (EffectMisc *)&pEVar3[-1].field_34; } uVar4 += 1; pEVar3 = (EffectMisc *)(pEVar3->contTable + 1); } while (uVar4 < miscEffect->count); } return; } void __cdecl lego::effect::Effect_Update_MiscEffectsAll(float elapsedGame) { Effect_Update_MiscEffect(&globs::effectGlobs.lazerHitEffect,elapsedGame); Effect_Update_MiscEffect(&globs::effectGlobs.pusherHitEffect,elapsedGame); Effect_Update_MiscEffect(&globs::effectGlobs.freezerHitEffect,elapsedGame); Effect_Update_MiscEffect(&globs::effectGlobs.pathDustEffect,elapsedGame); Effect_Update_MiscEffect(globs::effectGlobs.lavaErosionSmokeEffects,elapsedGame); Effect_Update_MiscEffect(globs::effectGlobs.lavaErosionSmokeEffects + 1,elapsedGame); Effect_Update_MiscEffect(globs::effectGlobs.lavaErosionSmokeEffects + 2,elapsedGame); Effect_Update_MiscEffect(globs::effectGlobs.lavaErosionSmokeEffects + 3,elapsedGame); Effect_Update_MiscEffect(&globs::effectGlobs.birdScarerEffect,elapsedGame); Effect_Update_MiscEffect(&globs::effectGlobs.upgradeEffect,elapsedGame); return; } BOOL __cdecl lego::effect::Effect_Spawn_Particle (MiscEffectType miscEffectType,Vector3F *position,Vector3F *opt_dir) { EffectMisc *pEVar1; Container *cont; float dirx; float diry; float dirz; pEVar1 = Effect_GetMiscEffectData(miscEffectType); if (((pEVar1->count < 10) && (pEVar1 != NULL)) && (pEVar1->cont != NULL)) { pEVar1->field_2c = 0; cont = gfx::Container_Clone(pEVar1->cont); pEVar1->contTable[pEVar1->count] = cont; gfx::Container_SetAnimationTime(pEVar1->contTable[pEVar1->count],0.0); gfx::Container_SetPosition (pEVar1->contTable[pEVar1->count],NULL,position->x,position->y,position->z); if (opt_dir == NULL) { dirz = 0.0; diry = 1.0; dirx = 0.0; cont = pEVar1->contTable[pEVar1->count]; } else { dirz = opt_dir->z; diry = opt_dir->y; dirx = opt_dir->x; cont = pEVar1->contTable[pEVar1->count]; } gfx::Container_SetOrientation(cont,NULL,dirx,diry,dirz,0.0,0.0,-1.0); pEVar1->count = pEVar1->count + 1; return TRUE; } return FALSE; } void __cdecl lego::game::ElectricFence_Initialise(Lego_Level *level) { uint uVar1; int iVar2; ElectricFence_GridBlock *pEVar3; ElectricFence_Block **ppEVar4; globs::efenceGlobs.fenceGrid = (ElectricFence_GridBlock *)io::Mem_Alloc(level->width * level->height * 0x14); if (globs::efenceGlobs.fenceGrid != NULL) { pEVar3 = globs::efenceGlobs.fenceGrid; for (uVar1 = level->width * level->height * 5 & 0x3fffffff; uVar1 != 0; uVar1 -= 1) { pEVar3->efence = NULL; pEVar3 = (ElectricFence_GridBlock *)&pEVar3->studObj; } for (iVar2 = 0; iVar2 != 0; iVar2 += -1) { *(undefined *)&pEVar3->efence = 0; pEVar3 = (ElectricFence_GridBlock *)((int)&pEVar3->efence + 1); } } globs::efenceGlobs.level = level; ppEVar4 = globs::efenceGlobs.listSet; for (iVar2 = 0x20; iVar2 != 0; iVar2 += -1) { *ppEVar4 = NULL; ppEVar4 = ppEVar4 + 1; } globs::efenceGlobs.freeList = NULL; globs::efenceGlobs.listCount = 0; return; } void __cdecl lego::game::ElectricFence_Shutdown(void) { ElectricFence_Block **ppEVar1; ppEVar1 = globs::efenceGlobs.listSet; do { if (*ppEVar1 != NULL) { io::Mem_Free(*ppEVar1); } ppEVar1 = ppEVar1 + 1; } while (ppEVar1 < &globs::efenceGlobs.freeList); globs::efenceGlobs.freeList = NULL; if (globs::efenceGlobs.fenceGrid != NULL) { io::Mem_Free(globs::efenceGlobs.fenceGrid); globs::efenceGlobs.fenceGrid = NULL; } return; } void __cdecl lego::game::ElectricFence_Restart(Lego_Level *level) { ElectricFence_Shutdown(); ElectricFence_Initialise(level); return; } void __cdecl lego::game::ElectricFence_UpdateBlockConnections(int bx,int by) { int iVar1; int iVar2; int iVar3; BOOL BVar4; int *pDirY; Point2I DIRECTIONS [4]; iVar3 = by; DIRECTIONS[0].y = 1; DIRECTIONS[1].x = 1; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].y = 0; DIRECTIONS[2].y = -1; DIRECTIONS[3].x = -1; Level_BlockUpdateSurface(globs::efenceGlobs.level,bx,by,0); pDirY = &DIRECTIONS[0].y; by = 4; do { iVar1 = pDirY[-1]; iVar2 = *pDirY; BVar4 = lego::map::Map3D_IsInsideDimensions ((globs::efenceGlobs.level)->map,iVar1 + bx,iVar3 + iVar2); if (BVar4 != 0) { Level_BlockUpdateSurface(globs::efenceGlobs.level,iVar1 + bx,iVar3 + iVar2,0); } pDirY = pDirY + 2; by += -1; } while (by != 0); return; } // Public creation function for electric fences. ElectricFence_Block * __cdecl lego::game::ElectricFence_CreateFence(LegoObject *liveObj) { LegoObject *liveObj_00; ElectricFence_Block *pEVar1; int local_4; liveObj_00 = liveObj; LegoObject_GetBlockPos(liveObj,&local_4,(int *)&liveObj); pEVar1 = ElectricFence_Create(liveObj_00,local_4,(int)liveObj); return pEVar1; } ElectricFence_Block * __cdecl lego::game::ElectricFence_Create(LegoObject *liveObj,int bx,int by) { LegoObject **ppLVar1; ElectricFence_Block *newEFence; if (globs::efenceGlobs.freeList == NULL) { ElectricFence_AddList(); } newEFence = globs::efenceGlobs.freeList; ppLVar1 = &(globs::efenceGlobs.freeList)->attachedObject; globs::efenceGlobs.freeList = (globs::efenceGlobs.freeList)->nextFree; *ppLVar1 = NULL; (newEFence->blockPos).x = 0; (newEFence->blockPos).y = 0; newEFence->timer = 0.0; newEFence->nextFree = NULL; newEFence->nextFree = newEFence; newEFence->attachedObject = liveObj; (newEFence->blockPos).x = bx; (newEFence->blockPos).y = by; globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].flags = FENCEGRID_FLAG_NONE; globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence = newEFence; liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_ACTIVEELECTRICFENCE; ElectricFence_UpdateBlockConnections(bx,by); return newEFence; } void __cdecl lego::game::ElectricFence_AddList(void) { ElectricFence_Block *pEVar1; ElectricFence_Block *pEVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::efenceGlobs.listCount & 0x1f); pEVar2 = (ElectricFence_Block *)io::Mem_Alloc(uVar4 * 0x14); globs::efenceGlobs.listSet[globs::efenceGlobs.listCount] = pEVar2; pEVar2 = globs::efenceGlobs.listSet[globs::efenceGlobs.listCount]; if (pEVar2 != NULL) { globs::efenceGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pEVar1 = pEVar2; do { pEVar1->nextFree = pEVar1 + 1; iVar3 += -1; pEVar1 = pEVar1 + 1; } while (iVar3 != 0); } pEVar2[uVar4 - 1].nextFree = globs::efenceGlobs.freeList; globs::efenceGlobs.freeList = pEVar2; } return; } // Public removal function for electric fences. void __cdecl lego::game::ElectricFence_RemoveFence(LegoObject *liveObj) { int local_4; if ((liveObj->flags2 & LIVEOBJ2_ACTIVEELECTRICFENCE) != LIVEOBJ2_NONE) { LegoObject_GetBlockPos(liveObj,&local_4,(int *)&liveObj); if (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * (int)liveObj + local_4]. efence != NULL) { ElectricFence_Remove (globs::efenceGlobs.fenceGrid [(globs::efenceGlobs.level)->width * (int)liveObj + local_4].efence,local_4, (int)liveObj); } } return; } void __cdecl lego::game::ElectricFence_Remove(ElectricFence_Block *efence,int bx,int by) { efence->nextFree = globs::efenceGlobs.freeList; globs::efenceGlobs.freeList = efence; globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].flags = FENCEGRID_FLAG_NONE; globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence = NULL; ElectricFence_UpdateBlockConnections(bx,by); return; } BOOL __cdecl lego::game::ElectricFence_Debug_PlaceFence(int bx,int by) { BOOL BVar1; LegoObject *liveObj; Point2F local_8; BVar1 = ElectricFence_CanPlaceFenceAtBlock(bx,by); if (BVar1 != 0) { lego::map::Map3D_BlockToWorldPos((globs::efenceGlobs.level)->map,bx,by,&local_8.x,&local_8.y); liveObj = LegoObject_CreateInWorld (globs::legoGlobs.contElectricFence,LegoObject_ElectricFence,0,0,local_8.x, local_8.y,0.0); ElectricFence_Create(liveObj,bx,by); return TRUE; } return 0; } BOOL __cdecl lego::game::ElectricFence_Debug_RemoveFence(int bx,int by) { LegoObject *liveObj; if (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence != NULL) { liveObj = (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence)-> attachedObject; ElectricFence_RemoveFence(liveObj); LegoObject_Remove(liveObj); return TRUE; } return 0; } BOOL __cdecl lego::game::ElectricFence_CanPlaceFenceAtBlock(int bx,int by) { Lego_SurfaceType8 LVar1; int iVar2; BOOL BVar3; uint uVar4; uint uVar5; uint uVar6; Point2I DIRECTIONS [8]; DIRECTIONS[4].y = 2; DIRECTIONS[5].x = 2; DIRECTIONS[6].y = -2; DIRECTIONS[7].x = -2; DIRECTIONS[0].y = 1; DIRECTIONS[1].x = 1; DIRECTIONS[2].y = -1; DIRECTIONS[3].x = -1; iVar2 = (globs::efenceGlobs.level)->width * by + bx; DIRECTIONS[4].x = 0; DIRECTIONS[5].y = 0; DIRECTIONS[6].x = 0; DIRECTIONS[7].y = 0; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].y = 0; if (((((*(byte *)&(globs::efenceGlobs.level)->blocks[iVar2].flags1 & 8) == 0) || (LVar1 = (globs::efenceGlobs.level)->blocks[iVar2].terrain, LVar1 == Lego_SurfaceType8_Lava)) || (LVar1 == Lego_SurfaceType8_Water)) || ((globs::efenceGlobs.fenceGrid[iVar2].efence != NULL || (BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bx,by,0), BVar3 != 0)))) { return 0; } uVar4 = 0; do { uVar5 = *(int *)((int)&DIRECTIONS[0].x + uVar4) + bx; uVar6 = by + *(int *)((int)&DIRECTIONS[0].y + uVar4); BVar3 = lego::map::Map3D_IsInsideDimensions((globs::efenceGlobs.level)->map,uVar5,uVar6); if ((BVar3 != 0) && ((globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * uVar6 + uVar5].efence != NULL || (BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,uVar5,uVar6,0) , BVar3 != 0)))) { return TRUE; } uVar5 = *(int *)((int)&DIRECTIONS[4].x + uVar4) + bx; uVar6 = *(int *)((int)&DIRECTIONS[4].y + uVar4) + by; BVar3 = lego::map::Map3D_IsInsideDimensions((globs::efenceGlobs.level)->map,uVar5,uVar6); if (BVar3 != 0) { if (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * uVar6 + uVar5].efence != NULL) { return 1; } BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,uVar5,uVar6,0); if (BVar3 != 0) { return 1; } } uVar4 += 8; if (0x1f < uVar4) { return 0; } } while( true ); } BOOL __cdecl lego::game::ElectricFence_CheckBuildingAtBlock(Lego_Level *level,int bx,int by,BOOL checkPowered) { BOOL BVar1; Point2I blockPos; blockPos.x = bx; blockPos.y = by; BVar1 = Level_Block_IsSolidBuilding(bx,by,TRUE); if (BVar1 != 0) { if (checkPowered == 0) { return 1; } BVar1 = Level_Block_IsPowered(&blockPos); if (BVar1 != 0) { return 1; } } return 0; } void __cdecl lego::game::ElectricFence_UpdateAll(float elapsedGame) { ElectricFence_RunThroughLists(ElectricFence_CallbackUpdate,&elapsedGame); LegoObject_RunThroughListsSkipUpgradeParts(ElectricFence_LiveObject_Callback_FUN_0040d650,NULL); LegoObject_RunThroughListsSkipUpgradeParts(ElectricFence_Callback_FUN_0040d510,&elapsedGame); return; } void __cdecl lego::game::ElectricFence_RunThroughLists(ElectricFence_RunThroughListsCallback callback,void *data) { int listSetCount; ElectricFence_Block *efence; ElectricFence_Block **pEFence; uint i; int listSetOff; i = 0; if (globs::efenceGlobs.listCount != 0) { pEFence = globs::efenceGlobs.listSet; do { if ((*pEFence != NULL) && (listSetCount = 1 << ((byte)i & 0x1f), listSetCount != 0)) { listSetOff = 0; do { efence = (ElectricFence_Block *)((int)&(*pEFence)->attachedObject + listSetOff); if ((efence != NULL) && (efence->nextFree == efence)) { (*callback)(efence,data); } listSetOff += 0x14; listSetCount += -1; } while (listSetCount != 0); } i += 1; pEFence = pEFence + 1; } while (i < globs::efenceGlobs.listCount); } return; } BOOL __cdecl lego::game::ElectricFence_FUN_0040d420(LegoObject *liveObj,uint bx,uint by) { StatsFlags2 sflags2; BOOL BVar1; float xPos; float yPos; ElectricFence_RunThroughLists(ElectricFence_CallbackUpdate,NULL); LegoObject_RunThroughListsSkipUpgradeParts(ElectricFence_LiveObject_Callback_FUN_0040d650,NULL); if (liveObj == NULL) { if ((globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence == NULL) && (BVar1 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bx,by,0), BVar1 == 0) ) { return 0; } } else { LegoObject_GetPosition(liveObj,&xPos,&yPos); lego::map::Map3D_WorldToBlockPos_NoZ ((globs::efenceGlobs.level)->map,xPos,yPos,(int *)&bx,(int *)&by); sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if (((sflags2 & STATS2_SELFPOWERED) == STATS2_NONE) && ((liveObj->flags3 & LIVEOBJ3_HASPOWER) == LIVEOBJ3_NONE)) { return 0; } } ElectricFence_Block_FUN_0040d780(bx,by,TRUE,0.0); return TRUE; } BOOL __cdecl lego::game::ElectricFence_Callback_FUN_0040d510(LegoObject *liveObj,float *pElapsedGame) { float fVar1; BOOL BVar2; Point2I *pPVar3; Point2I *pPVar4; float *pfVar5; Point2I *pPVar6; Direction rotation; float *pfVar7; Point2F local_10; Point2I local_8; fVar1 = *pElapsedGame; if (liveObj->type == LegoObject_Building) { LegoObject_GetBlockPos(liveObj,&local_8.x,&local_8.y); BVar2 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,local_8.x,local_8.y,TRUE); if (BVar2 != 0) { LegoObject_GetFaceDirection(liveObj,&local_10); if (ABS(local_10.x) <= ABS(local_10.y)) { if ((ushort)((ushort)(local_10.y < 0.0) << 8 | (ushort)(local_10.y == 0.0) << 0xe) == 0) { rotation = DIRECTION_UP; } else { rotation = DIRECTION_DOWN; } } else { if ((ushort)((ushort)(local_10.x < 0.0) << 8 | (ushort)(local_10.x == 0.0) << 0xe) == 0) { rotation = DIRECTION_RIGHT; } else { rotation = DIRECTION_LEFT; } } pPVar3 = gfx::Building_GetShapePoints(liveObj->building,(uint *)&pElapsedGame); pPVar4 = gfx::SelectPlace_TransformShapePoints(&local_8,pPVar3,(uint)pElapsedGame,rotation); pfVar7 = NULL; pfVar5 = pElapsedGame; pPVar3 = pPVar4; if (pElapsedGame != NULL) { do { pPVar6 = pPVar3 + 1; if (((pfVar7 == (float *)((int)pfVar5 - 1U)) || (pPVar4->x != pPVar6->x)) || (pPVar4->y != pPVar3[1].y)) { ElectricFence_Block_FUN_0040d780(pPVar4->x,pPVar4->y,FALSE,fVar1); pfVar5 = pElapsedGame; } else { pfVar7 = (float *)((int)pfVar7 + 1); pPVar6 = pPVar3 + 2; pPVar4 = pPVar4 + 1; } pfVar7 = (float *)((int)pfVar7 + 1); pPVar4 = pPVar4 + 1; pPVar3 = pPVar6; } while (pfVar7 < pfVar5); } } } return 0; } BOOL __cdecl lego::game::ElectricFence_LiveObject_Callback_FUN_0040d650(LegoObject *liveObj,void *data) { Point2I blockPos; if (liveObj->type == LegoObject_Building) { LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * blockPos.y + blockPos.x].flags = FENCEGRID_FLAG_NONE; } return 0; } void __cdecl lego::game::ElectricFence_CallbackUpdate(ElectricFence_Block *efence,float *pElapsedGame) { BOOL BVar1; int *pDirY; uint bx; uint by; Point2I DIRECTIONS [4]; ElectricFence_Block *efence_00; efence_00 = efence; DIRECTIONS[0].y = 1; DIRECTIONS[1].x = 1; DIRECTIONS[2].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].y = 0; globs::efenceGlobs.fenceGrid [(globs::efenceGlobs.level)->width * (efence->blockPos).y + (efence->blockPos).x].flags = FENCEGRID_FLAG_NONE; pDirY = &DIRECTIONS[0].y; efence = (ElectricFence_Block *)&DAT_00000004; do { bx = pDirY[-1] + (efence_00->blockPos).x; by = (efence_00->blockPos).y + *pDirY; BVar1 = lego::map::Map3D_IsInsideDimensions((globs::efenceGlobs.level)->map,bx,by); if (BVar1 != 0) { globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].flags = FENCEGRID_FLAG_NONE; } pDirY = pDirY + 2; efence = (ElectricFence_Block *)((int)&efence[-1].nextFree + 3); } while (efence != NULL); if ((pElapsedGame != NULL) && ((ushort)((ushort)(efence_00->timer < 0.0) << 8 | (ushort)(efence_00->timer == 0.0) << 0xe) == 0)) { efence_00->timer = efence_00->timer - *pElapsedGame; } return; } void __cdecl lego::game::ElectricFence_Block_FUN_0040d780(uint bx,uint by,BOOL param_3,float param_4) { float fVar1; short sVar2; BOOL BVar3; int iVar4; uint bxL; uint byL; ulonglong uVar5; uint loop; float local_58; Point2I *pDir; int shortBeam; uint bxFound; uint byFound; Point2I DIRECTIONS [8]; int dirX; uint bxS; uint byS; bool found; DIRECTIONS[4].y = 2; DIRECTIONS[5].x = 2; DIRECTIONS[6].y = -2; DIRECTIONS[7].x = -2; DIRECTIONS[0].y = 1; DIRECTIONS[1].x = 1; DIRECTIONS[2].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[4].x = 0; DIRECTIONS[5].y = 0; DIRECTIONS[6].x = 0; DIRECTIONS[7].y = 0; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].y = 0; loop = 0; globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].flags = globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].flags | FENCEGRID_FLAG_UNK_100; pDir = DIRECTIONS; do { found = false; dirX = pDir->x; bxS = bx + dirX; byS = DIRECTIONS[loop].y + by; BVar3 = lego::map::Map3D_IsInsideDimensions((globs::efenceGlobs.level)->map,bxS,byS); if ((BVar3 != 0) && ((globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * byS + bxS].efence != NULL || ((BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bxS,byS,1), BVar3 != 0 && (BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bx,by,0), BVar3 == 0)))))) { found = true; shortBeam = 1; bxFound = bxS; byFound = byS; } if (found) { LAB_0040d9a4: if (shortBeam == 0) { iVar4 = (globs::efenceGlobs.level)->width * byS + bx + dirX; globs::efenceGlobs.fenceGrid[iVar4].flags = globs::efenceGlobs.fenceGrid[iVar4].flags | FENCEGRID_FLAG_UNK_100; } iVar4 = byFound * (globs::efenceGlobs.level)->width + bxFound; if ((globs::efenceGlobs.fenceGrid[iVar4].efence == NULL) || (fVar1 = (globs::efenceGlobs.fenceGrid[iVar4].efence)->timer, (ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) != 0)) { if ((globs::efenceGlobs.fenceGrid[iVar4].flags & 1 << ((byte)loop & 0x1f)) == FENCEGRID_FLAG_NONE) { globs::efenceGlobs.fenceGrid[by * (globs::efenceGlobs.level)->width + bx].flags = globs::efenceGlobs.fenceGrid[by * (globs::efenceGlobs.level)->width + bx].flags | 1 << ((byte)loop - 2 & 3); local_58 = param_4; if ((ushort)((ushort)(param_4 < 200.0) << 8 | (ushort)(param_4 == 200.0) << 0xe) == 0) { local_58 = 200.0; } if (param_3 == 0) { if (local_58 != 0.0) { sVar2 = math::Maths_Rand(); uVar5 = __ftol((float10)200.0 / (float10)local_58); if ((int)((ulonglong)(uint)(int)sVar2 % (uVar5 & 0xffffffff)) == 0) goto LAB_0040dab9; } } else { LAB_0040dab9: ElectricFence_Block_UnkAreaDistanceBetweenBlocks(bx,by,bxFound,byFound); } } BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bxFound,byFound,0); if ((BVar3 == 0) && ((globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * byFound + bxFound]. flags & FENCEGRID_FLAG_UNK_100) == FENCEGRID_FLAG_NONE)) { ElectricFence_Block_FUN_0040d780(bxFound,byFound,param_3,param_4); } } } else { byL = by + DIRECTIONS[loop + 4].y; bxL = DIRECTIONS[loop + 4].x + bx; BVar3 = lego::map::Map3D_IsInsideDimensions((globs::efenceGlobs.level)->map,bxL,byL); if (((BVar3 != 0) && ((BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bxS,byS,0), BVar3 == 0 || (BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bx,by,0), BVar3 == 0 )))) && ((globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * byL + bxL]. efence != NULL || ((BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bxL,byL,1) , BVar3 != 0 && (BVar3 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bx,by,0), BVar3 == 0)))))) { found = true; shortBeam = 0; bxFound = bxL; byFound = byL; } if (found) goto LAB_0040d9a4; } loop += 1; pDir = pDir + 1; if (3 < loop) { return; } } while( true ); } BOOL __cdecl lego::game::ElectricFence_Block_UnkAreaDistanceBetweenBlocks (uint bxFrom,uint byFrom,uint bxTo,uint byTo) { bool bVar1; uint uVar2; uint uVar3; float10 fVar4; float local_58; float local_54; float local_50; Vector3F local_4c; Point2I DISTANCES_SET [2] [4]; DISTANCES_SET[1][0].y = 2; DISTANCES_SET[1][1].x = 2; DISTANCES_SET[1][2].y = -2; DISTANCES_SET[1][3].x = -2; DISTANCES_SET[0][0].y = 1; DISTANCES_SET[0][1].x = 1; DISTANCES_SET[0][2].y = -1; DISTANCES_SET[0][3].x = -1; DISTANCES_SET[1][0].x = 0; DISTANCES_SET[1][1].y = 0; DISTANCES_SET[1][2].x = 0; DISTANCES_SET[1][3].y = 0; DISTANCES_SET[0][0].x = 0; DISTANCES_SET[0][1].y = 0; DISTANCES_SET[0][2].x = 0; DISTANCES_SET[0][3].y = 0; bVar1 = false; uVar2 = 0; do { if ((bxTo == *(int *)((int)&DISTANCES_SET[0].x + uVar2) + bxFrom) && (byTo == byFrom + *(int *)((int)&DISTANCES_SET[0].y + uVar2))) { bVar1 = true; uVar3 = 1; break; } if ((bxTo == *(int *)((int)&DISTANCES_SET[1][0].x + uVar2) + bxFrom) && (byTo == *(int *)((int)&DISTANCES_SET[1][0].y + uVar2) + byFrom)) { bVar1 = true; uVar3 = 0; break; } uVar2 += 8; uVar3 = byTo; } while (uVar2 < 0x20); if (!bVar1) { return 0; } ElectricFence_Block_GetDistanceBetweenBlocks(bxFrom,byFrom,bxTo,byTo,&local_4c); lego::map::Map3D_BlockToWorldPos ((globs::efenceGlobs.level)->map,bxFrom,byFrom,&local_58,&local_54); fVar4 = lego::map::Map3D_GetWorldZ((globs::efenceGlobs.level)->map,local_58,local_54); local_50 = (float)fVar4; if (uVar3 == 0) { effect::Effect_ElectricFenceBeam_Spawn (1,local_58,local_54,local_50,local_4c.x,local_4c.y,local_4c.z); return TRUE; } effect::Effect_ElectricFenceBeam_Spawn (0,local_58,local_54,local_50,local_4c.x,local_4c.y,local_4c.z); return TRUE; } Vector3F * __cdecl lego::game::ElectricFence_Block_GetDistanceBetweenBlocks (uint bxFrom,uint byFrom,uint bxTo,uint byTo,Vector3F *out_vector) { float10 fVar1; Vector3F worldPosFrom; Vector3F worldPosTo; lego::map::Map3D_BlockToWorldPos ((globs::efenceGlobs.level)->map,bxFrom,byFrom,&worldPosFrom.x,&worldPosFrom.y); fVar1 = lego::map::Map3D_GetWorldZ((globs::efenceGlobs.level)->map,worldPosFrom.x,worldPosFrom.y); worldPosFrom.z = (float)fVar1; lego::map::Map3D_BlockToWorldPos ((globs::efenceGlobs.level)->map,bxTo,byTo,&worldPosTo.x,&worldPosTo.y); fVar1 = lego::map::Map3D_GetWorldZ((globs::efenceGlobs.level)->map,worldPosTo.x,worldPosTo.y); out_vector->x = worldPosTo.x - worldPosFrom.x; out_vector->y = worldPosTo.y - worldPosFrom.y; out_vector->z = (float)(fVar1 - (float10)worldPosFrom.z); return out_vector; } BOOL __cdecl lego::game::ElectricFence_TrySparkObject(LegoObject *liveObj) { float fVar1; BOOL BVar2; uint weaponID; uint by_01; int *pDir; uint i; uint bx_01; float10 fVar3; uint by; uint bx; float minDist; float local_40; uint bx_00; uint by_00; uint dirTarget; Point2F objectPos; Point2F wPos; Point2I DIRECTIONS_I [4]; float dist; bool success; DIRECTIONS_I[0].y = 1; DIRECTIONS_I[1].x = 1; DIRECTIONS_I[2].y = -1; DIRECTIONS_I[3].x = -1; DIRECTIONS_I[0].x = 0; DIRECTIONS_I[1].y = 0; DIRECTIONS_I[2].x = 0; DIRECTIONS_I[3].y = 0; minDist = 0.0; success = false; LegoObject_GetPosition(liveObj,&objectPos.x,&objectPos.y); lego::map::Map3D_WorldToBlockPos_NoZ ((globs::efenceGlobs.level)->map,objectPos.x,objectPos.y,(int *)&bx,(int *)&by); bx_01 = bx; by_01 = by; bx_00 = bx; by_00 = by; if (((*(byte *)((int)&globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx]. flags + 1) & 1) != 0) && (BVar2 = ElectricFence_CheckBuildingAtBlock(globs::efenceGlobs.level,bx,by,0), BVar2 == 0)) { if (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence == NULL) { i = 0; pDir = &DIRECTIONS_I[0].y; do { if ((globs::efenceGlobs.fenceGrid [(globs::efenceGlobs.level)->width * (by + *pDir) + pDir[-1] + bx].efence != NULL) && (fVar1 = (globs::efenceGlobs.fenceGrid [(globs::efenceGlobs.level)->width * (by + *pDir) + pDir[-1] + bx].efence)-> timer, (ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) != 0 )) { lego::map::Map3D_BlockToWorldPos ((globs::efenceGlobs.level)->map,pDir[-1] + bx,by + *pDir,&wPos.x,&wPos.y); local_40 = objectPos.x - wPos.x; dist = SQRT((objectPos.y - wPos.y) * (objectPos.y - wPos.y) + local_40 * local_40); if ((dist < minDist) || (minDist == 0.0)) { success = true; minDist = dist; dirTarget = i; } } i += 1; pDir = pDir + 2; } while (i < 4); by_01 = by_00; bx_01 = bx_00; if (success) { by_01 = by_00 + DIRECTIONS_I[dirTarget].y; bx_01 = bx_00 + DIRECTIONS_I[dirTarget].x; } } else { fVar1 = (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence)-> timer; if ((ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) != 0) { success = true; } } if (success) { ElectricFence_SparkObjectAndCreateBeam(liveObj,&objectPos,bx,by); ElectricFence_FUN_0040d420(NULL,bx_01,by_01); weaponID = tools::Weapon_GetWeaponIDByName("FenceSpark"); fVar3 = tools::Weapon_GetRechargeTime(weaponID); (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by_01 + bx_01].efence)-> timer = (float)fVar3; return TRUE; } } return 0; } void __cdecl lego::game::ElectricFence_SparkObjectAndCreateBeam (LegoObject *liveObj,Point2F *objWorldPos,uint bx,uint by) { uint weaponID; float10 fVar1; float10 fVar2; float10 fVar3; BOOL hit; float elapsed; Point2F *dir; Point2F local_2c; Point2F worldPos; lego::map::Map3D_BlockToWorldPos((globs::efenceGlobs.level)->map,bx,by,&worldPos.x,&worldPos.y); fVar1 = lego::map::Map3D_GetWorldZ((globs::efenceGlobs.level)->map,worldPos.x,worldPos.y); local_2c.x = objWorldPos->x; local_2c.y = objWorldPos->y; fVar2 = lego::map::Map3D_GetWorldZ((globs::efenceGlobs.level)->map,local_2c.x,local_2c.y); fVar3 = stats::StatsObject_GetCollHeight(liveObj); local_2c.x = local_2c.x - worldPos.x; local_2c.y = local_2c.y - worldPos.y; effect::Effect_ElectricFenceBeam_Spawn (FALSE,worldPos.x,worldPos.y,(float)fVar1,local_2c.x,local_2c.y, (float)(((float10)(float)fVar2 - fVar3 * (float10)0.5) - (float10)(float)fVar1)); dir = &local_2c; elapsed = 0.0; hit = TRUE; weaponID = tools::Weapon_GetWeaponIDByName("FenceSpark"); tools::Weapon_GenericDamageObject(liveObj,weaponID,hit,elapsed,dir); LegoObject_StartCrumbling(liveObj); return; } BOOL __cdecl lego::game::ElectricFence_Block_FUN_0040e110(Lego_Level *level,uint bx,uint by) { uint uVar1; BOOL BVar2; uint uVar3; int bx_01; int by_01; int *piVar4; int bx_00; int by_00; Point2I DIRECTIONS [4]; uVar1 = by; DIRECTIONS[0].y = 1; DIRECTIONS[1].x = 1; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[3].y = 0; if (((globs::efenceGlobs.fenceGrid == NULL) || (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence != NULL)) || (BVar2 = ElectricFence_CheckBuildingAtBlock(level,bx,by,0), BVar2 != 0)) { return 0; } piVar4 = &DIRECTIONS[0].y; by = 0; do { bx_00 = piVar4[-1] + bx; by_00 = uVar1 + *piVar4; if ((globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by_00 + bx_00].efence != NULL) || (BVar2 = ElectricFence_CheckBuildingAtBlock(level,bx_00,by_00,0), BVar2 != 0)) { uVar3 = by - 2 & 3; bx_01 = DIRECTIONS[uVar3].x + bx; by_01 = DIRECTIONS[uVar3].y + uVar1; if ((globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by_01 + bx_01].efence != NULL) || ((BVar2 = ElectricFence_CheckBuildingAtBlock(level,bx_01,by_01,0), BVar2 != 0 && (BVar2 = ElectricFence_CheckBuildingAtBlock(level,bx_00,by_00,0), BVar2 == 0)))) { return TRUE; } } piVar4 = piVar4 + 2; by += 1; if (3 < by) { return 0; } } while( true ); } void __cdecl lego::game::ElectricFence_Block_ElecFenceStud_FUN_0040e280 (Lego_Level *level,uint bx,uint by,BOOL addNew) { LegoObject *pLVar1; float local_8; float local_4; if (globs::efenceGlobs.fenceGrid != NULL) { if (addNew == 0) { if (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].studObj != NULL) { LegoObject_Remove(globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx]. studObj); globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].studObj = NULL; globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].flags = FENCEGRID_FLAG_NONE; } } else { if (globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].studObj == NULL) { lego::map::Map3D_BlockToWorldPos(level->map,bx,by,&local_8,&local_4); pLVar1 = LegoObject_CreateInWorld (globs::legoGlobs.contElectricFenceStud,LegoObject_ElectricFenceStud,0,0, local_8,local_4,0.0); globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].studObj = pLVar1; return; } } } return; } BOOL __cdecl lego::game::ElectricFence_Block_IsFence(int bx,int by) { return (uint)(globs::efenceGlobs.fenceGrid[(globs::efenceGlobs.level)->width * by + bx].efence != NULL); } void __cdecl lego::front::Encyclopedia_Initialise(Config *config,char *gameName) { char *pcVar1; File *pFVar2; uint uVar3; File **ppFVar4; globs::encyclopediaGlobs.vehicleFiles = (File **)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4); ppFVar4 = globs::encyclopediaGlobs.vehicleFiles; for (uVar3 = globs::legoGlobs.vehicleCount; uVar3 != 0; uVar3 -= 1) { *ppFVar4 = NULL; ppFVar4 = ppFVar4 + 1; } uVar3 = 0; if (globs::legoGlobs.vehicleCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (gameName,"Encyclopedia",globs::legoGlobs.vehicleName[uVar3],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { pFVar2 = io::File_Open(pcVar1,"r"); globs::encyclopediaGlobs.vehicleFiles[uVar3] = pFVar2; } uVar3 += 1; } while (uVar3 < globs::legoGlobs.vehicleCount); } globs::encyclopediaGlobs.minifigureFiles = (File **)io::Mem_Alloc(globs::legoGlobs.miniFigureCount * 4); ppFVar4 = globs::encyclopediaGlobs.minifigureFiles; for (uVar3 = globs::legoGlobs.miniFigureCount; uVar3 != 0; uVar3 -= 1) { *ppFVar4 = NULL; ppFVar4 = ppFVar4 + 1; } uVar3 = 0; if (globs::legoGlobs.miniFigureCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (gameName,"Encyclopedia",globs::legoGlobs.miniFigureName[uVar3],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { pFVar2 = io::File_Open(pcVar1,"r"); globs::encyclopediaGlobs.minifigureFiles[uVar3] = pFVar2; } uVar3 += 1; } while (uVar3 < globs::legoGlobs.miniFigureCount); } globs::encyclopediaGlobs.rockmonsterFiles = (File **)io::Mem_Alloc(globs::legoGlobs.rockMonsterCount * 4); ppFVar4 = globs::encyclopediaGlobs.rockmonsterFiles; for (uVar3 = globs::legoGlobs.rockMonsterCount; uVar3 != 0; uVar3 -= 1) { *ppFVar4 = NULL; ppFVar4 = ppFVar4 + 1; } uVar3 = 0; if (globs::legoGlobs.rockMonsterCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (gameName,"Encyclopedia",globs::legoGlobs.rockMonsterName[uVar3],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { pFVar2 = io::File_Open(pcVar1,"r"); globs::encyclopediaGlobs.rockmonsterFiles[uVar3] = pFVar2; } uVar3 += 1; } while (uVar3 < globs::legoGlobs.rockMonsterCount); } globs::encyclopediaGlobs.buildingFiles = (File **)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4); ppFVar4 = globs::encyclopediaGlobs.buildingFiles; for (uVar3 = globs::legoGlobs.buildingCount; uVar3 != 0; uVar3 -= 1) { *ppFVar4 = NULL; ppFVar4 = ppFVar4 + 1; } uVar3 = 0; if (globs::legoGlobs.buildingCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (gameName,"Encyclopedia",globs::legoGlobs.buildingName[uVar3],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { pFVar2 = io::File_Open(pcVar1,"r"); globs::encyclopediaGlobs.buildingFiles[uVar3] = pFVar2; } uVar3 += 1; } while (uVar3 < globs::legoGlobs.buildingCount); } pcVar1 = cfg::Config_BuildStringID(gameName,"Encyclopedia","PowerCrystal",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::encyclopediaGlobs.powercrystalFile = io::File_Open(pcVar1,"r"); } pcVar1 = cfg::Config_BuildStringID(gameName,"Encyclopedia","Ore",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::encyclopediaGlobs.oreFile = io::File_Open(pcVar1,"r"); } return; } void __cdecl lego::front::Encyclopedia_SelectObject(LegoObject *liveObj) { LegoObject *pLVar1; LegoObject_Type local_4; pLVar1 = liveObj; game::LegoObject_GetTypeAndID(liveObj,&local_4,(LegoObject_ID *)&liveObj); if (false) { switchD_0040e655_caseD_5: globs::encyclopediaGlobs.currentObjFile = NULL; globs::encyclopediaGlobs.flags = globs::encyclopediaGlobs.flags & ~ENCYCLOPEDIA_GLOB_FLAG_ACTIVE ; return; } switch(local_4) { case LegoObject_Vehicle: globs::encyclopediaGlobs.currentObjFile = globs::encyclopediaGlobs.vehicleFiles[(int)liveObj]; break; case LegoObject_MiniFigure: globs::encyclopediaGlobs.currentObjFile = globs::encyclopediaGlobs.minifigureFiles[(int)liveObj] ; break; case LegoObject_RockMonster: globs::encyclopediaGlobs.currentObjFile = globs::encyclopediaGlobs.rockmonsterFiles[(int)liveObj]; break; case LegoObject_Building: globs::encyclopediaGlobs.currentObjFile = globs::encyclopediaGlobs.buildingFiles[(int)liveObj]; break; default: goto switchD_0040e655_caseD_5; case LegoObject_PowerCrystal: globs::encyclopediaGlobs.currentObjFile = globs::encyclopediaGlobs.powercrystalFile; break; case LegoObject_Ore: globs::encyclopediaGlobs.currentObjFile = globs::encyclopediaGlobs.oreFile; } globs::encyclopediaGlobs.flags |= ENCYCLOPEDIA_GLOB_FLAG_ACTIVE|ENCYCLOPEDIA_GLOB_FLAG_NEEDSTEXT; globs::encyclopediaGlobs.currentObj = pLVar1; Panel_TextWindow_Clear(globs::panelGlobs.encyclopediaTextWnd); return; } void __cdecl lego::front::Encyclopedia_ClearSelection(void) { globs::encyclopediaGlobs.flags = globs::encyclopediaGlobs.flags & ~ENCYCLOPEDIA_GLOB_FLAG_ACTIVE; return; } void __cdecl lego::front::Encyclopedia_Update(float elapsedAbs) { BOOL BVar1; char *str; char buff [512]; if (((globs::encyclopediaGlobs.flags & ENCYCLOPEDIA_GLOB_FLAG_ACTIVE) != ENCYCLOPEDIA_GLOB_FLAG_NONE) && (BVar1 = Panel_IsFullyClosed(Panel_Encyclopedia), BVar1 == 0) ) { if ((globs::encyclopediaGlobs.flags & ENCYCLOPEDIA_GLOB_FLAG_NEEDSTEXT) != ENCYCLOPEDIA_GLOB_FLAG_NONE) { if (globs::encyclopediaGlobs.currentObjFile == NULL) { Panel_TextWindow_PrintF (globs::panelGlobs.encyclopediaTextWnd,"Object has no encyclopedia file."); } else { io::File_Seek(globs::encyclopediaGlobs.currentObjFile,0,SEEK_SET); str = io::File_GetS(buff,0x200,globs::encyclopediaGlobs.currentObjFile); while (str != NULL) { Panel_TextWindow_PrintF(globs::panelGlobs.encyclopediaTextWnd,"%s",buff); str = io::File_GetS(buff,0x200,globs::encyclopediaGlobs.currentObjFile); } } globs::encyclopediaGlobs.flags &= ~ENCYCLOPEDIA_GLOB_FLAG_NEEDSTEXT; } Panel_TextWindow_Update(globs::panelGlobs.encyclopediaTextWnd,0,elapsedAbs); } return; } void __cdecl lego::front::Encyclopedia_DrawSelectBox(Viewport *viewMain) { if (((((byte)globs::encyclopediaGlobs.flags & ENCYCLOPEDIA_GLOB_FLAG_ACTIVE) != 0) && (((byte)globs::panelGlobs.panelTable[11].flags & PANEL_FLAG_OPEN) != 0)) && (globs::encyclopediaGlobs.currentObj != NULL)) { lrr::Lego_DrawObjectSelectionBox(globs::encyclopediaGlobs.currentObj,viewMain,0.0,1.0,0.0); } return; } // Removes the current encyclopedia object if it matches the specified object. void __cdecl lego::front::Encyclopedia_RemoveCurrentReference(LegoObject *liveObj) { if (globs::encyclopediaGlobs.currentObj == liveObj) { globs::encyclopediaGlobs.currentObj = NULL; } return; } void __cdecl lego::game::Erode_Initialise(float triggerTime,float erodeTime,float lockTime) { int iVar1; BOOL *pBVar2; globs::erodeGlobs.ErodeTriggerTime = triggerTime * 25.0; globs::erodeGlobs.ErodeErodeTime = erodeTime * 25.0 * 0.2; globs::erodeGlobs.ErodeLockTime = lockTime * 25.0; globs::erodeGlobs.UnkBlocksCount = 0; pBVar2 = globs::erodeGlobs.activeStates; for (iVar1 = 2000; iVar1 != 0; iVar1 += -1) { *pBVar2 = 0; pBVar2 = pBVar2 + 1; } pBVar2 = globs::erodeGlobs.lockedStates; for (iVar1 = 1000; iVar1 != 0; iVar1 += -1) { *pBVar2 = 0; pBVar2 = pBVar2 + 1; } return; } BOOL __cdecl lego::game::Erode_GetFreeActiveIndex(int *out_index) { float *pfVar1; int index; index = 0; pfVar1 = (float *)globs::erodeGlobs.activeStates; do { if (*pfVar1 == 0.0) { *out_index = index; return TRUE; } pfVar1 = pfVar1 + 1; index += 1; } while (pfVar1 < globs::erodeGlobs.activeTimers); return 0; } // return (float)(6 - block->erodeSpeed) * erodeGlobs.ErodeErodeTime * 25.0f float10 __cdecl lego::game::Erode_GetBlockErodeRate(Point2I *blockPos) { return (float10)(6 - (uint)(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x]. erodeSpeed) * (float10)globs::erodeGlobs.ErodeErodeTime * (float10)25.0 ; } void __cdecl lego::game::Erode_AddActiveBlock(Point2I *blockPos,int unkModulusNum) { Lego_Level *pLVar1; BOOL BVar2; float10 fVar3; int erodeIndex; int local_8; undefined4 local_4; pLVar1 = globs::legoGlobs.currLevel; BVar2 = Erode_GetFreeActiveIndex(&erodeIndex); if (BVar2 != 0) { pLVar1->blocks[blockPos->y * pLVar1->width + blockPos->x].erodeLevel = (byte)unkModulusNum; globs::erodeGlobs.activeBlocks[erodeIndex].x = blockPos->x; globs::erodeGlobs.activeBlocks[erodeIndex].y = blockPos->y; fVar3 = Erode_GetBlockErodeRate(blockPos); local_8 = unkModulusNum + 1; local_4 = 0; globs::erodeGlobs.activeTimers[erodeIndex] = (float)(fVar3 / (float10)local_8); globs::erodeGlobs.activeStates[erodeIndex] = TRUE; Erode_Block_FUN_0040ed80(blockPos,TRUE); } return; } void __cdecl lego::game::Erode_Update(float elapsedGame) { float fVar1; Lego_Level *level; char cVar2; short sVar3; BOOL BVar4; int iVar5; float *pfVar6; uint uVar7; Point2I *blockPos; float10 fVar8; longlong lVar9; longlong lVar10; MiscEffectType miscEffectType; int local_24; Point2I local_20; Vector3F local_18; Vector3F local_c; level = globs::legoGlobs.currLevel; sVar3 = math::Maths_Rand(); globs::erodeGlobs.elapsedTimer = elapsedGame + globs::erodeGlobs.elapsedTimer; // if (globals::g_ErodeTimer > globals:g_ErodeTriggerTime) { if ((ushort)((ushort)(globs::erodeGlobs.elapsedTimer < globs::erodeGlobs.ErodeTriggerTime) << 8 | (ushort)(globs::erodeGlobs.elapsedTimer == globs::erodeGlobs.ErodeTriggerTime) << 0xe) == 0) { BVar4 = Erode_GetFreeActiveIndex(&local_24); if ((BVar4 != 0) && (uVar7 = 0, globs::erodeGlobs.UnkBlocksCount != 0)) { do { BVar4 = Erode_FindAdjacentBlockPos (globs::erodeGlobs.UnkBlocksList + ((int)sVar3 + uVar7) % globs::erodeGlobs.UnkBlocksCount,&local_20); if (BVar4 != 0) { BVar4 = Level_Block_IsPath(&local_20); if ((BVar4 == 0) || ((*(byte *)&level->blocks[local_20.y * level->width + local_20.x].flags2 & 0x10) != 0)) { iVar5 = local_20.y * level->width + local_20.x; level->blocks[iVar5].flags2 = level->blocks[iVar5].flags2 & ~BLOCK2_ERODELOCKED; globs::erodeGlobs.activeBlocks[local_24].x = local_20.x; globs::erodeGlobs.activeBlocks[local_24].y = local_20.y; fVar8 = Erode_GetBlockErodeRate(globs::erodeGlobs.activeBlocks + local_24); globs::erodeGlobs.activeTimers[local_24] = (float)fVar8; globs::erodeGlobs.activeStates[local_24] = 1; level->blocks[local_20.y * level->width + local_20.x].erodeLevel = 0; Erode_Block_FUN_0040ed80(&local_20,TRUE); front::Info_Send(Info_LavaErode,NULL,NULL,&local_20); break; } Erode_AddLockedBlock(&local_20); iVar5 = local_20.y * level->width + local_20.x; level->blocks[iVar5].flags2 = level->blocks[iVar5].flags2 | BLOCK2_ERODELOCKED; } uVar7 += 1; } while (uVar7 < globs::erodeGlobs.UnkBlocksCount); } globs::erodeGlobs.elapsedTimer = 0.0; } pfVar6 = globs::erodeGlobs.activeTimers; blockPos = globs::erodeGlobs.activeBlocks; do { if (pfVar6[-2000] != 0.0) { fVar8 = Erode_GetBlockErodeRate(blockPos); lVar9 = __ftol(((float10)*pfVar6 / fVar8) * (float10)4.0); *pfVar6 = *pfVar6 - elapsedGame; fVar8 = Erode_GetBlockErodeRate(blockPos); lVar10 = __ftol(((float10)*pfVar6 / fVar8) * (float10)4.0); cVar2 = (char)lVar10; if (cVar2 == (char)lVar9) goto LAB_0040ecc3; level->blocks[blockPos->y * level->width + blockPos->x].erodeLevel = 4 - cVar2; lego::map::Map3D_BlockToWorldPos(level->map,blockPos->x,blockPos->y,&local_18.x,&local_18.y); fVar8 = lego::map::Map3D_GetWorldZ(level->map,local_18.x,local_18.y); local_18.z = (float)fVar8; math::Maths_Vector3DRandom(&local_c); local_c.z = 0.0; switch(cVar2) { case '\0': pfVar6[-2000] = 0.0; level->blocks[blockPos->y * level->width + blockPos->x].terrain = Lego_SurfaceType8_Lava; miscEffectType = MISCOBJECT_LAVAEROSIONSMOKE1; break; case '\x01': miscEffectType = MISCOBJECT_LAVAEROSIONSMOKE2; break; case '\x02': miscEffectType = MISCOBJECT_LAVAEROSIONSMOKE3; break; case '\x03': miscEffectType = MISCOBJECT_LAVAEROSIONSMOKE4; break; default: goto switchD_0040ec49_caseD_4; } effect::Effect_Spawn_Particle(miscEffectType,&local_18,&local_c); switchD_0040ec49_caseD_4: Level_BlockUpdateSurface(level,blockPos->x,blockPos->y,0); } LAB_0040ecc3: blockPos = blockPos + 1; pfVar6 = pfVar6 + 1; if ((Point2I *)globs::erodeGlobs.activeStates <= blockPos) { pfVar6 = (float *)globs::erodeGlobs.lockedStates; do { if ((*pfVar6 != 0.0) && (fVar1 = pfVar6[-1000], pfVar6[-1000] = fVar1 - elapsedGame, fVar1 - elapsedGame < 0.0)) { *pfVar6 = 0.0; } pfVar6 = pfVar6 + 1; } while (pfVar6 < &globs::erodeGlobs.elapsedTimer); return; } } while( true ); } void __cdecl lego::game::Erode_AddLockedBlock(Point2I *blockPos) { BOOL *pLockState; int iVar1; iVar1 = 0; pLockState = globs::erodeGlobs.lockedStates; do { if (*pLockState == FALSE) { globs::erodeGlobs.lockedBlocks[iVar1].x = blockPos->x; globs::erodeGlobs.lockedBlocks[iVar1].y = blockPos->y; globs::erodeGlobs.lockedTimers[iVar1] = globs::erodeGlobs.ErodeLockTime; globs::erodeGlobs.lockedStates[iVar1] = 1; return; } pLockState = pLockState + 1; iVar1 += 1; } while (pLockState < &globs::erodeGlobs.elapsedTimer); return; } void __cdecl lego::game::Erode_Block_FUN_0040ed80(Point2I *blockPos,BOOL doState2_else_add3) { uint uVar1; int iVar2; uint uVar3; Point2I *pBlock; Erode_Globs *pEVar4; Lego_Level *level; level = globs::legoGlobs.currLevel; uVar1 = globs::erodeGlobs.UnkBlocksCount; if (doState2_else_add3 == 0) { uVar3 = 0; if (globs::erodeGlobs.UnkBlocksCount != 0) { pEVar4 = &globs::erodeGlobs; do { if ((blockPos->x == pEVar4->UnkBlocksList[0].x) && (blockPos->y == pEVar4->UnkBlocksList[0].y)) { iVar2 = globs::erodeGlobs.UnkBlocksCount - 1; globs::erodeGlobs.UnkBlocksCount = globs::erodeGlobs.UnkBlocksCount - 1; globs::erodeGlobs.UnkBlocksList[uVar3].x = globs::erodeGlobs.UnkBlocksList[iVar2].x; globs::erodeGlobs.UnkBlocksList[uVar3].y = globs::erodeGlobs.UnkBlocksList[uVar1 - 1].y; iVar2 = level->width * blockPos->y + blockPos->x; level->blocks[iVar2].flags1 = level->blocks[iVar2].flags1 & ~BLOCK1_ERODEACTIVE; break; } uVar3 += 1; pEVar4 = (Erode_Globs *)(pEVar4->UnkBlocksList + 1); } while (uVar3 < globs::erodeGlobs.UnkBlocksCount); } iVar2 = 0; pBlock = globs::erodeGlobs.activeBlocks; do { if ((blockPos->x == pBlock->x) && (blockPos->y == pBlock->y)) { globs::erodeGlobs.activeStates[iVar2] = 0; break; } pBlock = pBlock + 1; iVar2 += 1; } while (pBlock <= (Point2I *)((int)&globs::erodeGlobs.activeBlocks[1999].y + 3U)); Erode_AddLockedBlock(blockPos); } else { if ((((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1 & BLOCK1_ERODEACTIVE) == BLOCK1_NONE) && (globs::erodeGlobs.UnkBlocksCount < 2000)) { globs::erodeGlobs.UnkBlocksList[globs::erodeGlobs.UnkBlocksCount].x = blockPos->x; globs::erodeGlobs.UnkBlocksList[globs::erodeGlobs.UnkBlocksCount].y = blockPos->y; globs::erodeGlobs.UnkBlocksCount += 1; Level_Block_Proc_FUN_004301e0(blockPos); iVar2 = level->width * blockPos->y + blockPos->x; level->blocks[iVar2].flags1 = level->blocks[iVar2].flags1 | BLOCK1_ERODEACTIVE; return; } } return; } BOOL __cdecl lego::game::Erode_IsBlockLocked(Point2I *blockPos) { BOOL *pLockState; Point2I *pLockBlock; pLockBlock = globs::erodeGlobs.lockedBlocks; pLockState = globs::erodeGlobs.lockedStates; while (((*pLockState == FALSE || (blockPos->x != pLockBlock->x)) || (blockPos->y != pLockBlock->y) )) { pLockState = pLockState + 1; pLockBlock = pLockBlock + 1; if ((BOOL *)((int)globs::erodeGlobs.lockedStates + 3999U) < pLockState) { return 0; } } return TRUE; } BOOL __cdecl lego::game::Erode_FindAdjacentBlockPos(Point2I *blockPos,Point2I *out_adjacentblockPos) { Lego_Block *pLVar1; BlockFlags1 BVar2; Lego_Level *pLVar3; Point2I *pPVar4; BOOL BVar5; int iVar6; int *piVar7; Point2I DIRECTIONS [4]; pPVar4 = blockPos; pLVar3 = globs::legoGlobs.currLevel; DIRECTIONS[1].x = 1; DIRECTIONS[2].y = 1; DIRECTIONS[0].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].y = 0; if ((globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].terrain != Lego_SurfaceType8_Lava) { return 0; } blockPos = NULL; piVar7 = &DIRECTIONS[0].y; do { iVar6 = *piVar7; out_adjacentblockPos->x = piVar7[-1] + pPVar4->x; iVar6 = pPVar4->y + iVar6; out_adjacentblockPos->y = iVar6; pLVar1 = pLVar3->blocks + pLVar3->width * iVar6 + out_adjacentblockPos->x; BVar2 = pLVar1->flags1; if ((((BVar2 & BLOCK1_ERODEACTIVE) == BLOCK1_NONE) && ((BVar2 & BLOCK1_FLOOR) != BLOCK1_NONE)) && (pLVar1->erodeSpeed != Lego_ErodeType_None)) { BVar5 = Erode_IsBlockLocked(out_adjacentblockPos); if (BVar5 == 0) { return TRUE; } } piVar7 = piVar7 + 2; blockPos = (Point2I *)((int)&blockPos->x + 1); } while (blockPos < (Point2I *)&DAT_00000004); return 0; } void __cdecl lego::game::Fallin_Update(float elapsedGame) { short rng; Map3D *map; BOOL BVar1; uint i; Point2I blockPos; map = lrr::Lego_GetMap(); globs::s_Fallin_ElapsedTimer = globs::s_Fallin_ElapsedTimer - elapsedGame; // if (floatVal <= 0.0f) if ((ushort)((ushort)(globs::s_Fallin_ElapsedTimer < 0.0) << 8 | (ushort)(globs::s_Fallin_ElapsedTimer == 0.0) << 0xe) != 0) { i = 0; do { rng = math::Maths_Rand(); blockPos.x = (uint)(int)rng % map->blockWidth; rng = math::Maths_Rand(); blockPos.y = (uint)(int)rng % map->blockHeight; BVar1 = Fallin_Block_FUN_0040f0c0(&blockPos,TRUE); if (BVar1 != 0) { front::Info_Send(Info_Landslide,NULL,NULL,&blockPos); break; } i += 1; } while (i < 100); rng = math::Maths_Rand(); // div by 50 (0x32) globs::s_Fallin_ElapsedTimer = (float)((int)rng % 0x32) - -750.0; } return; } BOOL __cdecl lego::game::Fallin_Block_FUN_0040f0c0(Point2I *blockPos,BOOL allowCaveIn) { BOOL BVar1; DirectionFlags fallinDirs; int *pDirY; uint i; int count; Point2I blockOffPos; Point2I DIRECTIONS [4]; bool notSolidOrReinforced; i = 0; notSolidOrReinforced = true; fallinDirs = DIRECTION_FLAG_NONE; count = 0; lrr::Lego_GetMap(); DIRECTIONS[0].x = 0; DIRECTIONS[0].y = -1; DIRECTIONS[1].x = 1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = 1; DIRECTIONS[3].x = -1; DIRECTIONS[3].y = 0; BVar1 = Fallin_Block_UpdateFallinsUnk1(blockPos); if (BVar1 != 0) { pDirY = &DIRECTIONS[0].y; do { blockOffPos.x = pDirY[-1] + blockPos->x; blockOffPos.y = *pDirY + blockPos->y; BVar1 = Level_Block_IsWall(blockOffPos.x,blockOffPos.y); if (BVar1 != 0) { BVar1 = Level_Block_IsImmovable(&blockOffPos); if (BVar1 == 0) { BVar1 = Level_Block_IsReinforced(blockOffPos.x,blockOffPos.y); if (BVar1 != 0) goto LAB_0040f164; } else { LAB_0040f164: notSolidOrReinforced = false; } fallinDirs |= 1 << ((byte)i & 0x1f); BVar1 = Level_Block_IsCorner(blockOffPos.x,blockOffPos.y); if (BVar1 == 0) { count += 1; } } i += 1; pDirY = pDirY + 2; } while (i < 4); if (((notSolidOrReinforced) && (fallinDirs != DIRECTION_FLAG_NONE)) && (count != 0)) { Fallin_Block_FUN_0040f260(blockPos,fallinDirs,allowCaveIn); return TRUE; } } return FALSE; } BOOL __cdecl lego::game::Fallin_Block_UpdateFallinsUnk1(Point2I *blockPos) { BOOL BVar1; Lego_Level *level; Lego_SurfaceType8 terrain; level = globs::legoGlobs.currLevel; BVar1 = Level_Block_IsGround(blockPos->x,blockPos->y); if ((((BVar1 != 0) && (BVar1 = Level_Block_IsBusy(blockPos), BVar1 == 0)) && (terrain = level->blocks[level->width * blockPos->y + blockPos->x].terrain, terrain != Lego_SurfaceType8_Lava)) && ((terrain != Lego_SurfaceType8_Lake && (terrain != Lego_SurfaceType8_Water)))) { if ((level->SafeCaverns != BOOL3_FALSE) && (BVar1 = Level_Block_IsExposed(blockPos), BVar1 != 0) ) { return 0; } return TRUE; } return 0; } // WARNING: Unable to use type for symbol fallinDirs_00 void __cdecl lego::game::Fallin_Block_FUN_0040f260(Point2I *blockPos,DirectionFlags fallinDirs,BOOL allowCaveIn) { int rubbleCleared; Direction direction; BOOL BVar1; int idx; RockFallType rockFallType; float10 zPos; float dirX; float dirY; float xPos; Vector3F sfx3DPos; Point2F DIRECTIONS_F [4]; DirectionFlags fallinDirs_00; Point2I *blockPos_00; blockPos_00 = blockPos; DIRECTIONS_F[0].x = 0.0; DIRECTIONS_F[0].y = 1.0; DIRECTIONS_F[1].x = 1.0; DIRECTIONS_F[1].y = 0.0; DIRECTIONS_F[2].x = 0.0; DIRECTIONS_F[2].y = -1.0; DIRECTIONS_F[3].x = -1.0; DIRECTIONS_F[3].y = 0.0; // Remove all existing rubble layers so we can overwrite them. // This is probably what causes Ore spawns to be removed from rubble. rubbleCleared = Level_Block_ClearRubbleLayer(blockPos); while (rubbleCleared == 0) { rubbleCleared = Level_Block_ClearRubbleLayer(blockPos_00); } ai::AITask_DoClearTypeAction(blockPos_00,Message_ClearFallInComplete); fallinDirs_00 = fallinDirs; direction = (Direction)blockPos; rockFallType = (RockFallType)blockPos; switch(fallinDirs) { case DIRECTION_FLAG_N: case DIRECTION_FLAG_SEW: direction = DIRECTION_UP; rockFallType = ROCKFALL_3SIDES; break; case DIRECTION_FLAG_E: case DIRECTION_FLAG_EW: case DIRECTION_FLAG_NSW: direction = DIRECTION_RIGHT; rockFallType = ROCKFALL_3SIDES; break; case DIRECTION_FLAG_NE: direction = DIRECTION_RIGHT; rockFallType = ROCKFALL_OUTSIDECORNER; break; case DIRECTION_FLAG_S: case DIRECTION_FLAG_NS: case DIRECTION_FLAG_NEW: direction = DIRECTION_DOWN; rockFallType = ROCKFALL_3SIDES; break; case DIRECTION_FLAG_SE: direction = DIRECTION_DOWN; rockFallType = ROCKFALL_OUTSIDECORNER; break; case DIRECTION_FLAG_NSE: case DIRECTION_FLAG_W: direction = DIRECTION_LEFT; rockFallType = ROCKFALL_3SIDES; break; case DIRECTION_FLAG_NW: direction = DIRECTION_UP; rockFallType = ROCKFALL_OUTSIDECORNER; break; case DIRECTION_FLAG_SW: direction = DIRECTION_LEFT; rockFallType = ROCKFALL_OUTSIDECORNER; } lego::map::Map3D_BlockToWorldPos ((globs::legoGlobs.currLevel)->map,blockPos_00->x,blockPos_00->y,&xPos, (float *)&blockPos); dirY = DIRECTIONS_F[direction].y; dirX = DIRECTIONS_F[direction].x; zPos = lego::map::Map3D_GetWorldZ((globs::legoGlobs.currLevel)->map,xPos,(float)blockPos); BVar1 = effect::Effect_Spawn_RockFall (rockFallType,blockPos_00->x,blockPos_00->y,xPos,blockPos,(float)zPos,dirX,dirY) ; if (BVar1 != 0) { sfx3DPos.y = (float)blockPos; sfx3DPos.x = xPos; zPos = lego::map::Map3D_GetWorldZ((globs::legoGlobs.currLevel)->map,xPos,(float)blockPos); sfx3DPos.z = (float)zPos; idx = (globs::legoGlobs.currLevel)->width * blockPos_00->y + blockPos_00->x; (globs::legoGlobs.currLevel)->blocks[idx].flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1 | BLOCK1_ROCKFALLFX; idx = (globs::legoGlobs.currLevel)->width * blockPos_00->y + blockPos_00->x; (globs::legoGlobs.currLevel)->blocks[idx].flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1 | BLOCK1_LANDSLIDING; Level_Block_SetBusy(blockPos_00,TRUE); snd::SFX_Random_PlaySound3DOnContainer(NULL,SFX_FallIn,FALSE,FALSE,&sfx3DPos); } if ((allowCaveIn != 0) && (idx = (globs::legoGlobs.currLevel)->width * blockPos_00->y + blockPos_00->x, (globs::legoGlobs.currLevel)->blocks[idx].numLandSlides = (globs::legoGlobs.currLevel)->blocks[idx].numLandSlides + 1, globs::fallinGlobs_NumberOfLandSlidesTillCaveIn <= (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos_00->y + blockPos_00->x].numLandSlides)) { Fallin_LandSlideDoCaveIn(blockPos_00,fallinDirs_00); front::Info_Send(Info_Landslide,NULL,NULL,blockPos_00); } Level_BlockUpdateSurface(globs::legoGlobs.currLevel,blockPos_00->x,blockPos_00->y,0); return; } void __cdecl lego::game::Fallin_Initialise(int numLandSlidesTillCaveIn) { globs::fallinGlobs_NumberOfLandSlidesTillCaveIn = numLandSlidesTillCaveIn; return; } void __cdecl lego::game::Fallin_LandSlideDoCaveIn(Point2I *blockPos,DirectionFlags fallinDirs) { BOOL BVar1; int i; int *pAngleY; Point2I pAngle; Point2I ANGLES [8]; ANGLES[0].x = 0; ANGLES[0].y = 1; ANGLES[1].x = 1; ANGLES[1].y = 1; ANGLES[2].x = 1; ANGLES[2].y = 0; ANGLES[3].x = 1; ANGLES[3].y = -1; ANGLES[4].x = 0; ANGLES[4].y = -1; ANGLES[5].x = -1; ANGLES[5].y = -1; ANGLES[6].x = -1; ANGLES[6].y = 0; ANGLES[7].x = -1; ANGLES[7].y = 1; pAngleY = &ANGLES[0].y; i = 8; do { pAngle.x = pAngleY[-1] + blockPos->x; pAngle.y = blockPos->y + *pAngleY; BVar1 = lego::map::Map3D_IsInsideDimensions((globs::legoGlobs.currLevel)->map,pAngle.x,pAngle.y) ; if (BVar1 != 0) { BVar1 = Fallin_Block_FUN_0040f0c0(&pAngle,FALSE); if (BVar1 == 0) { BVar1 = Fallin_Block_UpdateFallinsUnk1(&pAngle); if (BVar1 != 0) { Fallin_Block_FUN_0040f260(&pAngle,fallinDirs,FALSE); } } } pAngleY = pAngleY + 2; i += -1; } while (i != 0); return; } FlocksItem * __cdecl lego::game::Flocks_LiveObject_Flocks_CreateSubdata (Vector3F *vector_1,Vector3F *vector_2,float turn,float speed,float tightness, float goalUpdate,Container *cont) { FlocksItem *pFVar1; pFVar1 = (FlocksItem *)io::Mem_Alloc(0xa0); if (pFVar1 == NULL) { return NULL; } pFVar1->float_30 = 0.0; pFVar1->rotationZ_2c = 0.0; pFVar1->rotationX_28 = 0.0; pFVar1->rotationY_24 = 0.0; (pFVar1->vector_18).y = 0.0; (pFVar1->vector_18).x = 0.0; (pFVar1->vector_18).z = 1.0; if (vector_2 == NULL) { (pFVar1->vector_0).x = 0.0; (pFVar1->vector_0).y = 0.0; (pFVar1->vector_0).z = 0.0; } else { (pFVar1->vector_0).x = vector_2->x; (pFVar1->vector_0).y = vector_2->y; (pFVar1->vector_0).z = vector_2->z; } if (vector_1 == NULL) { (pFVar1->vector_c).x = 0.0; (pFVar1->vector_c).y = 0.0; (pFVar1->vector_c).z = 0.0; } else { (pFVar1->vector_c).x = vector_1->x; (pFVar1->vector_c).y = vector_1->y; (pFVar1->vector_c).z = vector_1->z; } pFVar1->float_34 = 0.0; pFVar1->Turn2 = turn; pFVar1->Turn1 = turn; pFVar1->Speed2 = speed; pFVar1->Speed1 = speed; pFVar1->Tightness2 = tightness; pFVar1->Tightness1 = tightness; pFVar1->GoalUpdate2 = goalUpdate; pFVar1->GoalUpdate1 = goalUpdate; pFVar1->cont = cont; return pFVar1; } // Shared function used by multiple modules. void __cdecl lego::util::freeNonNull(void *ptr) { if (ptr != NULL) { io::Mem_Free(ptr); } return; } Flocks * __cdecl lego::game::Flocks_LiveObject_Flocks_CreateData (Vector3F *vector_1,Vector3F *vector_2,float turn,float speed,float tightness, Container *cont) { Flocks *pFVar1; FlocksItem *pFVar2; pFVar1 = (Flocks *)io::Mem_Alloc(0x28); if (pFVar1 == NULL) { return NULL; } pFVar2 = Flocks_LiveObject_Flocks_CreateSubdata(vector_1,vector_2,turn,speed,tightness,0.0,cont); pFVar1->flocksSubdata1 = pFVar2; if (vector_1 == NULL) { pFVar1->hasVector1 = 0; } else { pFVar1->hasVector1 = 1; } if (vector_2 != NULL) { pFVar1->hasVector2 = 1; pFVar1->flocksSubdata2 = NULL; pFVar1->numSubdata = 0; return pFVar1; } pFVar1->hasVector2 = 0; pFVar1->flocksSubdata2 = NULL; pFVar1->numSubdata = 0; return pFVar1; } void __cdecl lego::game::Flocks_FreeData(Flocks *flocksData) { FlocksItem *ptr; ptr = Flocks_Free_SubdataRecurse(flocksData); while (ptr != NULL) { util::freeNonNull(ptr); ptr = Flocks_Free_SubdataRecurse(flocksData); } util::freeNonNull(flocksData->flocksSubdata1); io::Mem_Free(flocksData); return; } void __cdecl lego::game::Flocks_Subdata_MathChangeRotationX(FlocksItem *flockSubdata,Vector3F *vector) { float fVar1; if ((ushort)((ushort)(vector->y < 1.0) << 8 | (ushort)(vector->y == 1.0) << 0xe) == 0) { fVar1 = flockSubdata->Turn1 + flockSubdata->rotationX_28; flockSubdata->rotationX_28 = fVar1; if ((ushort)((ushort)(fVar1 < 0.8) << 8 | (ushort)(fVar1 == 0.8) << 0xe) == 0) { flockSubdata->rotationX_28 = 0.8; return; } } else { if (-1.0 <= vector->y) { flockSubdata->rotationX_28 = flockSubdata->rotationX_28 * 0.95; return; } fVar1 = flockSubdata->rotationX_28 - flockSubdata->Turn1; flockSubdata->rotationX_28 = fVar1; if (fVar1 < -0.8) { flockSubdata->rotationX_28 = -0.8; return; } } return; } void __cdecl lego::game::Flocks_Subdata_MathChangeRotationsYZ(FlocksItem *subdata,Vector3F *ref_vector) { float fVar1; float fVar2; float fVar3; float fVar4; float fVar5; float fVar6; float fVar7; float fVar8; float fVar9; float fVar10; ref_vector->y = 0.0; (subdata->vector_18).y = 0.0; fVar1 = (subdata->vector_18).x; fVar7 = (subdata->vector_18).z; fVar1 = 1.0 / SQRT(fVar1 * fVar1 + fVar7 * fVar7 + 0.0); (subdata->vector_18).x = fVar1 * (subdata->vector_18).x; (subdata->vector_18).y = fVar1 * (subdata->vector_18).y; (subdata->vector_18).z = fVar1 * (subdata->vector_18).z; fVar8 = 1.0 / SQRT(ref_vector->x * ref_vector->x + ref_vector->z * ref_vector->z + ref_vector->y * ref_vector->y); fVar10 = fVar8 * ref_vector->x; fVar9 = fVar8 * ref_vector->y; fVar8 = fVar8 * ref_vector->z; ref_vector->x = fVar10; ref_vector->y = fVar9; ref_vector->z = fVar8; fVar1 = (subdata->vector_18).z; fVar7 = (subdata->vector_18).y; fVar2 = (subdata->vector_18).x; fVar3 = (subdata->vector_18).x; fVar4 = (subdata->vector_18).x; fVar5 = (subdata->vector_18).z; fVar6 = (subdata->vector_18).y; ref_vector->x = fVar9 * (subdata->vector_18).z - fVar8 * (subdata->vector_18).y; ref_vector->y = fVar3 * fVar8 - fVar10 * fVar5; ref_vector->z = fVar10 * fVar6 - fVar4 * fVar9; fVar1 = (1.0 - (fVar2 * fVar10 + fVar1 * fVar8 + fVar7 * fVar9)) * subdata->Turn1 * 10.0 * 0.5; if ((ushort)((ushort)(ref_vector->y < 0.01) << 8 | (ushort)(ref_vector->y == 0.01) << 0xe) == 0) { fVar1 = subdata->float_30 * 9.0 + fVar1; } else { if (0.01 <= ref_vector->y) goto LAB_0040fa04; fVar1 = subdata->float_30 * 9.0 - fVar1; } subdata->float_30 = fVar1 * 0.1; LAB_0040fa04: subdata->rotationY_24 = subdata->rotationY_24 + subdata->float_30; subdata->rotationZ_2c = -(subdata->float_30 * 9.0); return; } void __cdecl lego::game::Flocks_Subdata_Matrix_MultRotXYZ(FlocksItem *subdata) { Matrix4F matRotY; Matrix4F matRotZ; Matrix4F matRotX; Matrix4F matMultiply; math::Matrix_RotX(&matRotX,subdata->rotationX_28); math::Matrix_RotY(&matRotY,subdata->rotationY_24); math::Matrix_RotZ(&matRotZ,subdata->rotationZ_2c); math::Matrix_Mult(&matMultiply,&matRotY,&matRotX); math::Matrix_Mult(&subdata->matrix,&matMultiply,&matRotZ); return; } void __cdecl lego::game::Flocks_Callback_SubdataMoveAndTurn (Flocks *unused_flocksData,FlocksItem *subdata,float *pElapsed) { Vector3F *trans; float fVar1; float fVar2; float fVar3; float fVar4; Vector3F vector_b; Vector3F vector_a; Matrix4F matrix_b; Matrix4F matrix_a; vector_b.x = (subdata->vector_0).x - (subdata->vector_c).x; vector_b.y = (subdata->vector_0).y - (subdata->vector_c).y; trans = &subdata->vector_c; fVar2 = *pElapsed; vector_b.z = (subdata->vector_0).z - (subdata->vector_c).z; if (SQRT(vector_b.z * vector_b.z + vector_b.y * vector_b.y + vector_b.x * vector_b.x) < 1e-05) { math::Maths_Vector3DRandom(&vector_b); } Flocks_Subdata_MathChangeRotationX(subdata,&vector_b); Flocks_Subdata_MathChangeRotationsYZ(subdata,&vector_b); Flocks_Subdata_Matrix_MultRotXYZ(subdata); fVar1 = subdata->Speed1; fVar3 = (subdata->matrix).values[2][1]; fVar4 = (subdata->matrix).values[2][2]; (subdata->vector_18).x = (subdata->matrix).values[2][0]; fVar1 = fVar1 * fVar2; (subdata->vector_18).y = fVar3; (subdata->vector_18).z = fVar4; fVar2 = (subdata->vector_18).y; fVar3 = (subdata->vector_18).z; trans->x = (subdata->vector_18).x * fVar1 + trans->x; (subdata->vector_c).y = (subdata->vector_c).y + fVar2 * fVar1; (subdata->vector_c).z = (subdata->vector_c).z + fVar3 * fVar1; math::Matrix_Translate(&matrix_a,trans); math::Matrix_Copy(&matrix_b,&subdata->matrix); math::Matrix_Mult(&subdata->matrix,&matrix_a,&matrix_b); return; } // out_vector = random_vector() * { x, y, z } void __cdecl lego::math::Flocks_MathX_Vector3DRandomMultiply(Vector3F *out_vector,float x,float y,float z) { if (out_vector != NULL) { Maths_Vector3DRandom(out_vector); out_vector->x = x * out_vector->x; out_vector->y = y * out_vector->y; out_vector->z = z * out_vector->z; } return; } void __cdecl lego::game::Flocks_Callback_SubdataMoveTightness (Flocks *flocksData,FlocksItem *subData,float *pElapsed) { float fVar1; FlocksItem *pFVar2; float10 extraout_ST0; float10 fVar3; longlong lVar4; longlong lVar5; Vector3F direction; float tightness; fVar1 = subData->float_34; lVar4 = __ftol((float10)subData->float_34 / (float10)subData->GoalUpdate1); fVar3 = extraout_ST0; if (extraout_ST0 == (float10)0.0) { fVar3 = (float10)0.001; } fVar1 = (float)((float10)1.0 / fVar3 + (float10)fVar1); lVar5 = __ftol((float10)fVar1 / (float10)subData->GoalUpdate1); if ((int)lVar5 != (int)lVar4 && -1 < (int)lVar5 - (int)lVar4) { tightness = subData->Tightness1; math::Flocks_MathX_Vector3DRandomMultiply(&direction,tightness,tightness,tightness); pFVar2 = flocksData->flocksSubdata1; (subData->vector_0).x = (pFVar2->vector_c).x + direction.x; (subData->vector_0).y = (pFVar2->vector_c).y + direction.y; (subData->vector_0).z = (pFVar2->vector_c).z + direction.z; } subData->float_34 = fVar1; return; } void __cdecl lego::game::Flocks_SetVector2(Flocks *flocksData,Vector3F *vector2) { FlocksItem *pFVar1; pFVar1 = flocksData->flocksSubdata1; (pFVar1->vector_0).x = vector2->x; (pFVar1->vector_0).y = vector2->y; (pFVar1->vector_0).z = vector2->z; flocksData->hasVector2 = TRUE; return; } void __cdecl lego::game::Flocks_Subdata_MoveAndTurn(FlocksItem *subdata,float elapsed) { Flocks_Callback_SubdataMoveAndTurn(NULL,subdata,&elapsed); return; } void __cdecl lego::game::Flocks_Subdata_UpdateMove(Flocks *flocksData,float elapsed) { Flocks_Subdata_MoveAndTurn(flocksData->flocksSubdata1,elapsed); Flocks_CallbackForAllSubdata(flocksData,Flocks_Callback_SubdataMoveAndTurn,&elapsed); Flocks_CallbackForAllSubdata(flocksData,Flocks_Callback_SubdataMoveTightness,&elapsed); return; } void __cdecl lego::game::Flocks_LiveObject_Flocks_AddSubdata(Flocks *flockData,FlocksItem *subdata) { if ((flockData != NULL) && (subdata != NULL)) { subdata->subdataNext = flockData->flocksSubdata2; flockData->flocksSubdata2 = subdata; flockData->numSubdata = flockData->numSubdata + 1; } return; } FlocksItem * __cdecl lego::game::Flocks_Free_SubdataRecurse(Flocks *flocksData) { FlocksItem *pFVar1; FlocksItem *pFVar2; if ((flocksData != NULL) && (flocksData->numSubdata != 0)) { pFVar1 = flocksData->flocksSubdata2; pFVar2 = pFVar1->subdataNext; flocksData->numSubdata = flocksData->numSubdata - 1; flocksData->flocksSubdata2 = pFVar2; return pFVar1; } return NULL; } void __cdecl lego::game::Flocks_CallbackForAllSubdata(Flocks *flockData,FlocksCallback callback,void *data) { FlocksItem *subdata; for (subdata = flockData->flocksSubdata2; subdata != NULL; subdata = subdata->subdataNext) { (*callback)(flockData,subdata,data); } return; } // Maths_RandRange(0.0f, 1.0f) float10 __cdecl lego::math::Flocks_MathX_RandRangeOne(void) { float10 fVar1; fVar1 = Maths_RandRange(0.0,1.0); return fVar1; } void __cdecl lego::game::Flocks_Callback_FUN_0040fe00(Flocks *flocksData,FlocksItem *subdata,float *param_3) { float fVar1; float fVar2; float10 fVar3; fVar2 = *param_3; fVar3 = math::Flocks_MathX_RandRangeOne(); fVar2 = 1.0 / fVar2; fVar1 = (float)((fVar3 + fVar3) - (float10)1.0); subdata->Turn1 = fVar2 * fVar1 * subdata->Turn2 + subdata->Turn2; subdata->Tightness1 = fVar2 * fVar1 * subdata->Tightness2 + subdata->Tightness2; subdata->GoalUpdate1 = fVar2 * fVar1 * subdata->GoalUpdate2 + subdata->GoalUpdate2; return; } void __cdecl lego::game::Flocks_FUN_0040fe80(Flocks *flocksData,float randomness) { Flocks_CallbackForAllSubdata(flocksData,Flocks_Callback_FUN_0040fe00,&randomness); return; } void __cdecl lego::game::Flocks_SetParameters1(Flocks *flocksData,float turn,float speed,float tightness) { flocksData->flocksSubdata1->Turn1 = turn; flocksData->flocksSubdata1->Speed1 = speed; flocksData->flocksSubdata1->Tightness1 = tightness; return; } void __cdecl lego::game::Flocks_Callback_SetSubdataParametersFromGlobals(Flocks *flocksData,FlocksItem *subdata) { subdata->Turn2 = globs::flocksGlobs.Turn; subdata->Turn1 = globs::flocksGlobs.Turn; subdata->Speed2 = globs::flocksGlobs.Speed; subdata->Speed1 = globs::flocksGlobs.Speed; subdata->Tightness2 = globs::flocksGlobs.Tightness; subdata->Tightness1 = globs::flocksGlobs.Tightness; subdata->GoalUpdate2 = globs::flocksGlobs.GoalUpdate; subdata->GoalUpdate1 = globs::flocksGlobs.GoalUpdate; return; } void __cdecl lego::game::Flocks_SetGlobal_AndAllSubdataParameters (Flocks *flockData,float turn,float speed,float tightness,float goalUpdate) { globs::flocksGlobs.Speed = speed; globs::flocksGlobs.Turn = turn; globs::flocksGlobs.Tightness = tightness; globs::flocksGlobs.GoalUpdate = goalUpdate; Flocks_CallbackForAllSubdata(flockData,Flocks_Callback_SetSubdataParametersFromGlobals,NULL); return; } void __cdecl lego::game::Flocks_SetVector1(Flocks *flocksData,Vector3F *vector1) { FlocksItem *pFVar1; if ((flocksData != NULL) && (vector1 != NULL)) { flocksData->hasVector1 = TRUE; pFVar1 = flocksData->flocksSubdata1; (pFVar1->vector_c).x = vector1->x; (pFVar1->vector_c).y = vector1->y; (pFVar1->vector_c).z = vector1->z; } return; } void __cdecl lego::game::Flocks_Callback_SetSubdataVectorC (Flocks *flocksData,FlocksItem *subdata,Vector3F *vector) { (subdata->vector_c).x = vector->x; (subdata->vector_c).y = vector->y; (subdata->vector_c).z = vector->z; return; } void __cdecl lego::game::Flocks_SetAllSubdataVectorC(Flocks *flocksData,Vector3F *vector) { Flocks_CallbackForAllSubdata(flocksData,Flocks_Callback_SetSubdataVectorC,vector); return; } void __cdecl lego::game::Flocks_Callback_SetSubdataVector0 (Flocks *flocksData,FlocksItem *subdata,Vector3F *vector) { (subdata->vector_0).x = vector->x; (subdata->vector_0).y = vector->y; (subdata->vector_0).z = vector->z; return; } void __cdecl lego::game::Flocks_SetAllSubdataVector0(Flocks *flocksData,Vector3F *vector) { Flocks_CallbackForAllSubdata(flocksData,Flocks_Callback_SetSubdataVector0,vector); return; } void __cdecl lego::game::Flocks_Callback_FUN_00410000(Flocks *flocksData,FlocksItem *subdata,float *pElapsed) { Vector3F *pVVar1; float fVar2; float fVar3; float fVar4; float fVar5; float fVar6; float fVar7; float fVar8; float fVar9; float fVar10; float fVar11; float fVar12; fVar2 = *pElapsed; pVVar1 = &subdata->vector_c; fVar3 = (subdata->vector_0).x; fVar4 = pVVar1->x; fVar5 = (subdata->vector_0).y; fVar6 = (subdata->vector_c).y; fVar7 = (subdata->vector_c).z; fVar8 = (subdata->vector_0).z; Flocks_Callback_SubdataMoveAndTurn(flocksData,subdata,pElapsed); fVar11 = fVar3 - fVar4; fVar9 = fVar5 - fVar6; fVar12 = fVar8 - fVar7; fVar2 = subdata->Speed1 * fVar2; fVar10 = SQRT(fVar12 * fVar12 + fVar9 * fVar9 + fVar11 * fVar11); if (fVar2 <= fVar10) { fVar10 = 1.0 / fVar10; pVVar1->x = fVar10 * fVar11 * fVar2 + fVar4; (subdata->vector_c).y = fVar10 * fVar9 * fVar2 + fVar6; (subdata->vector_c).z = fVar10 * fVar12 * fVar2 + fVar7; } else { pVVar1->x = (subdata->vector_0).x; (subdata->vector_c).y = (subdata->vector_0).y; (subdata->vector_c).z = (subdata->vector_0).z; } (subdata->vector_0).x = fVar3; fVar2 = (subdata->vector_c).z; (subdata->matrix).values[3][0] = pVVar1->x; (subdata->matrix).values[3][2] = fVar2; (subdata->vector_0).y = fVar5; (subdata->vector_0).z = fVar8; (subdata->matrix).values[3][1] = (subdata->vector_c).y; return; } void __cdecl lego::game::Flocks_Callback_CompareVecs_0_c(Flocks *flocksData,FlocksItem *subdata,BOOL *pSuccess) { if ((((subdata->vector_c).x == (subdata->vector_0).x) && ((subdata->vector_c).y == (subdata->vector_0).y)) && ((subdata->vector_c).z == (subdata->vector_0).z)) { gfx::Container_Hide(subdata->cont,TRUE); return; } *pSuccess = 0; return; } BOOL __cdecl lego::game::Flocks_CompareAllVecs_0_c(Flocks *flocksData) { BOOL result; result = 1; Flocks_CallbackForAllSubdata(flocksData,Flocks_Callback_CompareVecs_0_c,&result); return result; } // Returns a temporary string buffer. char * __cdecl lego::front::Front_Util_ReplaceTextSpaces(char *str) { char cVar1; uint uVar2; uint uVar3; undefined4 *puVar4; char *pcVar5; undefined4 *puVar6; uVar2 = 0xffffffff; pcVar5 = str; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); if (0xff < ~uVar2 - 1) { return str; } uVar2 = 0xffffffff; do { pcVar5 = str; if (uVar2 == 0) break; uVar2 -= 1; pcVar5 = str + 1; cVar1 = *str; str = pcVar5; } while (cVar1 != '\0'); uVar2 = ~uVar2; puVar4 = (undefined4 *)(pcVar5 + -uVar2); puVar6 = (undefined4 *)globs::s_FrontReplaceSpacesBuff; for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar6 = *puVar4; puVar4 = puVar4 + 1; puVar6 = puVar6 + 1; } uVar3 = 0; for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar6 = *(undefined *)puVar4; puVar4 = (undefined4 *)((int)puVar4 + 1); puVar6 = (undefined4 *)((int)puVar6 + 1); } do { if (globs::s_FrontReplaceSpacesBuff[uVar3] == '_') { globs::s_FrontReplaceSpacesBuff[uVar3] = ' '; } uVar3 += 1; } while (uVar3 < 0x100); return globs::s_FrontReplaceSpacesBuff; } void __cdecl lego::front::Front_LevelSelect_LevelNamePrintF(Font *font,int x,int y,char *msg,...) { Font **pFont; uint i; char (*pMessage) [1024]; if (msg == NULL) { i = 0; if (globs::s_LevelSelectNameCount != 0) { pFont = globs::s_LevelSelectNameFonts; pMessage = globs::s_FrontLevelSelectNames; do { lego::image::Font_PrintF (*pFont,globs::s_LevelSelect_NameXs[i],globs::s_LevelSelect_NameYs[i], (char *)pMessage); i += 1; pMessage = pMessage[1]; pFont = pFont + 1; } while (i < globs::s_LevelSelectNameCount); } globs::s_LevelSelectNameCount = 0; return; } if (globs::s_LevelSelectNameCount < 0xf) { std::vsprintf((char *)globs::s_FrontLevelSelectNames[globs::s_LevelSelectNameCount],msg, &stack0x00000014); globs::s_LevelSelect_NameXs[globs::s_LevelSelectNameCount] = x; globs::s_LevelSelect_NameYs[globs::s_LevelSelectNameCount] = y; globs::s_LevelSelectNameFonts[globs::s_LevelSelectNameCount] = font; globs::s_LevelSelectNameCount += 1; } return; } void __cdecl lego::front::Front_Callback_TriggerPlayCredits(void) { Credits_Play(globs::legoGlobs.CreditsTextFile,globs::legoGlobs.fontCredits, globs::legoGlobs.CreditsBackAVI); return; } void __cdecl lego::front::Front_RockWipe_Play(void) { uint uVar1; if (globs::frontGlobs.rockWipeAnim != NULL) { globs::frontGlobs.rockWipeTimer = 0.0; // |= (ROCKWIPE_FLAG_ANIMATING|ROCKWIPE_FLAG_NOINPUT); (0x3) globs::frontGlobs.rockWipeFlags = globs::frontGlobs.rockWipeFlags & 0xffffff00 | globs::frontGlobs.rockWipeFlags & 0xff | ROCKWIPE_FLAG_ANIMATING | ROCKWIPE_FLAG_NOINPUT; uVar1 = main::Main_GetTime(); globs::frontGlobs.rockWipeLastUpdateTime = (float)(ulonglong)uVar1; snd::SFX_AddToQueue(SFX_RockWipe,SoundMode_Once); } return; } void __cdecl lego::front::Front_RockWipe_Stop(void) { // &= ~(ROCKWIPE_FLAG_ANIMATING|ROCKWIPE_FLAG_NOINPUT); (~0x3) globs::frontGlobs.rockWipeFlags = globs::frontGlobs.rockWipeFlags & ~(ROCKWIPE_FLAG_ANIMATING|ROCKWIPE_FLAG_NOINPUT); return; } Front_Cache * __cdecl lego::front::Front_Cache_FindByName(char *filename) { int cmp; Front_Cache *cache; cache = globals::g_ImageCache_NEXT; if (globals::g_ImageCache_NEXT == NULL) { return NULL; } do { cmp = std::_stricmp(filename,cache->path); if (cmp == 0) { return cache; } cache = cache->next; } while (cache != NULL); return NULL; } // Gets an existing cache item or creates a new one. Front_Cache * __cdecl lego::front::Front_Cache_Create(char *filename) { char cVar1; Front_Cache *cache; undefined4 *puVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; if ((filename == NULL) || (*filename == '\0')) { cache = NULL; } else { cache = Front_Cache_FindByName(filename); if (cache == NULL) { cache = (Front_Cache *)io::Mem_Alloc(0x10); // cache->filename = ::_strdup(filename); uVar3 = 0xffffffff; pcVar6 = filename; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); puVar2 = (undefined4 *)io::Mem_Alloc(~uVar3); uVar3 = 0xffffffff; cache->path = (char *)puVar2; do { pcVar6 = filename; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = filename + 1; cVar1 = *filename; filename = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar2 = *puVar5; puVar5 = puVar5 + 1; puVar2 = puVar2 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar2 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar2 = (undefined4 *)((int)puVar2 + 1); } cache->image = NULL; cache->next = globals::g_ImageCache_NEXT; cache->font = NULL; globals::g_ImageCache_NEXT = cache; return cache; } } return cache; } Image * __cdecl lego::front::Front_Cache_LoadImage(char *filename) { Front_Cache *cache; Image *image; if ((filename != NULL) && (*filename != '\0')) { cache = Front_Cache_Create(filename); if (cache->image == NULL) { image = lego::image::Image_LoadBMPScaled(filename,0,0); cache->image = image; } return cache->image; } return NULL; } Font * __cdecl lego::front::Front_Cache_LoadFont(char *filename) { Front_Cache *cache; Font *font; if ((filename != NULL) && (*filename != '\0')) { cache = Front_Cache_Create(filename); if (cache->font == NULL) { font = lego::image::Font_Load(filename); cache->font = font; } return cache->font; } return NULL; } char * __cdecl lego::front::Front_Util_StrCpy(char *str) { char cVar1; undefined4 *puVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; undefined4 *puVar7; if (str == NULL) { return (char *)NULL; } uVar3 = 0xffffffff; pcVar6 = str; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); puVar2 = (undefined4 *)io::Mem_Alloc(~uVar3); if (puVar2 == NULL) { return NULL; } uVar3 = 0xffffffff; do { pcVar6 = str; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = str + 1; cVar1 = *str; str = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); puVar7 = puVar2; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar7 = *puVar5; puVar5 = puVar5 + 1; puVar7 = puVar7 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } return (char *)puVar2; } MenuItem_SelectData * __cdecl lego::front::Front_MenuItem_CreateSelect (int *valuePtr,char *string1,char *string2,int x2,int y2,int selItemHeight,int scrollCount ,int xString1,int yString1,int xString2,int yString2,int field50, MenuItem_SelectCallback callback,Menu *opt_nextMenu) { MenuItem_SelectData *selectData; char *str; int iVar1; MenuItem_SelectData *pMVar2; selectData = (MenuItem_SelectData *)io::Mem_Alloc(0x5c); pMVar2 = selectData; for (iVar1 = 0x17; iVar1 != 0; iVar1 += -1) { pMVar2->selItemList = NULL; pMVar2 = (MenuItem_SelectData *)pMVar2->widths; } str = Front_Util_StrCpy(string1); selectData->string1 = str; str = Front_Util_StrCpy(string2); selectData->string2 = str; selectData->x2 = x2; selectData->valuePtr = valuePtr; selectData->y2 = y2; selectData->scrollCount = scrollCount; selectData->selItemHeight = selItemHeight; selectData->xString1 = xString1; selectData->xString2 = xString2; selectData->yString1 = yString1; selectData->yString2 = yString2; selectData->callback = callback; selectData->field_50 = field50; selectData->scrollStart = 0; selectData->nextMenu = opt_nextMenu; return selectData; } void __cdecl lego::front::Front_MenuItem_FreeSelect(MenuItem_SelectData *selectData) { uint *puVar1; uint uVar2; int iVar3; int iVar4; int iVar5; MenuItem_SelectData *selectData_00; selectData_00 = selectData; iVar4 = 0; if (selectData != NULL) { if (selectData->string1 != NULL) { io::Mem_Free(selectData->string1); } if (selectData->string2 != NULL) { io::Mem_Free(selectData->string2); } if (selectData->selItemList != NULL) { puVar1 = &selectData->selItemCount; selectData = NULL; if (0 < (int)*puVar1) { do { uVar2 = *(uint *)((int)selectData_00->selItemList->images + iVar4 + -8); if ((uVar2 & 1) == 0) { if ((uVar2 & 2) != 0) { iVar5 = iVar4 + 8; iVar3 = 3; do { lego::image::Image_Remove (*(Image **)((int)selectData_00->selItemList->images + iVar5 + -8)); iVar5 += 4; iVar3 += -1; } while (iVar3 != 0); } } else { io::Mem_Free(*(void **)((int)selectData_00->selItemList->images + iVar4 + -4)); } selectData = (MenuItem_SelectData *)((int)&selectData->selItemList + 1); iVar4 += 0x20; } while ((int)selectData < (int)selectData_00->selItemCount); } io::Mem_Free(selectData_00->selItemList); } io::Mem_Free(selectData_00); } return; } // To create a banner item, pass a string to bannerOrBMPName that does NOT contain // ".bmp" (case-insensitive), font must also be non-NULL for banner items. void __cdecl lego::front::Front_MenuItem_AddSelectItem (MenuItem_SelectData *selectData,char *bannerOrBMPName,BOOL enabled,Font *hiFont, int frontEndX,int frontEndY,BOOL frontEndOpen) { uint *puVar1; MenuItem_SelectItem *newSelItems; void *pvVar2; int iVar3; char *pcVar4; Image *image; uint uVar5; uint **ppuVar6; uint **selectData_heights; int iVar7; uint *apuStack24 [6]; MenuItem_SelectData *selectData_00; selectData_00 = selectData; if (selectData->selItemList == NULL) { newSelItems = (MenuItem_SelectItem *)io::Mem_Alloc((selectData->selItemCount + 1) * 0x20); iVar7 = 0; do { pvVar2 = io::Mem_Alloc(selectData->selItemCount * 4 + 4); uVar5 = selectData->selItemCount; *(void **)((int)apuStack24 + iVar7) = pvVar2; pvVar2 = io::Mem_Alloc(uVar5 * 4 + 4); *(void **)((int)apuStack24 + iVar7 + 0xc) = pvVar2; iVar7 += 4; } while (iVar7 < 0xc); } else { newSelItems = (MenuItem_SelectItem *) io::Mem_ReAlloc(selectData->selItemList,(selectData->selItemCount + 1) * 0x20); selectData_heights = selectData->heights; iVar7 = 0; do { pvVar2 = io::Mem_ReAlloc(selectData_heights[-3],selectData->selItemCount * 4 + 4); uVar5 = selectData->selItemCount; puVar1 = *selectData_heights; *(void **)((int)apuStack24 + iVar7) = pvVar2; pvVar2 = io::Mem_ReAlloc(puVar1,uVar5 * 4 + 4); *(void **)((int)apuStack24 + iVar7 + 0xc) = pvVar2; iVar7 += 4; selectData_heights = selectData_heights + 1; } while (iVar7 < 0xc); } if (newSelItems != NULL) { selectData->selItemList = newSelItems; newSelItems[selectData->selItemCount].banner = NULL; selectData_heights = selectData->heights; selectData->selItemList[selectData->selItemCount].flags = -(uint)(enabled != 0) & SELECTITEM_FLAG_ENABLED; iVar7 = 0; ppuVar6 = selectData_heights; do { iVar3 = iVar7 + 4; ppuVar6[-3] = *(uint **)((int)apuStack24 + iVar7); *ppuVar6 = *(uint **)((int)apuStack24 + iVar7 + 0xc); ppuVar6 = ppuVar6 + 1; iVar7 = iVar3; } while (iVar3 < 0xc); // Only the hackiest of the hackiest solutions... // If this parameter contains ".bmp" (case-insensitive), then it's an image filename. // Otherwise it's a banner string. if ((bannerOrBMPName != NULL) && (pcVar4 = util::Util_StrIStr(bannerOrBMPName,".bmp"), pcVar4 != NULL)) { util::Util_Tokenise(bannerOrBMPName,(char **)(apuStack24 + 3),","); iVar7 = 0; selectData->selItemList[selectData->selItemCount].flags = selectData->selItemList[selectData->selItemCount].flags | SELECTITEM_FLAG_HASIMAGE; selectData = (MenuItem_SelectData *)(apuStack24 + 3); do { image = Front_Cache_LoadImage((char *)selectData->selItemList); selectData_00->selItemList[selectData_00->selItemCount].images[iVar7] = image; image = selectData_00->selItemList[selectData_00->selItemCount].images[iVar7]; if (image != NULL) { lego::image::Image_SetPenZeroTrans(image); } iVar7 += 1; selectData_heights[-3][selectData_00->selItemCount] = image->width; puVar1 = *selectData_heights; selectData_heights = selectData_heights + 1; puVar1[selectData_00->selItemCount] = image->height; selectData = (MenuItem_SelectData *)selectData->widths; } while (iVar7 < 3); selectData_00->selItemList[selectData_00->selItemCount].frontEndX = frontEndX; selectData_00->selItemList[selectData_00->selItemCount].frontEndY = frontEndY; selectData_00->selItemList[selectData_00->selItemCount].frontEndOpen = frontEndOpen; selectData_00->selItemCount = selectData_00->selItemCount + 1; return; } selectData->selItemList[selectData->selItemCount].flags = selectData->selItemList[selectData->selItemCount].flags | SELECTITEM_FLAG_HASBANNER; pcVar4 = Front_Util_StrCpy(bannerOrBMPName); selectData->selItemList[selectData->selItemCount].banner = pcVar4; selectData->selItemList[selectData->selItemCount].frontEndX = frontEndX; selectData->selItemList[selectData->selItemCount].frontEndY = frontEndY; selectData->selItemList[selectData->selItemCount].frontEndOpen = frontEndOpen; uVar5 = lego::image::Font_GetStringWidth(hiFont,bannerOrBMPName); selectData->widths[2][selectData->selItemCount] = uVar5; selectData->widths[1][selectData->selItemCount] = selectData->widths[2][selectData->selItemCount]; selectData->widths[0][selectData->selItemCount] = selectData->widths[1][selectData->selItemCount]; uVar5 = lego::image::Font_GetHeight(hiFont); selectData->heights[2][selectData->selItemCount] = uVar5; selectData->heights[1][selectData->selItemCount] = selectData->heights[2][selectData->selItemCount]; (*selectData_heights)[selectData->selItemCount] = selectData->heights[1][selectData->selItemCount]; selectData->selItemCount = selectData->selItemCount + 1; } return; } MenuItem_CycleData * __cdecl lego::front::Front_MenuItem_CreateCycle (uint count,int *valuePtr,int x2,int y2,MenuItem_CycleCallback callback) { MenuItem_CycleData *cycleData; char **nameList; uint uVar1; int iVar2; cycleData = (MenuItem_CycleData *)io::Mem_Alloc(0x1c); if (cycleData == NULL) { return NULL; } nameList = (char **)io::Mem_Alloc(count * 4); cycleData->nameList = nameList; if (nameList == NULL) { Front_MenuItem_FreeCycle(cycleData); return NULL; } for (uVar1 = count & 0x3fffffff; uVar1 != 0; uVar1 -= 1) { *nameList = NULL; nameList = nameList + 1; } for (iVar2 = 0; iVar2 != 0; iVar2 += -1) { *(undefined *)nameList = 0; nameList = (char **)((int)nameList + 1); } cycleData->valuePtr = valuePtr; cycleData->callback = callback; cycleData->cycleCount = count; cycleData->nameCount = 0; cycleData->x2 = x2; cycleData->y2 = y2; return cycleData; } void __cdecl lego::front::Front_MenuItem_AddCycleName(MenuItem_CycleData *cycleData,char *name) { char *str; if (((cycleData != NULL) && (cycleData->nameList != NULL)) && (cycleData->nameCount < (int)cycleData->cycleCount)) { str = Front_Util_StrCpy(name); cycleData->nameList[cycleData->nameCount] = str; if (cycleData->nameList[cycleData->nameCount] != NULL) { cycleData->nameCount = cycleData->nameCount + 1; } } return; } void __cdecl lego::front::Front_MenuItem_FreeCycle(MenuItem_CycleData *cycleData) { int i; if (cycleData != NULL) { if (cycleData->nameList != NULL) { i = 0; if (0 < cycleData->nameCount) { do { if (cycleData->nameList[i] != NULL) { io::Mem_Free(cycleData->nameList[i]); } i += 1; } while (i < cycleData->nameCount); } io::Mem_Free(cycleData->nameList); } io::Mem_Free(cycleData); } return; } int __cdecl lego::input::msx(void) { return globs::INPUT.msx; } int __cdecl lego::input::msy(void) { return globs::INPUT.msy; } BOOL __cdecl lego::input::mslb(void) { return globs::INPUT.mslb; } MenuItem_TriggerData * __cdecl lego::front::Front_MenuItem_CreateTrigger(int *valuePtr,BOOL end,MenuItem_TriggerCallback callback) { MenuItem_TriggerData *triggerData; triggerData = (MenuItem_TriggerData *)io::Mem_Alloc(0xc); if (triggerData == NULL) { return NULL; } triggerData->valuePtr = valuePtr; triggerData->end = end; triggerData->callback = callback; return triggerData; } MenuItem_RealSliderData * __cdecl lego::front::Front_MenuItem_CreateRealSlider (float *valuePtr,float valueMin,float valueMax,float step,int x2,int y2, MenuItem_RealSliderCallback callback) { MenuItem_RealSliderData *realSliderData; if ((ushort)((ushort)(valueMax < valueMin) << 8 | (ushort)(valueMax == valueMin) << 0xe) != 0) { return NULL; } realSliderData = (MenuItem_RealSliderData *)io::Mem_Alloc(0x1c); if (realSliderData == NULL) { return NULL; } realSliderData->valuePtr = valuePtr; realSliderData->valueMin = valueMin; realSliderData->valueMax = valueMax; realSliderData->valueStep = step; realSliderData->x2 = x2; realSliderData->y2 = y2; realSliderData->callback = callback; return realSliderData; } MenuItem_SliderData * __cdecl lego::front::Front_MenuItem_CreateSlider (int *valuePtr,int valueMin,int valueMax,int x2,int y2,MenuItem_SliderCallback callback, Image *offBarImage,Image *onBarImage,Image *leftCapImage,Image *rightCapImage, Image *loPlusImage,Image *loMinusImage,Image *hiPlusImage,Image *hiMinusImage) { MenuItem_SliderData *sliderData; if (valueMax <= valueMin) { return NULL; } sliderData = (MenuItem_SliderData *)io::Mem_Alloc(0x38); if (sliderData == NULL) { return NULL; } sliderData->valuePtr = valuePtr; sliderData->x2 = x2; sliderData->y2 = y2; sliderData->callback = callback; sliderData->imageBarOff = offBarImage; sliderData->imageBarOn = onBarImage; sliderData->imageCapLeft = leftCapImage; sliderData->imageCapRight = rightCapImage; sliderData->imagePlusLo = loPlusImage; sliderData->imageMinusLo = loMinusImage; sliderData->valueMin = valueMin; sliderData->valueMax = valueMax; sliderData->imagePlusHi = hiPlusImage; sliderData->imageMinusHi = hiMinusImage; return sliderData; } void __cdecl lego::front::Front_MenuItem_FreeMenuItem(MenuItem *menuItem) { if (menuItem != NULL) { if (menuItem->banner != NULL) { io::Mem_Free(menuItem->banner); } if (true) { switch(menuItem->itemType) { case MenuItem_Type_Cycle: Front_MenuItem_FreeCycle((MenuItem_CycleData *)menuItem->itemData); io::Mem_Free(menuItem); return; case MenuItem_Type_Trigger: util::freeNonNull((void *)menuItem->itemData); io::Mem_Free(menuItem); return; case MenuItem_Type_TextInput: util::freeNonNull((void *)menuItem->itemData); io::Mem_Free(menuItem); return; case MenuItem_Type_Slider: util::freeNonNull((void *)menuItem->itemData); io::Mem_Free(menuItem); return; case MenuItem_Type_RealSlider: util::freeNonNull((void *)menuItem->itemData); io::Mem_Free(menuItem); return; case MenuItem_Type_Select: Front_MenuItem_FreeSelect((MenuItem_SelectData *)menuItem->itemData); } } io::Mem_Free(menuItem); } return; } MenuItem * __cdecl lego::front::Front_MenuItem_CreateBannerItem (char *banner,Font *loFont,Font *hiFont,int x1,int y1,MenuItem_Type itemType,BOOL centered ,void *itemData,BOOL notInTuto) { char cVar1; MenuItem *menuItem; char *pcVar2; int iVar3; uint uVar4; MenuItem *pMVar5; if (banner == NULL) { return NULL; } menuItem = (MenuItem *)io::Mem_Alloc(0x3c); if (menuItem == NULL) { return NULL; } pMVar5 = menuItem; for (iVar3 = 0xf; iVar3 != 0; iVar3 += -1) { pMVar5->banner = NULL; pMVar5 = (MenuItem *)&pMVar5->length; } uVar4 = 0xffffffff; pcVar2 = banner; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); menuItem->length = ~uVar4 - 1; pcVar2 = Front_Util_StrCpy(banner); menuItem->itemType = itemType; menuItem->banner = pcVar2; menuItem->x1 = x1; menuItem->itemData = itemData; menuItem->notInTuto = notInTuto; menuItem->fontLo = loFont; menuItem->fontHi = hiFont; menuItem->y1 = y1; if (((centered != 0) && (loFont != NULL)) && (hiFont != NULL)) { uVar4 = lego::image::Font_GetStringWidth(loFont,banner); menuItem->centerOffLo = -(uVar4 >> 1); uVar4 = lego::image::Font_GetStringWidth(hiFont,banner); menuItem->centerOffHi = -(uVar4 >> 1); return menuItem; } menuItem->centerOffLo = 0; menuItem->centerOffHi = 0; return menuItem; } MenuItem * __cdecl lego::front::Front_MenuItem_CreateImageItem (char *banner,Font *loFont,Font *hiFont,char *loImageName,char *hiImageName,int x1,int y1, MenuItem_Type itemType,BOOL centered,char *toolTipName,void *itemData) { char cVar1; MenuItem *menuItem; char *pcVar2; Image *pIVar3; BOOL BVar4; int iVar5; uint uVar6; MenuItem *pMVar7; if (banner != NULL) { menuItem = (MenuItem *)io::Mem_Alloc(0x3c); if (menuItem != NULL) { pMVar7 = menuItem; for (iVar5 = 0xf; iVar5 != 0; iVar5 += -1) { pMVar7->banner = NULL; pMVar7 = (MenuItem *)&pMVar7->length; } uVar6 = 0xffffffff; pcVar2 = banner; do { if (uVar6 == 0) break; uVar6 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); menuItem->length = ~uVar6 - 1; pcVar2 = Front_Util_StrCpy(banner); menuItem->banner = pcVar2; menuItem->fontHi = hiFont; menuItem->fontLo = loFont; pIVar3 = lego::image::Image_LoadBMPScaled(loImageName,0,0); menuItem->imageLo = pIVar3; if (pIVar3 != NULL) { pIVar3 = lego::image::Image_LoadBMPScaled(hiImageName,0,0); menuItem->imageHi = pIVar3; if (pIVar3 != NULL) { menuItem->isImageItem = TRUE; } menuItem->itemData = itemData; menuItem->itemType = itemType; menuItem->x1 = x1; menuItem->y1 = y1; BVar4 = ToolTip_GetType(toolTipName,&menuItem->toolTipType); if (BVar4 == 0) { menuItem->toolTipType = ToolTip_Null; } if (((centered != 0) && (menuItem->imageLo != NULL)) && (menuItem->imageHi != NULL)) { menuItem->centerOffLo = -(menuItem->imageLo->width >> 1); menuItem->centerOffHi = -(menuItem->imageHi->width >> 1); return menuItem; } menuItem->centerOffLo = 0; menuItem->centerOffHi = 0; return menuItem; } } } return NULL; } void __cdecl lego::front::Front_Menu_FreeMenu(Menu *menu) { int iVar1; if (menu != NULL) { if (menu->title != NULL) { io::Mem_Free(menu->title); } if (menu->fullName != NULL) { io::Mem_Free(menu->fullName); } if (menu->items != NULL) { io::Mem_Free(menu->items); } // FIXME: menu->items is already freed!!!!! WHHHHHYYYYYYYYYYY!? iVar1 = 0; if (0 < menu->itemCount) { do { if (menu->items[iVar1] != NULL) { Front_MenuItem_FreeMenuItem(menu->items[iVar1]); } iVar1 += 1; } while (iVar1 < menu->itemCount); } if (menu->menuImage != NULL) { lego::image::Image_Remove(menu->menuImage); } io::Mem_Free(menu); } return; } BOOL __cdecl lego::front::Front_Menu_LoadMenuImage(Menu *menu,char *filename,BOOL light) { char cVar1; uint numParts; int transBool; Image *image; uint uVar2; uint uVar3; undefined4 *puVar4; char *pcVar5; undefined4 *puVar6; float10 fVar7; char *stringParts [4]; char buff [1024]; stringParts[0] = NULL; stringParts[1] = NULL; stringParts[2] = NULL; stringParts[3] = NULL; if (filename == NULL) { return FALSE; } // std::strcpy(buff, filename); uVar2 = 0xffffffff; do { pcVar5 = filename; if (uVar2 == 0) break; uVar2 -= 1; pcVar5 = filename + 1; cVar1 = *filename; filename = pcVar5; } while (cVar1 != '\0'); uVar2 = ~uVar2; puVar4 = (undefined4 *)(pcVar5 + -uVar2); puVar6 = (undefined4 *)buff; for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar6 = *puVar4; puVar4 = puVar4 + 1; puVar6 = puVar6 + 1; } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar6 = *(undefined *)puVar4; puVar4 = (undefined4 *)((int)puVar4 + 1); puVar6 = (undefined4 *)((int)puVar6 + 1); } numParts = util::Util_Tokenise(buff,stringParts,":"); // cfg: filename.bmp[:xPos:yPos[:trans=0/1]] if (2 < numParts) { menu->flags = menu->flags | MENU_FLAG_HASPOSITION; fVar7 = std::atof(stringParts[1]); (menu->currPosition).x = (float)fVar7; fVar7 = std::atof(stringParts[2]); (menu->currPosition).y = (float)fVar7; } if (light != 0) { image = Front_Cache_LoadImage(stringParts[0]); menu->menuImage = image; if ((image != NULL) && (numParts == 4)) { transBool = std::atoi(stringParts[3]); if (transBool == 1) { lego::image::Image_SetPenZeroTrans(menu->menuImage); } } return (uint)(menu->menuImage != NULL); } image = Front_Cache_LoadImage(stringParts[0]); menu->menuImageDark = image; if ((image != NULL) && (numParts == 4)) { transBool = std::atoi(stringParts[3]); if (transBool == 1) { lego::image::Image_SetupTrans(menu->menuImageDark,0.0,0.0,0.0,0.0,0.0,0.0); } } return (uint)(menu->menuImageDark != NULL); } Menu * __cdecl lego::front::Front_Menu_CreateMenu (char *title,char *fullName,Font *menuFont,int positionX,int positionY,BOOL autoCenter, BOOL displayTitle,int centerX,BOOL canScroll,char *anchored_str) { char cVar1; Menu *menu; char *pcVar2; MenuItem **menuItems; int iVar3; uint uVar4; Menu *pMVar5; char *stringParts [100]; menu = (Menu *)io::Mem_Alloc(0xa0); if (menu == NULL) { return NULL; } pMVar5 = menu; for (iVar3 = 0x28; iVar3 != 0; iVar3 += -1) { pMVar5->title = NULL; pMVar5 = (Menu *)&pMVar5->fullName; } pcVar2 = Front_Util_StrCpy(title); menu->title = pcVar2; pcVar2 = Front_Util_StrCpy(fullName); menu->fullName = pcVar2; if (menu->title == NULL) { return NULL; } if (pcVar2 == NULL) { return NULL; } uVar4 = 0xffffffff; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *title; title = title + 1; } while (cVar1 != '\0'); menu->titleLength = ~uVar4 - 1; menuItems = (MenuItem **)io::Mem_Alloc(0x3c); menu->items = menuItems; if (menuItems == NULL) { Front_Menu_FreeMenu(menu); return NULL; } menu->menuFont = menuFont; (menu->position).y = positionY; menu->autoCenter = autoCenter; menu->displayTitle = displayTitle; (menu->position).x = positionX; menu->itemCapacity = 0xf; menu->itemCount = 0; menu->itemFocus = 0; menu->closed = FALSE; menu->centerX = centerX; menu->flags = -(uint)(canScroll != 0) & MENU_FLAG_CANSCROLL; if (anchored_str != NULL) { menu->anchored = TRUE; util::Util_Tokenise(anchored_str,stringParts,":"); iVar3 = std::atoi(stringParts[0]); (menu->anchoredPosition).x = iVar3; iVar3 = std::atoi(stringParts[1]); (menu->anchoredPosition).y = iVar3; } return menu; } BOOL __cdecl lego::front::Front_Menu_AddMenuItem(Menu *menu,MenuItem *menuItem) { MenuItem **newMenuItems; int capacity; if ((menuItem == NULL) || (menu == NULL)) { return FALSE; } capacity = menu->itemCapacity; if (menu->itemCount == capacity) { if (menu->items == NULL) { // Before questioning your sanity like I did with the `+ 0x3c`... // Capacity is always increased by 15, and this is an array of pointers. // So `(15 * sizeof(MenuItem*)) == 0x3c`, which BY PURE COINCIDENCE is the same // as `sizeof(MenuItem)`. Heh... // // This is simply `(capacity + 15) * sizeof(MenuItem*)` newMenuItems = (MenuItem **)io::Mem_Alloc(capacity * 4 + 0x3c); } else { newMenuItems = (MenuItem **)io::Mem_ReAlloc(menu->items,capacity * 4 + 0x3c); } if (newMenuItems == NULL) { return 0; } menu->items = newMenuItems; menu->itemCapacity = menu->itemCapacity + 15; } menu->items[menu->itemCount] = menuItem; menu->itemCount = menu->itemCount + 1; return TRUE; } BOOL __cdecl lego::front::Front_Maths_IsPointInsideRect(int ptX,int ptY,int rcX,int rcY,int rcWidth,int rcHeight) { if ((rcX <= ptX) && (ptX <= rcWidth + rcX)) { if ((rcY <= ptY) && (ptY <= rcHeight + rcY)) { return TRUE; } } return 0; } BOOL __cdecl lego::front::Front_Maths_IsPointInsideRectCentered (int ptX,int ptY,int rcX,int rcY,int rcWidth,int rcHeight,BOOL shouldCenterX) { int iVar1; BOOL BVar2; if (shouldCenterX == 0) { iVar1 = 0; } else { iVar1 = -(rcWidth / 2); } BVar2 = Front_Maths_IsPointInsideRect(ptX,ptY,iVar1 + rcX,rcY,rcWidth,rcHeight); return BVar2; } // Returns -2 if colliding with string1, -3 if colliding with string2, -1 if not colliding, or a // positive value if colliding with a selectItem string. int __cdecl lego::front::Front_MenuItem_Select_TestStringCollision (Menu *menu,MenuItem *menuItem,MenuItem_SelectData *selectData) { MenuItem *pMVar1; MenuItem *pMVar2; BOOL inside; uint rcWidth; MenuItem_SelectItem *selectItem; int iVar3; uint rcHeight; int i; pMVar1 = menuItem; rcHeight = 0; if (menuItem->fontHi == NULL) { menuItem = NULL; } else { pMVar2 = (MenuItem *)lego::image::Font_GetStringWidth(menuItem->fontHi,selectData->string1); rcHeight = lego::image::Font_GetHeight(menuItem->fontHi); menuItem = pMVar2; } inside = Front_Maths_IsPointInsideRectCentered (globs::INPUT.msx,globs::INPUT.msy,selectData->xString1 + (menu->position).x, selectData->yString1 + (menu->position).y,(int)menuItem,rcHeight,FALSE); if (inside != 0) { return -2; } if (pMVar1->fontHi == NULL) { rcWidth = 0; } else { rcWidth = lego::image::Font_GetStringWidth(pMVar1->fontHi,selectData->string2); } inside = Front_Maths_IsPointInsideRectCentered (globs::INPUT.msx,globs::INPUT.msy,selectData->xString2 + (menu->position).x, selectData->yString2 + (menu->position).y,rcWidth,rcHeight,FALSE); if (inside != 0) { return -3; } i = 0; if (0 < selectData->scrollCount) { while (iVar3 = selectData->scrollStart + i, iVar3 < (int)selectData->selItemCount) { selectItem = selectData->selItemList + iVar3; if ((*(byte *)&selectItem->flags & 4) != 0) { inside = Front_Maths_IsPointInsideRectCentered (globs::INPUT.msx,globs::INPUT.msy, pMVar1->x1 + selectData->x2 + selectItem->frontEndX + globs::frontGlobs.scrollOffset.x + (menu->position).x, selectData->selItemHeight * i + pMVar1->y1 + selectData->y2 + selectItem->frontEndY + globs::frontGlobs.scrollOffset.y + (menu->position).y,selectData->widths[0][iVar3], selectData->heights[0][iVar3],menu->autoCenter); if (inside != 0) { return i + selectData->scrollStart; } } i += 1; if (selectData->scrollCount <= i) { return -1; } } } return -1; } BOOL __cdecl lego::front::Front_Menu_IsLevelItemUnderMouse(Menu *menu,int itemIndex) { MenuItem *menuItem; int iVar1; if ((itemIndex < menu->itemCount) && (menuItem = menu->items[itemIndex], menuItem->itemType == MenuItem_Type_Select)) { iVar1 = Front_MenuItem_Select_TestStringCollision (menu,menuItem,(MenuItem_SelectData *)menuItem->itemData); return (uint)(iVar1 != -1); } return FALSE; } BOOL __cdecl lego::front::Front_Menu_GetItemBounds (Menu *menu,int itemIndex,int *out_rcX,int *out_rcY,int *out_rcWidth,int *out_rcHeight) { Font *font; uint uVar1; int iVar2; uint uVar3; Image *image; int iVar4; int iVar5; int iVar6; int iVar7; int iVar8; int iVar9; MenuItem *item; if (menu->itemCount <= itemIndex) { return 0; } item = menu->items[itemIndex]; if (item->itemType == MenuItem_Type_Slider) { iVar6 = item->centerOffHi + (menu->position).x + item->x1; iVar9 = item->itemData; iVar2 = item->y1 + (menu->position).y; if (menu->itemFocus == itemIndex) { font = item->fontHi; } else { font = item->fontLo; } uVar1 = lego::image::Font_GetStringWidth(font,item->banner); if (menu->itemFocus == itemIndex) { font = menu->items[itemIndex]->fontHi; } else { font = menu->items[itemIndex]->fontLo; } uVar3 = lego::image::Font_GetHeight(font); iVar4 = item->x1 + (menu->position).x + *(int *)(iVar9 + 0xc); iVar5 = item->y1 + (menu->position).y + *(int *)(iVar9 + 0x10); if (*(int *)(iVar9 + 0x24) == 0) { iVar7 = 0; } else { iVar7 = *(int *)(*(int *)(iVar9 + 0x24) + 4); } if (*(int *)(iVar9 + 0x28) == 0) { iVar9 = 0; } else { iVar9 = *(int *)(*(int *)(iVar9 + 0x28) + 4); } iVar8 = iVar6; if (iVar4 <= iVar6) { iVar8 = iVar4; } *out_rcX = iVar8; iVar8 = iVar2; if (iVar5 <= iVar2) { iVar8 = iVar5; } // HARDCODED DIMENSIONS!!! iVar4 += iVar9 + 0x68 + iVar7; *out_rcY = iVar8; if (iVar4 < (int)(iVar6 + uVar1)) { iVar4 = iVar6 + uVar1; } *out_rcWidth = iVar4; iVar9 = iVar2 + uVar3; if ((int)(iVar2 + uVar3) <= iVar5 + 0x14) { iVar9 = iVar5 + 0x14; } *out_rcHeight = iVar9; *out_rcWidth = *out_rcWidth - *out_rcX; *out_rcHeight = *out_rcHeight - *out_rcY; return TRUE; } if (item->itemType == MenuItem_Type_Select) { return 0; } *out_rcX = item->centerOffHi + (menu->position).x + item->x1; *out_rcY = menu->items[itemIndex]->y1 + (menu->position).y; item = menu->items[itemIndex]; if (item->isImageItem != 0) { if (menu->itemFocus == itemIndex) { image = item->imageHi; } else { image = item->imageLo; } *out_rcWidth = image->width; if (menu->itemFocus == itemIndex) { *out_rcHeight = menu->items[itemIndex]->imageHi->height; return TRUE; } *out_rcHeight = menu->items[itemIndex]->imageLo->height; return TRUE; } if (menu->itemFocus == itemIndex) { font = item->fontHi; } else { font = item->fontLo; } uVar1 = lego::image::Font_GetStringWidth(font,item->banner); *out_rcWidth = uVar1; if (menu->itemFocus == itemIndex) { uVar1 = lego::image::Font_GetHeight(menu->items[itemIndex]->fontHi); *out_rcHeight = uVar1; return TRUE; } uVar1 = lego::image::Font_GetHeight(menu->items[itemIndex]->fontLo); *out_rcHeight = uVar1; return TRUE; } // itemIndex is not assigned on failure. BOOL __cdecl lego::front::Front_Menu_FindItemUnderMouse(Menu *menu,int *out_itemIndex) { BOOL BVar1; BOOL BVar2; int itemIndex; int rcHeight; int rcWidth; int rcY; int rcX; itemIndex = 0; rcX = 0; rcY = 0; rcWidth = 0; rcHeight = 0; BVar2 = 0; while( true ) { BVar1 = Front_Menu_GetItemBounds(menu,itemIndex,&rcX,&rcY,&rcWidth,&rcHeight); if (BVar1 == 0) { BVar2 = Front_Menu_IsLevelItemUnderMouse(menu,itemIndex); if (BVar2 == 0) { return FALSE; } } if (BVar2 != 0) break; BVar1 = Front_Maths_IsPointInsideRect (globs::INPUT.msx,globs::INPUT.msy,rcX,rcY,rcWidth,rcHeight); if (BVar1 != 0) break; itemIndex += 1; } if (out_itemIndex != NULL) { *out_itemIndex = itemIndex; } return TRUE; } BOOL __cdecl lego::front::Front_GetMousePressedState(void) { BOOL result; if ((globs::INPUT.mslb != 0) || (result = TRUE, globals::s_frontMousePressedState != TRUE)) { result = 0; } globals::s_frontMousePressedState = globs::INPUT.mslb; return result; } BOOL __cdecl lego::front::Front_MenuItem_SliderHandleInput (Menu *menu,MenuItem *menuItem,MenuItem_SliderData *sliderData) { Image *pIVar1; BOOL BVar2; int iVar3; int rcX; float10 fVar4; longlong lVar5; rcX = (menu->position).x + sliderData->x2 + menuItem->x1; iVar3 = (menu->position).y + menuItem->y1 + sliderData->y2; BVar2 = Front_Maths_IsPointInsideRect(globs::INPUT.msx,globs::INPUT.msy,rcX,iVar3,100,0x14); if (BVar2 != 0) { fVar4 = ((float10)globs::INPUT.msx - (float10)rcX) * (float10)0.01; if ((ushort)((ushort)(fVar4 < (float10)1.0) << 8 | (ushort)(fVar4 == (float10)1.0) << 0xe) == 0) { fVar4 = (float10)1.0; } if (fVar4 < (float10)0.0) { fVar4 = (float10)0.0; } lVar5 = __ftol((float10)(sliderData->valueMax - sliderData->valueMin) * fVar4); *sliderData->valuePtr = (int)lVar5; return TRUE; } pIVar1 = sliderData->imageMinusLo; if ((pIVar1 != NULL) && (sliderData->imagePlusLo != NULL)) { BVar2 = Front_Maths_IsPointInsideRect (globs::INPUT.msx,globs::INPUT.msy,(rcX - pIVar1->width) + -4,iVar3, pIVar1->width,pIVar1->height); if (BVar2 == 0) { BVar2 = Front_Maths_IsPointInsideRect (globs::INPUT.msx,globs::INPUT.msy, sliderData->imageCapRight->width + 0x68 + rcX,iVar3, sliderData->imagePlusLo->width,sliderData->imagePlusLo->height); if (BVar2 == 0) { return 0; } iVar3 = *sliderData->valuePtr; if (iVar3 < sliderData->valueMax) { *sliderData->valuePtr = iVar3 + 1; } } else { iVar3 = *sliderData->valuePtr; if (sliderData->valueMin < iVar3) { *sliderData->valuePtr = iVar3 + -1; return TRUE; } } return TRUE; } return FALSE; } BOOL __cdecl lego::front::Front_MenuItem_CheckNotInTutoAnyTutorialFlags(MenuItem *menuItem) { TutorialFlags tutoFlags; if ((menuItem != NULL) && (menuItem->notInTuto != 0)) { tutoFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (tutoFlags != TUTORIAL_NONE) { return TRUE; } } return FALSE; } Menu * __cdecl lego::front::Front_Menu_UpdateMenuItemsInput(float elapsed,Menu *menu) { undefined *puVar1; float *pfVar2; MenuItem_SliderData *sliderData; MenuItem_SelectData *selectData; int **ppiVar3; float **ppfVar4; MenuItem_Type MVar5; undefined4 *puVar6; int *piVar7; BOOL BVar8; int iVar9; int iVar10; int iVar11; MenuItem *menuItem; int key; int local_4; bool isHandled; bool isPressed; local_4 = -1; iVar10 = menu->itemFocus; isHandled = false; if (iVar10 < 0) { menuItem = NULL; } else { menuItem = menu->items[iVar10]; } if (((byte)globs::frontGlobs.rockWipeFlags & 2) != 0) { return menu; } isPressed = true; if ((menuItem == NULL) && (-1 < iVar10)) { menu->closed = TRUE; } BVar8 = Front_Menu_FindItemUnderMouse(menu,&local_4); if (BVar8 != 0) { menu->itemFocus = local_4; menuItem = menu->items[local_4]; } BVar8 = Front_MenuItem_CheckNotInTutoAnyTutorialFlags(menuItem); if (BVar8 != 0) { return menu; } BVar8 = Front_GetMousePressedState(); if ((BVar8 == 0) || (BVar8 = Front_Menu_FindItemUnderMouse(menu,&local_4), BVar8 == 0)) { isPressed = false; } if ((menuItem == NULL) && (menu->itemFocus < 0)) { return menu; } // IsKeyPressed(KEY_CURSORRIGHT) (205) if (((globs::INPUT.Key_Map[205] != false) && (globs::INPUT.prevKey_Map[205] != globs::INPUT.Key_Map[205])) || (isPressed)) { snd::SFX_Random_PlaySoundNormal(SFX_Okay,FALSE); if (true) { switch(menuItem->itemType) { case MenuItem_Type_Cycle: iVar10 = menuItem->itemData; **(int **)(iVar10 + 0xc) = (**(int **)(iVar10 + 0xc) + 1) % *(int *)(iVar10 + 8); isHandled = isPressed; if (*(code **)(iVar10 + 0x18) != NULL) { (**(code **)(iVar10 + 0x18))(**(undefined4 **)(iVar10 + 0xc)); } break; case MenuItem_Type_TextInput: iVar10 = menuItem->itemData; iVar11 = *(int *)(iVar10 + 8) + 1; iVar9 = *(int *)(iVar10 + 4) + -1; *(int *)(iVar10 + 8) = iVar11; isHandled = isPressed; if (iVar9 < iVar11) { *(int *)(iVar10 + 8) = iVar9; } break; case MenuItem_Type_Slider: sliderData = (MenuItem_SliderData *)menuItem->itemData; if (isPressed) { Front_MenuItem_SliderHandleInput(menu,menuItem,sliderData); if (sliderData->callback != NULL) { (*sliderData->callback)(*sliderData->valuePtr); } } else { *sliderData->valuePtr = *sliderData->valuePtr + 1; piVar7 = sliderData->valuePtr; iVar10 = sliderData->valueMax; if (*piVar7 != iVar10 && iVar10 <= *piVar7) { *piVar7 = iVar10; } isHandled = false; if (sliderData->callback != NULL) { (*sliderData->callback)(*sliderData->valuePtr); } } break; case MenuItem_Type_RealSlider: ppfVar4 = (float **)menuItem->itemData; **ppfVar4 = (float)ppfVar4[3] + **ppfVar4; pfVar2 = (float *)**ppfVar4; if ((ushort)((ushort)((float)pfVar2 < (float)ppfVar4[2]) << 8 | (ushort)((float)pfVar2 == (float)ppfVar4[2]) << 0xe) == 0) { **ppfVar4 = (float)ppfVar4[2]; } isHandled = isPressed; if (ppfVar4[6] != NULL) { (*(code *)ppfVar4[6])(**ppfVar4); } break; case MenuItem_Type_Select: selectData = (MenuItem_SelectData *)menuItem->itemData; iVar10 = Front_MenuItem_Select_TestStringCollision(menu,menuItem,selectData); if (isPressed) { if (iVar10 == -3) { if (selectData->scrollStart < 1) break; iVar10 = selectData->scrollStart + -1; } else { if (iVar10 != -2) { if (iVar10 != -1) { if (selectData->nextMenu != NULL) { *selectData->valuePtr = iVar10; if (selectData->callback != NULL) { (*selectData->callback)(elapsed,iVar10); } if ((menu == (globs::frontGlobs.mainMenuSet)->menus[3]) || (menu == *(globs::frontGlobs.saveMenuSet)->menus)) { globals::g_saveMenuSelectedIndex = iVar10; globals::g_saveMenuOutputSelectedIndex = iVar10; } return selectData->nextMenu; } *selectData->valuePtr = iVar10; if (selectData->callback != NULL) { (*selectData->callback)(elapsed,iVar10); } menu->closed = TRUE; if ((menu == (globs::frontGlobs.mainMenuSet)->menus[3]) || (menu == *(globs::frontGlobs.saveMenuSet)->menus)) { globals::g_saveMenuSelectedIndex = iVar10; globals::g_saveMenuOutputSelectedIndex = iVar10; } } break; } if ((int)(selectData->selItemCount - selectData->scrollCount) <= selectData->scrollStart ) break; iVar10 = selectData->scrollStart + 1; } selectData->scrollStart = iVar10; } } } } // IsKeyPressed(KEY_CURSORLEFT) (203) if (((globs::INPUT.Key_Map[203] != false) && (globs::INPUT.prevKey_Map[203] != globs::INPUT.Key_Map[203])) && (true)) { switch(menuItem->itemType) { case MenuItem_Type_Cycle: // Unreachable code because condition is already handled in CursorRight-or-isPressed // block. iVar10 = menuItem->itemData; **(int **)(iVar10 + 0xc) = **(int **)(iVar10 + 0xc) + -1; if (**(int **)(iVar10 + 0xc) < 0) { **(int **)(iVar10 + 0xc) = *(int *)(iVar10 + 8) + -1; } break; case MenuItem_Type_TextInput: iVar10 = menuItem->itemData; iVar9 = *(int *)(iVar10 + 8) + -1; *(int *)(iVar10 + 8) = iVar9; if (iVar9 < 0) { *(undefined4 *)(iVar10 + 8) = 0; } break; case MenuItem_Type_Slider: ppiVar3 = (int **)menuItem->itemData; **ppiVar3 = **ppiVar3 + -1; if ((int)**ppiVar3 < (int)ppiVar3[1]) { **ppiVar3 = (int)ppiVar3[1]; } if (ppiVar3[5] != NULL) { (*(code *)ppiVar3[5])(**ppiVar3); } break; case MenuItem_Type_RealSlider: ppfVar4 = (float **)menuItem->itemData; **ppfVar4 = **ppfVar4 - (float)ppfVar4[3]; if ((float)**ppfVar4 < (float)ppfVar4[1]) { **ppfVar4 = (float)ppfVar4[1]; } if (ppfVar4[6] != NULL) { (*(code *)ppfVar4[6])(**ppfVar4); } } } if ((isPressed) && (!isHandled)) { MVar5 = menuItem->itemType; if (MVar5 == MenuItem_Type_Cycle) { piVar7 = *(int **)(menuItem->itemData + 0xc); *piVar7 = (*piVar7 + 1) % *(int *)(menuItem->itemData + 8); } else { if (MVar5 == MenuItem_Type_Trigger) { puVar6 = (undefined4 *)menuItem->itemData; if ((code *)puVar6[2] != NULL) { (*(code *)puVar6[2])(); } if (puVar6[1] != 0) { menu->closed = TRUE; *(undefined4 *)*puVar6 = 1; } } else { if (MVar5 == MenuItem_Type_Next) { return (Menu *)menuItem->itemData; } } } } if (menuItem->itemType == MenuItem_Type_TextInput) { piVar7 = (int *)menuItem->itemData; key = 0; do { if ((globs::INPUT.Key_Map[key] != false) && (globs::INPUT.prevKey_Map[key] != globs::INPUT.Key_Map[key])) { if ((key == 0xe) && (iVar10 = piVar7[2], 0 < iVar10)) { if (iVar10 < piVar7[1]) { do { puVar1 = (undefined *)(*piVar7 + iVar10); iVar10 += 1; puVar1[-1] = *puVar1; } while (iVar10 < piVar7[1]); } piVar7[2] = piVar7[2] + -1; piVar7[1] = piVar7[1] + -1; } if (((piVar7[1] != piVar7[3]) && (piVar7[2] < piVar7[3] + -1)) && (globs::constant::c_keyCharMap[key] != 0)) { iVar10 = piVar7[1] + -1; if (piVar7[2] <= iVar10) { do { puVar1 = (undefined *)(*piVar7 + iVar10); iVar10 += -1; puVar1[1] = *puVar1; } while (piVar7[2] <= iVar10); } *(undefined *)(*piVar7 + piVar7[2]) = *(undefined *)(globs::constant::c_keyCharMap + key); // IsKeyDown(KEY_LEFTSHIFT) (42) || IsKeyDown(KEY_RIGHTSHIFT) (56) // "Unshift characters?" if ((globs::INPUT.Key_Map[42] != false) || (globs::INPUT.Key_Map[54] != false)) { *(char *)(*piVar7 + piVar7[2]) = *(char *)(*piVar7 + piVar7[2]) + -0x20; } piVar7[2] = piVar7[2] + 1; piVar7[1] = piVar7[1] + 1; } } key += 1; } while (key < 0x100); } return menu; } uint __cdecl lego::front::Front_Input_GetKeyCharacter(Keys32 diKey) { return globs::constant::c_keyCharMap[diKey]; } // valueIndex == (value - valueMin); // valueRange == (valueMax - valueMin); void __cdecl lego::front::Front_MenuItem_DrawSlider (MenuItem_SliderData *sliderData,uint x,uint y,int valueIndex,uint valueRange) { float fVar1; float fVar2; ulonglong uVar3; int iVar4; BOOL BVar5; longlong lVar6; Image *pIVar7; uint uVar8; uint uVar9; Point2F destPos; uint local_18; undefined4 uStack20; Area2F src; float fillWidth; local_18 = y; uStack20 = 0; src.x = 0.0; src.y = 0.0; src.height = 20.0; fillWidth = (float)(ulonglong)((uint)(valueIndex * 100) / valueRange); fVar1 = (float)(ulonglong)x; uVar3 = (ulonglong)y; fVar2 = (float)uVar3; destPos.x = fVar1; destPos.y = fVar2; src.width = fillWidth; lego::image::Image_DisplayScaled(sliderData->imageBarOn,&src,&destPos,NULL); src.width = 100.0 - fillWidth; destPos.x = fVar1 + fillWidth; src.y = 0.0; src.height = 20.0; destPos.y = fVar2; src.x = fillWidth; lego::image::Image_DisplayScaled(sliderData->imageBarOff,&src,&destPos,NULL); if (sliderData->imageCapLeft != NULL) { destPos.x = fVar1; destPos.y = fVar2; lego::image::Image_DisplayScaled(sliderData->imageCapLeft,NULL,&destPos,NULL); } if (sliderData->imageCapRight != NULL) { destPos.x = fVar1 - -100.0; destPos.y = fVar2; lego::image::Image_DisplayScaled(sliderData->imageCapRight,NULL,&destPos,NULL); } pIVar7 = sliderData->imageMinusLo; if ((pIVar7 != NULL) && (sliderData->imageMinusHi != NULL)) { destPos.x = fVar1 - (float)(pIVar7->width + 4); uVar9 = pIVar7->height; uVar8 = pIVar7->width; destPos.y = fVar2; lVar6 = __ftol((float10)uVar3); iVar4 = (int)lVar6; lVar6 = __ftol((float10)destPos.x); BVar5 = Front_Maths_IsPointInsideRect (globs::INPUT.msx,globs::INPUT.msy,(int)lVar6,iVar4,uVar8,uVar9); if (BVar5 == 0) { pIVar7 = sliderData->imageMinusLo; } else { pIVar7 = sliderData->imageMinusHi; } lego::image::Image_DisplayScaled(pIVar7,NULL,&destPos,NULL); } pIVar7 = sliderData->imagePlusLo; if ((pIVar7 != NULL) && (sliderData->imagePlusHi != NULL)) { destPos.x = ((float)sliderData->imageCapRight->width + fVar1) - -104.0; uVar9 = pIVar7->height; uVar8 = pIVar7->width; destPos.y = fVar2; lVar6 = __ftol((float10)uVar3); iVar4 = (int)lVar6; lVar6 = __ftol((float10)destPos.x); BVar5 = Front_Maths_IsPointInsideRect (globs::INPUT.msx,globs::INPUT.msy,(int)lVar6,iVar4,uVar8,uVar9); if (BVar5 != 0) { lego::image::Image_DisplayScaled(sliderData->imagePlusHi,NULL,&destPos,NULL); return; } lego::image::Image_DisplayScaled(sliderData->imagePlusLo,NULL,&destPos,NULL); } return; } uint __cdecl lego::front::Front_Menu_GetOverlayCount(Menu *menu) { uint count; MenuOverlay *overlay; count = 0; for (overlay = menu->overlays; overlay != NULL; overlay = overlay->previous) { count += 1; } return count; } BOOL __cdecl lego::front::Front_Menu_ShouldRandomPlay(void) { int iVar1; // Returns a 1-in-400 chance of TRUE. iVar1 = std::rand(); return (uint)(iVar1 % 400 == 0); } void __cdecl lego::front::Front_Menu_UpdateOverlays(Menu *menu) { MenuOverlay *pMVar1; uint uVar2; uint uVar3; BOOL BVar4; int iVar5; ulonglong uVar6; ulonglong uVar7; Area2F destArea; if (globs::frontGlobs.overlayImageOrFlic == NULL) { pMVar1 = menu->overlays; if (pMVar1 != NULL) { if (menu->playRandom == BOOL3_TRUE) { BVar4 = Front_Menu_ShouldRandomPlay(); if (BVar4 == 0) { uVar2 = 0; } else { uVar2 = Front_Menu_GetOverlayCount(menu); } if (uVar2 != 0) { uVar3 = std::rand(); for (uVar3 %= uVar2; uVar3 != 0; uVar3 -= 1) { pMVar1 = pMVar1->previous; } BVar4 = lego::image::Flic_Setup (pMVar1->filename,&globs::frontGlobs.overlayImageOrFlic,FLICDISK); if (BVar4 != 0) { snd::SFX_AddToQueue(pMVar1->sfxType,SoundMode_Once); globs::frontGlobs.overlayPosition.y = (pMVar1->position).x; globs::frontGlobs.overlayPosition.x = (pMVar1->position).y; globs::frontGlobs.overlayStartTime = main::Main_GetTime(); globs::frontGlobs.overlayCurrTime = globs::frontGlobs.overlayStartTime; return; } } } else { if (-1 < globals::g_saveMenuOverlayState) { for (iVar5 = 4 - globals::g_saveMenuOverlayState; iVar5 != 0; iVar5 += -1) { pMVar1 = pMVar1->previous; } BVar4 = lego::image::Flic_Setup (pMVar1->filename,&globs::frontGlobs.overlayImageOrFlic,FLICDISK); if (BVar4 != 0) { snd::SFX_AddToQueue(pMVar1->sfxType,SoundMode_Once); globs::frontGlobs.overlayPosition.y = (pMVar1->position).x; globs::frontGlobs.overlayPosition.x = (pMVar1->position).y; globs::frontGlobs.overlayStartTime = main::Main_GetTime(); globs::frontGlobs.overlayCurrTime = globs::frontGlobs.overlayStartTime; } globals::g_saveMenuSelectedIndex = -1; globals::g_saveMenuOverlayState = -1; globals::g_saveMenuOverlayPlaying = 1; return; } if (-1 < globals::g_saveMenuSelectedIndex) { globals::g_saveMenuOverlayState = globals::g_saveMenuSelectedIndex; globals::g_saveMenu_UnkNextMenu = NULL; } } } } else { // Flic_GetWidth uVar2 = gfx::AnimClone_IsLws__Flic_GetWidth((AnimClone *)globs::frontGlobs.overlayImageOrFlic); uVar3 = lego::image::Flic_GetHeight(globs::frontGlobs.overlayImageOrFlic); destArea.x = (float)globs::frontGlobs.overlayPosition.y; destArea.y = (float)globs::frontGlobs.overlayPosition.x; destArea.width = (float)(ulonglong)uVar2; destArea.height = (float)(ulonglong)uVar3; uVar3 = main::Main_GetTime(); uVar2 = globs::frontGlobs.overlayStartTime; uVar6 = __ftol((float10)(ulonglong) (globs::frontGlobs.overlayCurrTime - globs::frontGlobs.overlayStartTime) * (float10)0.025); uVar7 = __ftol((float10)(ulonglong)(uVar3 - uVar2) * (float10)0.025); if ((globals::g_saveMenuOverlayPlaying != 0) && (uVar7 &= 0xffffffff, (int)(uint)((globs::frontGlobs.overlayImageOrFlic)->fsHeader).frames <= (globs::frontGlobs.overlayImageOrFlic)->currentframe)) { uVar7 = uVar6 & 0xffffffff; globals::g_saveMenuOverlayState = -2; } globs::frontGlobs.overlayCurrTime = uVar3; BVar4 = lego::image::Flic_Animate (globs::frontGlobs.overlayImageOrFlic,&destArea, (uint)((int)uVar7 != (int)uVar6),0); if (BVar4 == 0) { lego::image::Flic_Close(globs::frontGlobs.overlayImageOrFlic); io::Mem_Free(globs::frontGlobs.overlayImageOrFlic); globs::frontGlobs.overlayImageOrFlic = NULL; globs::frontGlobs.overlayStartTime = 0; globs::frontGlobs.overlayCurrTime = 0; snd::Sound3D_Stream_Stop(0); } if ((globals::g_saveMenuOverlayPlaying != 0) && (globs::INPUT.mslb != 0)) { globals::g_saveMenuOverlayState = -2; globals::g_saveMenuOverlayPlaying = 0; return; } } return; } void __cdecl lego::front::Front_MenuItem_DrawSelectItem (int x,int y,Font *font,MenuItem_SelectData *selectData,uint selIndex, MenuItem_SelectImageType imageType) { Image *image; MenuItem_SelectItem *selItemData; int iVar1; Point2F destPos; selItemData = selectData->selItemList + selIndex; if ((*(byte *)&selItemData->flags & SELECTITEM_FLAG_HASBANNER) != 0) { lego::image::Font_PrintF(font,x,y,selItemData->banner); return; } destPos.y = (float)y; destPos.x = (float)x; image = selectData->selItemList[selIndex].images[imageType]; // HARDCODED SCREEN RESOLUTION!! // // if (image && (x+image->width > 0 && x < 640) && // (y+image->height > 0 && y < 480)) if ((((image != NULL) && (x < 640)) && (iVar1 = -image->width, x != iVar1 && SBORROW4(x,iVar1) == (int)(x + image->width) < 0)) && ((iVar1 = -image->height, y != iVar1 && SBORROW4(y,iVar1) == (int)(y + image->height) < 0 && (y < 480)))) { lego::image::Image_DisplayScaled(image,NULL,&destPos,NULL); } return; } void __cdecl lego::front::Front_MenuItem_DrawSaveImage (Menu *menu,int selIndex,MenuItem_SelectData *selectData,BOOL bigSize) { Image *image; char *pcVar1; int iVar2; char buff [8]; Size2F destSize; Point2F destPos; int local_1c; undefined4 uStack24; char *stringParts [5]; if ((menu == (globs::frontGlobs.mainMenuSet)->menus[3]) || (menu == *(globs::frontGlobs.saveMenuSet)->menus)) { image = globals::g_saveMenuImages[selIndex]; if (image != NULL) { std::sprintf(buff,"pos%d",selIndex + 1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::SaveImage",buff,0); pcVar1 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar1); util::Util_Tokenise(pcVar1,stringParts,"|"); iVar2 = std::atoi(stringParts[0]); destPos.x = (float)iVar2; iVar2 = std::atoi(stringParts[1]); destPos.y = (float)iVar2; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::SaveImage","Width",0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::SaveImage","Width",0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); } iVar2 = std::atoi(pcVar1); destSize.width = (float)iVar2; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::SaveImage","Height",0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::SaveImage","Height",0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); } iVar2 = std::atoi(pcVar1); destSize.height = (float)iVar2; if (bigSize != 0) { local_1c = globs::frontGlobs.saveImageBigSize.height; uStack24 = 0; destPos.x = destPos.x - ((float)(ulonglong)(uint)globs::frontGlobs.saveImageBigSize.width - destSize.width) * 0.25; destPos.y = destPos.y - ((float)(ulonglong)(uint)globs::frontGlobs.saveImageBigSize.height - destSize.height) * 0.25; destSize.width = destSize.width - ((float)(ulonglong)(uint)globs::frontGlobs.saveImageBigSize.width - destSize.width) * -0.5; destSize.height = destSize.height - ((float)(ulonglong)(uint)globs::frontGlobs.saveImageBigSize.height - destSize.height) * -0.5; } lego::image::Image_DisplayScaled(image,NULL,&destPos,&destSize); } } return; } // WARNING: Type propagation algorithm not settling void __cdecl lego::front::Front_Menu_DrawLoadSaveText(Menu **pMenu,Menu **ref_currMenu,Menu **ref_nextMenu) { int *piVar1; int j; char *format; int iVar2; int i; longlong lVar3; Menu *menu; // MainMenuFull::Menu4 "Load_Level_Save" menu = *pMenu; if ((menu != (globs::frontGlobs.mainMenuSet)->menus[3]) && (menu != *(globs::frontGlobs.saveMenuSet)->menus)) goto LAB_0041287c; // SaveMenu::Menu1 "Load_Level_Save" if ((menu == *(globs::frontGlobs.saveMenuSet)->menus) && (-1 < globals::g_saveMenuSelectedIndex)) { if (globals::g_saveMenuCompletionPercents[globals::g_saveMenuSelectedIndex] == 0) { globs::frontGlobs.saveMenuKeepOpen = FALSE; (*pMenu)->closed = TRUE; } else { globals::g_saveMenuOverwriteShowing = TRUE; } } TextWindow_Clear((globs::frontGlobs.saveTextWnd)->textWindow); TextWindow_PrintF((globs::frontGlobs.saveTextWnd)->textWindow,"\n"); if (globals::g_saveMenuOverlayState == -2) { if (globals::g_saveMenu_UnkNextMenu != NULL) { *ref_currMenu = globals::g_saveMenu_UnkNextMenu; } globals::g_saveMenu_UnkNextMenu = NULL; globals::g_frontSelectHoverIndex = -1; globals::g_saveMenuSelectingIndex = -1; LAB_00412766: *ref_nextMenu = NULL; globals::g_saveMenuSelectedIndex = -1; format = (globs::frontGlobs.saveTextWnd)->LoadText; if (*pMenu != (globs::frontGlobs.mainMenuSet)->menus[3]) { format = (globs::frontGlobs.saveTextWnd)->SaveText; } TextWindow_PrintF((globs::frontGlobs.saveTextWnd)->textWindow,format); } else { if (globals::g_saveMenuOverlayState == -1) goto LAB_00412766; globals::g_saveMenu_UnkNextMenu = *ref_currMenu; *ref_currMenu = *ref_nextMenu; globals::g_saveMenuSelectingIndex = globals::g_saveMenuOverlayState; } if (globals::g_saveMenuSelectingIndex < 0) { if (-1 < globals::g_frontSelectHoverIndex) { ref_currMenu = (Menu **)(float)(ulonglong) globals::g_saveMenuCompletionPercents [globals::g_frontSelectHoverIndex]; if ((ushort)((ushort)((float)ref_currMenu < 100.0) << 8 | (ushort)((float)ref_currMenu == 100.0) << 0xe) == 0) { // 100.0f ref_currMenu = (Menu **)&DAT_42c80000; } TextWindow_PrintF((globs::frontGlobs.saveTextWnd)->textWindow,"\n"); lVar3 = __ftol((float10)(float)ref_currMenu); TextWindow_PrintF((globs::frontGlobs.saveTextWnd)->textWindow, (globs::frontGlobs.saveTextWnd)->SlotText,(int)lVar3); } } else { TextWindow_Clear((globs::frontGlobs.saveTextWnd)->textWindow); // MainMenuFull::Menu4 "Load_Level_Save" if (*pMenu == (globs::frontGlobs.mainMenuSet)->menus[3]) { TextWindow_PrintF((globs::frontGlobs.saveTextWnd)->textWindow, (globs::frontGlobs.saveTextWnd)->LoadSelText, globals::g_saveMenuSelectingIndex + 1,0); } } if ((globs::frontGlobs.saveTextWnd)->textWindow != NULL) { TextWindow_Update((globs::frontGlobs.saveTextWnd)->textWindow,0,1.0,NULL); } LAB_0041287c: menu = *pMenu; // MainMenuFull::Menu4 "Load_Level_Save" if (((menu == (globs::frontGlobs.mainMenuSet)->menus[3]) && (true)) && (i = 0, 0 < menu->itemCount)) { do { if (menu->items[i]->itemType == MenuItem_Type_Select) { piVar1 = (int *)menu->items[i]->itemData; j = 0; if (0 < piVar1[7]) { iVar2 = 0; do { j += 1; // frontGlobs.langLoadGame std::sprintf(*(char **)(*piVar1 + 4 + iVar2),"%s %d",0x558514,j); iVar2 += 0x20; } while (j < piVar1[7]); } } menu = *pMenu; i += 1; } while (i < menu->itemCount); } return; } void __cdecl lego::front::Front_MenuItem_DrawSelectTextWindow(Menu **pMenu) { Size2F destSize; Point2F destPos; MenuTextWindow *menuWnd; menuWnd = globs::frontGlobs.saveLevelWnd; // MainMenuFull::Menu2 "Missions" || MainMenuFull::Menu3 "Training_Missions" if ((*pMenu == (globs::frontGlobs.mainMenuSet)->menus[1]) || (*pMenu == (globs::frontGlobs.mainMenuSet)->menus[2])) { if ((globs::frontGlobs.saveLevelWnd)->PanelImage != NULL) { destPos.x = ((globs::frontGlobs.saveLevelWnd)->PanelArea).x; destPos.y = ((globs::frontGlobs.saveLevelWnd)->PanelArea).y; destSize.width = ((globs::frontGlobs.saveLevelWnd)->PanelArea).width; destSize.height = ((globs::frontGlobs.saveLevelWnd)->PanelArea).height; lego::image::Image_DisplayScaled ((globs::frontGlobs.saveLevelWnd)->PanelImage,NULL,&destPos,&destSize); } if (menuWnd->textWindow != NULL) { TextWindow_Update(menuWnd->textWindow,0,1.0,NULL); TextWindow_Clear(menuWnd->textWindow); TextWindow_PrintF(menuWnd->textWindow,"\n"); // MainMenuFull::Menu2 "Missions" if ((*pMenu == (globs::frontGlobs.mainMenuSet)->menus[1]) && (menuWnd->LevelText != NULL)) { TextWindow_PrintF(menuWnd->textWindow,menuWnd->LevelText); TextWindow_PrintF(menuWnd->textWindow,"\n"); } // MainMenuFull::Menu3 "Training_Missions" if ((*pMenu == (globs::frontGlobs.mainMenuSet)->menus[2]) && (menuWnd->TutorialText != NULL)) { TextWindow_PrintF(menuWnd->textWindow,menuWnd->TutorialText); TextWindow_PrintF(menuWnd->textWindow,"\n"); } globals::g_levelSelectPrinting = TRUE; } } return; } void __cdecl lego::front::Front_Menu_DrawMenuImage(Menu *menu,BOOL light) { Point2F destPos; Area2F srcArea; Image *image; if (light == 0) { image = menu->menuImageDark; if (image != NULL) { if ((*(byte *)&menu->flags & 1) != 0) { lego::image::Image_DisplayScaled(image,NULL,&menu->currPosition,NULL); return; } // HARDCODED SCREEN RESOLUTION!! srcArea.x = -(float)globs::frontGlobs.scrollOffset.x; srcArea.y = -(float)globs::frontGlobs.scrollOffset.y; srcArea.width = 640.0; srcArea.height = 480.0; destPos.x = 0.0; destPos.y = 0.0; lego::image::Image_DisplayScaled(image,&srcArea,&destPos,NULL); } } else { image = menu->menuImage; if (image != NULL) { if ((*(byte *)&menu->flags & 1) != 0) { lego::image::Image_DisplayScaled(image,NULL,&menu->currPosition,NULL); return; } // HARDCODED SCREEN RESOLUTION!! srcArea.x = -(float)globs::frontGlobs.scrollOffset.x; srcArea.y = -(float)globs::frontGlobs.scrollOffset.y; srcArea.width = 640.0; srcArea.height = 480.0; destPos.x = 0.0; destPos.y = 0.0; lego::image::Image_DisplayScaled(image,&srcArea,&destPos,NULL); return; } } return; } Menu * __cdecl lego::front::Front_Menu_Update(float elapsed,Menu *menu,BOOL *optout_menuTransition) { Font **ppFVar1; MenuItem *pMVar2; float fVar3; MenuItem *pMVar4; int *piVar5; MenuItem_SliderData *pMVar6; float **ppfVar7; char **ppcVar8; MenuItem_SelectData *pMVar9; ulonglong uVar10; float fVar11; Viewport *view; Container *pCVar12; char *pcVar13; uint uVar14; BOOL BVar15; int iVar16; Font *pFVar17; Menu *pMVar18; uint selIndex; MenuItem_SelectItem *pMVar19; MenuItem_SelectImageType MVar20; int iVar21; int iVar22; int iVar23; int local_864; Point2F local_850; char origChar; Menu *currMenu; Container *local_840; Viewport *local_83c; undefined4 uStack2104; Point2F local_834; Menu *nextMenu; Pointer_Type currPointer; Vector3F origCamUp; Vector3F origCamDir; Vector3F origCamPos; char buff [2048]; int centerOffHi; int y1; int xPos; int yPos; save::Front_Save_GetCurrentSaveData(); currPointer = Pointer_GetCurrentType(); view = globs::legoGlobs.viewMain; local_83c = globs::legoGlobs.viewMain; local_840 = lego::view::Viewport_GetCamera(globs::legoGlobs.viewMain); globals::g_saveMenuSelectedIndex = -1; menu->itemFocus = -1; if (optout_menuTransition != NULL) { *optout_menuTransition = FALSE; } Pointer_SetCurrent_IfTimerFinished(Pointer_Standard); currMenu = menu; nextMenu = menu; if ((globals::g_saveMenuOverwriteShowing == 0) && (globals::g_saveMenu_UnkNextMenu == NULL)) { currMenu = Front_Menu_UpdateMenuItemsInput(elapsed,menu); } if (((menu == *(globs::frontGlobs.saveMenuSet)->menus) && (-1 < globals::g_saveMenuSelectedIndex)) && (globals::g_saveMenuOverwriteResult < 0)) { menu->closed = FALSE; currMenu->closed = FALSE; } if (-1 < globals::g_saveMenuOverlayState) { currMenu = nextMenu; } xPos = (menu->position).x; yPos = (menu->position).y; if ((globs::frontGlobs.rockWipeAnim != NULL) && (((byte)globs::frontGlobs.rockWipeFlags & 1) != 0) ) { lego::view::Viewport_Clear(view,TRUE); gfx::Container_SetParent(globs::frontGlobs.rockWipeAnim,globs::legoGlobs.rootCont); pCVar12 = lego::view::Viewport_GetCamera(view); local_840 = pCVar12; gfx::Container_GetPosition(pCVar12,NULL,&origCamPos); gfx::Container_GetOrientation(pCVar12,NULL,&origCamDir,&origCamUp); gfx::Container_SetPosition(pCVar12,NULL,0.0,0.0,5.0); gfx::Container_SetOrientation(pCVar12,NULL,0.0,0.0,1.0,0.0,1.0,0.0); gfx::Container_SetAnimationTime(globs::frontGlobs.rockWipeAnim,globs::frontGlobs.rockWipeTimer); } Front_Menu_DrawMenuImage(menu,TRUE); if (menu != *(globs::frontGlobs.saveMenuSet)->menus) { Front_Menu_UpdateOverlays(menu); } Front_Menu_DrawLoadSaveText(&menu,&currMenu,&nextMenu); if (menu->displayTitle != 0) { pcVar13 = Front_Util_ReplaceTextSpaces(menu->fullName); uVar14 = lego::image::Font_GetStringWidth(menu->menuFont,pcVar13); iVar23 = (menu->anchoredPosition).y; iVar21 = (int)globs::mainGlobs.appWidth / 2; pcVar13 = Front_Util_ReplaceTextSpaces(menu->fullName); lego::image::Font_PrintF(menu->menuFont,iVar21 - (uVar14 >> 1),iVar23 + yPos,pcVar13); } globals::g_frontSelectHoverIndex = -1; local_834.x = 0.0; if (0 < menu->itemCount) { do { fVar11 = local_834.x; if ((((float)menu->itemFocus == local_834.x) && (globals::g_saveMenuOverwriteShowing == 0)) && (BVar15 = Front_MenuItem_CheckNotInTutoAnyTutorialFlags(menu->items[(int)local_834.x]), BVar15 == 0)) { pMVar2 = menu->items[(int)fVar11]; y1 = pMVar2->y1; fVar3 = (float)pMVar2->x1; centerOffHi = pMVar2->centerOffHi; local_850.x = fVar3; if (pMVar2->fontHi != NULL) { pcVar13 = Front_Util_ReplaceTextSpaces(pMVar2->banner); lego::image::Font_PrintF (pMVar2->fontHi,centerOffHi + (int)fVar3 + xPos,y1 + yPos,"%s",pcVar13); } pMVar4 = menu->items[menu->itemFocus]; if (true) { switch(pMVar4->itemType) { case MenuItem_Type_Cycle: piVar5 = (int *)pMVar4->itemData; if (pMVar2->fontHi != NULL) { pcVar13 = Front_Util_ReplaceTextSpaces(*(char **)(*piVar5 + *(int *)piVar5[3] * 4)); iVar21 = y1 + piVar5[5]; pFVar17 = pMVar2->fontHi; iVar23 = centerOffHi + piVar5[4] + (int)local_850.x; LAB_004134b1: iVar21 += yPos; iVar23 += xPos; LAB_004134b2: lego::image::Font_PrintF(pFVar17,iVar23,iVar21,pcVar13); } break; case MenuItem_Type_TextInput: ppcVar8 = (char **)pMVar4->itemData; origChar = (*ppcVar8)[(int)ppcVar8[2]]; globals::s_frontTextInputCaretBlinker += 1; // if ((s_frontTextInputCaretBlinker / 2) % 2 != 0) if ((globals::s_frontTextInputCaretBlinker != 0) && (uVar14 = globals::s_frontTextInputCaretBlinker / 2 >> 0x1f, ((globals::s_frontTextInputCaretBlinker / 2 ^ uVar14) - uVar14 & 1 ^ uVar14) != uVar14)) { // Caret underscore is overwritten by a space in Front_Util_ReplaceTextSpaces. (*ppcVar8)[(int)ppcVar8[2]] = '_'; } if (pMVar2->fontHi != NULL) { pcVar13 = Front_Util_ReplaceTextSpaces(*ppcVar8); lego::image::Font_PrintF (pMVar2->fontHi,(int)(ppcVar8[4] + centerOffHi + (int)local_850.x + xPos), (int)(ppcVar8[5] + y1 + yPos),"%s",pcVar13); } if ((globals::s_frontTextInputCaretBlinker != 0) && (uVar14 = globals::s_frontTextInputCaretBlinker / 2 >> 0x1f, ((globals::s_frontTextInputCaretBlinker / 2 ^ uVar14) - uVar14 & 1 ^ uVar14) != uVar14)) { (*ppcVar8)[(int)ppcVar8[2]] = origChar; } break; case MenuItem_Type_Slider: pMVar6 = (MenuItem_SliderData *)pMVar4->itemData; Front_MenuItem_DrawSlider (pMVar6,(int)fVar3 + xPos + pMVar6->x2,y1 + yPos + pMVar6->y2, *pMVar6->valuePtr - pMVar6->valueMin,pMVar6->valueMax - pMVar6->valueMin); break; case MenuItem_Type_RealSlider: ppfVar7 = (float **)pMVar4->itemData; // if (menuItem->fontHi != NULL) if (pMVar2->fontHi != NULL) { lego::image::Font_PrintF (pMVar2->fontHi,(int)ppfVar7[4] + xPos + (int)fVar3 + centerOffHi, (int)ppfVar7[5] + yPos + y1,"%.2f",(double)**ppfVar7); } break; case MenuItem_Type_Select: pMVar4 = menu->items[(int)fVar11]; pMVar9 = (MenuItem_SelectData *)pMVar4->itemData; uVar14 = Front_MenuItem_Select_TestStringCollision(menu,pMVar4,pMVar9); local_864 = 0; globals::g_frontSelectHoverIndex = uVar14; if (0 < pMVar9->scrollCount) { do { selIndex = pMVar9->scrollStart + local_864; if ((int)pMVar9->selItemCount <= (int)selIndex) break; pMVar19 = pMVar9->selItemList + selIndex; iVar23 = -((int)pMVar9->widths[0][selIndex] / 2); MVar20 = ~pMVar19->flags >> 1 & 2; if (menu->autoCenter == 0) { iVar23 = 0; } if (uVar14 == selIndex) { Front_MenuItem_DrawSelectItem ((int)local_850.x + globs::frontGlobs.scrollOffset.x + xPos + pMVar9->x2 + pMVar19->frontEndX + iVar23, y1 + globs::frontGlobs.scrollOffset.y + yPos + pMVar9->selItemHeight * local_864 + pMVar9->y2 + pMVar19->frontEndY,pMVar2->fontHi,pMVar9,selIndex,MVar20); if (pMVar9->callback != NULL) { (*pMVar9->callback)(elapsed,uVar14); } BVar15 = TRUE; } else { if (MVar20 == MenuItem_SelectImage_Light) { MVar20 = MenuItem_SelectImage_Dark; } Front_MenuItem_DrawSelectItem ((int)local_850.x + globs::frontGlobs.scrollOffset.x + xPos + pMVar9->x2 + pMVar19->frontEndX + iVar23, y1 + globs::frontGlobs.scrollOffset.y + yPos + pMVar9->selItemHeight * local_864 + pMVar9->y2 + pMVar19->frontEndY,pMVar2->fontLo,pMVar9,selIndex,MVar20); BVar15 = FALSE; } Front_MenuItem_DrawSaveImage(menu,local_864 + pMVar9->scrollStart,pMVar9,BVar15); local_864 += 1; } while (local_864 < pMVar9->scrollCount); } // -2 if ((uVar14 == 0xfffffffe) && (pMVar9->scrollStart < (int)(pMVar9->selItemCount - pMVar9->scrollCount))) { pFVar17 = pMVar2->fontHi; joined_r0x00413184: if (pFVar17 != NULL) { lego::image::Font_PrintF (pFVar17,pMVar9->xString1 + xPos,pMVar9->yString1 + yPos,pMVar9->string1); } } else { if (pMVar9->scrollStart < (int)(pMVar9->selItemCount - pMVar9->scrollCount)) { pFVar17 = pMVar2->fontLo; goto joined_r0x00413184; } } // -3 if (uVar14 == 0xfffffffd) { if (0 < pMVar9->scrollStart) { pFVar17 = pMVar2->fontHi; LAB_004131c3: if (pFVar17 != NULL) { pcVar13 = pMVar9->string2; iVar21 = pMVar9->yString2 + yPos; iVar23 = pMVar9->xString2 + xPos; goto LAB_004134b2; } } } else { if (0 < pMVar9->scrollStart) { pFVar17 = pMVar2->fontLo; goto LAB_004131c3; } } } } } else { pMVar2 = menu->items[(int)fVar11]; iVar23 = pMVar2->x1; iVar21 = pMVar2->y1; iVar22 = pMVar2->centerOffLo; ppFVar1 = &pMVar2->fontLo; if (pMVar2->fontLo != NULL) { pcVar13 = Front_Util_ReplaceTextSpaces(pMVar2->banner); lego::image::Font_PrintF (menu->items[(int)fVar11]->fontLo,iVar22 + iVar23 + xPos,iVar21 + yPos,"%s", pcVar13); } pMVar2 = menu->items[(int)fVar11]; if (true) { switch(pMVar2->itemType) { case MenuItem_Type_Cycle: piVar5 = (int *)pMVar2->itemData; if (*ppFVar1 != NULL) { pcVar13 = Front_Util_ReplaceTextSpaces(*(char **)(*piVar5 + *(int *)piVar5[3] * 4)); iVar21 += yPos + piVar5[5]; pFVar17 = *ppFVar1; iVar23 = iVar22 + piVar5[4] + iVar23 + xPos; goto LAB_004134b2; } break; case MenuItem_Type_TextInput: ppcVar8 = (char **)pMVar2->itemData; if (*ppFVar1 != NULL) { pcVar13 = Front_Util_ReplaceTextSpaces(*ppcVar8); lego::image::Font_PrintF (*ppFVar1,(int)(ppcVar8[4] + iVar22 + iVar23 + xPos), (int)(ppcVar8[5] + iVar21 + yPos),"%s",pcVar13); } break; case MenuItem_Type_Slider: pMVar6 = (MenuItem_SliderData *)pMVar2->itemData; Front_MenuItem_DrawSlider (pMVar6,iVar23 + xPos + pMVar6->x2,iVar21 + yPos + pMVar6->y2, *pMVar6->valuePtr - pMVar6->valueMin,pMVar6->valueMax - pMVar6->valueMin); break; case MenuItem_Type_RealSlider: ppfVar7 = (float **)pMVar2->itemData; if (*ppFVar1 != NULL) { lego::image::Font_PrintF (*ppFVar1,(int)ppfVar7[4] + xPos + iVar23 + iVar22, (int)ppfVar7[5] + yPos + iVar21,"%.2f",(double)**ppfVar7); } break; case MenuItem_Type_Select: pMVar9 = (MenuItem_SelectData *)pMVar2->itemData; iVar22 = 0; if (0 < pMVar9->scrollCount) { do { local_850.x = (float)(iVar22 + pMVar9->scrollStart); if ((int)pMVar9->selItemCount <= (int)local_850.x) break; iVar16 = -((int)pMVar9->widths[0][(int)local_850.x] / 2); pMVar19 = pMVar9->selItemList + (int)local_850.x; MVar20 = ~pMVar19->flags >> 1 & 2; if (menu->autoCenter == 0) { iVar16 = 0; } if (MVar20 == MenuItem_SelectImage_Light) { MVar20 = MenuItem_SelectImage_Dark; } Front_MenuItem_DrawSelectItem (iVar23 + globs::frontGlobs.scrollOffset.x + xPos + pMVar9->x2 + pMVar19->frontEndX + iVar16, iVar21 + globs::frontGlobs.scrollOffset.y + yPos + pMVar9->selItemHeight * iVar22 + pMVar9->y2 + pMVar19->frontEndY,*ppFVar1,pMVar9,(uint)local_850.x, MVar20); Front_MenuItem_DrawSaveImage(menu,iVar22 + pMVar9->scrollStart,pMVar9,0); iVar22 += 1; } while (iVar22 < pMVar9->scrollCount); } if ((pMVar9->scrollStart < (int)(pMVar9->selItemCount - pMVar9->scrollCount)) && (*ppFVar1 != NULL)) { lego::image::Font_PrintF (*ppFVar1,pMVar9->xString1 + xPos,pMVar9->yString1 + yPos,pMVar9->string1); } if ((0 < pMVar9->scrollStart) && (pFVar17 = *ppFVar1, pFVar17 != NULL)) { pcVar13 = pMVar9->string2; iVar21 = pMVar9->yString2; iVar23 = pMVar9->xString2; goto LAB_004134b1; } } } } local_834.x = (float)((int)local_834.x + 1); } while ((int)local_834.x < menu->itemCount); } Front_MenuItem_DrawSelectTextWindow(&menu); iVar23 = 0; pMVar18 = menu; if (0 < menu->itemCount) { do { pMVar2 = pMVar18->items[iVar23]; if (pMVar2->isImageItem != 0) { if (pMVar18->itemFocus == iVar23) { if (pMVar2->imageHi != NULL) { local_834.x = (float)(pMVar2->x1 + (pMVar18->position).x); local_834.y = (float)(pMVar2->y1 + (pMVar18->position).y); lego::image::Image_DisplayScaled(pMVar2->imageHi,NULL,&local_834,NULL); } ToolTip_Activate(pMVar2->toolTipType); pMVar18 = menu; } else { if (pMVar2->imageLo != NULL) { local_850.x = (float)(pMVar2->x1 + (pMVar18->position).x); local_850.y = (float)(pMVar2->y1 + (pMVar18->position).y); lego::image::Image_DisplayScaled(pMVar2->imageLo,NULL,&local_850,NULL); pMVar18 = menu; } } } iVar23 += 1; } while (iVar23 < pMVar18->itemCount); } if (((((globs::mainGlobs.flags & MAIN_FLAG_SHOWVERSION) != MAIN_FLAG_NONE) && (globs::frontGlobs.versionFont != NULL)) && (globs::frontGlobs.versionString != NULL)) && (globs::mainGlobs.programmerLevel == PROGRAMMER_OFF)) { lego::image::Font_PrintF (globs::frontGlobs.versionFont,0x221,0x1c2,globs::frontGlobs.versionString); } Front_LevelSelect_LevelNamePrintF(NULL,0,0,NULL); if ((menu == *(globs::frontGlobs.saveMenuSet)->menus) && (globals::g_saveMenuOverwriteShowing != 0)) { // GHIDRA FAIL: Missing argument // std::sprintf(buff, frontGlobs.langOverwriteMessage, g_SaveMenu_OutNumber); std::sprintf(buff,globs::frontGlobs.langOverwriteMessage, globals::g_saveMenuOutputSelectedIndex + 1); globals::g_saveMenuOverwriteResult = lrr::Lego_SaveMenu_ConfirmMessage_FUN_004354f0 (globs::frontGlobs.langOverwriteTitle,buff,globs::frontGlobs.langOverwriteOK, globs::frontGlobs.langOverwriteCancel); if (globals::g_saveMenuOverwriteResult == 0) { globs::frontGlobs.saveMenuKeepOpen = TRUE; menu->closed = TRUE; globals::g_saveMenuOverwriteShowing = FALSE; globals::g_saveMenuOutputSelectedIndex = -1; } else { if (globals::g_saveMenuOverwriteResult == 1) { globs::frontGlobs.saveMenuKeepOpen = FALSE; menu->closed = TRUE; globals::g_saveMenuOverwriteShowing = FALSE; } } } if ((globs::frontGlobs.rockWipeAnim != NULL) && (((byte)globs::frontGlobs.rockWipeFlags & 1) != 0) ) { gfx::Container_Hide(globs::frontGlobs.rockWipeLight,0); lego::view::Viewport_Render(local_83c,globs::legoGlobs.rootCont,0.0); gfx::Container_Hide(globs::frontGlobs.rockWipeLight,TRUE); pCVar12 = local_840; gfx::Container_SetPosition(local_840,NULL,origCamPos.x,origCamPos.y,origCamPos.z); gfx::Container_SetOrientation (pCVar12,NULL,origCamDir.x,origCamDir.y,origCamDir.z,origCamUp.x,origCamUp.y, origCamUp.z); gfx::Container_SetParent(globs::frontGlobs.rockWipeAnim,NULL); local_83c = (Viewport *)gfx::Container_GetAnimationFrames(globs::frontGlobs.rockWipeAnim); uStack2104 = 0; local_840 = (Container *)(float)ZEXT48(local_83c); local_83c = (Viewport *)main::Main_GetTime(); uStack2104 = 0; uVar10 = ZEXT48(local_83c); local_850.x = ((float)uVar10 - globs::frontGlobs.rockWipeLastUpdateTime) * 0.001 * 25.0; local_850.x = local_850.x + local_850.x; if ((ushort)((ushort)(local_850.x < 3.0) << 8 | (ushort)(local_850.x == 3.0) << 0xe) == 0) { local_850.x = 3.0; } fVar11 = (float)local_840 * 0.5; if (((ushort)((ushort)(globs::frontGlobs.rockWipeTimer < fVar11) << 8 | (ushort)(globs::frontGlobs.rockWipeTimer == fVar11) << 0xe) != 0) && (fVar11 <= local_850.x + globs::frontGlobs.rockWipeTimer)) { if (optout_menuTransition != NULL) { *optout_menuTransition = TRUE; } globals::g_saveMenuOverlayState = -1; globals::g_saveMenuSelectedIndex = -1; globals::g_saveMenu_UnkNextMenu = NULL; globals::g_saveMenuOverlayPlaying = 0; if (globs::frontGlobs.overlayImageOrFlic != NULL) { globs::frontGlobs.overlayStartTime = 0; globs::frontGlobs.overlayCurrTime = 0; } } if ((ushort)((ushort)(globs::frontGlobs.rockWipeTimer < (float)local_840) << 8 | (ushort)(globs::frontGlobs.rockWipeTimer == (float)local_840) << 0xe) == 0) { Front_RockWipe_Stop(); } globs::frontGlobs.rockWipeTimer = local_850.x + globs::frontGlobs.rockWipeTimer; globs::frontGlobs.rockWipeLastUpdateTime = (float)uVar10; } Pointer_DrawPointer(globs::INPUT.msx,globs::INPUT.msy); Pointer_SetCurrent_IfTimerFinished(currPointer); return currMenu; } void __cdecl lego::front::Front_Menu_UpdateMousePosition(Menu *menu) { float10 fVar1; longlong lVar2; uint imageHeight; float mouseY; if ((menu->menuImage == NULL) || ((*(byte *)&menu->flags & MENU_FLAG_CANSCROLL) == 0)) { globs::frontGlobs.scrollOffset.x = 0; globs::frontGlobs.scrollOffset.y = 0; } else { // HARDCODED SCREEN RESOLUTION!! mouseY = (float)globs::INPUT.msy; // If mouseY is not between 200.0f and 280.0f. if (((ushort)((ushort)(mouseY < 280.0) << 8 | (ushort)(mouseY == 280.0) << 0xe) == 0) || (mouseY < 200.0)) { imageHeight = menu->menuImage->height; if ((mouseY < 480.0) && ((globs::INPUT.mslb == 0 && (globs::INPUT.msrb == 0)))) { fVar1 = (float10)globs::INPUT.msy * (float10)0.2083333 - (float10)50.0; fVar1 = fVar1 * fVar1 * (float10)0.02; if (mouseY < 240.0) { fVar1 = -fVar1; } lVar2 = __ftol(fVar1 * (float10)-0.25); globs::frontGlobs.scrollOffset.y += (int)lVar2; } if (0 < globs::frontGlobs.scrollOffset.y) { globs::frontGlobs.scrollOffset.y = 0; } if (SBORROW4(globs::frontGlobs.scrollOffset.y + -480,-imageHeight) != (int)(globs::frontGlobs.scrollOffset.y + -480 + imageHeight) < 0) { globs::frontGlobs.scrollOffset.y = 480 - imageHeight; return; } } } return; } void __cdecl lego::front::Front_LoadSaveSlotImages(void) { char *pcVar1; Image *pIVar2; int iVar3; float *pfVar4; uint saveIndex; Image **pImage; uint *puVar5; int iVar6; int *piVar7; SaveData local_b8; iVar6 = 0; pImage = globals::g_saveMenuImages; do { iVar3 = iVar6; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::SaveImage","Path",0); // Yet another memory leak with this unreleased name. pcVar1 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar1); // Max valid size of SaveImage Path in game is 184, but only due to field reuse // optimization, other areas use 128 buffer sizes. std::sprintf((char *)&local_b8,"%s\\%d.dat",pcVar1,iVar3); pIVar2 = lego::image::Image_LoadBMPScaled((char *)&local_b8,0,0); *pImage = pIVar2; pImage = pImage + 1; iVar6 += 1; } while (pImage < &DAT_004dc8a4); // Functionally this entire block does nothing, it was likely some debug check at one // point. saveIndex = 0; puVar5 = globals::g_saveMenuCompletionPercents; do { // For some reason the first field is zeroed out manually, this may actally be a // substruct of size 0xb4... local_b8.field_0x0 = 0; piVar7 = &local_b8.SliderMusicVolume; for (iVar6 = 0x2d; iVar6 != 0; iVar6 += -1) { *piVar7 = 0; piVar7 = piVar7 + 1; } save::Front_Save_ReadSaveFile(saveIndex,&local_b8,TRUE); *puVar5 = 0; if (8 < local_b8.missionsCount) { // missionsTable[NUM_TUTORIALS].reward.items[Reward_Score].percentFloat; pfVar4 = &local_b8.missionsTable[8].reward.items[9].percentFloat; // missionsCount - NUM_TUTORIALS iVar6 = local_b8.missionsCount - 8; do { if (*pfVar4 == 0.0) { iVar3 = 0; } else { iVar3 = 4; } *puVar5 = *puVar5 + iVar3; pfVar4 = pfVar4 + 0xc64; iVar6 += -1; } while (iVar6 != 0); } io::Mem_Free(local_b8.missionsTable); puVar5 = puVar5 + 1; saveIndex += 1; } while (puVar5 < &globals::g_saveMenuOverwriteShowing); return; } void __cdecl lego::front::Front_FreeSaveSlotImages(void) { Image **pImage; pImage = globals::g_saveMenuImages; do { if (*pImage != NULL) { lego::image::Image_Remove(*pImage); } pImage = pImage + 1; } while (pImage < &DAT_004dc8a4); return; } // WARNING: Type propagation algorithm not settling void __cdecl lego::front::Front_ScreenMenuLoop(Menu *menu) { float elapsed; Menu *pMVar1; DWORD currTime; RewardLevel *rewards; char *pcVar2; BOOL menuTransitioning; Menu *nextMenu; float local_90; DWORD lastTime; uint timeDelta; undefined4 uStack132; char buff [128]; bool menuChanged; int menuClosed; menuChanged = false; menuTransitioning = FALSE; local_90 = 1.0; Front_LoadSaveSlotImages(); globals::g_saveMenu_UnkNextMenu = NULL; globals::g_saveMenuOverlayState = -1; globals::g_saveMenuSelectedIndex = -1; globals::g_saveMenuSelectingIndex = -1; globals::g_saveMenuOverwriteResult = -1; globals::g_saveMenuOutputSelectedIndex = -1; globals::g_saveMenuOverlayPlaying = FALSE; globals::g_saveMenuOverwriteShowing = FALSE; globals::g_levelSelectPrinting = FALSE; globs::frontGlobs.saveMenuHasSaved = TRUE; globs::frontGlobs.saveMenuKeepOpen = TRUE; globs::frontGlobs.overlayImageOrFlic = NULL; lastTime = timeGetTime(); menuClosed = menu->closed; elapsed = local_90; while (local_90 = elapsed, menuClosed == 0) { if (menuChanged) { Front_Menu_Update(elapsed,menu,&menuTransitioning); } else { nextMenu = Front_Menu_Update(elapsed,menu,NULL); } // if ((submenu == globals::menu::g_MainMenuFull->menus[0]) ... if ((menu == *(globs::frontGlobs.mainMenuSet)->menus) && (nextMenu != menu)) { globs::frontGlobs.selectLoadSaveIndex = -1; Front_Callback_SelectLoadSave(elapsed,-1); } Front_Menu_UpdateMousePosition(menu); ToolTip_Update(globs::INPUT.msx,globs::INPUT.msy,elapsed); snd::SFX_Update(elapsed); main::Main_LoopUpdate(FALSE); currTime = timeGetTime(); pMVar1 = nextMenu; timeDelta = currTime - lastTime; uStack132 = 0; local_90 = (float)(ulonglong)timeDelta * 0.025; lastTime = currTime; if ((!menuChanged) && (nextMenu != menu)) { Front_RockWipe_Play(); menuChanged = true; if (globs::frontGlobs.rockWipeAnim == NULL) { menuTransitioning = TRUE; } } if ((menuChanged) && (menuTransitioning != 0)) { if ((menu->menuImage != pMVar1->menuImage) && (globs::frontGlobs.overlayImageOrFlic != NULL)) { lego::image::Flic_Close(globs::frontGlobs.overlayImageOrFlic); io::Mem_Free(globs::frontGlobs.overlayImageOrFlic); snd::Sound3D_Stream_Stop(FALSE); globs::frontGlobs.overlayImageOrFlic = NULL; globs::frontGlobs.overlayStartTime = 0; globs::frontGlobs.overlayCurrTime = 0; } globs::frontGlobs.scrollOffset.y = 0; globs::frontGlobs.scrollOffset.x = 0; menuChanged = false; menuTransitioning = FALSE; menu = pMVar1; } elapsed = local_90; menuClosed = menu->closed; } Front_FreeSaveSlotImages(); if ((((nextMenu == *(globs::frontGlobs.saveMenuSet)->menus) && (-1 < globals::g_saveMenuOutputSelectedIndex)) && (rewards = reward::GetRewardLevel(), rewards != NULL)) && (rewards = reward::GetRewardLevel(), rewards->saveHasCapture != 0)) { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::SaveImage","Path",0); // MORE MEMORY LEAKS!!!! GAHHHHHH pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); std::sprintf(buff,"%s\\%d.dat",pcVar2,globals::g_saveMenuOutputSelectedIndex); lego::image::Image_SaveBMP(&rewards->saveCaptureImage,buff); } if (globs::frontGlobs.overlayImageOrFlic != NULL) { lego::image::Flic_Close(globs::frontGlobs.overlayImageOrFlic); io::Mem_Free(globs::frontGlobs.overlayImageOrFlic); snd::Sound3D_Stream_Stop(FALSE); globs::frontGlobs.overlayImageOrFlic = NULL; globs::frontGlobs.overlayStartTime = 0; globs::frontGlobs.overlayCurrTime = 0; } Front_RockWipe_Stop(); return; } void __cdecl lego::front::Front_RunScreenMenu(MenuSet *menuSet,uint menuIndex) { int i; int i_next; i = 0; if (0 < (int)menuSet->menuCount) { do { i_next = i + 1; menuSet->menus[i]->closed = FALSE; i = i_next; } while (i_next < (int)menuSet->menuCount); } Front_ScreenMenuLoop(menuSet->menus[menuIndex]); return; } MenuItem_Type __cdecl lego::front::Front_MenuItem_ParseTypeString(char *itemTypeName) { int cmp; cmp = std::_stricmp(itemTypeName,"cycle"); if (cmp == 0) { return MenuItem_Type_Cycle; } cmp = std::_stricmp(itemTypeName,"trigger"); if (cmp == 0) { return MenuItem_Type_Trigger; } cmp = std::_stricmp(itemTypeName,"textinput"); if (cmp == 0) { return MenuItem_Type_TextInput; } cmp = std::_stricmp(itemTypeName,"slider"); if (cmp == 0) { return MenuItem_Type_Slider; } cmp = std::_stricmp(itemTypeName,"realslider"); if (cmp == 0) { return MenuItem_Type_RealSlider; } cmp = std::_stricmp(itemTypeName,"next"); // return MenuItem_Type_Next (5) or MenuItem_Type_Invalid (-1) if no match. return (-(uint)(cmp != 0) & 0xfffffffa) + MenuItem_Type_Next; } // Returns str. char * __cdecl lego::front::Front_Util_StringReplaceChar(char *str,char origChar,char newChar) { char *pcVar1; char *s; char c; c = *str; s = str; while (c != '\0') { if (c == origChar) { *s = newChar; } pcVar1 = s + 1; s = s + 1; c = *pcVar1; } return str; } MenuOverlay_Type __cdecl lego::front::Front_Menu_GetOverlayType(MenuOverlay *menuOverlay) { char *pcVar1; int cmp; char *ext; char c; ext = menuOverlay->filename; c = *ext; // Memory access violation if there's no '.' extension. while (c != '.') { pcVar1 = ext + 1; ext = ext + 1; c = *pcVar1; } cmp = std::_stricmp(".avi",ext); if (cmp != 0) { cmp = std::_stricmp(".bmp",ext); if (cmp != 0) { cmp = std::_stricmp(".lws",ext); // return MenuOverlay_Type_Lws (3) or MenuOverlay_Type_Flic (0) if no match. return (-(uint)(cmp != 0) & 0xfffffffd) + MenuOverlay_Type_Lws; } return MenuOverlay_Type_Image; } return MenuOverlay_Type_Animation; } // ref_overlay functions as an input argument for the last overlay, and output argument for the new // overlay (which is linked to the previous via linked list) MenuOverlay * __cdecl lego::front::Front_Menu_CreateOverlay (char *filename,MenuOverlay **linkedOverlay,int positionX,int positionY,SFX_ID sfxType) { MenuOverlay *menuOverlay; int cmp; char *pcVar1; MenuOverlay_Type MVar2; int iVar3; MenuOverlay *pMVar4; menuOverlay = (MenuOverlay *)io::Mem_Alloc(0x20); pMVar4 = menuOverlay; for (iVar3 = 8; iVar3 != 0; iVar3 += -1) { pMVar4->filename = NULL; pMVar4 = (MenuOverlay *)&pMVar4->overlayType; } // Okay... so don't use a filename that STARTS with "null"...? cmp = std::_strnicmp(filename,"Null",4); if (cmp != 0) { if (filename != NULL) { pcVar1 = Front_Util_StrCpy(filename); menuOverlay->filename = pcVar1; } MVar2 = Front_Menu_GetOverlayType(menuOverlay); menuOverlay->overlayType = MVar2; menuOverlay->field_1c = 0; pMVar4 = *linkedOverlay; (menuOverlay->position).x = positionX; menuOverlay->previous = pMVar4; menuOverlay->sfxType = sfxType; (menuOverlay->position).y = positionY; *linkedOverlay = menuOverlay; } return menuOverlay; } void __cdecl lego::front::Front_Menu_LoadSliderImages(int numParts,char **stringParts,Image **outImages) { Image *image; int iVar1; char **ppcVar2; if (numParts == 0x10) { // Slider images start at index 8. ppcVar2 = stringParts + 8; iVar1 = 8; do { image = Front_Cache_LoadImage(*ppcVar2); *outImages = image; if (image != NULL) { lego::image::Image_SetPenZeroTrans(image); } ppcVar2 = ppcVar2 + 1; outImages = outImages + 1; iVar1 += -1; } while (iVar1 != 0); return; } for (iVar1 = 8; iVar1 != 0; iVar1 += -1) { *outImages = NULL; outImages = outImages + 1; } return; } MenuSet * __cdecl lego::front::Front_CreateMenuSet(uint menuCount) { MenuSet *menuSet; Menu **ppMVar1; uint uVar2; int iVar3; menuSet = (MenuSet *)io::Mem_Alloc(8); menuSet->menus = NULL; menuSet->menuCount = 0; ppMVar1 = (Menu **)io::Mem_Alloc(menuCount * 4); uVar2 = menuCount & 0x3fffffff; menuSet->menus = ppMVar1; for (; uVar2 != 0; uVar2 -= 1) { *ppMVar1 = NULL; ppMVar1 = ppMVar1 + 1; } for (iVar3 = 0; iVar3 != 0; iVar3 += -1) { *(undefined *)ppMVar1 = 0; ppMVar1 = (Menu **)((int)ppMVar1 + 1); } menuSet->menuCount = menuCount; return menuSet; } MenuSet * __cdecl lego::front::Front_LoadMenuSet(Config *unused_config,char *menuName,void *dst,void *callback,...) { MenuItem_Type MVar1; float *valuePtr; char *pcVar2; uint uVar3; MenuSet *menuCol; char *pcVar4; char *pcVar5; int iVar6; int iVar7; BoolTri BVar8; uint uVar9; char *pcVar10; Menu *pMVar11; int menuIndex; Font *loFont; Font *hiFont; SFX_ID SVar12; MenuItem_Type MVar13; MenuItem_CycleData *cycleData; int valueMax; int valueMin; MenuItem *submenu; MenuItemCallbackPair *pMVar14; MenuItemCallbackPair *argPtrNext; MenuItemCallbackPair *argptr; float10 fVar15; Image *offBarImage; Image *onBarImage; Font *pFVar16; Image *leftCapImage; Font *pFVar17; Image *rightCapImage; float valueMax_00; Image *loPlusImage; float step; Image *loMinusImage; MenuItem_Type MVar18; Image *hiPlusImage; MenuItem_CycleData *itemData; Image *hiMinusImage; MenuItem_TriggerCallback p_Var19; MenuItem_SliderData *itemData_00; MenuItem_RealSliderCallback callback_00; MenuItem_CycleCallback callback_01; char **local_dd0; char *str; int local_dc8; SFX_ID local_dc4; char *local_dc0; int menuCount; int menuNumber; int itemNumber; Image *sliderImages [8]; char *stringParts [100]; char menuPathBuff [1024]; char overlayBuff [1024]; char menuSetPathBuff [1024]; MenuItem_SliderCallback argCallback; int *argValue; BOOL isLight; pMVar14 = (MenuItemCallbackPair *)&dst; std::sprintf(menuSetPathBuff,"Menu::%s",menuName); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuSetPathBuff,"MenuCount",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuSetPathBuff,"MenuCount",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); } uVar3 = std::atoi(pcVar2); menuCount = uVar3; menuCol = Front_CreateMenuSet(uVar3); menuIndex = 0; if (0 < (int)uVar3) { do { menuNumber = menuIndex + 1; local_dc8 = 0; std::sprintf(menuPathBuff,"%s::Menu%i",menuSetPathBuff,menuNumber); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"Title",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); pcVar4 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"FullName",0); pcVar4 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar4); pcVar5 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"Position",0); pcVar5 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar5); util::Util_Tokenise(pcVar5,stringParts,":"); iVar6 = std::atoi(stringParts[0]); iVar7 = std::atoi(stringParts[1]); if (pcVar5 != NULL) { io::Mem_Free(pcVar5); } pcVar5 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"MenuFont",0); pcVar5 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar5); loFont = Front_Cache_LoadFont(pcVar5); pcVar5 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"AutoCenter",0); BVar8 = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar5); uVar3 = (uint)(BVar8 == BOOL3_TRUE); pcVar5 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"DisplayTitle",0); BVar8 = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar5); local_dc4 = (SFX_ID)(BVar8 != BOOL3_FALSE); pcVar5 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"Anchored",0); local_dc0 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar5); if (((uVar3 != 0) && (pcVar2 != NULL)) && (*pcVar2 != '\0')) { uVar9 = lego::image::Font_GetStringWidth(loFont,pcVar2); local_dc8 = -((int)uVar9 / 2); } pcVar5 = local_dc0; pcVar10 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"CanScroll",0); BVar8 = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar10); uVar9 = (uint)(BVar8 == BOOL3_TRUE); SVar12 = local_dc4; pcVar4 = Front_Util_StringReplaceChar(pcVar4,'_',' '); pcVar10 = Front_Util_StringReplaceChar(pcVar2,'_',' '); pMVar11 = Front_Menu_CreateMenu (pcVar10,pcVar4,loFont,iVar6,iVar7,uVar3,SVar12,local_dc8,uVar9,pcVar5); isLight = 1; menuCol->menus[menuIndex] = pMVar11; pcVar4 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"MenuImage",0); pcVar4 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar4); Front_Menu_LoadMenuImage(menuCol->menus[menuIndex],pcVar4,isLight); isLight = 0; pcVar4 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"MenuImageDark",0); pcVar4 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar4); Front_Menu_LoadMenuImage(menuCol->menus[menuIndex],pcVar4,isLight); std::sprintf(menuCol->menus[menuIndex]->name,"%s",menuPathBuff); pcVar4 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,menuCol->menus[menuIndex]->name,"PlayRandom",0); BVar8 = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar4); menuCol->menus[menuIndex]->playRandom = BVar8; io::Mem_Free(pcVar2); menuIndex = menuNumber; uVar3 = menuCount; } while (menuNumber < menuCount); } menuIndex = 0; if ((int)uVar3 < 1) { return menuCol; } LAB_00414425: menuNumber = menuIndex + 1; MVar1 = menuCol->menus[menuIndex]->autoCenter; std::sprintf(menuPathBuff,"%s::Menu%i",menuSetPathBuff,menuNumber); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"LoFont",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); loFont = Front_Cache_LoadFont(pcVar2); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"HiFont",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); hiFont = Front_Cache_LoadFont(pcVar2); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"ItemCount",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,"ItemCount",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); } local_dc0 = (char *)std::atoi(pcVar2); local_dd0 = (char **)0x1; do { std::sprintf(overlayBuff,"Overlay%i",local_dd0); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,overlayBuff,0); str = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (str == NULL) { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEFLICS) != MAIN_FLAG_NONE) break; std::sprintf(overlayBuff,"!Overlay%i",local_dd0); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,overlayBuff,0); str = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (str == NULL) break; } util::Util_Tokenise(str,stringParts,":"); SVar12 = snd::SFX_GetType(stringParts[1],&local_dc4); if (SVar12 == SFX_NULL) { local_dc4 = SVar12; } SVar12 = local_dc4; iVar6 = std::atoi(stringParts[3]); iVar7 = std::atoi(stringParts[2]); Front_Menu_CreateOverlay(stringParts[0],&menuCol->menus[menuIndex]->overlays,iVar7,iVar6,SVar12) ; if (str != NULL) { io::Mem_Free(str); } local_dd0 = (char **)((int)local_dd0 + 1); } while( true ); iVar6 = 0; argptr = pMVar14; if (0 < (int)local_dc0) { do { itemNumber = iVar6 + 1; std::sprintf(overlayBuff,"Item%i",itemNumber); if (str != NULL) { io::Mem_Free(str); } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,menuPathBuff,overlayBuff,0); str = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); iVar6 = util::Util_Tokenise(str,stringParts,":"); MVar13 = Front_MenuItem_ParseTypeString(stringParts[0]); pMVar14 = argptr; if (false) goto switchD_00414714_caseD_2; MVar18 = MVar1; switch(MVar13) { case MenuItem_Type_Cycle: argValue = (int *)argptr->value; pMVar14 = argptr + 1; callback_01 = (MenuItem_CycleCallback)argptr->callback; iVar6 = std::atoi(stringParts[4]); iVar7 = std::atoi(stringParts[3]); uVar3 = std::atoi(stringParts[6]); cycleData = Front_MenuItem_CreateCycle(uVar3,argValue,iVar7,iVar6,callback_01); isLight = 0; MVar18 = MenuItem_Type_Cycle; MVar13 = MVar1; itemData = cycleData; iVar6 = std::atoi(stringParts[2]); iVar7 = std::atoi(stringParts[1]); pFVar16 = loFont; pFVar17 = hiFont; pcVar2 = Front_Util_StringReplaceChar(stringParts[5],'_',' '); submenu = Front_MenuItem_CreateBannerItem (pcVar2,pFVar16,pFVar17,iVar7,iVar6,MVar18,MVar13,itemData,isLight); Front_Menu_AddMenuItem(menuCol->menus[menuIndex],submenu); local_dc8 = 0; iVar6 = std::atoi(stringParts[6]); if (0 < iVar6) { local_dd0 = stringParts + 7; do { pcVar2 = Front_Util_StringReplaceChar(*local_dd0,'_',' '); Front_MenuItem_AddCycleName(cycleData,pcVar2); local_dc8 += 1; local_dd0 = local_dd0 + 1; iVar6 = std::atoi(stringParts[6]); } while (local_dc8 < iVar6); } break; case MenuItem_Type_Trigger: if (iVar6 == 8) { argValue = (int *)argptr->value; pMVar14 = argptr + 1; p_Var19 = (MenuItem_TriggerCallback)argptr->callback; iVar6 = std::atoi(stringParts[7]); pMVar11 = (Menu *)Front_MenuItem_CreateTrigger(argValue,(uint)(iVar6 == 1),p_Var19); MVar13 = MenuItem_Type_Trigger; LAB_00414992: pcVar2 = stringParts[6]; iVar6 = std::atoi(stringParts[2]); iVar7 = std::atoi(stringParts[1]); submenu = Front_MenuItem_CreateImageItem (____EMPTYSTR__,loFont,hiFont,stringParts[3],stringParts[4],iVar7, iVar6,MVar13,MVar18,pcVar2,pMVar11); pMVar11 = menuCol->menus[menuIndex]; argptr = pMVar14; goto LAB_00414b5a; } if (iVar6 != 5) break; argValue = (int *)argptr->value; argPtrNext = argptr + 1; isLight = 0; p_Var19 = (MenuItem_TriggerCallback)argptr->callback; iVar6 = std::atoi(stringParts[4]); itemData_00 = (MenuItem_SliderData *) Front_MenuItem_CreateTrigger(argValue,(uint)(iVar6 == 1),p_Var19); MVar13 = MenuItem_Type_Trigger; LAB_00414a6e: iVar6 = std::atoi(stringParts[2]); iVar7 = std::atoi(stringParts[1]); pcVar2 = stringParts[3]; argptr = argPtrNext; goto LAB_00414b41; case MenuItem_Type_Slider: argValue = (int *)argptr->value; Front_Menu_LoadSliderImages(iVar6,stringParts,sliderImages); isLight = 0; argCallback = (MenuItem_SliderCallback)argptr->callback; offBarImage = sliderImages[0]; onBarImage = sliderImages[1]; leftCapImage = sliderImages[2]; rightCapImage = sliderImages[3]; loPlusImage = sliderImages[4]; loMinusImage = sliderImages[5]; hiPlusImage = sliderImages[6]; hiMinusImage = sliderImages[7]; iVar6 = std::atoi(stringParts[4]); iVar7 = std::atoi(stringParts[3]); valueMax = std::atoi(stringParts[7]); valueMin = std::atoi(stringParts[6]); itemData_00 = Front_MenuItem_CreateSlider (argValue,valueMin,valueMax,iVar7,iVar6,argCallback,offBarImage, onBarImage,leftCapImage,rightCapImage,loPlusImage,loMinusImage, hiPlusImage,hiMinusImage); MVar13 = MenuItem_Type_Slider; goto LAB_00414b10; case MenuItem_Type_RealSlider: valuePtr = (float *)argptr->value; isLight = 0; callback_00 = (MenuItem_RealSliderCallback)argptr->callback; iVar6 = std::atoi(stringParts[4]); iVar7 = std::atoi(stringParts[3]); fVar15 = std::atof(stringParts[8]); step = (float)fVar15; fVar15 = std::atof(stringParts[7]); valueMax_00 = (float)fVar15; fVar15 = std::atof(stringParts[6]); itemData_00 = (MenuItem_SliderData *) Front_MenuItem_CreateRealSlider (valuePtr,(float)fVar15,valueMax_00,step,iVar7,iVar6,callback_00); MVar13 = MenuItem_Type_RealSlider; LAB_00414b10: argptr = argptr + 1; iVar6 = std::atoi(stringParts[2]); iVar7 = std::atoi(stringParts[1]); pcVar2 = stringParts[5]; LAB_00414b41: pFVar16 = loFont; pFVar17 = hiFont; pcVar2 = Front_Util_StringReplaceChar(pcVar2,'_',' '); submenu = Front_MenuItem_CreateBannerItem (pcVar2,pFVar16,pFVar17,iVar7,iVar6,MVar13,MVar18,itemData_00,isLight); pMVar11 = menuCol->menus[menuIndex]; LAB_00414b5a: Front_Menu_AddMenuItem(pMVar11,submenu); pMVar14 = argptr; break; case MenuItem_Type_Next: if (iVar6 == 8) { iVar6 = std::atoi(stringParts[7] + 4); pMVar11 = menuCol->menus[iVar6 + -1]; MVar13 = MenuItem_Type_Next; goto LAB_00414992; } if (iVar6 == 6) { iVar6 = std::atoi(stringParts[4] + 4); isLight = 1; } else { if (*stringParts[4] == '\0') { isLight = 0; itemData_00 = NULL; argPtrNext = argptr; MVar13 = MVar1; MVar18 = MenuItem_Type_Next; goto LAB_00414a6e; } iVar6 = std::atoi(stringParts[4] + 4); isLight = 0; } pMVar11 = menuCol->menus[iVar6 + -1]; MVar18 = MenuItem_Type_Next; MVar13 = MVar1; iVar6 = std::atoi(stringParts[2]); iVar7 = std::atoi(stringParts[1]); pFVar16 = loFont; pFVar17 = hiFont; pcVar2 = Front_Util_StringReplaceChar(stringParts[3],'_',' '); submenu = Front_MenuItem_CreateBannerItem (pcVar2,pFVar16,pFVar17,iVar7,iVar6,MVar18,MVar13,pMVar11,isLight); pMVar11 = menuCol->menus[menuIndex]; goto LAB_00414b5a; } switchD_00414714_caseD_2: iVar6 = itemNumber; argptr = pMVar14; } while (itemNumber < (int)local_dc0); } if (str != NULL) { io::Mem_Free(str); } menuIndex = menuNumber; if (menuCount <= menuNumber) { return menuCol; } goto LAB_00414425; } int __cdecl lego::front::Front_GetMenuIDByName(MenuSet *menuSet,char *name) { int cmp; int i; i = 0; if ((int)menuSet->menuCount < 1) { return -1; } // Access violation if the last menu is null. while ((menuSet->menus[i] == NULL || (cmp = std::_stricmp(menuSet->menus[i]->title,name), cmp != 0))) { i += 1; if ((int)menuSet->menuCount <= i) { return -1; } } return i; } BOOL __cdecl lego::front::Front_IsIntrosEnabled(void) { char *keyPath; BoolTri BVar1; keyPath = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DontPlayAvis",0); BVar1 = cfg::Config_GetBoolValue(globs::legoGlobs.config,keyPath); if ((BVar1 != BOOL3_TRUE) && (globs::mainGlobs.programmerLevel < PROGRAMMER_MODE_3)) { return TRUE; } return FALSE; } void __cdecl lego::front::Front_Callback_SliderBrightness(int slider_0_10) { float r; float r_00; r = (float)slider_0_10 * 0.1; r_00 = r * 0.8 - -0.2; gfx::Container_SetColourAlpha(globs::legoGlobs.spotlightTop,r,r,r,1.0); gfx::Container_SetColourAlpha(globs::legoGlobs.pointLightFP,r_00,r_00,r_00,1.0); gfx::Container_Light_SetSpotPenumbra(globs::legoGlobs.spotlightTop,r * 1.5 - -0.5); gfx::Container_Light_SetSpotUmbra(globs::legoGlobs.spotlightTop,r * 0.8 - -0.2); return; } void __cdecl lego::front::Front_Callback_SliderSoundVolume(int slider_0_10) { snd::Sound3D_SetGlobalVolumePrescaled(slider_0_10); return; } void __cdecl lego::front::Front_Callback_SliderMusicVolume(int slider_0_10) { main::Main_SetCDVolume((float)slider_0_10 * 0.1111111,(float)slider_0_10 * 0.1111111); return; } int __cdecl lego::front::Front_CalcSliderCDVolume(void) { BOOL BVar1; int iVar2; longlong lVar3; float rightVol; float leftVol; iVar2 = 0; BVar1 = main::Main_GetCDVolume(&leftVol,&rightVol); if (BVar1 != 0) { lVar3 = __ftol(((float10)rightVol + (float10)leftVol) * (float10)0.5 * (float10)9.0); iVar2 = (int)lVar3; } return iVar2; } void __cdecl lego::front::Front_Callback_CycleWallDetail(int cycle_High_Low) { if (cycle_High_Low == 0) { globs::legoGlobs.flags1 |= GAME1_USEDETAIL; } else { if (cycle_High_Low == 1) { globs::legoGlobs.flags1 = globs::legoGlobs.flags1 & ~GAME1_USEDETAIL; return; } } return; } void __cdecl lego::front::Front_Callback_CycleAutoGameSpeed(int cycle_On_Off) { Info_SetAutoGameSpeed((uint)(cycle_On_Off == 0)); return; } void __cdecl lego::front::Front_Callback_CycleMusic(int cycle_On_Off) { lrr::Lego_SetMusicPlaying((uint)(cycle_On_Off == 0)); return; } void __cdecl lego::front::Front_Callback_CycleSound(int cycle_On_Off) { lrr::Lego_SetSoundOn((uint)(cycle_On_Off == 0)); return; } void __cdecl lego::front::Front_Callback_CycleHelpWindow(int cycle_Off_On) { if (cycle_Off_On == 0) { HelpWindow_SetEnabled(FALSE,TRUE); } else { if (cycle_Off_On == 1) { HelpWindow_SetEnabled(FALSE,FALSE); return; } } return; } void __cdecl lego::front::Front_Callback_TriggerReplayObjective(void) { game::Objective_SetStatus(LEVELSTATUS_INCOMPLETE); return; } void __cdecl lego::front::Front_Callback_SliderGameSpeed(int slider_0_5) { if (true) { switch(slider_0_5) { case 0: globs::legoGlobs.gameSpeed = 0.3333333; return; case 1: globs::legoGlobs.gameSpeed = 0.6666667; return; case 3: globs::legoGlobs.gameSpeed = 1.333333; return; case 4: globs::legoGlobs.gameSpeed = 1.666667; return; case 5: globs::legoGlobs.gameSpeed = 2.0; return; } } globs::legoGlobs.gameSpeed = 1.0; return; } void __cdecl lego::front::Front_UpdateSliderGameSpeed(void) { // This function can be replaced with: // `sliderGameSpeed = Front_CalcSliderGameSpeed();` if (globs::legoGlobs.gameSpeed < 0.6666666) { globs::frontGlobs.sliderGameSpeed = 0; return; } if (globs::legoGlobs.gameSpeed < 1.0) { globs::frontGlobs.sliderGameSpeed = 1; return; } if (globs::legoGlobs.gameSpeed < 1.333333) { globs::frontGlobs.sliderGameSpeed = 2; return; } if (globs::legoGlobs.gameSpeed < 1.666667) { globs::frontGlobs.sliderGameSpeed = 3; return; } globs::frontGlobs.sliderGameSpeed = 4; if (2.0 <= globs::legoGlobs.gameSpeed) { globs::frontGlobs.sliderGameSpeed = 5; } return; } int __cdecl lego::front::Front_CalcSliderGameSpeed(void) { int iVar1; // Game Speed to slider levels is calculated in 3rd's: // 0 = below 2/3 (< 66%) // 1 = below 3/3 (< 100%) // 2 = below 4/3 (< 133%) // 3 = below 5/3 (< 166%) // 4 = below 6/3 (< 200%) // 5 = equal or above (6/3) (>=200%) if (globs::legoGlobs.gameSpeed < 0.6666666) { return 0; } if (globs::legoGlobs.gameSpeed < 1.0) { return 1; } if (globs::legoGlobs.gameSpeed < 1.333333) { return 2; } if (globs::legoGlobs.gameSpeed < 1.666667) { return 3; } iVar1 = 4; if (2.0 <= globs::legoGlobs.gameSpeed) { iVar1 = 5; } return iVar1; } void __cdecl lego::front::Front_Callback_SelectLoadSave(float elapsedAbs,int selectIndex) { SaveData *currSave; LevelSet *levelSet; MenuItem_SelectData *selectData; BOOL keepLocked; SaveReward *saveReward; save::Front_Save_SetSaveNumber(selectIndex); currSave = save::Front_Save_GetCurrentSaveData(); if (currSave == NULL) { keepLocked = TRUE; selectData = (MenuItem_SelectData *) (globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; saveReward = NULL; } else { keepLocked = FALSE; selectData = (MenuItem_SelectData *) (globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; currSave = save::Front_Save_GetCurrentSaveData(); saveReward = currSave->missionsTable; } Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,saveReward,levelSet,selectData,keepLocked); Front_Levels_UpdateAvailable (globs::frontGlobs.startTutorialLink,NULL,&globs::frontGlobs.tutorialLevels, (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[2]->items[1]->itemData, FALSE); return; } void __cdecl lego::front::Front_UpdateOptionsSliders(void) { int saveIndex; SaveData *save; saveIndex = lego::save::Front_Save_GetSaveNumber(); save = lego::save::Front_Save_GetSaveDataAt(saveIndex); if (save != NULL) { Front_Callback_SliderSoundVolume(save->SliderSoundVolume); Front_Callback_SliderBrightness(save->SliderBrightness); Front_Callback_SliderMusicVolume(save->SliderMusicVolume); } return; } void __cdecl lego::front::Front_Callback_TriggerBackSave(void) { SaveData *currSave; LevelSet *levelSet; MenuItem_SelectData *selectData; BOOL keepLocked; globs::frontGlobs.saveMenuHasSaved = FALSE; globs::frontGlobs.saveMenuKeepOpen = FALSE; globals::g_saveMenuSelectedIndex = -1; currSave = save::Front_Save_GetCurrentSaveData(); if (currSave != NULL) { keepLocked = FALSE; selectData = (MenuItem_SelectData *) (globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; currSave = save::Front_Save_GetCurrentSaveData(); Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,currSave->missionsTable,levelSet,selectData, keepLocked); return; } Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,NULL,&globs::frontGlobs.missionLevels, (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData, TRUE); return; } void __cdecl lego::front::Front_RestartLevel(void) { char *levelName; int i; MenuSet *menuSet; char buff [128]; std::sprintf(buff,"%s",(globs::legoGlobs.currLevel)->name); lrr::Lego_SetPaused(FALSE,FALSE); game::Level_Free(); levelName = util::Util_StrCpy(buff); lrr::Lego_LoadLevel(levelName); i = 0; menuSet = globs::frontGlobs.pausedMenuSet; if (0 < (int)(globs::frontGlobs.pausedMenuSet)->menuCount) { do { if (menuSet->menus[i] != NULL) { menuSet->menus[i]->closed = TRUE; menuSet = globs::frontGlobs.pausedMenuSet; } i += 1; } while (i < (int)menuSet->menuCount); } globs::frontGlobs.triggerRestartMission = FALSE; globs::legoGlobs.flags1 |= GAME1_PAUSED; save::ObjectRecall_Save_CreateNewObjectRecall(); return; } void __cdecl lego::front::Front_Save_GetLevelCompleteWithPoints(SaveData *saveData,char *out_buffer) { uint *puVar1; int score; SaveData *pSVar2; int iVar3; int totalScore; uint index; longlong lVar4; SaveData *saveData_00; saveData_00 = saveData; if (saveData != NULL) { puVar1 = &saveData->missionsCount; totalScore = 0; index = 0; // totalCompleted = 0; saveData = NULL; pSVar2 = NULL; if (*puVar1 != 0) { iVar3 = 0; do { score = Front_Save_GetLevelScore(index,saveData_00); totalScore += score; if ((*(byte *)((int)&saveData_00->missionsTable->flags + iVar3) & 1) != 0) { // totalCompleted++; saveData = (SaveData *)((int)&saveData->field_0x0 + 1); } index += 1; iVar3 += 0x3190; pSVar2 = saveData; } while (index < saveData_00->missionsCount); } // if (totalCompleted != 0) if (pSVar2 != NULL) { lVar4 = __ftol(((float10)ZEXT48(pSVar2) / (float10)saveData_00->missionsCount) * (float10)100.0); // Some hardcoded language text here... std::sprintf(out_buffer,"Game %i%% complete with %i points scored",(int)lVar4,totalScore); } } return; } void __cdecl lego::front::Front_UpdateGameSpeedSliderLevel(void) { globs::frontGlobs.sliderGameSpeed = Front_CalcSliderGameSpeed(); return; } // WARNING: Type propagation algorithm not settling // param isOptions: 0 = PausedMenu, 1 = OptionsMenu, 2 = not supported BOOL __cdecl lego::front::Front_Options_Update(float elapsed,Menu_ModalType modalType) { Menu *pMVar1; int iVar2; BOOL BVar3; MenuSet *menuSet; uint uVar4; // param isOptions: 0 = PausedMenu, 1 = OptionsMenu, 2 = not supported uVar4 = 1; Front_UpdateGameSpeedSliderLevel(); menuSet = globs::frontGlobs.pausedMenuSet; if ((modalType != Menu_Modal_Paused) && (menuSet = globs::frontGlobs.optionsMenuSet, modalType != Menu_Modal_Options)) { return TRUE; } if (((((globals::s_FrontOptionsMenu != NULL) && (globs::frontGlobs.triggerRestartMission == 0)) && (globs::frontGlobs.triggerQuitMission == 0)) && ((globs::frontGlobs.triggerReplayObjective == 0 && (globals::s_FrontOptionsMenuSet == menuSet) ))) && (BVar3 = game::Objective_IsShowing(), BVar3 == 0)) { LAB_0041535f: BVar3 = game::Objective_IsShowing(); if (BVar3 == 0) { globals::s_FrontOptionsMenu = Front_Menu_Update(elapsed,globals::s_FrontOptionsMenu,NULL); } if (modalType != Menu_Modal_Paused) { if (modalType == Menu_Modal_Options) { iVar2 = (*menuSet->menus)->closed; (*menuSet->menus)->closed = 0; uVar4 = (uint)(iVar2 == 1); } return uVar4; } uVar4 = 1; pMVar1 = *menuSet->menus; if ((pMVar1->closed != 1) && (menuSet->menus[2]->closed != 1)) { uVar4 = 0; } pMVar1->closed = 0; menuSet->menus[2]->closed = 0; return uVar4; } globs::frontGlobs.triggerQuitMission = 0; globals::s_FrontOptionsMenu = (Menu *)((Menu *)menuSet->menus)->title; globals::s_FrontOptionsMenuSet = menuSet; if (globs::frontGlobs.triggerReplayObjective == 0) { if (globs::frontGlobs.triggerRestartMission != 1) goto LAB_0041535f; } else { if (*menuSet->menus != NULL) { (*menuSet->menus)->closed = 1; } // Access violation for OptionsMenu??? // // I think this is a bug where this assignment was meant to check BOOL3_FALSE, while the // assignment below to reset `triggerReplayObjective` should have been for all menu // types. if (menuSet->menus[2] != NULL) { menuSet->menus[2]->closed = TRUE; } if (modalType == Menu_Modal_Paused) { globs::frontGlobs.triggerReplayObjective = 0; return FALSE; } } return FALSE; } // levelKey is either "StartLevel" or "TutorialStartLevel" BOOL __cdecl lego::front::Front_LoadLevelSet(Config *config,LevelSet *levelSet,char *levelKey) { uint size; char **ppcVar1; LevelLink **ppLVar2; BOOL *pBVar3; char *fullName; uint uVar4; int i; uint count; char *nextName; nextName = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",levelKey,0); nextName = cfg::Config_GetStringValue(globs::legoGlobs.config,nextName); if (nextName == NULL) { return FALSE; } count = 1; // MEMORY LEAKS!! MEMORY LEAKS EVERYWHERE!!! nextName = cfg::Config_BuildStringID(globs::legoGlobs.gameName,nextName,"NextLevel",0); for (nextName = cfg::Config_GetStringValue(globs::legoGlobs.config,nextName); nextName != NULL; nextName = cfg::Config_GetStringValue(globs::legoGlobs.config,nextName)) { count += 1; nextName = cfg::Config_BuildStringID(globs::legoGlobs.gameName,nextName,"NextLevel",0); } size = count * 4; levelSet->count = count; ppcVar1 = (char **)io::Mem_Alloc(size); levelSet->idNames = ppcVar1; ppcVar1 = (char **)io::Mem_Alloc(size); levelSet->langNames = ppcVar1; ppLVar2 = (LevelLink **)io::Mem_Alloc(size); levelSet->levels = ppLVar2; for (uVar4 = count & 0x3fffffff; uVar4 != 0; uVar4 -= 1) { *ppLVar2 = NULL; ppLVar2 = ppLVar2 + 1; } for (i = 0; i != 0; i += -1) { *(undefined *)ppLVar2 = 0; ppLVar2 = (LevelLink **)((int)ppLVar2 + 1); } pBVar3 = (BOOL *)io::Mem_Alloc(size); levelSet->visitedList = pBVar3; for (count &= 0x3fffffff; count != 0; count -= 1) { *pBVar3 = 0; pBVar3 = pBVar3 + 1; } for (i = 0; i != 0; i += -1) { *(undefined *)pBVar3 = 0; pBVar3 = (BOOL *)((int)pBVar3 + 1); } if (levelSet->idNames != NULL) { if (levelSet->langNames != NULL) { nextName = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",levelKey,0); nextName = cfg::Config_GetStringValue(globs::legoGlobs.config,nextName); *levelSet->idNames = nextName; nextName = *levelSet->idNames; fullName = cfg::Config_BuildStringID(globs::legoGlobs.gameName,nextName,"FullName",0); fullName = cfg::Config_GetStringValue(globs::legoGlobs.config,fullName); *levelSet->langNames = fullName; if (*levelSet->langNames == NULL) { fullName = Front_Util_StrCpy(*levelSet->idNames); *levelSet->langNames = fullName; } else { Front_Util_StringReplaceChar(*levelSet->langNames,'_',' '); } i = 1; if (1 < levelSet->count) { do { nextName = cfg::Config_BuildStringID(globs::legoGlobs.gameName,nextName,"NextLevel",0); nextName = cfg::Config_GetStringValue(globs::legoGlobs.config,nextName); levelSet->idNames[i] = nextName; nextName = levelSet->idNames[i]; fullName = cfg::Config_BuildStringID(globs::legoGlobs.gameName,nextName,"FullName",0); fullName = cfg::Config_GetStringValue(globs::legoGlobs.config,fullName); levelSet->langNames[i] = fullName; if (levelSet->langNames[i] == NULL) { fullName = Front_Util_StrCpy(levelSet->idNames[i]); levelSet->langNames[i] = fullName; } else { Front_Util_StringReplaceChar(levelSet->langNames[i],'_',' '); } i += 1; } while (i < levelSet->count); } return TRUE; } return FALSE; } return FALSE; } // Plays an alread-loaded Movie_t from the G98CMovie C wrapper API. // Allows terminating the movie playback during runtime with isSkippable. void __cdecl lego::front::Front_PlayMovie(Movie_t *mov,BOOL skippable) { BOOL BVar1; uint uVar2; ulonglong uVar3; float local_1c; RECT rect; // HARDCODED SCREEN RESOLUTION!! rect.left = 0; rect.top = 0; rect.right = 640; rect.bottom = 480; local_1c = 0.0; BVar1 = video::Movie_Update(mov,1.0,&rect); if (BVar1 != 0) { while( true ) { main::Main_LoopUpdate(FALSE); local_1c = local_1c - -1.0; uVar3 = video::Movie_GetDuration(mov); if ((float)(uVar3 & 0xffffffff) < local_1c) break; if (skippable != 0) { uVar2 = input::Input_AnyKeyPressed(); if (uVar2 != 0) { return; } if (globs::INPUT.msrb != 0) { return; } if (globs::INPUT.mslb != 0) { return; } } BVar1 = video::Movie_Update(mov,1.0,&rect); if (BVar1 == 0) { return; } } } return; } void __cdecl lego::front::Front_PlayIntroSplash(char *imageKey,BOOL skippable,char *timeKey) { char *pcVar1; DWORD DVar2; Image *image; DWORD DVar3; uint uVar4; float10 fVar5; longlong lVar6; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",timeKey,0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",timeKey,0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); } fVar5 = std::atof(pcVar1); timeKey = (char *)(float)fVar5; if ((float)timeKey == 0.0) { // 3.0; // default seconds timeKey = (char *)1077936128; } DVar2 = timeGetTime(); lVar6 = __ftol((float10)(float)timeKey * (float10)-1000.0); if (imageKey != NULL) { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",imageKey,0); pcVar1 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar1); if ((pcVar1 != NULL) && (image = lego::image::Image_LoadBMPScaled(pcVar1,0,0), image != NULL)) { while( true ) { lego::image::Image_DisplayScaled(image,NULL,NULL,NULL); main::Main_LoopUpdate(0); Sleep(100); DVar3 = timeGetTime(); if (DVar2 - (int)lVar6 <= DVar3) break; if ((skippable != 0) && (((uVar4 = input::Input_AnyKeyPressed(), uVar4 != 0 || (globs::INPUT.msrb != 0)) || (globs::INPUT.mslb != 0)))) break; } lego::image::Image_Remove(image); } } return; } void __cdecl lego::front::Front_PlayIntroMovie(char *aviKey,BOOL skippable) { char *keyPath; char *fName; BOOL exists; Movie_t *mov; if (aviKey != NULL) { keyPath = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",aviKey,0); fName = cfg::Config_GetStringValue(globs::legoGlobs.config,keyPath); if (fName != NULL) { exists = io::File_Exists(fName); if (exists != 0) { mov = video::Movie_Load(fName); Front_PlayMovie(mov,skippable); video::Movie_Free(mov); io::Mem_Free(fName); } } } return; } void __cdecl lego::game::Front_PlayLevelMovie(char *levelName,BOOL skippable) { char *keyPath; char *videoName; BOOL exists; Movie_t *mov; if (levelName != NULL) { keyPath = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"Video",0); videoName = cfg::Config_GetStringValue(globs::legoGlobs.config,keyPath); if (videoName != NULL) { exists = io::File_Exists(videoName); if (exists != 0) { mov = video::Movie_Load(videoName); front::Front_PlayMovie(mov,skippable); video::Movie_Free(mov); } io::Mem_Free(videoName); } } return; } // WARNING: Type propagation algorithm not settling void __cdecl lego::front::Front_LoadLevels(MenuSet *unused_mainMenuFull) { int menuIDLevels; int menuIDTuto; int menuIDLoadSave; MenuItem_SelectData *loadSelectData; MenuItem *loadSelectItem; MenuItem_SelectData *saveSelectData; MenuItem *saveSelectItem; char *pcVar1; SaveData *currSave; int i; Menu *pMVar2; int iVar3; code *pcVar4; char buff [100]; MenuItem *pcVar6; MenuItem *menuLoadSave; globs::frontGlobs.startMissionLink = Front_LevelSet_LoadLevelLinks (&globs::frontGlobs.missionLevels,*globs::frontGlobs.missionLevels.idNames); globs::frontGlobs.startTutorialLink = Front_LevelSet_LoadLevelLinks (&globs::frontGlobs.tutorialLevels,*globs::frontGlobs.tutorialLevels.idNames); Front_Levels_ResetVisited(); menuIDLevels = Front_GetMenuIDByName(globs::frontGlobs.mainMenuSet,"Levels"); menuIDTuto = Front_GetMenuIDByName(globs::frontGlobs.mainMenuSet,"Tutorials"); menuIDLoadSave = Front_GetMenuIDByName(globs::frontGlobs.mainMenuSet,"Load Level Save"); // Create menu item for Load Game menu selection. loadSelectData = Front_MenuItem_CreateSelect (&globs::frontGlobs.selectLoadSaveIndex,____EMPTYSTR__,____EMPTYSTR__,-200,-100,60, 5,-20,200,-20,-40,0,Front_Callback_SelectLoadSave, (globs::frontGlobs.mainMenuSet)->menus[menuIDLevels]); menuLoadSave = (MenuItem *) ((MenuItem *)(globs::frontGlobs.mainMenuSet)->menus[menuIDLoadSave]->items)->banner ; loadSelectItem = Front_MenuItem_CreateBannerItem (____EMPTYSTR__,menuLoadSave->fontLo,menuLoadSave->fontHi,0,0,MenuItem_Type_Select, TRUE,loadSelectData,FALSE); Front_Menu_AddMenuItem((globs::frontGlobs.mainMenuSet)->menus[menuIDLoadSave],loadSelectItem); // Create menu item for Save Game menu selection. saveSelectData = Front_MenuItem_CreateSelect (&globs::frontGlobs.selectLoadSaveIndex,____EMPTYSTR__,____EMPTYSTR__,-200,-100,60, 5,-20,200,-20,-40,0,Front_Callback_SelectLoadSave,NULL); pcVar6 = (MenuItem *) ((MenuItem *)(globs::frontGlobs.mainMenuSet)->menus[menuIDLoadSave]->items)->banner; saveSelectItem = Front_MenuItem_CreateBannerItem (____EMPTYSTR__,pcVar6->fontLo,pcVar6->fontHi,0,0,MenuItem_Type_Select,TRUE, saveSelectData,FALSE); Front_Menu_AddMenuItem(*(globs::frontGlobs.saveMenuSet)->menus,saveSelectItem); // NOTE: This DOES NOT loop through the last index [5] in the array. i = 0; currSave = globs::frontGlobs.saveData; do { i += 1; iVar3 = i; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","Save_Game",0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); std::sprintf(buff,"%s %i",pcVar1,iVar3); Front_Util_StringReplaceChar(buff,'_',' '); Front_Save_GetLevelCompleteWithPoints(currSave,buff); Front_MenuItem_AddSelectItem (loadSelectData,buff,TRUE, (*(globs::frontGlobs.mainMenuSet)->menus[menuIDLoadSave]->items)->fontHi,0,0,0); Front_MenuItem_AddSelectItem (saveSelectData,buff,TRUE, (*(globs::frontGlobs.mainMenuSet)->menus[menuIDLoadSave]->items)->fontHi,0,0,0); currSave = currSave + 1; } while ((int)currSave < 0x558418); save::Front_Save_LoadAllSaveFiles(); pcVar4 = Front_Callback_SelectMissionItem; pMVar2 = NULL; currSave = save::Front_Save_GetCurrentSaveData(); // 4 ->&frontGlobs.triggerCredits[4] ->&frontGlobs.selectMissionIndex MainMenuFull_AddMissionsDisplay (4,globs::frontGlobs.startMissionLink,&globs::frontGlobs.missionLevels, (globs::frontGlobs.mainMenuSet)->menus[menuIDLevels],currSave,pMVar2,pcVar4); pcVar4 = Front_Callback_SelectTutorialItem; pMVar2 = NULL; currSave = save::Front_Save_GetCurrentSaveData(); // 5 ->&frontGlobs.triggerCredits[5] ->&frontGlobs.selectTutorialIndex MainMenuFull_AddMissionsDisplay (5,globs::frontGlobs.startTutorialLink,&globs::frontGlobs.tutorialLevels, (globs::frontGlobs.mainMenuSet)->menus[menuIDTuto],currSave,pMVar2,pcVar4); return; } // Only called during Lego_Initialise. void __cdecl lego::save::Front_ResetSaveNumber(void) { globs::frontGlobs.saveNumber = -1; return; } void __cdecl lego::front::Front_LoadMenuTextWindow(Config *config,char *configPath,MenuTextWindow *menuWnd) { char cVar1; char *pcVar2; int iVar3; TextWindow *textWnd; Image *image; uint uVar4; uint uVar5; undefined4 *puVar6; char *pcVar7; undefined4 *puVar8; Area2F area; char *stringParts [5]; area.y = 0.0; area.width = 0.0; area.x = 0.0; area.height = 0.0; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"Load",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar4 = 0xffffffff; do { pcVar7 = pcVar2; if (uVar4 == 0) break; uVar4 -= 1; pcVar7 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar7; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar7 + -uVar4); puVar8 = (undefined4 *)menuWnd->LoadText; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"Save",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar4 = 0xffffffff; do { pcVar7 = pcVar2; if (uVar4 == 0) break; uVar4 -= 1; pcVar7 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar7; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar7 + -uVar4); puVar8 = (undefined4 *)menuWnd->SaveText; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"Slot",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar4 = 0xffffffff; do { pcVar7 = pcVar2; if (uVar4 == 0) break; uVar4 -= 1; pcVar7 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar7; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar7 + -uVar4); puVar8 = (undefined4 *)menuWnd->SlotText; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"SaveSel",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar4 = 0xffffffff; do { pcVar7 = pcVar2; if (uVar4 == 0) break; uVar4 -= 1; pcVar7 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar7; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar7 + -uVar4); puVar8 = (undefined4 *)menuWnd->SaveSelText; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"LoadSel",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar4 = 0xffffffff; do { pcVar7 = pcVar2; if (uVar4 == 0) break; uVar4 -= 1; pcVar7 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar7; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar7 + -uVar4); puVar8 = (undefined4 *)menuWnd->LoadSelText; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"Level",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar4 = 0xffffffff; do { pcVar7 = pcVar2; if (uVar4 == 0) break; uVar4 -= 1; pcVar7 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar7; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar7 + -uVar4); puVar8 = (undefined4 *)menuWnd->LevelText; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"Tutorial",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar4 = 0xffffffff; do { pcVar7 = pcVar2; if (uVar4 == 0) break; uVar4 -= 1; pcVar7 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar7; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar7 + -uVar4); puVar8 = (undefined4 *)menuWnd->TutorialText; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"Window",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { iVar3 = util::Util_Tokenise(pcVar2,stringParts,"|"); if (iVar3 == 4) { iVar3 = std::atoi(stringParts[0]); area.x = (float)iVar3; (menuWnd->WindowArea).x = area.x; iVar3 = std::atoi(stringParts[1]); area.y = (float)iVar3; (menuWnd->WindowArea).y = area.y; iVar3 = std::atoi(stringParts[2]); area.width = (float)iVar3; (menuWnd->WindowArea).width = area.width; iVar3 = std::atoi(stringParts[3]); area.height = (float)iVar3; (menuWnd->WindowArea).height = area.height; textWnd = TextWindow_Create(globs::legoGlobs.fontStandard,&area,0x200); menuWnd->textWindow = textWnd; } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,configPath,"Panel",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { iVar3 = util::Util_Tokenise(pcVar2,stringParts,"|"); if ((iVar3 == 5) && (stringParts[0] != NULL)) { image = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); menuWnd->PanelImage = image; if (image != NULL) { iVar3 = std::atoi(stringParts[1]); (menuWnd->PanelArea).x = (float)iVar3; iVar3 = std::atoi(stringParts[2]); (menuWnd->PanelArea).y = (float)iVar3; iVar3 = std::atoi(stringParts[3]); (menuWnd->PanelArea).width = (float)iVar3; iVar3 = std::atoi(stringParts[4]); image = menuWnd->PanelImage; (menuWnd->PanelArea).height = (float)iVar3; lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); } } } return; } BOOL __cdecl lego::front::Front_LevelSelect_PlayLevelNameSFX(int levelNumber) { BOOL BVar1; SFX_ID sfxType; char buff [128]; std::sprintf(buff,"Stream_LevelName_Level%d",levelNumber); BVar1 = snd::SFX_GetType(buff,&sfxType); if (BVar1 != 0) { BVar1 = snd::SFX_Random_SetAndPlayGlobalSample(sfxType,NULL); } return BVar1; } BOOL __cdecl lego::front::Front_LevelSelect_PlayTutoLevelNameSFX(int levelNumber) { BOOL BVar1; SFX_ID sfxType; char buff [128]; std::sprintf(buff,"Stream_LevelName_TLevel%d",levelNumber); BVar1 = snd::SFX_GetType(buff,&sfxType); if (BVar1 != 0) { BVar1 = snd::SFX_Random_SetAndPlayGlobalSample(sfxType,NULL); } return BVar1; } // Load MenuSets and LevelSets. void __cdecl lego::front::Front_Initialise(Config *config) { char cVar1; char *pcVar2; int iVar3; char *pcVar4; uint uVar5; uint uVar6; undefined4 *puVar7; MenuTextWindow *pMVar8; char *pcVar9; undefined4 *puVar10; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","MenuWipe",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 == NULL) { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","!MenuWipe",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 == NULL) goto LAB_004161da; if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEANIMATION) == MAIN_FLAG_NONE) { iVar3 = std::_strnicmp(pcVar2,"Null",4); goto joined_r0x004161b8; } } else { iVar3 = std::_strnicmp(pcVar2,"Null",4); joined_r0x004161b8: if (iVar3 != 0) { globs::frontGlobs.rockWipeAnim = gfx::Container_Load(NULL,pcVar2,"LWS",TRUE); } } io::Mem_Free(pcVar2); LAB_004161da: globs::frontGlobs.saveTextWnd = (MenuTextWindow *)io::Mem_Alloc(0x728); pMVar8 = globs::frontGlobs.saveTextWnd; for (iVar3 = 0x1ca; iVar3 != 0; iVar3 += -1) { pMVar8->textWindow = NULL; pMVar8 = (MenuTextWindow *)&pMVar8->PanelImage; } Front_LoadMenuTextWindow(config,"Menu::SaveText",globs::frontGlobs.saveTextWnd); globs::frontGlobs.saveLevelWnd = (MenuTextWindow *)io::Mem_Alloc(0x728); pMVar8 = globs::frontGlobs.saveLevelWnd; for (iVar3 = 0x1ca; iVar3 != 0; iVar3 += -1) { pMVar8->textWindow = NULL; pMVar8 = (MenuTextWindow *)&pMVar8->PanelImage; } Front_LoadMenuTextWindow(config,"Menu::LevelText",globs::frontGlobs.saveLevelWnd); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","Save_Game",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar4 = Front_Util_ReplaceTextSpaces(pcVar2); uVar5 = 0xffffffff; do { pcVar9 = pcVar4; if (uVar5 == 0) break; uVar5 -= 1; pcVar9 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar9; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar9 + -uVar5); puVar10 = (undefined4 *)globs::frontGlobs.langSaveGame; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } io::Mem_Free(pcVar2); } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","Load_Game",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar4 = Front_Util_ReplaceTextSpaces(pcVar2); uVar5 = 0xffffffff; do { pcVar9 = pcVar4; if (uVar5 == 0) break; uVar5 -= 1; pcVar9 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar9; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar9 + -uVar5); puVar10 = (undefined4 *)globs::frontGlobs.langLoadGame; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } io::Mem_Free(pcVar2); } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::Overwrite","Title",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar4 = Front_Util_ReplaceTextSpaces(pcVar2); uVar5 = 0xffffffff; do { pcVar9 = pcVar4; if (uVar5 == 0) break; uVar5 -= 1; pcVar9 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar9; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar9 + -uVar5); puVar10 = (undefined4 *)globs::frontGlobs.langOverwriteTitle; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } io::Mem_Free(pcVar2); } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::Overwrite","Text",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar4 = Front_Util_ReplaceTextSpaces(pcVar2); uVar5 = 0xffffffff; do { pcVar9 = pcVar4; if (uVar5 == 0) break; uVar5 -= 1; pcVar9 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar9; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar9 + -uVar5); puVar10 = (undefined4 *)globs::frontGlobs.langOverwriteMessage; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } io::Mem_Free(pcVar2); } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::Overwrite","Ok",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar5 = 0xffffffff; do { pcVar4 = pcVar2; if (uVar5 == 0) break; uVar5 -= 1; pcVar4 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar4; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar4 + -uVar5); puVar10 = (undefined4 *)globs::frontGlobs.langOverwriteOK; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu::Overwrite","Cancel",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { pcVar2 = Front_Util_ReplaceTextSpaces(pcVar2); uVar5 = 0xffffffff; do { pcVar4 = pcVar2; if (uVar5 == 0) break; uVar5 -= 1; pcVar4 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar4; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar4 + -uVar5); puVar10 = (undefined4 *)globs::frontGlobs.langOverwriteCancel; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } } globs::frontGlobs.versionFont = globs::legoGlobs.fontBriefingHi; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","Version",0); globs::frontGlobs.versionString = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","DefaultLevelBMPS",0); globs::frontGlobs.strDefaultLevelBMPS = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2) ; globs::frontGlobs.rockWipeLight = gfx::Container_MakeLight(globs::legoGlobs.rootCont,D3DRMLIGHT_DIRECTIONAL,0.8,0.8,0.8); gfx::Container_Hide(globs::frontGlobs.rockWipeLight,1); globs::frontGlobs.mainMenuSet = Front_LoadMenuSet(config,"MainMenuFull",&globs::frontGlobs.triggerCredits, Front_Callback_TriggerPlayCredits,0x55801c,0,0xffffffff); globs::frontGlobs.saveMenuSet = Front_LoadMenuSet(config,"SaveMenu",&globs::frontGlobs.triggerBackSave, Front_Callback_TriggerBackSave,0xffffffff); Front_LoadLevelSet(globs::legoGlobs.config,&globs::frontGlobs.missionLevels,"StartLevel"); Front_LoadLevelSet(globs::legoGlobs.config,&globs::frontGlobs.tutorialLevels,"TutorialStartLevel") ; // NOTE: Front_Levels_ResetVisited CANNOT be called between // Front_LevelSelect_LoadLevelSet and Front_LevelSelect_LoadLevels. Front_LoadLevels(globs::frontGlobs.mainMenuSet); globs::frontGlobs.pausedMenuSet = Front_LoadMenuSet(config,"PausedMenu",&globs::frontGlobs.triggerContinueMission,NULL,0x558030 ,Front_Callback_SliderGameSpeed,0x558034,Front_Callback_SliderSoundVolume, 0x558038,Front_Callback_SliderMusicVolume,0x55803c, Front_Callback_SliderBrightness,0x558040,Front_Callback_CycleHelpWindow, 0x558044,Front_Callback_TriggerReplayObjective,0x558048,0,0x55804c,0, 0x558050,Front_Callback_CycleWallDetail,0x558054,Front_Callback_CycleMusic, 0x558058,Front_Callback_CycleSound,0x55805c, Front_Callback_CycleAutoGameSpeed,0xffffffff); globs::frontGlobs.optionsMenuSet = Front_LoadMenuSet(config,"OptionsMenu",&globs::frontGlobs.sliderGameSpeed, Front_Callback_SliderGameSpeed,0x558034,Front_Callback_SliderSoundVolume, 0x558038,Front_Callback_SliderMusicVolume,0x55803c, Front_Callback_SliderBrightness,0x558040,Front_Callback_CycleHelpWindow, 0x558044,Front_Callback_TriggerReplayObjective,0x55802c,0,0xffffffff); globs::frontGlobs.sliderSFXVolume = 8; globs::frontGlobs.triggerContinueMission = 0; globs::frontGlobs.sliderBrightness = 5; globs::frontGlobs.cycleHelpWindow = 1; globs::frontGlobs.triggerReplayObjective = 0; globs::frontGlobs.sliderGameSpeed = Front_CalcSliderGameSpeed(); globs::frontGlobs.sliderMusicVolume = Front_CalcSliderCDVolume(); globs::frontGlobs.saveMenuHasNoData = FALSE; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","MaxLevelScreens",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","MaxLevelScreens",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); } globs::frontGlobs.maxLevelScreens = std::atoi(pcVar2); if (globs::frontGlobs.maxLevelScreens == 0) { globs::frontGlobs.maxLevelScreens = 1; } globs::frontGlobs.unused_zero_864 = 0; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","SaveImage","BigWidth",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","SaveImage","BigWidth",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); } globs::frontGlobs.saveImageBigSize.width = std::atoi(pcVar2); if (globs::frontGlobs.saveImageBigSize.width == 0) { globs::frontGlobs.saveImageBigSize.width = 80; } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","SaveImage","BigHeight",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","SaveImage","BigHeight",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); } globs::frontGlobs.saveImageBigSize.height = std::atoi(pcVar2); if (globs::frontGlobs.saveImageBigSize.height == 0) { globs::frontGlobs.saveImageBigSize.height = 60; } Front_Save_SetShouldClearUnlockedLevels(TRUE); return; } void __cdecl lego::front::Front_SaveOptionParameters(void) { SaveData *currSave; currSave = save::Front_Save_GetCurrentSaveData(); if (currSave != NULL) { currSave->SliderGameSpeed = globs::frontGlobs.sliderGameSpeed; currSave->SliderSoundVolume = globs::frontGlobs.sliderSFXVolume; currSave->SliderBrightness = globs::frontGlobs.sliderBrightness; } return; } void __cdecl lego::front::Front_LoadOptionParameters(BOOL loadOptions,BOOL resetFront) { SaveData *currSave; if (resetFront != 0) { // Reset frontEnd triggers/selections. globs::frontGlobs.triggerQuitApp = 0; globs::frontGlobs.selectMissionIndex = -1; globs::frontGlobs.selectTutorialIndex = -1; globs::frontGlobs.triggerContinueMission = 0; } if (loadOptions != 0) { // Reset options sliders. if (globs::frontGlobs.selectLoadSaveIndex != -1) { currSave = save::Front_Save_GetCurrentSaveData(); if (currSave != NULL) { currSave = save::Front_Save_GetCurrentSaveData(); globs::frontGlobs.sliderGameSpeed = currSave->SliderGameSpeed; globs::frontGlobs.sliderSFXVolume = currSave->SliderSoundVolume; globs::frontGlobs.sliderBrightness = currSave->SliderBrightness; return; } } // 100% (out of 200%) // 80% // 100% globs::frontGlobs.sliderGameSpeed = 1; globs::frontGlobs.sliderSFXVolume = 8; globs::frontGlobs.sliderBrightness = 5; } return; } void __cdecl lego::front::Front_PrepareScreenMenuType(Menu_ScreenType screenType) { SaveData *currSave; BOOL BVar1; LevelSet *levelSet; SaveReward *saveReward; MenuItem_SelectData *select; switch(screenType) { case Menu_Screen_Title: globs::frontGlobs.selectLoadSaveIndex = -1; Front_LoadOptionParameters(TRUE,TRUE); currSave = save::Front_Save_GetCurrentSaveData(); if (currSave == NULL) { if (globs::frontGlobs.shouldClearUnlockedLevels != 0) { Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,NULL,&globs::frontGlobs.missionLevels, (MenuItem_SelectData *) (globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData,TRUE); } } else { LAB_00416af1: BVar1 = FALSE; select = (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; currSave = save::Front_Save_GetCurrentSaveData(); Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,currSave->missionsTable,levelSet,select,BVar1); } break; case Menu_Screen_Missions: Front_LoadOptionParameters(TRUE,TRUE); currSave = save::Front_Save_GetCurrentSaveData(); if (currSave == NULL) { if (globs::frontGlobs.shouldClearUnlockedLevels == 0) goto LAB_004169dd; BVar1 = TRUE; select = (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; saveReward = NULL; } else { BVar1 = FALSE; select = (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; currSave = save::Front_Save_GetCurrentSaveData(); saveReward = currSave->missionsTable; } Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,saveReward,levelSet,select,BVar1); LAB_004169dd: Front_Levels_UpdateAvailable (globs::frontGlobs.startTutorialLink,NULL,&globs::frontGlobs.tutorialLevels, (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[2]->items[1]->itemData, FALSE); Front_Save_SetShouldClearUnlockedLevels(TRUE); return; case Menu_Screen_Training: Front_LoadOptionParameters(TRUE,TRUE); currSave = save::Front_Save_GetCurrentSaveData(); if (currSave == NULL) { if (globs::frontGlobs.shouldClearUnlockedLevels == 0) goto LAB_00416a8d; BVar1 = TRUE; select = (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; saveReward = NULL; } else { BVar1 = FALSE; select = (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; currSave = save::Front_Save_GetCurrentSaveData(); saveReward = currSave->missionsTable; } Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,saveReward,levelSet,select,BVar1); LAB_00416a8d: Front_Levels_UpdateAvailable (globs::frontGlobs.startTutorialLink,NULL,&globs::frontGlobs.tutorialLevels, (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[2]->items[1]->itemData, FALSE); Front_Save_SetShouldClearUnlockedLevels(TRUE); return; case Menu_Screen_Load_unused: Front_LoadOptionParameters(FALSE,TRUE); Front_Save_SetShouldClearUnlockedLevels(TRUE); return; case Menu_Screen_Save: Front_LoadOptionParameters(FALSE,TRUE); currSave = save::Front_Save_GetCurrentSaveData(); if (currSave != NULL) goto LAB_00416af1; if (globs::frontGlobs.shouldClearUnlockedLevels != 0) { Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,NULL,&globs::frontGlobs.missionLevels, (MenuItem_SelectData *) (globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData,TRUE); globs::frontGlobs.saveMenuHasNoData = TRUE; } break; default: goto switchD_004168fd_caseD_5; } Front_Levels_UpdateAvailable (globs::frontGlobs.startTutorialLink,NULL,&globs::frontGlobs.tutorialLevels, (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[2]->items[1]->itemData, FALSE); switchD_004168fd_caseD_5: Front_Save_SetShouldClearUnlockedLevels(TRUE); return; } void __cdecl lego::front::Front_RunScreenMenuType(Menu_ScreenType screenType) { MenuSet *menuSet; uint menuIndex; menuSet = globs::frontGlobs.mainMenuSet; Front_PrepareScreenMenuType(screenType); snd::SFX_AddToQueue(SFX_AmbientMusicLoop,SoundMode_Loop); if (true) { switch(screenType) { case Menu_Screen_Title: // MainMenuFull::Menu1 "Main" menuIndex = 0; break; case Menu_Screen_Missions: // MainMenuFull::Menu2 "Missions" menuIndex = 1; break; case Menu_Screen_Training: // MainMenuFull::Menu3 "Training_Missions" menuIndex = 2; break; default: goto switchD_00416bd6_caseD_3; case Menu_Screen_Save: // SaveMenu::Menu1 "Load_A_Saved_Game" (save a game) menuIndex = 0; menuSet = globs::frontGlobs.saveMenuSet; } Front_RunScreenMenu(menuSet,menuIndex); } switchD_00416bd6_caseD_3: snd::Sound3D_Stream_Stop(TRUE); snd::Sound3D_Stream_Stop(FALSE); return; } BOOL __cdecl lego::front::Front_IsFrontEndEnabled(void) { char *keyPath; BoolTri BVar1; keyPath = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","FrontEnd",0); BVar1 = cfg::Config_GetBoolValue(globs::legoGlobs.config,keyPath); if ((BVar1 == BOOL3_TRUE) && (globs::mainGlobs.programmerLevel < PROGRAMMER_MODE_3)) { return TRUE; } return FALSE; } // Always returns false, as the underlying field is always -1. BOOL __cdecl lego::front::Front_IsMissionSelected(void) { return (uint)(globs::frontGlobs.selectMissionIndex != -1); } // Always returns false, as the underlying field is always -1. BOOL __cdecl lego::front::Front_IsTutorialSelected(void) { return (uint)(globs::frontGlobs.selectTutorialIndex != -1); } char * __cdecl lego::front::Front_GetSelectedLevel(void) { BOOL BVar1; int setIndex; BVar1 = Front_IsMissionSelected(); if (BVar1 == 0) { BVar1 = Front_IsTutorialSelected(); if (BVar1 == 0) { return NULL; } setIndex = Front_LevelLink_FindSetIndexOf (globs::frontGlobs.startTutorialLink,globs::frontGlobs.selectTutorialIndex) ; if (setIndex != -1) { return globs::frontGlobs.tutorialLevels.idNames[setIndex]; } } else { setIndex = Front_LevelLink_FindSetIndexOf (globs::frontGlobs.startMissionLink,globs::frontGlobs.selectMissionIndex); if (setIndex != -1) { return globs::frontGlobs.missionLevels.idNames[setIndex]; } } return NULL; } BOOL __cdecl lego::front::Front_IsTriggerAppQuit(void) { return globs::frontGlobs.triggerQuitApp; } BOOL __cdecl lego::front::Front_IsTriggerMissionQuit(void) { return (uint)(globs::frontGlobs.triggerQuitMission != 0); } BOOL __cdecl lego::front::Front_IsTriggerMissionRestart(void) { return (uint)(globs::frontGlobs.triggerRestartMission != 0); } // Returns the tutorials LevelSet if a tutorial level is selected, otherwise // the missions LevelSet is always returned (regardless of having a select). LevelSet * __cdecl lego::front::Front_Levels_GetTutoOrMissions(void) { BOOL BVar1; LevelSet *levelSet; BVar1 = Front_IsTutorialSelected(); levelSet = &globs::frontGlobs.tutorialLevels; if (BVar1 == 0) { levelSet = &globs::frontGlobs.missionLevels; } return levelSet; } int __cdecl lego::front::Front_LevelSet_IndexOf(LevelSet *levelSet,char *levelName) { int cmp; int i; i = 0; if (levelSet->count < 1) { return -1; } do { cmp = std::_stricmp(levelName,levelSet->idNames[i]); if (cmp == 0) { return i; } i += 1; } while (i < levelSet->count); return -1; } // Resets links and recurse callback states. Required after RunThroughRecurse function. void __cdecl lego::front::Front_Levels_ResetVisited(void) { int i; i = 0; if (0 < globs::frontGlobs.missionLevels.count) { do { if (globs::frontGlobs.missionLevels.levels[i] != NULL) { globs::frontGlobs.missionLevels.levels[i]->visited = 0; globs::frontGlobs.missionLevels.visitedList[i] = 0; } i += 1; } while (i < globs::frontGlobs.missionLevels.count); } i = 0; if (0 < globs::frontGlobs.tutorialLevels.count) { do { if (globs::frontGlobs.tutorialLevels.levels[i] != NULL) { globs::frontGlobs.tutorialLevels.levels[i]->visited = 0; globs::frontGlobs.tutorialLevels.visitedList[i] = 0; } i += 1; } while (i < globs::frontGlobs.tutorialLevels.count); } return; } void __cdecl lego::front::Front_LevelSet_SetLinkVisited(LevelSet *levelSet,char *levelName,BOOL visited) { byte *ptrNext; int cmp; int i; byte *ptrName; byte **pIDName; bool clt; byte cnext; i = 0; if (levelSet->count < 1) { return; } pIDName = (byte **)levelSet->idNames; do { ptrNext = *pIDName; ptrName = (byte *)levelName; do { cnext = *ptrNext; clt = cnext < *ptrName; if (cnext != *ptrName) { LAB_00416e3d: cmp = (1 - (uint)clt) - (uint)(clt != 0); goto LAB_00416e42; } if (cnext == 0) break; cnext = ptrNext[1]; clt = cnext < ptrName[1]; if (cnext != ptrName[1]) goto LAB_00416e3d; ptrNext = ptrNext + 2; ptrName = ptrName + 2; } while (cnext != 0); cmp = 0; LAB_00416e42: if (cmp == 0) { levelSet->visitedList[i] = visited; return; } i += 1; pIDName = pIDName + 1; if (levelSet->count <= i) { return; } } while( true ); } BOOL __cdecl lego::front::Front_LevelSet_IsLinkVisited(LevelSet *levelSet,char *levelName) { byte *ptrNext; int cmp; int i; byte *ptrName; byte **pIDName; bool clt; byte cnext; i = 0; if (levelSet->count < 1) { return FALSE; } pIDName = (byte **)levelSet->idNames; do { ptrNext = *pIDName; ptrName = (byte *)levelName; do { cnext = *ptrNext; clt = cnext < *ptrName; if (cnext != *ptrName) { LAB_00416ead: cmp = (1 - (uint)clt) - (uint)(clt != 0); goto LAB_00416eb2; } if (cnext == 0) break; cnext = ptrNext[1]; clt = cnext < ptrName[1]; if (cnext != ptrName[1]) goto LAB_00416ead; ptrNext = ptrNext + 2; ptrName = ptrName + 2; } while (cnext != 0); cmp = 0; LAB_00416eb2: if (cmp == 0) { return levelSet->visitedList[i]; } i += 1; pIDName = pIDName + 1; if (levelSet->count <= i) { return FALSE; } } while( true ); } void __cdecl lego::front::Front_LevelSet_SetLevelLink(LevelSet *levelSet,char *levelName,LevelLink *link) { byte *ptrNext; int cmp; int i; byte *ptrName; byte **pIDName; bool clt; byte cnext; i = 0; if (levelSet->count < 1) { return; } pIDName = (byte **)levelSet->idNames; do { ptrNext = *pIDName; ptrName = (byte *)levelName; do { cnext = *ptrNext; clt = cnext < *ptrName; if (cnext != *ptrName) { LAB_00416f1d: cmp = (1 - (uint)clt) - (uint)(clt != 0); goto LAB_00416f22; } if (cnext == 0) break; cnext = ptrNext[1]; clt = cnext < ptrName[1]; if (cnext != ptrName[1]) goto LAB_00416f1d; ptrNext = ptrNext + 2; ptrName = ptrName + 2; } while (cnext != 0); cmp = 0; LAB_00416f22: if (cmp == 0) { levelSet->levels[i] = link; return; } i += 1; pIDName = pIDName + 1; if (levelSet->count <= i) { return; } } while( true ); } LevelLink * __cdecl lego::front::Front_LevelSet_GetLevelLink(LevelSet *levelSet,char *levelName) { byte *ptrNext; int cmp; int i; byte *ptrName; byte **pIDName; bool clt; byte cnext; i = 0; if (levelSet->count < 1) { return NULL; } pIDName = (byte **)levelSet->idNames; do { // iVar3 = std::strcmp(levelCol->NextLevels[i],levelName); ptrNext = *pIDName; ptrName = (byte *)levelName; do { cnext = *ptrNext; clt = cnext < *ptrName; if (cnext != *ptrName) { LAB_00416f8d: cmp = (1 - (uint)clt) - (uint)(clt != 0); goto LAB_00416f92; } if (cnext == 0) break; cnext = ptrNext[1]; clt = cnext < ptrName[1]; if (cnext != ptrName[1]) goto LAB_00416f8d; ptrNext = ptrNext + 2; ptrName = ptrName + 2; } while (cnext != 0); cmp = 0; LAB_00416f92: if (cmp == 0) { return levelSet->levels[i]; } i += 1; pIDName = pIDName + 1; if (levelSet->count <= i) { return NULL; } } while( true ); } LevelLink * __cdecl lego::front::Front_LevelSet_LoadLevelLinks(LevelSet *levelSet,char *levelName) { BOOL isLinked; LevelLink *info; int setIndex; char *linkNames; uint numParts; LevelLink **levelLinks; LevelLink *linkInfo; uint i; char *stringParts [15]; if (levelName != NULL) { isLinked = Front_LevelSet_IsLinkVisited(levelSet,levelName); if (isLinked != 0) { linkInfo = Front_LevelSet_GetLevelLink(levelSet,levelName); return linkInfo; } info = (LevelLink *)io::Mem_Alloc(0x14); Front_LevelSet_SetLinkVisited(levelSet,levelName,TRUE); Front_LevelSet_SetLevelLink(levelSet,levelName,info); if (info != NULL) { setIndex = Front_LevelSet_IndexOf(levelSet,levelName); if (setIndex != -1) { linkNames = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"LevelLinks",0); // FIXME: This string is never freed. linkNames = cfg::Config_GetStringValue(globs::legoGlobs.config,linkNames); info->setIndex = setIndex; i = 0; if (linkNames == NULL) { info->linkLevels = NULL; } else { numParts = util::Util_Tokenise(linkNames,stringParts,","); if (numParts == 0) goto LAB_004170bd; levelLinks = (LevelLink **)io::Mem_Alloc(numParts * 4); info->linkLevels = levelLinks; if (numParts != 0) { do { linkInfo = Front_LevelSet_LoadLevelLinks(levelSet,stringParts[i]); info->linkLevels[i] = linkInfo; i += 1; } while (i < numParts); info->linkCount = i; return info; } } info->linkCount = 0; return info; } LAB_004170bd: io::Mem_Free(info); return NULL; } } return NULL; } BOOL __cdecl lego::front::Front_LevelLink_RunThroughLinks (LevelLink *startLink,LevelLink_RunThroughLinksCallback callback,void *data) { BOOL BVar1; uint i; if ((startLink != NULL) && (startLink->visited == 0)) { startLink->visited = TRUE; BVar1 = (*callback)(startLink,data); if (BVar1 != 0) { return TRUE; } if ((startLink->linkLevels != NULL) && (i = 0, startLink->linkCount != 0)) { do { BVar1 = Front_LevelLink_RunThroughLinks(startLink->linkLevels[i],callback,data); if (BVar1 != 0) { return TRUE; } i += 1; } while (i < startLink->linkCount); return FALSE; } } return FALSE; } BOOL __cdecl lego::front::Front_LevelLink_Callback_IncCount(LevelLink *link,int *pCount) { *pCount = *pCount + 1; return FALSE; } BOOL __cdecl lego::front::Front_LevelLink_Callback_FindByLinkIndex (LevelLink *link,SearchLevelLinkFindIndex_10 *search) { int linkIndex; linkIndex = search->currentIndex; if (search->searchIndex == linkIndex) { search->resultIndex = linkIndex; search->resultLink = link; return TRUE; } search->currentIndex = linkIndex + 1; return FALSE; } LevelLink * __cdecl lego::front::Front_LevelLink_FindByLinkIndex(LevelLink *startLink,int linkIndex) { BOOL BVar1; SearchLevelLinkFindIndex_10 search; search.resultLink = NULL; search.currentIndex = 0; search.resultIndex = 0; search.searchIndex = linkIndex; BVar1 = Front_LevelLink_RunThroughLinks (startLink,Front_LevelLink_Callback_FindByLinkIndex,&search); if (BVar1 != 0) { Front_Levels_ResetVisited(); return search.resultLink; } Front_Levels_ResetVisited(); return NULL; } int __cdecl lego::front::Front_LevelLink_FindSetIndexOf(LevelLink *startLink,int linkIndex) { LevelLink *link; link = Front_LevelLink_FindByLinkIndex(startLink,linkIndex); if (link != NULL) { return link->setIndex; } return -1; } void __cdecl lego::front::Front_Levels_UpdateAvailable_Recursive (LevelLink *link,SearchLevelSelectInfo_14 *search,BOOL unlocked) { MenuItem_SelectItem *levelData; MenuItem_SelectItemFlags lflags; SaveRewardFlags completed; uint i; MenuItem_SelectItem *levelsList; i = 0; if ((link != NULL) && (link->visited == 0)) { if ((PROGRAMMER_MODE_1 < globs::mainGlobs.programmerLevel) || ((globs::mainGlobs.flags & MAIN_FLAG_LEVELSOPEN) != MAIN_FLAG_NONE)) { search->keepLocked = FALSE; } link->visited = TRUE; if (((search->saveReward == NULL) || (PROGRAMMER_MODE_1 < globs::mainGlobs.programmerLevel)) || ((globs::mainGlobs.flags & MAIN_FLAG_LEVELSOPEN) != MAIN_FLAG_NONE)) { completed = (SaveRewardFlags)(search->keepLocked == 0); } else { completed = search->saveReward[link->setIndex].flags & SAVEREWARD_FLAG_COMPLETED; } if (((completed == SAVEREWARD_FLAG_NONE) && (unlocked == 0)) && (levelsList = search->selectData->selItemList, levelData = levelsList + search->index, levelsList[search->index].frontEndOpen == 0)) { lflags = levelData->flags & ~SELECTITEM_FLAG_ENABLED; } else { levelsList = search->selectData->selItemList; levelData = levelsList + search->index; lflags = levelsList[search->index].flags | SELECTITEM_FLAG_ENABLED; } levelData->flags = lflags; search->index = search->index + 1; if (link->linkCount != 0) { do { Front_Levels_UpdateAvailable_Recursive(link->linkLevels[i],search,completed); i += 1; } while (i < link->linkCount); } } return; } // When opt_saveReward is null, keepLocked states if all appropriate levels will be set to their // default locked state if true, or unlocked if false. void __cdecl lego::front::Front_Levels_UpdateAvailable (LevelLink *startLink,SaveReward *opt_saveReward,LevelSet *levelSet, MenuItem_SelectData *selectData,BOOL keepLocked) { SearchLevelSelectInfo_14 search; search.levelSet = levelSet; search.selectData = selectData; search.saveReward = opt_saveReward; search.index = 0; search.keepLocked = keepLocked; Front_Levels_UpdateAvailable_Recursive(startLink,&search,TRUE); Front_Levels_ResetVisited(); return; } int __cdecl lego::front::Front_Save_GetLevelScore(uint index,SaveData *saveData) { longlong lVar1; lVar1 = __ftol((float10)saveData->missionsTable[index].reward.items[9].percentFloat); return (int)lVar1; } // Callback when hovering over level item. void __cdecl lego::front::Front_Callback_SelectMissionItem(float elapsedAbs,int selectIndex) { Font *font; LevelLink *info; SaveData *currSave; uint strWidth; int score; char *pcVar1; char *completeText; char *incompleteText; int soundResult; int iVar2; undefined4 *puVar3; char buffLevel [64]; char buffMsg [300]; char *langName; MenuTextWindow *menuTextWnd; SaveRewardFlags srflags; menuTextWnd = globs::frontGlobs.saveLevelWnd; font = (globs::frontGlobs.mainMenuSet)->menus[1]->menuFont; info = Front_LevelLink_FindByLinkIndex(globs::frontGlobs.startMissionLink,selectIndex); langName = globs::frontGlobs.missionLevels.langNames[info->setIndex]; buffLevel[0] = '\0'; puVar3 = (undefined4 *)(buffLevel + 1); for (iVar2 = 0xf; iVar2 != 0; iVar2 += -1) { *puVar3 = 0; puVar3 = puVar3 + 1; } *(undefined2 *)puVar3 = 0; *(undefined *)((int)puVar3 + 2) = 0; currSave = save::Front_Save_GetCurrentSaveData(); globs::frontGlobs.levelSelectLastNumber = globs::frontGlobs.levelSelectHoverNumber; globs::frontGlobs.levelSelectHoverNumber = info->setIndex + 1; if ((globs::mainGlobs.flags & MAIN_FLAG_TESTERCALL) != MAIN_FLAG_NONE) { std::sprintf(buffLevel," (Level %d)",info->setIndex + 1); } // Fallback to ID name when language name (cfg: FullName) isn't defined. if ((langName == NULL) || (*langName == '\0')) { langName = globs::frontGlobs.missionLevels.idNames[info->setIndex]; } if (menuTextWnd->textWindow == NULL) { strWidth = lego::image::Font_GetStringWidth(font,langName); // HARDCODED SCREEN RESOLUTION!! (390) Front_LevelSelect_LevelNamePrintF (font,(int)globs::mainGlobs.appWidth / 2 - (int)strWidth / 2,390,langName); } else { if ((globals::g_levelSelectPrinting != 0) && (TextWindow_PrintF(menuTextWnd->textWindow,langName), (globs::mainGlobs.flags & MAIN_FLAG_TESTERCALL) != MAIN_FLAG_NONE)) { TextWindow_PrintF(menuTextWnd->textWindow,buffLevel); } } if (currSave != NULL) { srflags = currSave->missionsTable[info->setIndex].flags; if (((srflags & SAVEREWARD_FLAG_COMPLETED) != SAVEREWARD_FLAG_NONE) && ((srflags & SAVEREWARD_FLAG_TUTORIAL) == SAVEREWARD_FLAG_NONE)) { score = Front_Save_GetLevelScore(info->setIndex,currSave); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","Level_Completed",0); completeText = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); std::sprintf(buffMsg," %s (%i)",completeText,score); Front_Util_StringReplaceChar(buffMsg,'_',' '); goto LAB_0041757a; } } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Menu","Level_Incomplete",0); incompleteText = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); std::sprintf(buffMsg," %s",incompleteText); Front_Util_StringReplaceChar(buffMsg,'_',' '); LAB_0041757a: if ((menuTextWnd->textWindow != NULL) && (globals::g_levelSelectPrinting != 0)) { // Ahhh, lovely... nested printf calls without sanitization, // it may be possible to intentionally corrupt memory with this. TextWindow_PrintF(menuTextWnd->textWindow,buffMsg); if (globs::frontGlobs.levelSelectHoverNumber != globs::frontGlobs.levelSelectLastNumber) { globs::frontGlobs.levelSelectSFXStopped = TRUE; globs::frontGlobs.levelSelectSFXTimer = 0.0; } if ((globs::frontGlobs.levelSelectSFXStopped != 0) && (globs::frontGlobs.levelSelectSFXTimer = elapsedAbs + globs::frontGlobs.levelSelectSFXTimer, (ushort)((ushort)(globs::frontGlobs.levelSelectSFXTimer * 25.0 < 500.0) << 8 | (ushort)(globs::frontGlobs.levelSelectSFXTimer * 25.0 == 500.0) << 0xe) == 0)) { // Uhhh, well then... // tutorial levels are kind of hardcoded to max of 9...??? if ((int)globs::frontGlobs.levelSelectHoverNumber < 9) { soundResult = Front_LevelSelect_PlayTutoLevelNameSFX (globs::frontGlobs.levelSelectHoverNumber); } else { // levelSelectHoverNumber - NUM_TUTORIALS soundResult = Front_LevelSelect_PlayLevelNameSFX (globs::frontGlobs.levelSelectHoverNumber - 8); } if (soundResult != 0) { globs::frontGlobs.levelSelectSFXStopped = FALSE; } } } globals::g_levelSelectPrinting = FALSE; return; } // Callback when hovering over level item. void __cdecl lego::front::Front_Callback_SelectTutorialItem(float elapsedAbs,int selectIndex) { LevelLink *info; BOOL BVar1; char *langLevelName; MenuTextWindow *menuTextWnd; menuTextWnd = globs::frontGlobs.saveLevelWnd; info = Front_LevelLink_FindByLinkIndex(globs::frontGlobs.startTutorialLink,selectIndex); langLevelName = globs::frontGlobs.tutorialLevels.langNames[info->setIndex]; globs::frontGlobs.levelSelectLastNumber = globs::frontGlobs.levelSelectHoverNumber; globs::frontGlobs.levelSelectHoverNumber = info->setIndex + 1; if ((langLevelName == NULL) || (*langLevelName == '\0')) { // Fallback to config level ID name if no language name is defined. langLevelName = globs::frontGlobs.tutorialLevels.idNames[info->setIndex]; } if ((menuTextWnd->textWindow != NULL) && (globals::g_levelSelectPrinting != 0)) { TextWindow_PrintF(menuTextWnd->textWindow,langLevelName); if (globs::frontGlobs.levelSelectHoverNumber != globs::frontGlobs.levelSelectLastNumber) { globs::frontGlobs.levelSelectSFXStopped = TRUE; globs::frontGlobs.levelSelectSFXTimer = 0.0; } if ((globs::frontGlobs.levelSelectSFXStopped != 0) && (globs::frontGlobs.levelSelectSFXTimer = elapsedAbs + globs::frontGlobs.levelSelectSFXTimer, (ushort)((ushort)(globs::frontGlobs.levelSelectSFXTimer * 25.0 < 500.0) << 8 | (ushort)(globs::frontGlobs.levelSelectSFXTimer * 25.0 == 500.0) << 0xe) == 0)) { BVar1 = Front_LevelSelect_PlayTutoLevelNameSFX(globs::frontGlobs.levelSelectHoverNumber); if (BVar1 != 0) { globs::frontGlobs.levelSelectSFXStopped = FALSE; } } } globals::g_levelSelectPrinting = FALSE; return; } BOOL __cdecl lego::front::Front_LevelInfo_Callback_AddItem(LevelLink *link,SearchLevelSelectAdd *search) { char cVar1; char *pcVar2; int frontEndX; int frontEndY; BoolTri frontEndOpen; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; undefined4 *puVar7; char buff [1024]; char *levelID; levelID = search->levelSet->idNames[link->setIndex]; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelID,"FrontEndX",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelID,"FrontEndX",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); } frontEndX = std::atoi(pcVar2); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelID,"FrontEndY",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelID,"FrontEndY",0); pcVar2 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar2); } frontEndY = std::atoi(pcVar2); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelID,"FrontEndOpen",0); frontEndOpen = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar2); if (frontEndOpen == BOOL3_ERROR) { frontEndOpen = BOOL3_FALSE; } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelID,"MenuBMP",0); pcVar2 = cfg::Config_GetStringValue(globs::legoGlobs.config,pcVar2); if (pcVar2 != NULL) { Front_MenuItem_AddSelectItem (search->itemData,pcVar2,FALSE,NULL,frontEndX,frontEndY,frontEndOpen); io::Mem_Free(pcVar2); return FALSE; } uVar3 = 0xffffffff; pcVar2 = globs::frontGlobs.strDefaultLevelBMPS; do { pcVar6 = pcVar2; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); puVar7 = (undefined4 *)buff; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar7 = *puVar5; puVar5 = puVar5 + 1; puVar7 = puVar7 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } Front_MenuItem_AddSelectItem(search->itemData,buff,FALSE,NULL,frontEndX,frontEndY,frontEndOpen); return FALSE; } void __cdecl lego::front::MainMenuFull_AddMissionsDisplay (int valueOffset,LevelLink *startLink,LevelSet *levelSet,Menu *menu,SaveData *saveData, Menu *opt_nextMenu,void *callback) { Menu *menu_00; MenuItem_SelectData *itemData; MenuItem *menuItem; SearchLevelSelectAdd search; menu_00 = menu; search.levelSet = levelSet; search.menu_4 = menu; search.itemData = NULL; search.currSave = saveData; levelSet = NULL; Front_LevelLink_RunThroughLinks(startLink,Front_LevelLink_Callback_IncCount,&levelSet); Front_Levels_ResetVisited(); // &frontGlobs.triggerCredits[valueOffset] itemData = Front_MenuItem_CreateSelect ((int *)((int)globs::frontGlobs.saveData + valueOffset * 4 + -0x70), ____EMPTYSTR__,____EMPTYSTR__,0,0,0,(int)levelSet,0,0,0,0,0, (MenuItem_SelectCallback)callback,opt_nextMenu); menuItem = Front_MenuItem_CreateBannerItem ("Levels!!!",NULL,NULL,0,0,MenuItem_Type_Select,TRUE,itemData,FALSE); Front_Menu_AddMenuItem(menu_00,menuItem); search.itemData = itemData; Front_LevelLink_RunThroughLinks(startLink,Front_LevelInfo_Callback_AddItem,&search); Front_Levels_ResetVisited(); return; } BOOL __cdecl lego::save::Front_Save_ReadSaveFile(uint saveIndex,SaveData *out_saveData,BOOL readOnly) { uint saveIndex_00; File *file; SaveReward *saveReward; int iVar1; SaveData *saveData; undefined4 tutoCount; char buff [100]; saveIndex_00 = saveIndex; if (saveIndex < 6) { std::sprintf(buff,"%s\\%i.sav","Saves",saveIndex); file = io::File_Open(buff,"rb"); saveData = out_saveData; if (file != NULL) { // missionCount = 0; saveIndex = 0; tutoCount = 0; // Read the data directly into the structure. // This means we can learn from the file format! :D io::File_Read(out_saveData,0xb0,1,file); front::Front_LevelLink_RunThroughLinks (globs::frontGlobs.startMissionLink,front::Front_LevelLink_Callback_IncCount, &saveIndex); front::Front_Levels_ResetVisited(); front::Front_LevelLink_RunThroughLinks (globs::frontGlobs.startTutorialLink,front::Front_LevelLink_Callback_IncCount, &tutoCount); front::Front_Levels_ResetVisited(); if ((saveData->missionsCount != saveIndex) && (readOnly == 0)) { Front_Save_WriteSaveFiles(saveIndex_00,NULL); for (iVar1 = 0x2e; iVar1 != 0; iVar1 += -1) { saveData->field_0x0 = 0; saveData = (SaveData *)&saveData->SliderMusicVolume; } return FALSE; } saveReward = (SaveReward *)io::Mem_Alloc(saveData->missionsCount * 0x3190); saveData->missionsTable = saveReward; io::File_Read(saveReward,0x3190,saveData->missionsCount,file); io::File_Close(file); return TRUE; } if (readOnly == 0) { Front_Save_WriteSaveFiles(saveIndex_00,NULL); } } return FALSE; } // WARNING: Function: _alloca4k replaced with injection: alloca_probe // Write *.sav and *.osf save files. // // When saveData is NULL, basic empty save files are created(?) BOOL __cdecl lego::save::Front_Save_WriteSaveFiles(uint saveIndex,SaveData *opt_saveData) { File *file; int iVar1; uint uVar2; int *piVar3; SaveReward *pSVar4; uint missionCount; SaveData save; char buff [100]; SaveReward mission; mission.reward.items[9].BoxImage = (Image *)0x417b0a; if (saveIndex < 6) { std::sprintf(buff,"%s\\%i.sav","Saves",saveIndex); uVar2 = 0; if (opt_saveData == NULL) { io::File_MakeDir("Saves"); file = io::File_Open(buff,"wb"); if (file != NULL) { save.field_0x0 = 0; piVar3 = &save.SliderMusicVolume; for (iVar1 = 0x2d; iVar1 != 0; iVar1 += -1) { *piVar3 = 0; piVar3 = piVar3 + 1; } pSVar4 = &mission; mission.flags = SAVEREWARD_FLAG_NONE; save.SliderSoundVolume = 7; for (iVar1 = 0xc63; pSVar4 = (SaveReward *)&pSVar4->reward, iVar1 != 0; iVar1 += -1) { pSVar4->flags = SAVEREWARD_FLAG_NONE; } save.SliderMusicVolume = 5; save.SliderBrightness = 5; save.SliderGameSpeed = 1; save.missionsCount = 0; front::Front_LevelLink_RunThroughLinks (globs::frontGlobs.startMissionLink,front::Front_LevelLink_Callback_IncCount, &save.missionsCount); front::Front_Levels_ResetVisited(); io::File_Write(&save,0xb4,1,file); if (save.missionsCount != 0) { do { io::File_Write(&mission,0x3190,1,file); uVar2 += 1; } while (uVar2 < save.missionsCount); } io::File_Close(file); return TRUE; } } else { missionCount = 0; front::Front_LevelLink_RunThroughLinks (globs::frontGlobs.startMissionLink,front::Front_LevelLink_Callback_IncCount, &missionCount); front::Front_Levels_ResetVisited(); if (missionCount != opt_saveData->missionsCount) { Front_Save_WriteSaveFiles(saveIndex,NULL); return TRUE; } file = io::File_Open(buff,"wb"); if (file != NULL) { io::File_Write(opt_saveData,0xb0,1,file); if (opt_saveData->missionsCount != 0) { io::File_Write(opt_saveData->missionsTable,0x3190,opt_saveData->missionsCount,file); } io::File_Close(file); std::sprintf(buff,"%s\\%i.osf","Saves",saveIndex); ObjectRecall_SaveRROSFile(buff); return TRUE; } } } return FALSE; } void __cdecl lego::save::Front_Save_LoadAllSaveFiles(void) { BOOL BVar1; SaveData *out_saveData; uint saveIndex; saveIndex = 0; out_saveData = globs::frontGlobs.saveData; do { if ((globs::mainGlobs.flags & MAIN_FLAG_CLEANSAVES) == MAIN_FLAG_NONE) { BVar1 = Front_Save_ReadSaveFile(saveIndex,out_saveData,FALSE); if (BVar1 == 0) goto LAB_00417d53; } else { Front_Save_WriteSaveFiles(saveIndex,NULL); LAB_00417d53: Front_Save_ReadSaveFile(saveIndex,out_saveData,FALSE); } out_saveData = out_saveData + 1; saveIndex += 1; // if (saveNumber < 6) if ((SaveData *)((int)&globs::frontGlobs.saveData[5].field_0xb4 + 3U) < out_saveData) { return; } } while( true ); } SaveData * __cdecl lego::save::Front_Save_GetSaveDataAt(int saveIndex) { if ((saveIndex < 6) && (-1 < saveIndex)) { return globs::frontGlobs.saveData + saveIndex; } return NULL; } SaveData * __cdecl lego::save::Front_Save_GetCurrentSaveData(void) { SaveData *saveData; if (globs::frontGlobs.saveNumber != -1) { saveData = Front_Save_GetSaveDataAt(globs::frontGlobs.saveNumber); return saveData; } return NULL; } int __cdecl lego::save::Front_Save_GetSaveNumber(void) { return globs::frontGlobs.saveNumber; } void __cdecl lego::save::Front_Save_SetSaveNumber(int saveNumber) { globs::frontGlobs.saveNumber = saveNumber; return; } void __cdecl lego::front::Front_Save_SetLevelCompleted(uint levelIndex) { SaveData *currSave; BOOL BVar1; currSave = save::Front_Save_GetCurrentSaveData(); if (currSave != NULL) { BVar1 = Front_IsTutorialSelected(); if (BVar1 == 0) { // if (levelIndex >= NUM_TUTORIALS) if (7 < levelIndex) { if (currSave->missionsCount <= levelIndex && levelIndex != currSave->missionsCount) { return; } currSave->missionsTable[levelIndex].flags = currSave->missionsTable[levelIndex].flags | SAVEREWARD_FLAG_COMPLETED; return; } } else { // if (levelIndex >= NUM_TUTORIALS) if (7 < levelIndex) { return; } } currSave->missionsTable[levelIndex].flags = currSave->missionsTable[levelIndex].flags | SAVEREWARD_FLAG_COMPLETED; currSave->missionsTable[levelIndex].flags = currSave->missionsTable[levelIndex].flags | SAVEREWARD_FLAG_TUTORIAL; } return; } void __cdecl lego::front::Front_Save_SetSaveStruct18(SaveStruct_18 *savestruct18) { SaveData *currSave; int iVar1; SaveStruct_18 *pSVar2; currSave = save::Front_Save_GetCurrentSaveData(); if (currSave != NULL) { pSVar2 = &currSave->saveStruct18_1c; for (iVar1 = 6; iVar1 != 0; iVar1 += -1) { *(undefined4 *)pSVar2 = *(undefined4 *)savestruct18; savestruct18 = (SaveStruct_18 *)&savestruct18->field_0x4; pSVar2 = (SaveStruct_18 *)&pSVar2->field_0x4; } } return; } BOOL __cdecl lego::front::Front_Save_SetRewardLevel(int levelIndex,RewardLevel *rewardLevel) { SaveData *currSave; int iVar1; SaveReward *pSVar2; currSave = save::Front_Save_GetCurrentSaveData(); if ((currSave != NULL) && (levelIndex < (int)currSave->missionsCount)) { // std::memcpy( & save->missionsTable[levelIndex].reward, reward ); pSVar2 = currSave->missionsTable + levelIndex; for (iVar1 = 0xc63; pSVar2 = (SaveReward *)&pSVar2->reward, iVar1 != 0; iVar1 += -1) { pSVar2->flags = rewardLevel->Enabled; rewardLevel = (RewardLevel *)&rewardLevel->saveHasCapture; } return TRUE; } return FALSE; } RewardLevel * __cdecl lego::front::Front_Save_GetRewardLevel(int levelIndex) { SaveData *currSave; currSave = save::Front_Save_GetCurrentSaveData(); if ((currSave != NULL) && (levelIndex < (int)currSave->missionsCount)) { return &currSave->missionsTable[levelIndex].reward; } return NULL; } BOOL __cdecl lego::front::Front_Save_WriteCurrentSaveFiles(void) { SaveData *currSave; BOOL BVar1; currSave = save::Front_Save_GetCurrentSaveData(); BVar1 = save::Front_Save_WriteSaveFiles(globs::frontGlobs.saveNumber,currSave); return BVar1; } BOOL __cdecl lego::front::Front_Save_GetHasNoSaveData(void) { return globs::frontGlobs.saveMenuHasNoData; } void __cdecl lego::front::Front_Save_SetHasNoSaveData(BOOL state) { globs::frontGlobs.saveMenuHasNoData = state; return; } void __cdecl lego::front::Front_Save_WriteEmptySaveFiles(void) { uint saveIndex; SaveData *opt_saveData; opt_saveData = NULL; saveIndex = save::Front_Save_GetSaveNumber(); save::Front_Save_WriteSaveFiles(saveIndex,opt_saveData); Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,NULL,&globs::frontGlobs.missionLevels, (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData, TRUE); return; } void __cdecl lego::save::Front_Save_CopySaveData(SaveData *out_saveData) { SaveData *pSVar1; SaveReward *pSVar2; int iVar3; uint uVar4; SaveData *pSVar5; SaveReward *pSVar6; pSVar1 = Front_Save_GetCurrentSaveData(); if (pSVar1 != NULL) { pSVar1 = Front_Save_GetCurrentSaveData(); pSVar5 = out_saveData; for (iVar3 = 0x2e; iVar3 != 0; iVar3 += -1) { pSVar5->field_0x0 = pSVar1->field_0x0; pSVar1 = (SaveData *)&pSVar1->SliderMusicVolume; pSVar5 = (SaveData *)&pSVar5->SliderMusicVolume; } pSVar2 = (SaveReward *)io::Mem_Alloc(out_saveData->missionsCount * 0x3190); out_saveData->missionsTable = pSVar2; if (pSVar2 != NULL) { uVar4 = out_saveData->missionsCount; pSVar1 = Front_Save_GetCurrentSaveData(); pSVar2 = pSVar1->missionsTable; pSVar6 = out_saveData->missionsTable; for (uVar4 = uVar4 * 0x3190 >> 2; uVar4 != 0; uVar4 -= 1) { pSVar6->flags = pSVar2->flags; pSVar2 = (SaveReward *)&pSVar2->reward; pSVar6 = (SaveReward *)&pSVar6->reward; } for (iVar3 = 0; iVar3 != 0; iVar3 += -1) { *(undefined *)&pSVar6->flags = *(undefined *)&pSVar2->flags; pSVar2 = (SaveReward *)((int)&pSVar2->flags + 1); pSVar6 = (SaveReward *)((int)&pSVar6->flags + 1); } } } return; } void __cdecl lego::front::Front_Save_SetSaveData(SaveData *saveData) { SaveData *pSVar1; SaveData *pSVar2; int iVar3; pSVar1 = save::Front_Save_GetCurrentSaveData(); if (pSVar1 != NULL) { pSVar1 = save::Front_Save_GetCurrentSaveData(); if (pSVar1->missionsTable != NULL) { pSVar1 = save::Front_Save_GetCurrentSaveData(); io::Mem_Free(pSVar1->missionsTable); } pSVar2 = save::Front_Save_GetCurrentSaveData(); pSVar1 = saveData; for (iVar3 = 0x2e; iVar3 != 0; iVar3 += -1) { pSVar2->field_0x0 = pSVar1->field_0x0; pSVar1 = (SaveData *)&pSVar1->SliderMusicVolume; pSVar2 = (SaveData *)&pSVar2->SliderMusicVolume; } pSVar1 = save::Front_Save_GetCurrentSaveData(); pSVar1->missionsTable = saveData->missionsTable; } return; } void __cdecl lego::front::Front_Save_SetShouldClearUnlockedLevels(BOOL state) { globs::frontGlobs.shouldClearUnlockedLevels = state; return; } // Returns true if all non-tutorial levels have 100% score. BOOL __cdecl lego::front::Front_Save_IsGame100Percented(void) { SaveData *currSave; uint completion; uint uVar1; int iVar2; longlong lVar3; currSave = save::Front_Save_GetCurrentSaveData(); if (currSave != NULL) { completion = 0; uVar1 = 8; currSave = save::Front_Save_GetCurrentSaveData(); if (8 < currSave->missionsCount) { iVar2 = 0x18c80; do { currSave = save::Front_Save_GetCurrentSaveData(); lVar3 = __ftol((float10)*(float *)((currSave->missionsTable->reward).items[9].Text + iVar2 + -0x1c)); completion += (int)lVar3; uVar1 += 1; iVar2 += 0x3190; currSave = save::Front_Save_GetCurrentSaveData(); } while (uVar1 < currSave->missionsCount); } currSave = save::Front_Save_GetCurrentSaveData(); if (99 < completion / (currSave->missionsCount - 8)) { return TRUE; } } return FALSE; } void __cdecl lego::front::HelpWindow_SetFont(Font *font) { globs::helpwindowGlobs.font = font; return; } void __cdecl lego::front::HelpWindow_ClearFlag1(void) { // &= ~HELPWINDOW_UNK_1 (~0x1) globs::helpwindowGlobs.flags = globs::helpwindowGlobs.flags & ~HELPWINDOW_GLOB_FLAG_UNK_1; return; } void __cdecl lego::front::HelpWindow_Initialise(Config *config,char *gameName) { char *pcVar1; char cVar2; char *pcVar3; int iVar4; Area2F rect; char *stringParts [16]; HelpWindow_LoadLevelsInfo(config,gameName); pcVar3 = cfg::Config_BuildStringID(gameName,"HelpWindow","BackGroundImage",0); pcVar3 = cfg::Config_GetStringValue(config,pcVar3); if (pcVar3 != NULL) { util::Util_Tokenise(pcVar3,stringParts,","); globs::helpwindowGlobs.BackgroundImage = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); if (globs::helpwindowGlobs.BackgroundImage != NULL) { lego::image::Image_SetupTrans(globs::helpwindowGlobs.BackgroundImage,0.0,0.0,0.0,0.0,0.0,0.0); } iVar4 = std::atoi(stringParts[1]); globs::helpwindowGlobs.BackgroundPosition.x = (float)iVar4; iVar4 = std::atoi(stringParts[2]); globs::helpwindowGlobs.BackgroundPosition.y = (float)iVar4; io::Mem_Free(pcVar3); } HelpWindow_LoadButtons(config,gameName); pcVar3 = cfg::Config_BuildStringID(gameName,"HelpWindow","TextWindowArea",0); pcVar3 = cfg::Config_GetStringValue(config,pcVar3); if (pcVar3 != NULL) { util::Util_Tokenise(pcVar3,stringParts,","); iVar4 = std::atoi(stringParts[0]); rect.x = (float)iVar4; iVar4 = std::atoi(stringParts[1]); rect.y = (float)iVar4; iVar4 = std::atoi(stringParts[2]); rect.width = (float)iVar4; iVar4 = std::atoi(stringParts[3]); rect.height = (float)iVar4; globs::helpwindowGlobs.textWnd = TextWindow_Create(globs::helpwindowGlobs.font,&rect,0x400); globs::helpwindowGlobs.TextWindowBottom = rect.y + rect.height; globs::helpwindowGlobs.TextWindowPosition.x = rect.x; globs::helpwindowGlobs.TextWindowPosition.y = rect.y; io::Mem_Free(pcVar3); } pcVar3 = cfg::Config_BuildStringID(gameName,"HelpWindow","CanBuildMessage",0); globs::helpwindowGlobs.CanBuildMessage = cfg::Config_GetStringValue(config,pcVar3); if (globs::helpwindowGlobs.CanBuildMessage != NULL) { cVar2 = *globs::helpwindowGlobs.CanBuildMessage; pcVar3 = globs::helpwindowGlobs.CanBuildMessage; while (cVar2 != '\0') { if (cVar2 == '_') { *pcVar3 = ' '; } pcVar1 = pcVar3 + 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } } pcVar3 = cfg::Config_BuildStringID(gameName,"HelpWindow","CanTransportMessage",0); globs::helpwindowGlobs.CanTransportMessage = cfg::Config_GetStringValue(config,pcVar3); if (globs::helpwindowGlobs.CanTransportMessage != NULL) { cVar2 = *globs::helpwindowGlobs.CanTransportMessage; pcVar3 = globs::helpwindowGlobs.CanTransportMessage; while (cVar2 != '\0') { if (cVar2 == '_') { *pcVar3 = ' '; } pcVar1 = pcVar3 + 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } } pcVar3 = cfg::Config_BuildStringID(gameName,"HelpWindow","CanBuildAndTransportMessage",0); globs::helpwindowGlobs.CanBuildAndTransportMessage = cfg::Config_GetStringValue(config,pcVar3); if (globs::helpwindowGlobs.CanBuildAndTransportMessage != NULL) { cVar2 = *globs::helpwindowGlobs.CanBuildAndTransportMessage; pcVar3 = globs::helpwindowGlobs.CanBuildAndTransportMessage; while (cVar2 != '\0') { if (cVar2 == '_') { *pcVar3 = ' '; } pcVar1 = pcVar3 + 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } } // |= (HELPWINDOW_UNK_4|HELPWINDOW_UNK_2) (0x4 | 0x2) globs::helpwindowGlobs.flags = globs::helpwindowGlobs.flags & 0xffffff00 | globs::helpwindowGlobs.flags & 0xff | HELPWINDOW_GLOB_FLAG_UNK_4 | HELPWINDOW_GLOB_FLAG_UNK_2 ; HelpWindow_SetEnabled(FALSE,FALSE); return; } void __cdecl lego::front::HelpWindow_LoadLevelsInfo(Config *config,char *gameName) { char *pcVar1; char cVar2; char *pcVar3; uint id; uint lvl; char *(*papcVar4) [16]; char buff [1024]; id = 0; if (globs::legoGlobs.vehicleCount != 0) { papcVar4 = globs::helpwindowGlobs.VehicleInfos; do { lvl = 0; do { std::sprintf(buff,"HelpWindow::HelpWindowInfo::%sL%i",globs::legoGlobs.vehicleName[id],lvl); pcVar3 = cfg::Config_BuildStringID(gameName,buff,0); pcVar3 = cfg::Config_GetStringValue(config,pcVar3); (*papcVar4)[0] = pcVar3; // Underscores -> spaces if (pcVar3 != NULL) { cVar2 = *pcVar3; while (cVar2 != '\0') { if (cVar2 == '_') { *pcVar3 = ' '; } pcVar1 = pcVar3 + 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } } lvl += 1; papcVar4 = (char *(*) [16])(*papcVar4 + 1); } while (lvl < 0x10); id += 1; } while (id < globs::legoGlobs.vehicleCount); } id = 0; if (globs::legoGlobs.miniFigureCount != 0) { papcVar4 = globs::helpwindowGlobs.MiniFigureInfos; do { lvl = 0; do { std::sprintf(buff,"HelpWindow::HelpWindowInfo::%sL%i",globs::legoGlobs.miniFigureName[id], lvl); pcVar3 = cfg::Config_BuildStringID(gameName,buff,0); pcVar3 = cfg::Config_GetStringValue(config,pcVar3); (*papcVar4)[0] = pcVar3; // Underscores -> spaces if (pcVar3 != NULL) { cVar2 = *pcVar3; while (cVar2 != '\0') { if (cVar2 == '_') { *pcVar3 = ' '; } pcVar1 = pcVar3 + 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } } lvl += 1; papcVar4 = (char *(*) [16])(*papcVar4 + 1); } while (lvl < 0x10); id += 1; } while (id < globs::legoGlobs.miniFigureCount); } id = 0; if (globs::legoGlobs.buildingCount != 0) { papcVar4 = globs::helpwindowGlobs.BuildingInfos; do { lvl = 0; do { std::sprintf(buff,"HelpWindow::HelpWindowInfo::%sL%i",globs::legoGlobs.buildingName[id],lvl) ; pcVar3 = cfg::Config_BuildStringID(gameName,buff,0); pcVar3 = cfg::Config_GetStringValue(config,pcVar3); (*papcVar4)[0] = pcVar3; // Underscores -> spaces if (pcVar3 != NULL) { cVar2 = *pcVar3; while (cVar2 != '\0') { if (cVar2 == '_') { *pcVar3 = ' '; } pcVar1 = pcVar3 + 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } } lvl += 1; papcVar4 = (char *(*) [16])(*papcVar4 + 1); } while (lvl < 0x10); id += 1; } while (id < globs::legoGlobs.buildingCount); } return; } void __cdecl lego::front::HelpWindow_LoadButtons(Config *config,char *gameName) { char *pcVar1; int iVar2; char *stringParts [16]; pcVar1 = cfg::Config_BuildStringID(gameName,"HelpWindow","ContinueButton",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 != NULL) { util::Util_Tokenise(pcVar1,stringParts,","); iVar2 = std::atoi(stringParts[0]); globs::helpwindowGlobs.Buttons[0].window.x = (float)iVar2 + globs::helpwindowGlobs.BackgroundPosition.x; iVar2 = std::atoi(stringParts[1]); globs::helpwindowGlobs.Buttons[0].window.y = (float)iVar2 + globs::helpwindowGlobs.BackgroundPosition.y; iVar2 = std::atoi(stringParts[2]); globs::helpwindowGlobs.Buttons[0].window.width = (float)iVar2; iVar2 = std::atoi(stringParts[3]); globs::helpwindowGlobs.Buttons[0].window.height = (float)iVar2; globs::helpwindowGlobs.Buttons[0].HiImage = lego::image::Image_LoadBMPScaled(stringParts[4],0,0) ; globs::helpwindowGlobs.Buttons[0].LoImage = lego::image::Image_LoadBMPScaled(stringParts[5],0,0) ; globs::helpwindowGlobs.Buttons[0].Text = util::Util_RemoveUnderscores(stringParts[6]); ToolTip_SetContent(ToolTip_InfoMenuContinue,globs::helpwindowGlobs.Buttons[0].Text); } pcVar1 = cfg::Config_BuildStringID(gameName,"HelpWindow","CancelFutureButton",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 != NULL) { util::Util_Tokenise(pcVar1,stringParts,","); iVar2 = std::atoi(stringParts[0]); globs::helpwindowGlobs.Buttons[1].window.x = (float)iVar2 + globs::helpwindowGlobs.BackgroundPosition.x; iVar2 = std::atoi(stringParts[1]); globs::helpwindowGlobs.Buttons[1].window.y = (float)iVar2 + globs::helpwindowGlobs.BackgroundPosition.y; iVar2 = std::atoi(stringParts[2]); globs::helpwindowGlobs.Buttons[1].window.width = (float)iVar2; iVar2 = std::atoi(stringParts[3]); globs::helpwindowGlobs.Buttons[1].window.height = (float)iVar2; globs::helpwindowGlobs.Buttons[1].HiImage = lego::image::Image_LoadBMPScaled(stringParts[4],0,0) ; globs::helpwindowGlobs.Buttons[1].LoImage = lego::image::Image_LoadBMPScaled(stringParts[5],0,0) ; globs::helpwindowGlobs.Buttons[1].Text = util::Util_RemoveUnderscores(stringParts[6]); ToolTip_SetContent(ToolTip_InfoMenuDisableFuture,globs::helpwindowGlobs.Buttons[1].Text); } return; } void __cdecl lego::front::HelpWindow_IfFlag4_AndParam_Clear1_Set2_Else_Clear3(BOOL state) { if ((globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_4) != HELPWINDOW_GLOB_FLAG_NONE) { if (state != 0) { // &= ~HELPWINDOW_UNK_1; (~0x1) // |= HELPWINDOW_UNK_2; (0x2) globs::helpwindowGlobs.flags = globs::helpwindowGlobs.flags & 0xffffff00 | globs::helpwindowGlobs.flags & 0xfe | HELPWINDOW_GLOB_FLAG_UNK_2; return; } globs::helpwindowGlobs.flags &= ~(HELPWINDOW_GLOB_FLAG_UNK_1|HELPWINDOW_GLOB_FLAG_UNK_2); } return; } void __cdecl lego::front::HelpWindow_RecallDependencies (LegoObject_Type objType,LegoObject_ID objID,uint objLevel,BOOL noHelpWindow) { BOOL BVar1; game::Dependencies_Prepare_Unk(); BVar1 = game::Dependencies_Object_GetLevelFlag_100(objType,objID,objLevel); if (BVar1 == 0) { game::Dependencies_Object_AddLevelFlag_100(objType,objID,objLevel); if (noHelpWindow == 0) { globs::helpwindowGlobs.activeObjType = objType; globs::helpwindowGlobs.activeObjID = objID; globs::helpwindowGlobs.activeObjLevel = objLevel; if (objType == LegoObject_Vehicle) { globs::helpwindowGlobs.activeObjName = globs::helpwindowGlobs.VehicleInfos[objID][objLevel]; } else { if (objType == LegoObject_MiniFigure) { globs::helpwindowGlobs.activeObjName = globs::helpwindowGlobs.MiniFigureInfos[objID][objLevel]; } else { if (objType == LegoObject_Building) { globs::helpwindowGlobs.activeObjName = globs::helpwindowGlobs.BuildingInfos[objID][objLevel]; } } } TextWindow_Clear(globs::helpwindowGlobs.textWnd); globs::helpwindowGlobs.flags |= HELPWINDOW_GLOB_FLAG_UNK_8; HelpWindow_Object_Unlock(objType,objID,objLevel); globs::helpwindowGlobs.flags |= HELPWINDOW_GLOB_FLAG_UNK_1; globs::helpwindowGlobs.float_d58 = 0.0; globs::helpwindowGlobs.float_d5c = 0.0; } } return; } void __cdecl lego::front::HelpWindow_Object_Unlock(LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { LegoObject_ID LVar1; LegoObject_ID LVar2; BOOL BVar3; LegoObject_ID *pUnlock; uint i; DependencyUnlocks unlocks; i = 0; globs::helpwindowGlobs.unlockedCount = 0; game::Dependencies_Object_Unlock(objType,objID,objLevel,&unlocks); if (unlocks.count != 0) { pUnlock = unlocks.objIDs; do { BVar3 = game::Dependencies_Object_IsLevelFlag4(pUnlock[-0x20],*pUnlock,pUnlock[0x20]); if (BVar3 != 0) { LVar1 = *pUnlock; globs::helpwindowGlobs.unlockedObjTypes[globs::helpwindowGlobs.unlockedCount] = pUnlock[-0x20]; LVar2 = pUnlock[0x20]; globs::helpwindowGlobs.unlockedObjIndexes[globs::helpwindowGlobs.unlockedCount] = LVar1; globs::helpwindowGlobs.unlockedObjLevels[globs::helpwindowGlobs.unlockedCount] = LVar2; globs::helpwindowGlobs.unlockedCount += 1; } i += 1; pUnlock = pUnlock + 1; } while (i < unlocks.count); } return; } void __cdecl lego::front::HelpWindow_Close_FUN_00418900(void) { if (((globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_2) != HELPWINDOW_GLOB_FLAG_NONE) && ((globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_1) != HELPWINDOW_GLOB_FLAG_NONE)) { lrr::Lego_SetPaused(FALSE,FALSE); lrr::Lego_SetMenuNextPosition(NULL); globs::helpwindowGlobs.flags &= ~HELPWINDOW_GLOB_FLAG_UNK_1; } return; } void __cdecl lego::front::HelpWindow_FUN_00418930(void) { BOOL BVar1; TutorialFlags TVar2; Image *image; char *pcVar3; LegoObject_Type *pLVar4; uint uVar5; int iVar6; int iVar7; float10 fVar8; longlong lVar9; char *format; undefined8 uVar10; float local_14; Point2F local_10; Point2F local_8; BVar1 = HelpWindow_IsEnabled(); if (BVar1 == 0) { HelpWindow_Close_FUN_00418900(); } BVar1 = HelpWindow_IsEnabled(); if (BVar1 == 0) { return; } if ((globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_2) == HELPWINDOW_GLOB_FLAG_NONE) { return; } if ((globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_1) == HELPWINDOW_GLOB_FLAG_NONE) { return; } TVar2 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((TVar2 & TUTORIAL_FLAG_NOHELPWINDOW) != TUTORIAL_NONE) { return; } lrr::Lego_SetPaused(0,TRUE); if ((globs::helpwindowGlobs.activeObjName == NULL) && (globs::helpwindowGlobs.unlockedCount == 0)) { HelpWindow_Close_FUN_00418900(); return; } if (globs::helpwindowGlobs.BackgroundImage != NULL) { lego::image::Image_DisplayScaled (globs::helpwindowGlobs.BackgroundImage,NULL, &globs::helpwindowGlobs.BackgroundPosition,NULL); } if ((globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_8) != HELPWINDOW_GLOB_FLAG_NONE) { if (globs::helpwindowGlobs.activeObjName != NULL) { TextWindow_PrintF(globs::helpwindowGlobs.textWnd,"%s",globs::helpwindowGlobs.activeObjName); } globs::helpwindowGlobs.flags &= ~HELPWINDOW_GLOB_FLAG_UNK_8; } if (globs::helpwindowGlobs.activeObjName == NULL) { lVar9 = __ftol((float10)globs::helpwindowGlobs.TextWindowPosition.y); local_14 = (float)lVar9; } else { TextWindow_Update(globs::helpwindowGlobs.textWnd,0,0.0,(int *)&local_14); } if (globs::helpwindowGlobs.unlockedCount == 0) goto LAB_00418cb8; local_8.x = local_14; local_8.y = 0.0; iVar7 = 0; iVar6 = 0; local_10.y = (float)(ulonglong)(uint)local_14 - -10.0; local_10.x = globs::helpwindowGlobs.TextWindowPosition.x; if (globs::helpwindowGlobs.unlockedCount != 0) { pLVar4 = globs::helpwindowGlobs.unlockedObjTypes; uVar5 = globs::helpwindowGlobs.unlockedCount; do { if (*pLVar4 == LegoObject_Vehicle) { iVar6 += 1; } else { if (*pLVar4 == LegoObject_Building) { iVar7 += 1; } } pLVar4 = pLVar4 + 1; uVar5 -= 1; } while (uVar5 != 0); } if (iVar6 == 0) { if (globs::helpwindowGlobs.CanBuildMessage != NULL) { uVar10 = CONCAT44(globs::helpwindowGlobs.CanBuildMessage,0x4a2d60); lVar9 = __ftol((float10)local_10.y); iVar6 = (int)lVar9; lVar9 = __ftol((float10)local_10.x); iVar7 = (int)lVar9; goto override_prt_418b00_2c9bc250; } } else { if (iVar7 == 0) { if (globs::helpwindowGlobs.CanTransportMessage != NULL) { uVar10 = CONCAT44(globs::helpwindowGlobs.CanTransportMessage,0x4a2d60); lVar9 = __ftol((float10)local_10.y); iVar6 = (int)lVar9; lVar9 = __ftol((float10)local_10.x); iVar7 = (int)lVar9; override_prt_418b00_2c9bc250: lego::image::Font_PrintF (globs::helpwindowGlobs.font,iVar7,iVar6,(char *)uVar10, (char *)((ulonglong)uVar10 >> 0x20)); } } else { if (globs::helpwindowGlobs.CanBuildAndTransportMessage != NULL) { uVar10 = CONCAT44(globs::helpwindowGlobs.CanBuildAndTransportMessage,0x4a2d60); lVar9 = __ftol((float10)local_10.y); iVar6 = (int)lVar9; lVar9 = __ftol((float10)local_10.x); iVar7 = (int)lVar9; goto override_prt_418b00_2c9bc250; } } } uVar5 = lego::image::Font_GetHeight(globs::helpwindowGlobs.font); local_8.x = (float)(uVar5 + 10); local_8.y = 0.0; local_10.y = (float)(ulonglong)(uint)local_8.x + local_10.y; fVar8 = std::floor((double)globs::helpwindowGlobs.float_d58); local_10.y = (float)((float10)local_10.y - ((float10)globs::helpwindowGlobs.float_d58 - fVar8) * (float10)45.0); fVar8 = std::floor((double)globs::helpwindowGlobs.float_d58); lVar9 = __ftol(fVar8); uVar5 = (uint)lVar9; if (uVar5 < globs::helpwindowGlobs.unlockedCount) { pLVar4 = globs::helpwindowGlobs.unlockedObjTypes + uVar5; do { local_10.x = globs::helpwindowGlobs.TextWindowPosition.x; image = Interface_GetObjectBuildImage(*pLVar4,pLVar4[0x1e],TRUE); if (image != NULL) { if (globs::helpwindowGlobs.TextWindowBottom <= (float)image->height + local_10.y) { if (globs::helpwindowGlobs.float_d5c == 0.0) { local_8.y = 0.0; local_8.x = (float)((globs::helpwindowGlobs.unlockedCount - uVar5) - 1); globs::helpwindowGlobs.float_d5c = (float)(ulonglong)(uint)local_8.x; } if (globs::helpwindowGlobs.float_d58 < globs::helpwindowGlobs.float_d5c) { local_8.x = 345.0; local_8.y = 350.0; lrr::Lego_SetMenuNextPosition(&local_8); } break; } lego::image::Image_DisplayScaled(image,NULL,&local_10,NULL); } local_10.x = local_10.x - -50.0; local_10.y = local_10.y - -10.0; pcVar3 = game::Object_GetLangTheName(*pLVar4,pLVar4[0x1e]); format = "%s"; lVar9 = __ftol((float10)local_10.y); iVar6 = (int)lVar9; lVar9 = __ftol((float10)local_10.x); lego::image::Font_PrintF(globs::helpwindowGlobs.font,(int)lVar9,iVar6,format,pcVar3); local_10.y = local_10.y - -35.0; uVar5 += 1; pLVar4 = pLVar4 + 1; if (globs::helpwindowGlobs.unlockedCount <= uVar5) { HelpWindow_DrawButtons(); return; } } while( true ); } LAB_00418cb8: HelpWindow_DrawButtons(); return; } BOOL __cdecl lego::front::HelpWindow_FUN_00418cd0 (uint mouseX,uint mouseY,BOOL leftButton,BOOL leftLast,BOOL leftReleased,float elapsed) { float fVar1; float fVar2; float fVar3; BOOL BVar4; MenuButton *pMVar5; uint uVar6; if (((globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_2) != HELPWINDOW_GLOB_FLAG_NONE) && ((globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_1) != HELPWINDOW_GLOB_FLAG_NONE)) { globs::helpwindowGlobs.flags &= ~(HELPWINDOW_GLOB_FLAG_UNK_10|HELPWINDOW_GLOB_FLAG_UNK_20); fVar3 = (float)(ulonglong)mouseX; if ((345.0 <= fVar3) && ((((fVar1 = (float)(globs::legoGlobs.NextButtonImage)->width - -345.0, (ushort)((ushort)(fVar3 < fVar1) << 8 | (ushort)(fVar3 == fVar1) << 0xe) != 0 && (fVar1 = (float)(ulonglong)mouseY, 350.0 <= fVar1)) && (fVar2 = (float)(globs::legoGlobs.NextButtonImage)->height - -350.0, (ushort)((ushort)(fVar1 < fVar2) << 8 | (ushort)(fVar1 == fVar2) << 0xe) != 0)) && (ToolTip_Activate(ToolTip_More), leftReleased != 0)))) { HelpWindow_FUN_00418f60(3,5.0); lrr::Lego_SetPointerSFX(PointerSFX_Okay); } uVar6 = 0; pMVar5 = globs::helpwindowGlobs.Buttons; do { fVar1 = (pMVar5->window).x; fVar2 = (pMVar5->window).y; if (((fVar1 <= fVar3) && (fVar1 = fVar1 + (pMVar5->window).width, (ushort)((ushort)(fVar3 < fVar1) << 8 | (ushort)(fVar3 == fVar1) << 0xe) != 0)) && ((fVar1 = (float)(ulonglong)mouseY, fVar2 <= fVar1 && (fVar2 = fVar2 + (pMVar5->window).height, (ushort)((ushort)(fVar1 < fVar2) << 8 | (ushort)(fVar1 == fVar2) << 0xe) != 0)))) { globs::helpwindowGlobs.flags |= HELPWINDOW_GLOB_FLAG_UNK_10; globs::helpwindowGlobs.count_d60 = uVar6; BVar4 = HelpWindow_FUN_00418ef0(uVar6,leftButton,leftLast); if ((BVar4 != 0) && (leftReleased != 0)) { HelpWindow_FUN_00418f60(uVar6,elapsed); lrr::Lego_SetPointerSFX(PointerSFX_Okay); } if ((leftButton == 0) && (leftReleased == 0)) { HelpWindow_ToolTip_FUN_00418eb0(uVar6); } return TRUE; } pMVar5 = pMVar5 + 1; uVar6 += 1; } while (pMVar5 < globs::helpwindowGlobs.Buttons + 2); HelpWindow_FUN_00418ef0(4,leftButton,leftLast); } return 0; } void __cdecl lego::front::HelpWindow_ToolTip_FUN_00418eb0(int param_1) { if (true) { switch(param_1) { case 0: ToolTip_Activate(ToolTip_InfoMenuContinue); return; case 1: ToolTip_Activate(ToolTip_InfoMenuDisableFuture); } } return; } BOOL __cdecl lego::front::HelpWindow_FUN_00418ef0(int param_1,int param_2,int param_3) { int iVar1; iVar1 = globs::helpwindowGlobs.field_d64; if (param_2 == 0) { globs::helpwindowGlobs.field_d64 = 4; } else { if (globs::helpwindowGlobs.field_d64 == 4) { if (param_3 == 0) { globs::helpwindowGlobs.field_d64 = param_1; globs::helpwindowGlobs.flags = globs::helpwindowGlobs.flags | HELPWINDOW_GLOB_FLAG_UNK_20; return (uint)(param_1 == 4); } } else { if (globs::helpwindowGlobs.field_d64 == param_1) { globs::helpwindowGlobs.flags = globs::helpwindowGlobs.flags | HELPWINDOW_GLOB_FLAG_UNK_20; return (uint)(globs::helpwindowGlobs.field_d64 == param_1); } } } return (uint)(iVar1 == param_1); } void __cdecl lego::front::HelpWindow_FUN_00418f60(undefined4 param_1,float elapsed) { switch(param_1) { case 0: HelpWindow_Close_FUN_00418900(); return; case 1: HelpWindow_SetEnabled(1,0); HelpWindow_Close_FUN_00418900(); return; case 2: if (((ushort)((ushort)(globs::helpwindowGlobs.float_d58 < 0.0) << 8 | (ushort)(globs::helpwindowGlobs.float_d58 == 0.0) << 0xe) == 0) && (globs::helpwindowGlobs.float_d58 = globs::helpwindowGlobs.float_d58 - elapsed * 0.2, globs::helpwindowGlobs.float_d58 < 0.0)) { globs::helpwindowGlobs.float_d58 = 0.0; return; } break; case 3: if ((globs::helpwindowGlobs.float_d58 < globs::helpwindowGlobs.float_d5c) && (globs::helpwindowGlobs.float_d58 = globs::helpwindowGlobs.float_d58 - elapsed * -0.2, globs::helpwindowGlobs.float_d5c <= globs::helpwindowGlobs.float_d58)) { globs::helpwindowGlobs.float_d58 = globs::helpwindowGlobs.float_d5c; lrr::Lego_SetMenuNextPosition(NULL); } } return; } void __cdecl lego::front::HelpWindow_DrawButtons(void) { Image *image; float *pfVar1; int buttonIndex; Point2F position; buttonIndex = 0; pfVar1 = &globs::helpwindowGlobs.Buttons[0].window.y; do { position.x = pfVar1[-1]; position.y = *pfVar1; image = HelpWindow_GetButtonImage(buttonIndex); if (image != NULL) { lego::image::Image_DisplayScaled(image,NULL,&position,NULL); } pfVar1 = pfVar1 + 7; buttonIndex += 1; } while (pfVar1 < &globs::helpwindowGlobs.Buttons[2].window.y); return; } Image * __cdecl lego::front::HelpWindow_GetButtonImage(int buttonIndex) { if ((buttonIndex == 1) && (((byte)globs::helpwindowGlobs.flags & 4) == 0)) { return globs::helpwindowGlobs.Buttons[1].LoImage; } if ((((byte)globs::helpwindowGlobs.flags & 0x10) != 0) && (globs::helpwindowGlobs.count_d60 == buttonIndex)) { if (((byte)globs::helpwindowGlobs.flags & 0x20) != 0) { return globs::helpwindowGlobs.Buttons[buttonIndex].LoImage; } return globs::helpwindowGlobs.Buttons[buttonIndex].HiImage; } return NULL; } BOOL __cdecl lego::front::HelpWindow_IsEnabled_AndFlags_3_AndNoTutorialFlags(void) { BOOL BVar1; HelpWindow_GlobFlags HVar2; TutorialFlags TVar3; HelpWindow_GlobFlags HVar4; BVar1 = HelpWindow_IsEnabled(); HVar2 = globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_1; HVar4 = globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_UNK_2; TVar3 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((((BVar1 != 0) && (HVar4 != HELPWINDOW_GLOB_FLAG_NONE)) && (HVar2 != HELPWINDOW_GLOB_FLAG_NONE)) && (TVar3 == TUTORIAL_NONE)) { return TRUE; } return 0; } BOOL __cdecl lego::front::HelpWindow_IsEnabled(void) { return globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_ENABLED; } void __cdecl lego::front::HelpWindow_SetEnabled(BOOL toggle,BOOL enable) { if (toggle != 0) { enable = globs::helpwindowGlobs.flags & HELPWINDOW_GLOB_FLAG_ENABLED; } if (enable == HELPWINDOW_GLOB_FLAG_NONE) { globs::helpwindowGlobs.flags = globs::helpwindowGlobs.flags | HELPWINDOW_GLOB_FLAG_ENABLED; return; } globs::helpwindowGlobs.flags = globs::helpwindowGlobs.flags & ~HELPWINDOW_GLOB_FLAG_ENABLED; return; } void __cdecl lego::front::Info_Initialise(Font *font) { globs::infoGlobs.infoName[0] = "Info_CrystalFound"; globs::infoGlobs.infoName[1] = "Info_OreSeamFound"; globs::infoGlobs.infoName[2] = "Info_RockMonster"; globs::infoGlobs.infoName[3] = "Info_LavaRockMonster"; globs::infoGlobs.infoName[4] = "Info_IceRockMonster"; globs::infoGlobs.infoName[5] = "Info_UnderAttack"; globs::infoGlobs.infoName[6] = "Info_Landslide"; globs::infoGlobs.infoName[7] = "Info_CaveIn"; globs::infoGlobs.infoName[8] = "Info_Constructed"; globs::infoGlobs.infoName[9] = "Info_CavernLocated"; globs::infoGlobs.infoName[10] = "Info_LegoManDeath"; globs::infoGlobs.infoName[11] = "Info_VehicleDeath"; globs::infoGlobs.infoName[12] = "Info_BuildingDeath"; globs::infoGlobs.infoName[13] = "Info_DynamitePlaced"; globs::infoGlobs.infoName[14] = "Info_NoPower"; globs::infoGlobs.infoName[15] = "Info_PowerDrain"; globs::infoGlobs.infoName[16] = "Info_AirDepleting"; globs::infoGlobs.infoName[17] = "Info_AirLow"; globs::infoGlobs.infoName[18] = "Info_AirOut"; globs::infoGlobs.infoName[19] = "Info_AirRestored"; globs::infoGlobs.infoName[20] = "Info_TrainDriver"; globs::infoGlobs.infoName[21] = "Info_TrainDynamite"; globs::infoGlobs.infoName[22] = "Info_TrainRepair"; globs::infoGlobs.infoName[23] = "Info_TrainPilot"; globs::infoGlobs.infoName[24] = "Info_TrainSailor"; globs::infoGlobs.infoName[25] = "Info_TrainScanner"; globs::infoGlobs.infoName[26] = "Info_OreCollected"; globs::infoGlobs.infoName[27] = "Info_WallDug"; globs::infoGlobs.infoName[28] = "Info_WallReinforced"; globs::infoGlobs.infoName[29] = "Info_CrystalPower"; globs::infoGlobs.infoName[30] = "Info_LavaErode"; globs::infoGlobs.infoName[31] = "Info_SlugEmerge"; globs::infoGlobs.infoName[32] = "Info_PathCompleted"; globs::infoGlobs.infoName[33] = "Info_FoundMinifigure"; globs::infoGlobs.infoName[34] = "Info_CanUpgradeMinifigure"; globs::infoGlobs.infoName[35] = "Info_CanTrainMinifigure"; globs::infoGlobs.infoName[36] = "Info_CrystalSeamFound"; globs::infoGlobs.infoName[37] = "Info_GenericSeamFound"; globs::infoGlobs.infoName[38] = "Info_GenericDeath"; globs::infoGlobs.infoName[39] = "Info_GenericMonster"; globs::infoGlobs.font = font; globs::infoGlobs.flags = globs::infoGlobs.flags | (INFO_GLOB_FLAG_UNK_8|INFO_GLOB_FLAG_AUTOGAMESPEED); return; } BOOL __cdecl lego::front::Info_GetInfoType(char *infoName,Info_Type *out_infoType) { int cmp; char **pInfoName; Info_Type i; i = Info_CrystalFound; pInfoName = (char **)&globs::infoGlobs; do { cmp = std::_stricmp(*pInfoName,infoName); if (cmp == 0) { *out_infoType = i; return TRUE; } pInfoName = (char **)((int)pInfoName + 4); i += Info_OreSeamFound; } while (pInfoName < globs::infoGlobs.infoDataTable); return 0; } void * __cdecl lego::front::Info_GetTypePtr4(Info_Type infoType) { return globs::infoGlobs.infoDataTable[infoType].ptr_4; } void __cdecl lego::front::Info_SetOverFlowImageFile(char *filename) { globs::infoGlobs.OverFlowImage = lego::image::Image_LoadBMPScaled(filename,0,0); lego::image::Image_SetPenZeroTrans(globs::infoGlobs.OverFlowImage); return; } void __cdecl lego::front::Info_SetAutoGameSpeed(BOOL autoOn) { if (autoOn != 0) { globs::infoGlobs.flags = globs::infoGlobs.flags | INFO_GLOB_FLAG_AUTOGAMESPEED; return; } globs::infoGlobs.flags = globs::infoGlobs.flags & ~INFO_GLOB_FLAG_AUTOGAMESPEED; return; } void __cdecl lego::front::Info_SetTypeChangeGameSpeed(Info_Type infoType,BOOL changeSpeedOn) { InfoDataFlags IVar1; IVar1 = globs::infoGlobs.infoDataTable[infoType].flags; if (changeSpeedOn != 0) { globs::infoGlobs.infoDataTable[infoType].flags = IVar1 | INFOTYPE_FLAG_CHANGEGAMESPEED; return; } globs::infoGlobs.infoDataTable[infoType].flags = IVar1 & ~INFOTYPE_FLAG_CHANGEGAMESPEED; return; } void __cdecl lego::front::Info_SetTypeText(Info_Type infoType,char *text) { char *buffer; buffer = globs::infoGlobs.infoDataTable[infoType].text; if (buffer != NULL) { io::Mem_Free(buffer); } Info_SetText_internal(text,&globs::infoGlobs.infoDataTable[infoType].text); return; } void __cdecl lego::front::Info_SetTypeFlag_20000(Info_Type infoType,BOOL setFlag20000) { InfoDataFlags IVar1; IVar1 = globs::infoGlobs.infoDataTable[infoType].flags; if (setFlag20000 != 0) { globs::infoGlobs.infoDataTable[infoType].flags = IVar1 | INFOTYPE_FLAG_UNK_20000; return; } globs::infoGlobs.infoDataTable[infoType].flags = IVar1 & ~INFOTYPE_FLAG_UNK_20000; return; } void __cdecl lego::front::Info_SetText_internal(char *text,char **pInfoText) { char *pcVar1; char cVar2; char *pcVar3; BOOL BVar4; uint uVar5; int iVar6; Image *pIVar7; char *pcVar8; char *pcVar9; uint local_30; Info_Type local_2c; char acStack40 [8]; char local_20 [32]; pcVar9 = text; uVar5 = 0xffffffff; local_30 = 0; pcVar3 = text; do { if (uVar5 == 0) break; uVar5 -= 1; cVar2 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar2 != '\0'); pcVar3 = (char *)io::Mem_Alloc(~uVar5 + 0xb); *pInfoText = pcVar3; cVar2 = *pcVar9; while (cVar2 != '\0') { cVar2 = *pcVar9; if (cVar2 == '_') { *pcVar3 = ' '; } else { if (cVar2 == '$') { pcVar8 = pcVar9 + 1; iVar6 = 0; pIVar7 = NULL; cVar2 = pcVar9[1]; pcVar9 = pcVar8; while (cVar2 != '$') { local_20[iVar6] = cVar2; pcVar1 = pcVar8 + 1; iVar6 += 1; pcVar8 = pcVar8 + 1; pcVar9 = pcVar9 + 1; cVar2 = *pcVar1; } local_20[iVar6] = '\0'; BVar4 = Pointer_GetType(local_20,(Pointer_Type *)&text); if (BVar4 == 0) { BVar4 = Info_GetInfoType(local_20,&local_2c); if (BVar4 != 0) { pIVar7 = (Image *)Info_GetTypePtr4(local_2c); } } else { pIVar7 = Pointer_GetImage((Pointer_Type)text); } if (pIVar7 != NULL) { *pcVar3 = '%'; pcVar3 = pcVar3 + 1; acStack40[local_30] = (char)pIVar7; local_30 += 1; *pcVar3 = 'b'; } } else { if ((cVar2 == '\\') && (pcVar9[1] == 'n')) { *pcVar3 = '\n'; pcVar9 = pcVar9 + 1; } else { *pcVar3 = cVar2; } } } pcVar8 = pcVar9 + 1; pcVar3 = pcVar3 + 1; pcVar9 = pcVar9 + 1; cVar2 = *pcVar8; } *pcVar3 = '\0'; pcVar3 = pcVar3 + 1; uVar5 = 0; *pcVar3 = (char)local_30; do { pcVar3 = pcVar3 + 1; if (uVar5 < local_30) { *pcVar3 = acStack40[uVar5]; } else { *pcVar3 = '\0'; } uVar5 += 1; } while (uVar5 < 5); return; } void __cdecl lego::front::Info_SetTypeImageFile(Info_Type infoType,char *filename) { Image *image; image = lego::image::Image_LoadBMPScaled(filename,0,0); globs::infoGlobs.infoDataTable[infoType].ptr_4 = image; lego::image::Image_SetPenZeroTrans(image); return; } void __cdecl lego::front::Info_SetTypeSFX(Info_Type infoType,SFX_ID sfxID) { globs::infoGlobs.infoDataTable[infoType].sfxType = sfxID; return; } BOOL __cdecl lego::front::Info_EnumerateMessageInstances(int handle,InfoEnumerateCallback callback,void *data) { BOOL stop; InfoMessageInstance *instance; instance = globs::infoGlobs.infoMessageTable[handle].instance; if (instance == NULL) { return 0; } do { stop = (*callback)(instance,data); if (stop != 0) { return TRUE; } instance = instance->next; } while (instance != NULL); return 0; } void __cdecl lego::front::Info_AddMessageInstance(int handle,InfoMessageInstance *instance) { InfoMessageInstance *pIVar1; InfoMessageInstance *pIVar2; int iVar3; pIVar1 = globs::infoGlobs.infoMessageTable[handle].instance; if (pIVar1 == NULL) { globs::infoGlobs.infoMessageTable[handle].instance = instance; instance->next = NULL; globs::infoGlobs.infoMessageTable[handle].instanceCount = globs::infoGlobs.infoMessageTable[handle].instanceCount + 1; return; } iVar3 = 1; pIVar2 = pIVar1->next; while (pIVar2 != NULL) { iVar3 += 1; if (iVar3 == 9) { // Maximum of 9 instances for a single type, pop the oldest one. Info_RemoveMessageInstance(handle,0); } pIVar1 = pIVar1->next; pIVar2 = pIVar1->next; } pIVar1->next = instance; instance->next = NULL; globs::infoGlobs.infoMessageTable[handle].instanceCount = globs::infoGlobs.infoMessageTable[handle].instanceCount + 1; return; } InfoMessageInstance * __cdecl lego::front::Info_GetMessageInstance(int handle,int instanceIndex) { InfoMessageInstance *instance; instance = globs::infoGlobs.infoMessageTable[handle].instance; if ((instanceIndex < 0) || ((int)globs::infoGlobs.infoMessageTable[handle].instanceCount <= instanceIndex)) { instance = NULL; } else { if (0 < instanceIndex) { do { instance = instance->next; instanceIndex += -1; } while (instanceIndex != 0); return instance; } } return instance; } InfoMessageInstance * __cdecl lego::front::Info_RemoveMessageInstance(int handle,int instanceIndex) { InfoMessageInstance *instance; InfoMessageInstance *prevInstance; instance = Info_GetMessageInstance(handle,instanceIndex); if (instance == NULL) { return NULL; } prevInstance = Info_GetMessageInstance(handle,instanceIndex + -1); if (instanceIndex == 0) { globs::infoGlobs.infoMessageTable[handle].instance = instance->next; } else { prevInstance->next = instance->next; } globs::infoGlobs.infoMessageTable[handle].instanceCount = globs::infoGlobs.infoMessageTable[handle].instanceCount - 1; return instance; } // Finds the index of the InfoMessageInstance that references the specified object. BOOL __cdecl lego::front::Info_Callback_FindObjectReference (InfoMessageInstance *instance,SearchInfoObject_8 *search) { if (instance->object == search->object) { return TRUE; } search->index = search->index + 1; return FALSE; } // Removes all info messages referencing the specified object. void __cdecl lego::front::Info_RemoveObjectReferences(LegoObject *liveObj) { int found; uint handle; uint handleNext; uint *pMessageInstanceCount; SearchInfoObject_8 search; search.object = liveObj; handle = 0; if (globs::infoGlobs.infoMessageCount != 0) { pMessageInstanceCount = &globs::infoGlobs.infoMessageTable[0].instanceCount; do { // Repeatedly search for all info message instances that reference this object until // none are left. search.index = 0; found = Info_EnumerateMessageInstances(handle,Info_Callback_FindObjectReference,&search); while (found != 0) { Info_RemoveMessageInstance(handle,search.index); search.index = 0; found = Info_EnumerateMessageInstances(handle,Info_Callback_FindObjectReference,&search); } handleNext = handle; if (*pMessageInstanceCount == 0) { handleNext = handle - 1; pMessageInstanceCount = pMessageInstanceCount + -5; Info_RemoveMessage(handle); } handle = handleNext + 1; pMessageInstanceCount = pMessageInstanceCount + 5; } while (handle < globs::infoGlobs.infoMessageCount); } return; } BOOL __cdecl lego::front::Info_Callback_FindBlockPos (InfoMessageInstance *infoInstance,SearchInfoBlockPos_8 *search) { if (((infoInstance->blockPos).x == search->pBlockPos->x) && ((infoInstance->blockPos).y == search->pBlockPos->y)) { return TRUE; } search->index = search->index + 1; return 0; } void __cdecl lego::front::Info_RemoveAllAtBlockPos(Point2I *blockPos) { int iVar1; uint *pCount; uint handle; uint uVar2; Info_Type *pInfoType; SearchInfoBlockPos_8 search; search.pBlockPos = blockPos; handle = 0; if (globs::infoGlobs.infoMessageCount != 0) { pCount = &globs::infoGlobs.infoMessageTable[0].instanceCount; pInfoType = &globs::infoGlobs.infoMessageTable[0].infoType; do { uVar2 = handle; if ((*pInfoType == Info_Landslide) || (*pInfoType == Info_CaveIn)) { search.index = 0; iVar1 = Info_EnumerateMessageInstances(handle,Info_Callback_FindBlockPos,&search); while (iVar1 != 0) { Info_RemoveMessageInstance(handle,search.index); search.index = 0; iVar1 = Info_EnumerateMessageInstances(handle,Info_Callback_FindBlockPos,&search); } if (*pCount == 0) { uVar2 = handle - 1; pInfoType = pInfoType + -5; pCount = pCount + -5; Info_RemoveMessage(handle); } } handle = uVar2 + 1; pInfoType = pInfoType + 5; pCount = pCount + 5; } while (handle < globs::infoGlobs.infoMessageCount); } return; } BOOL __cdecl lego::front::Info_Callback_FindObjectAndBlockPos (InfoMessageInstance *instance,SearchInfoObjectBlockPos_8 *search) { Point2I *searchBlockPos; LegoObject *searchObj; searchObj = search->optObject; if ((((searchObj != NULL) || (search->optBlockPos != NULL)) && ((searchObj == NULL || (instance->object != searchObj)))) && (((searchBlockPos = search->optBlockPos, searchBlockPos == NULL || ((instance->blockPos).x != searchBlockPos->x)) || ((instance->blockPos).y != searchBlockPos->y)))) { return FALSE; } return TRUE; } BOOL __cdecl lego::front::Info_HasTypeAtObjectOrBlockPos (Info_Type infoType,LegoObject *opt_liveObj,Point2I *opt_blockPos) { BOOL found; uint handle; Info_Type *pInfoType; SearchInfoObjectBlockPos_8 search; if ((((infoType != Info_LegoManDeath) && (infoType != Info_BuildingDeath)) && (infoType != Info_VehicleDeath)) && (infoType != Info_GenericDeath)) { search.optBlockPos = opt_blockPos; handle = 0; search.optObject = opt_liveObj; if (globs::infoGlobs.infoMessageCount != 0) { pInfoType = &globs::infoGlobs.infoMessageTable[0].infoType; do { if (infoType == *pInfoType) { found = Info_EnumerateMessageInstances(handle,Info_Callback_FindObjectAndBlockPos,&search) ; if (found != 0) { return TRUE; } } handle += 1; pInfoType = pInfoType + 5; } while (handle < globs::infoGlobs.infoMessageCount); return 0; } } return 0; } InfoMessageInstance * __cdecl lego::front::Info_CreateInstance(Point2I *opt_blockPos,LegoObject *opt_liveObj,char *opt_text) { InfoMessageInstance *instance; instance = (InfoMessageInstance *)io::Mem_Alloc(0x14); if (instance == NULL) { return NULL; } if (opt_blockPos == NULL) { (instance->blockPos).y = -1; (instance->blockPos).x = -1; } else { (instance->blockPos).x = opt_blockPos->x; (instance->blockPos).y = opt_blockPos->y; } instance->object = opt_liveObj; if (opt_text != NULL) { Info_SetText_internal(opt_text,&instance->text); return instance; } instance->text = NULL; return instance; } void __cdecl lego::front::Info_SetFlag4(BOOL state) { if (state != 0) { globs::infoGlobs.flags = globs::infoGlobs.flags | INFO_GLOB_FLAG_UNK_4; return; } globs::infoGlobs.flags = globs::infoGlobs.flags & ~INFO_GLOB_FLAG_UNK_4; return; } BOOL __cdecl lego::front::Info_HasTypeText(Info_Type infoType) { return (uint)(globs::infoGlobs.infoDataTable[infoType].text != NULL); } int __cdecl lego::front::Info_FindExistingMessageType(Info_Type infoType) { int i; Info_Type *pMsgInfoType; i = 0; if (0 < (int)globs::infoGlobs.infoMessageCount) { pMsgInfoType = &globs::infoGlobs.infoMessageTable[0].infoType; do { if (*pMsgInfoType == infoType) { return i; } i += 1; pMsgInfoType = pMsgInfoType + 5; } while (i < (int)globs::infoGlobs.infoMessageCount); } return -1; } float10 __cdecl lego::front::Info_FUN_00419a80(void) { Info_Type IVar1; Info_Type *pInfoType; uint count; float10 fVar2; fVar2 = (float10)333.0; if (globs::infoGlobs.infoMessageCount != 0) { pInfoType = &globs::infoGlobs.infoMessageTable[0].infoType; count = globs::infoGlobs.infoMessageCount; do { IVar1 = *pInfoType; pInfoType = pInfoType + 5; count -= 1; fVar2 = fVar2 - (float10)*(int *)((int)globs::infoGlobs.infoDataTable[IVar1].ptr_4 + 8); } while (count != 0); } return fVar2; } void __cdecl lego::front::Info_Send (Info_Type infoType,char *opt_text,LegoObject *opt_liveObj,Point2I *opt_blockPos) { float fVar1; void *pvVar2; InfoMessage *pIVar3; uint uVar4; TutorialFlags tutFlags; BOOL BVar5; uint handle; InfoMessageInstance *instance; ProgrammerMode progMode; float10 fVar6; if (((byte)globs::infoGlobs.flags & INFO_GLOB_FLAG_UNK_4) != 0) { tutFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((tutFlags & TUTORIAL_FLAG_NOINFO) == TUTORIAL_NONE) { if (((((byte)globs::infoGlobs.flags & INFO_GLOB_FLAG_UNK_8) != 0) && ((globs::infoGlobs.infoDataTable[infoType].flags & INFOTYPE_FLAG_UNK_20000) != INFOTYPE_FLAG_NONE)) && (fVar1 = globs::infoGlobs.infoDataTable[infoType].float_c, (ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) != 0)) { globs::infoGlobs.infoDataTable[infoType].float_c = 25.0; if (((infoType == Info_LegoManDeath) || (infoType == Info_VehicleDeath)) || (infoType == Info_BuildingDeath)) { globs::infoGlobs.infoDataTable[10].float_c = 25.0; globs::infoGlobs.infoDataTable[11].float_c = 25.0; globs::infoGlobs.infoDataTable[12].float_c = 25.0; globs::infoGlobs.infoDataTable[38].float_c = 25.0; } snd::SFX_Random_SetAndPlayGlobalSample (globs::infoGlobs.infoDataTable[infoType].sfxType,NULL); } BVar5 = Info_HasTypeAtObjectOrBlockPos(infoType,opt_liveObj,opt_blockPos); if (BVar5 == 0) { BVar5 = Info_HasTypeText(infoType); if (BVar5 != 0) { pvVar2 = globs::infoGlobs.infoDataTable[infoType].ptr_4; if (((((byte)globs::infoGlobs.flags & INFO_GLOB_FLAG_UNK_8) != 0) && ((globs::infoGlobs.infoDataTable[infoType].flags & INFOTYPE_FLAG_UNK_20000) == INFOTYPE_FLAG_NONE)) && (fVar1 = globs::infoGlobs.infoDataTable[infoType].float_c, (ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) != 0)) { globs::infoGlobs.infoDataTable[infoType].float_c = 25.0; if ((((infoType == Info_LegoManDeath) || (infoType == Info_VehicleDeath)) || (infoType == Info_BuildingDeath)) || (infoType == Info_GenericDeath)) { globs::infoGlobs.infoDataTable[10].float_c = 25.0; globs::infoGlobs.infoDataTable[11].float_c = 25.0; globs::infoGlobs.infoDataTable[12].float_c = 25.0; globs::infoGlobs.infoDataTable[38].float_c = 25.0; } snd::SFX_Random_SetAndPlayGlobalSample (globs::infoGlobs.infoDataTable[infoType].sfxType,NULL); } if (globs::infoGlobs.infoMessageCount != 0x28) { handle = Info_FindExistingMessageType(infoType); uVar4 = globs::infoGlobs.infoMessageCount; if (handle == 0xffffffff) { pIVar3 = globs::infoGlobs.infoMessageTable + globs::infoGlobs.infoMessageCount; globs::infoGlobs.infoMessageCount = globs::infoGlobs.infoMessageCount + 1; pIVar3->float_c = -(float)*(int *)((int)pvVar2 + 4); fVar6 = Info_FUN_00419a80(); globs::infoGlobs.infoMessageTable[uVar4].next = (InfoMessage *)(float)fVar6; handle = uVar4; } globs::infoGlobs.infoMessageTable[handle].infoType = infoType; instance = Info_CreateInstance(opt_blockPos,opt_liveObj,opt_text); Info_AddMessageInstance(handle,instance); progMode = main::Main_ProgrammerMode(); if (((progMode < 5) && (((byte)globs::infoGlobs.flags & INFO_GLOB_FLAG_AUTOGAMESPEED) != 0)) && ((globs::infoGlobs.infoDataTable[infoType].flags & INFOTYPE_FLAG_CHANGEGAMESPEED) != INFOTYPE_FLAG_NONE)) { fVar6 = game::Lego_GetGameSpeed(); if ((ushort)((ushort)(fVar6 < (float10)1.0) << 8 | (ushort)(fVar6 == (float10)1.0) << 0xe) == 0) { lrr::Lego_SetGameSpeed(1.0); } } } } } } } return; } void __cdecl lego::front::Info_GotoFirst(void) { if ((globs::infoGlobs.infoMessageCount != 0) && (globs::infoGlobs.infoMessageTable[0].instanceCount != 0)) { if (((globs::infoGlobs.infoMessageTable[0].instance)->object != NULL) || ((0 < ((globs::infoGlobs.infoMessageTable[0].instance)->blockPos).x && (0 < ((globs::infoGlobs.infoMessageTable[0].instance)->blockPos).y)))) { lrr::Lego_Goto((globs::infoGlobs.infoMessageTable[0].instance)->object, &(globs::infoGlobs.infoMessageTable[0].instance)->blockPos,FALSE); } } return; } void __cdecl lego::front::Info_UpdateMessage(uint handle) { InfoMessage *pIVar1; int iVar2; InfoMessage *pIVar3; InfoMessageInstance **ppIVar4; InfoMessage *pIVar5; InfoMessageInstance *local_14 [5]; if (handle < globs::infoGlobs.infoMessageCount) { if (handle != 0) { pIVar3 = globs::infoGlobs.infoMessageTable + handle; ppIVar4 = local_14; for (iVar2 = 5; pIVar1 = globs::infoGlobs.infoMessageTable + handle, iVar2 != 0; iVar2 += -1) { *ppIVar4 = pIVar3->instance; pIVar3 = (InfoMessage *)&pIVar3->instanceCount; ppIVar4 = ppIVar4 + 1; } do { handle -= 1; pIVar3 = pIVar1 + -1; pIVar5 = pIVar1; for (iVar2 = 5; iVar2 != 0; iVar2 += -1) { pIVar5->instance = pIVar3->instance; pIVar3 = (InfoMessage *)&pIVar3->instanceCount; pIVar5 = (InfoMessage *)&pIVar5->instanceCount; } pIVar1 = pIVar1 + -1; } while (handle != 0); ppIVar4 = local_14; pIVar3 = globs::infoGlobs.infoMessageTable; for (iVar2 = 5; iVar2 != 0; iVar2 += -1) { pIVar3->instance = *ppIVar4; ppIVar4 = ppIVar4 + 1; pIVar3 = (InfoMessage *)&pIVar3->instanceCount; } } globs::infoGlobs.flags |= INFO_GLOB_FLAG_UNK_1|INFO_GLOB_FLAG_UNK_2; } return; } void __cdecl lego::front::Info_PopFirstMessage(void) { if (globs::infoGlobs.infoMessageCount != 0) { Info_RemoveMessage(0); } return; } void __cdecl lego::front::Info_RemoveMessage(uint handle) { InfoMessageInstance *instance; InfoMessage *pIVar1; int iVar2; uint uVar3; InfoMessage *pIVar4; InfoMessage *pIVar5; if (handle < globs::infoGlobs.infoMessageCount) { instance = Info_RemoveMessageInstance(handle,0); if ((instance != NULL) && (instance->text != NULL)) { io::Mem_Free(instance->text); } if (globs::infoGlobs.infoMessageTable[handle].instanceCount == 0) { if (handle < globs::infoGlobs.infoMessageCount) { pIVar1 = globs::infoGlobs.infoMessageTable + handle; uVar3 = handle; do { uVar3 += 1; pIVar4 = pIVar1 + 1; pIVar5 = pIVar1; for (iVar2 = 5; iVar2 != 0; iVar2 += -1) { pIVar5->instance = pIVar4->instance; pIVar4 = (InfoMessage *)&pIVar4->instanceCount; pIVar5 = (InfoMessage *)&pIVar5->instanceCount; } pIVar1 = pIVar1 + 1; } while (uVar3 < globs::infoGlobs.infoMessageCount); } globs::infoGlobs.infoMessageCount -= 1; } if (handle == 0) { globs::infoGlobs.flags &= ~INFO_GLOB_FLAG_UNK_1; } } return; } void __cdecl lego::front::Info_ClearAllMessages(void) { if (globs::infoGlobs.infoMessageCount != 0) { do { Info_RemoveMessage(0); } while (globs::infoGlobs.infoMessageCount != 0); } return; } void __cdecl lego::front::Info_Draw(float elapsedAbs) { Image *image; int y; int x; Font *font; uint uVar1; InfoMessage **ppIVar2; longlong lVar3; char *msg; InfoMessage *pIVar4; Point2F local_8; local_8.y = 333.0; uVar1 = 0; if (globs::infoGlobs.infoMessageCount == 0) { return; } ppIVar2 = &globs::infoGlobs.infoMessageTable[0].next; while( true ) { image = (Image *)globs::infoGlobs.infoDataTable[(int)ppIVar2[-2]].ptr_4; if ((ushort)((ushort)(local_8.y < (float)*ppIVar2) << 8 | (ushort)(local_8.y == (float)*ppIVar2) << 0xe) == 0) { *ppIVar2 = (InfoMessage *)((float)*ppIVar2 - elapsedAbs * -8.0); } if (local_8.y < (float)*ppIVar2) { *ppIVar2 = (InfoMessage *)local_8.y; } if ((float)ppIVar2[-1] < 0.0) { ppIVar2[-1] = (InfoMessage *)((float)ppIVar2[-1] - elapsedAbs * -3.0); } if ((ushort)((ushort)((float)ppIVar2[-1] < 0.0) << 8 | (ushort)((float)ppIVar2[-1] == 0.0) << 0xe) == 0) { ppIVar2[-1] = NULL; } local_8.y = (float)*ppIVar2; local_8.x = (float)ppIVar2[-1]; lego::image::Image_DisplayScaled(image,NULL,&local_8,NULL); if (local_8.y < 0.0) break; pIVar4 = ppIVar2[-3]; msg = "%i"; lVar3 = __ftol((float10)local_8.y); y = (int)lVar3 + 10; lVar3 = __ftol((float10)local_8.x); x = (int)lVar3 + 2; font = Interface_GetFont(); lego::image::Font_PrintF(font,x,y,msg,pIVar4); uVar1 += 1; ppIVar2 = ppIVar2 + 5; local_8.y = local_8.y - (float)image->height; if (globs::infoGlobs.infoMessageCount <= uVar1) { return; } } local_8.y = 0.0; lego::image::Image_DisplayScaled(globs::infoGlobs.OverFlowImage,NULL,&local_8,NULL); return; } void __cdecl lego::front::Info_DrawPanel(float elapsedAbs) { char cVar1; uint uVar2; char *msg; char *pcVar3; if (((globs::infoGlobs.flags & INFO_GLOB_FLAG_UNK_1) == INFO_GLOB_FLAG_NONE) || (globs::infoGlobs.infoMessageCount == 0)) { if (((byte)globs::panelGlobs.panelTable[7].flags & PANEL_FLAG_CLOSED) == 0) { Panel_ToggleOpenClosed(Panel_Information); } } else { if (((byte)globs::panelGlobs.panelTable[7].flags & PANEL_FLAG_OPEN) == 0) { Panel_ToggleOpenClosed(Panel_Information); } if ((globs::infoGlobs.flags & INFO_GLOB_FLAG_UNK_2) != INFO_GLOB_FLAG_NONE) { Panel_TextWindow_Clear(globs::panelGlobs.infoTextWnd); msg = (globs::infoGlobs.infoMessageTable[0].instance)->text; if (msg == NULL) { msg = globs::infoGlobs.infoDataTable[globs::infoGlobs.infoMessageTable[0].infoType].text; } uVar2 = 0xffffffff; pcVar3 = msg; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar1 != '\0'); uVar2 = ~uVar2; if (msg[uVar2] == '\0') { Panel_TextWindow_PrintF(globs::panelGlobs.infoTextWnd,msg); } else { Panel_TextWindow_PrintF (globs::panelGlobs.infoTextWnd,msg,(uint)(byte)msg[uVar2 + 1], (uint)(byte)msg[uVar2 + 2],(uint)(byte)msg[uVar2 + 3],(uint)(byte)msg[uVar2 + 4], (uint)(byte)msg[uVar2 + 5]); } Panel_TextWindow_Update(globs::panelGlobs.infoTextWnd,globs::infoGlobs.int_6ec,elapsedAbs); Info_FUN_0041a180(); globs::infoGlobs.flags &= ~INFO_GLOB_FLAG_UNK_2; } } Panel_TextWindow_Update(globs::panelGlobs.infoTextWnd,globs::infoGlobs.int_6ec,elapsedAbs); return; } BOOL __cdecl lego::front::Info_Update_FUN_0041a0d0(int mouseX,int mouseY,BOOL leftReleased) { void *pvVar1; int iVar2; uint i; InfoMessage **ppIVar3; longlong lVar4; i = 0; if (globs::infoGlobs.infoMessageCount == 0) { return 0; } ppIVar3 = &globs::infoGlobs.infoMessageTable[0].next; do { pvVar1 = globs::infoGlobs.infoDataTable[(int)ppIVar3[-2]].ptr_4; iVar2 = *(int *)((int)pvVar1 + 8); if ((-1 < mouseX) && (mouseX <= *(int *)((int)pvVar1 + 4))) { lVar4 = __ftol((float10)(float)*ppIVar3); if (((int)lVar4 <= mouseY) && (mouseY <= iVar2 + (int)lVar4)) { if (leftReleased != 0) { if (((globs::infoGlobs.flags & INFO_GLOB_FLAG_UNK_1) != INFO_GLOB_FLAG_NONE) && (i == 0)) { Panel_ToggleOpenClosed(Panel_Information); globs::infoGlobs.flags = globs::infoGlobs.flags & ~INFO_GLOB_FLAG_UNK_1; return TRUE; } Info_UpdateMessage(i); } return TRUE; } } i += 1; ppIVar3 = ppIVar3 + 5; if (globs::infoGlobs.infoMessageCount <= i) { return 0; } } while( true ); } void __cdecl lego::front::Info_FUN_0041a180(void) { int avail; uint linesCount; uint linesCapacity; Panel_TextWindow_GetInfo(globs::panelGlobs.infoTextWnd,&linesCount,&linesCapacity); avail = linesCount - linesCapacity; if (avail < 0) { avail = 0; } ScrollInfo_SetSubStruct28_Fields1C_20(0,avail,0); Info_UpdateInt6EC_FromScrollInfo(); return; } void __cdecl lego::front::Info_UpdateInt6EC_FromScrollInfo(void) { int local_8; int local_4; ScrollInfo_GetSubStruct28_Fields1C_20(0,&local_8,&local_4); globs::infoGlobs.int_6ec = local_8 - local_4; return; } void __cdecl lego::front::Info_FUN_0041a1f0(float elapsed) { float *pfVar1; pfVar1 = &globs::infoGlobs.infoDataTable[0].float_c; do { if ((ushort)((ushort)(*pfVar1 < 0.0) << 8 | (ushort)(*pfVar1 == 0.0) << 0xe) == 0) { *pfVar1 = *pfVar1 - elapsed; } pfVar1 = pfVar1 + 5; } while (pfVar1 < &globs::infoGlobs.infoMessageTable[0].float_c); return; } Font * __cdecl lego::front::Interface_GetFont(void) { return globs::interfaceGlobs.font; } void __cdecl lego::front::Interface_Initialise(uint x_565,uint y_18,Font *font) { ToolTip_SetRightAlign(ToolTip_InterfaceMenu,TRUE); globs::interfaceGlobs.currMenuPosition.x = (float)(ulonglong)x_565; globs::interfaceGlobs.menuItemName[0] = "Interface_MenuItem_BackToDefault"; globs::interfaceGlobs.currMenuPosition.y = (float)(ulonglong)y_18; globs::interfaceGlobs.font = font; globs::interfaceGlobs.menuItemName[1] = "Interface_MenuItem_TeleportMan"; globs::interfaceGlobs.menuItemName[2] = "Interface_MenuItem_BuildBuilding"; globs::interfaceGlobs.menuItemName[3] = "Interface_MenuItem_BuildSmallVehicle"; globs::interfaceGlobs.menuItemName[4] = "Interface_MenuItem_BuildLargeVehicle"; globs::interfaceGlobs.menuItemName[5] = "Interface_MenuItem_LayPath"; globs::interfaceGlobs.menuItemName[7] = "Interface_MenuItem_RepairLava"; globs::interfaceGlobs.menuItemName[8] = "Interface_MenuItem_GeologistTest"; globs::interfaceGlobs.menuItemName[9] = "Interface_MenuItem_ClearRubble"; globs::interfaceGlobs.menuItemName[10] = "Interface_MenuItem_Dam"; globs::interfaceGlobs.menuItemName[17] = "Interface_MenuItem_SelectMan"; globs::interfaceGlobs.menuItemName[32] = "Interface_MenuItem_DeleteMan"; globs::interfaceGlobs.menuItemName[41] = "Interface_MenuItem_DeleteVehicle"; globs::interfaceGlobs.menuItemName[40] = "Interface_MenuItem_DeleteBuilding"; globs::interfaceGlobs.menuItemName[43] = "Interface_MenuItem_Attack"; globs::interfaceGlobs.menuItemName[18] = "Interface_MenuItem_SelectVehicle"; globs::interfaceGlobs.menuItemName[22] = "Interface_MenuItem_UnLoadVehicle"; globs::interfaceGlobs.menuItemName[23] = "Interface_MenuItem_UnLoadMinifigure"; globs::interfaceGlobs.menuItemName[20] = "Interface_MenuItem_VehiclePickUp"; globs::interfaceGlobs.menuItemName[21] = "Interface_MenuItem_MinifigurePickUp"; globs::interfaceGlobs.menuItemName[25] = "Interface_MenuItem_GetOut"; globs::interfaceGlobs.menuItemName[24] = "Interface_MenuItem_GetIn"; globs::interfaceGlobs.menuItemName[26] = "Interface_MenuItem_GotoDock"; globs::interfaceGlobs.menuItemName[11] = "Interface_MenuItem_Dig"; globs::interfaceGlobs.menuItemName[12] = "Interface_MenuItem_Reinforce"; globs::interfaceGlobs.menuItemName[13] = "Interface_MenuItem_Dynamite"; globs::interfaceGlobs.menuItemName[64] = "Interface_MenuItem_UpgradeMan"; globs::interfaceGlobs.menuItemName[31] = "Interface_MenuItem_GoFeed"; globs::interfaceGlobs.menuItemName[45] = "Interface_MenuItem_GotoFirstPerson"; globs::interfaceGlobs.menuItemName[46] = "Interface_MenuItem_GotoSecondPerson"; globs::interfaceGlobs.menuItemName[57] = "Interface_MenuItem_TrainSkill"; globs::interfaceGlobs.menuItemName[34] = "Interface_MenuItem_PowerOn"; globs::interfaceGlobs.menuItemName[35] = "Interface_MenuItem_PowerOff"; globs::interfaceGlobs.menuItemName[65] = "Interface_MenuItem_UpgradeBuilding"; globs::interfaceGlobs.menuItemName[36] = "Interface_MenuItem_Repair"; globs::interfaceGlobs.menuItemName[19] = "Interface_MenuItem_SelectBuilding"; globs::interfaceGlobs.menuItemName[44] = "Interface_MenuItem_GotoTopView"; globs::interfaceGlobs.menuItemName[48] = "Interface_MenuItem_GetTool"; globs::interfaceGlobs.menuItemName[49] = "Interface_MenuItem_GetDrill"; globs::interfaceGlobs.menuItemName[50] = "Interface_MenuItem_GetSpade"; globs::interfaceGlobs.menuItemName[51] = "Interface_MenuItem_GetHammer"; globs::interfaceGlobs.menuItemName[52] = "Interface_MenuItem_GetSpanner"; globs::interfaceGlobs.menuItemName[58] = "Interface_MenuItem_TrainDriver"; globs::interfaceGlobs.menuItemName[59] = "Interface_MenuItem_TrainEngineer"; globs::interfaceGlobs.menuItemName[60] = "Interface_MenuItem_TrainGeologist"; globs::interfaceGlobs.menuItemName[61] = "Interface_MenuItem_TrainPilot"; globs::interfaceGlobs.menuItemName[62] = "Interface_MenuItem_TrainSailor"; globs::interfaceGlobs.menuItemName[63] = "Interface_MenuItem_TrainDynamite"; globs::interfaceGlobs.menuItemName[73] = "Interface_MenuItem_Build"; globs::interfaceGlobs.menuItemName[14] = "Interface_MenuItem_PlaceFence"; globs::interfaceGlobs.menuItemName[37] = "Interface_MenuItem_MakeTeleporterPrimary"; globs::interfaceGlobs.menuItemName[15] = "Interface_MenuItem_DeselectDig"; globs::interfaceGlobs.menuItemName[72] = "Interface_MenuItem_ClearSelection"; globs::interfaceGlobs.menuItemName[71] = "Interface_MenuItem_Encyclopedia"; globs::interfaceGlobs.menuItemName[38] = "Interface_MenuItem_EjectCrystal"; globs::interfaceGlobs.menuItemName[39] = "Interface_MenuItem_EjectOre"; globs::interfaceGlobs.menuItemName[47] = "Interface_MenuItem_TrackObject"; globs::interfaceGlobs.menuItemName[27] = "Interface_MenuItem_LegoManGoto"; globs::interfaceGlobs.menuItemName[30] = "Interface_MenuItem_LegoManDig"; globs::interfaceGlobs.menuItemName[28] = "Interface_MenuItem_VehicleGoto"; globs::interfaceGlobs.menuItemName[29] = "Interface_MenuItem_VehicleDig"; globs::interfaceGlobs.menuItemName[6] = "Interface_MenuItem_RemovePath"; globs::interfaceGlobs.menuItemName[66] = "Interface_MenuItem_UpgradeVehicle"; globs::interfaceGlobs.menuItemName[67] = "Interface_MenuItem_UpgradeEngine"; globs::interfaceGlobs.menuItemName[68] = "Interface_MenuItem_UpgardeDrill"; globs::interfaceGlobs.menuItemName[69] = "Interface_MenuItem_UpgardeScan"; globs::interfaceGlobs.menuItemName[70] = "Interface_MenuItem_UpgardeCarry"; globs::interfaceGlobs.menuItemName[42] = "Interface_MenuItem_DeleteElectricFence"; globs::interfaceGlobs.menuItemName[53] = "Interface_MenuItem_GetLaser"; globs::interfaceGlobs.menuItemName[54] = "Interface_MenuItem_GetPusherGun"; globs::interfaceGlobs.menuItemName[55] = "Interface_MenuItem_GetFreezerGun"; globs::interfaceGlobs.menuItemName[56] = "Interface_MenuItem_GetBirdScarer"; globs::interfaceGlobs.menuItemName[33] = "Interface_MenuItem_DropBirdScarer"; globs::interfaceGlobs.menuItemName[16] = "Interface_MenuItem_CancelConstruction"; Interface_AddAllMenuItems(); Interface_SetScrollParameters(x_565,y_18,globs::mainGlobs.appWidth + 10,y_18,750.0); Interface_ResetMenu(); return; } void __cdecl lego::front::Interface_AddAllMenuItems(void) { Interface_AddMenuItems (Interface_Menu_Main,4,Interface_MenuItem_TeleportMan,Interface_MenuItem_BuildBuilding, Interface_MenuItem_BuildSmallVehicle,Interface_MenuItem_BuildLargeVehicle); Interface_AddMenuItems (Interface_Menu_Ground,3,Interface_MenuItem_LayPath,Interface_MenuItem_RemovePath, Interface_MenuItem_PlaceFence); Interface_AddMenuItems(Interface_Menu_Erode,1,Interface_MenuItem_RepairLava); Interface_AddMenuItems(Interface_Menu_PlaceFence,1,Interface_MenuItem_PlaceFence); Interface_AddMenuItems(Interface_Menu_Construction,1,Interface_MenuItem_CancelConstruction); Interface_AddMenuItems (Interface_Menu_Rubble,2,Interface_MenuItem_ClearRubble,Interface_MenuItem_PlaceFence); Interface_AddMenuItems (Interface_Menu_Wall,4,Interface_MenuItem_Dig,Interface_MenuItem_Reinforce, Interface_MenuItem_Dynamite,Interface_MenuItem_DeselectDig); Interface_AddMenuItems (Interface_Menu_Tracker,2,Interface_MenuItem_Attack,Interface_MenuItem_TrackObject); Interface_AddMenuItems (Interface_Menu_LandVehicle,7,Interface_MenuItem_UnLoadVehicle, Interface_MenuItem_VehiclePickUp,Interface_MenuItem_UpgradeVehicle, Interface_MenuItem_GetOut,Interface_MenuItem_GotoFirstPerson, Interface_MenuItem_GotoSecondPerson,Interface_MenuItem_DeleteVehicle); Interface_AddMenuItems (Interface_Menu_WaterVehicle,6,Interface_MenuItem_UnLoadVehicle, Interface_MenuItem_VehiclePickUp,Interface_MenuItem_GetOut, Interface_MenuItem_GotoFirstPerson,Interface_MenuItem_GotoSecondPerson, Interface_MenuItem_GotoDock); Interface_AddMenuItems (Interface_Menu_UnmannedVehicle,2,Interface_MenuItem_GetIn, Interface_MenuItem_DeleteVehicle); Interface_AddMenuItems (Interface_Menu_LegoMan,10,Interface_MenuItem_GoFeed,Interface_MenuItem_UnLoadMinifigure ,Interface_MenuItem_MinifigurePickUp,Interface_MenuItem_GetTool, Interface_MenuItem_DropBirdScarer,Interface_MenuItem_UpgradeMan, Interface_MenuItem_TrainSkill,Interface_MenuItem_GotoFirstPerson, Interface_MenuItem_GotoSecondPerson,Interface_MenuItem_DeleteMan); Interface_AddMenuItems (Interface_Menu_Building,4,Interface_MenuItem_Repair,Interface_MenuItem_PowerOn, Interface_MenuItem_UpgradeBuilding,Interface_MenuItem_DeleteBuilding); Interface_AddMenuItems(Interface_Menu_ElectricFence,1,Interface_MenuItem_DeleteElectricFence); Interface_AddMenuItems (Interface_Menu_FP,3,Interface_MenuItem_GotoTopView,Interface_MenuItem_GotoSecondPerson, Interface_MenuItem_GotoFirstPerson); Interface_AddMenuItems (Interface_Menu_GetTool,8,Interface_MenuItem_GetDrill,Interface_MenuItem_GetSpade, Interface_MenuItem_GetHammer,Interface_MenuItem_GetSpanner,Interface_MenuItem_GetLaser, Interface_MenuItem_GetPusherGun,Interface_MenuItem_GetFreezerGun, Interface_MenuItem_GetBirdScarer); Interface_AddMenuItems (Interface_Menu_TrainSkill,6,Interface_MenuItem_TrainDriver, Interface_MenuItem_TrainEngineer,Interface_MenuItem_TrainGeologist, Interface_MenuItem_TrainPilot,Interface_MenuItem_TrainSailor, Interface_MenuItem_TrainDynamite); Interface_AddMenuItems (Interface_Menu_UpgradeVehicle,4,Interface_MenuItem_UpgradeEngine, Interface_MenuItem_UpgardeDrill,Interface_MenuItem_UpgardeScan, Interface_MenuItem_UpgardeCarry); return; } void __cdecl lego::front::Interface_AddMenuItems(Interface_MenuType menuType,uint numItems,...) { Interface_MenuItemType IVar1; Interface_MenuItemType *pIVar2; Interface_MenuItemType *pIVar3; uint uVar4; int iVar5; Interface_MenuItemType *pIVar6; Interface_MenuItemType local_78 [30]; globs::interfaceGlobs.menuList[menuType].iconCount = numItems; pIVar2 = (Interface_MenuItemType *)io::Mem_Alloc(numItems * 4); globs::interfaceGlobs.menuList[menuType].iconList = pIVar2; pIVar3 = (Interface_MenuItemType *)&stack0x0000000c; if (numItems != 0) { pIVar6 = local_78; do { IVar1 = *pIVar3; pIVar3 = pIVar3 + 1; *pIVar6 = IVar1; pIVar6 = pIVar6 + 1; numItems -= 1; } while (numItems != 0); } pIVar3 = local_78; for (uVar4 = globs::interfaceGlobs.menuList[menuType].iconCount & 0x3fffffff; uVar4 != 0; uVar4 -= 1) { *pIVar2 = *pIVar3; pIVar3 = pIVar3 + 1; pIVar2 = pIVar2 + 1; } for (iVar5 = 0; iVar5 != 0; iVar5 += -1) { *(undefined *)pIVar2 = *(undefined *)pIVar3; pIVar3 = (Interface_MenuItemType *)((int)pIVar3 + 1); pIVar2 = (Interface_MenuItemType *)((int)pIVar2 + 1); } return; } void __cdecl lego::front::Interface_Shutdown(void) { Interface_Menu *pIVar1; pIVar1 = globs::interfaceGlobs.menuList; do { if (pIVar1->iconList != NULL) { io::Mem_Free(pIVar1->iconList); } pIVar1 = pIVar1 + 1; } while (pIVar1 < (Interface_Menu *)&globs::interfaceGlobs.selBlockPos); io::Mem_Free(globs::interfaceGlobs.vehicleItemIcons); io::Mem_Free(globs::interfaceGlobs.vehicleItemIcons_no); io::Mem_Free(globs::interfaceGlobs.vehicleItemIcons_pr); io::Mem_Free(globs::interfaceGlobs.vehicleItemClicks); io::Mem_Free(globs::interfaceGlobs.vehicleItemF2Keys); io::Mem_Free(globs::interfaceGlobs.vehicleItemFlags); io::Mem_Free(globs::interfaceGlobs.buildingItemIcons); io::Mem_Free(globs::interfaceGlobs.buildingItemIcons_no); io::Mem_Free(globs::interfaceGlobs.buildingItemIcons_pr); io::Mem_Free(globs::interfaceGlobs.buildingItemClicks); io::Mem_Free(globs::interfaceGlobs.buildingItemF2Keys); io::Mem_Free(globs::interfaceGlobs.buildingItemFlags); return; } void __cdecl lego::front::Interface_ClearStates(void) { int iVar1; uint uVar2; uint uVar3; uint *puVar4; Interface_MenuItemFlags *pIVar5; BOOL (*paBVar6) [15]; globs::interfaceGlobs.flags = INTERFACE_GLOB_FLAG_NONE; puVar4 = globs::interfaceGlobs.menuItemClicks; for (iVar1 = 0x4a; iVar1 != 0; iVar1 += -1) { *puVar4 = 0; puVar4 = puVar4 + 1; } pIVar5 = globs::interfaceGlobs.menuItemFlags; for (iVar1 = 0x4a; uVar2 = globs::legoGlobs.vehicleCount, puVar4 = globs::interfaceGlobs.vehicleItemClicks, iVar1 != 0; iVar1 += -1) { *pIVar5 = INTERFACE_MENUITEM_FLAG_NONE; pIVar5 = pIVar5 + 1; } for (; uVar3 = globs::legoGlobs.vehicleCount, pIVar5 = globs::interfaceGlobs.vehicleItemFlags, uVar2 != 0; uVar2 = uVar2 - 1) { *puVar4 = 0; puVar4 = puVar4 + 1; } for (; uVar2 = globs::legoGlobs.buildingCount, puVar4 = globs::interfaceGlobs.buildingItemClicks, uVar3 != 0; uVar3 = uVar3 - 1) { *pIVar5 = INTERFACE_MENUITEM_FLAG_NONE; pIVar5 = pIVar5 + 1; } for (; uVar3 = globs::legoGlobs.buildingCount, pIVar5 = globs::interfaceGlobs.buildingItemFlags, uVar2 != 0; uVar2 = uVar2 - 1) { *puVar4 = 0; puVar4 = puVar4 + 1; } for (; uVar3 != 0; uVar3 = uVar3 - 1) { *pIVar5 = INTERFACE_MENUITEM_FLAG_NONE; pIVar5 = pIVar5 + 1; } paBVar6 = globs::interfaceGlobs.objectBools; for (iVar1 = 300; iVar1 != 0; iVar1 += -1) { (*paBVar6)[0] = 0; paBVar6 = (BOOL (*) [15])(*paBVar6 + 1); } Interface_ResetMenu(); return; } void __cdecl lego::front::Interface_ResetMenu(void) { globs::interfaceGlobs.currMenuType = Interface_Menu_Main; globs::interfaceGlobs.currMenuPosition.x = globs::interfaceGlobs.slideEndPosition.x; globs::interfaceGlobs.flags = globs::interfaceGlobs.flags | (INTERFACE_GLOB_FLAG_UNK_4|INTERFACE_GLOB_FLAG_UNK_80); return; } BOOL __cdecl lego::front::Interface_GetMenuItemType(char *menuItemName,Interface_MenuItemType *out_menuItemType) { int cmp; char **pName; Interface_MenuItemType i; i = Interface_MenuItem_Back; pName = globs::interfaceGlobs.menuItemName; do { cmp = std::_stricmp((char *)*pName,menuItemName); if (cmp == 0) { *out_menuItemType = i; return TRUE; } pName = (char **)((Image **)pName + 1); i += Interface_MenuItem_TeleportMan; } while (pName < globs::interfaceGlobs.menuItemIcons); return FALSE; } void __cdecl lego::front::Interface_InitBuildItems(void) { uint uVar1; uint uVar2; uint *puVar3; undefined4 *puVar4; Interface_MenuItemFlags *pIVar5; globs::interfaceGlobs.vehicleItemClicks = (uint *)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4) ; puVar3 = globs::interfaceGlobs.vehicleItemClicks; for (uVar1 = globs::legoGlobs.vehicleCount; uVar1 != 0; uVar1 -= 1) { *puVar3 = 0; puVar3 = puVar3 + 1; } globs::interfaceGlobs.vehicleItemF2Keys = (Keys8 *)io::Mem_Alloc(globs::legoGlobs.vehicleCount); uVar1 = globs::legoGlobs.vehicleCount; puVar4 = (undefined4 *)globs::interfaceGlobs.vehicleItemF2Keys; for (uVar2 = globs::legoGlobs.vehicleCount >> 2; uVar2 != 0; uVar2 -= 1) { *puVar4 = 0; puVar4 = puVar4 + 1; } for (uVar1 &= 3; uVar1 != 0; uVar1 -= 1) { *(undefined *)puVar4 = 0; puVar4 = (undefined4 *)((int)puVar4 + 1); } globs::interfaceGlobs.vehicleItemFlags = (Interface_MenuItemFlags *)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4); pIVar5 = globs::interfaceGlobs.vehicleItemFlags; for (uVar1 = globs::legoGlobs.vehicleCount; uVar1 != 0; uVar1 -= 1) { *pIVar5 = INTERFACE_MENUITEM_FLAG_NONE; pIVar5 = pIVar5 + 1; } globs::interfaceGlobs.buildingItemClicks = (uint *)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4); puVar3 = globs::interfaceGlobs.buildingItemClicks; for (uVar1 = globs::legoGlobs.buildingCount; uVar1 != 0; uVar1 -= 1) { *puVar3 = 0; puVar3 = puVar3 + 1; } globs::interfaceGlobs.buildingItemF2Keys = (Keys8 *)io::Mem_Alloc(globs::legoGlobs.buildingCount); uVar1 = globs::legoGlobs.buildingCount; puVar4 = (undefined4 *)globs::interfaceGlobs.buildingItemF2Keys; for (uVar2 = globs::legoGlobs.buildingCount >> 2; uVar2 != 0; uVar2 -= 1) { *puVar4 = 0; puVar4 = puVar4 + 1; } for (uVar1 &= 3; uVar1 != 0; uVar1 -= 1) { *(undefined *)puVar4 = 0; puVar4 = (undefined4 *)((int)puVar4 + 1); } globs::interfaceGlobs.buildingItemFlags = (Interface_MenuItemFlags *)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4); pIVar5 = globs::interfaceGlobs.buildingItemFlags; for (uVar1 = globs::legoGlobs.buildingCount; uVar1 != 0; uVar1 -= 1) { *pIVar5 = INTERFACE_MENUITEM_FLAG_NONE; pIVar5 = pIVar5 + 1; } return; } void __cdecl lego::front::Interface_LoadBuildItems(Config *config,char *gameName) { char *pcVar1; Image *pIVar2; BOOL BVar3; uint i; Keys8 key; char *stringParts [20]; globs::interfaceGlobs.vehicleItemIcons = (Image **)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4); globs::interfaceGlobs.vehicleItemIcons_no = (Image **)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4); globs::interfaceGlobs.vehicleItemIcons_pr = (Image **)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4); i = 0; if (globs::legoGlobs.vehicleCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (gameName,"InterfaceBuildImages",globs::legoGlobs.vehicleName[i],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { globs::interfaceGlobs.vehicleItemIcons[i] = NULL; globs::interfaceGlobs.vehicleItemIcons_no[i] = NULL; globs::interfaceGlobs.vehicleItemIcons_pr[i] = NULL; } else { util::Util_Tokenise(pcVar1,stringParts,":"); pIVar2 = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); globs::interfaceGlobs.vehicleItemIcons[i] = pIVar2; pIVar2 = lego::image::Image_LoadBMPScaled(stringParts[1],0,0); globs::interfaceGlobs.vehicleItemIcons_no[i] = pIVar2; pIVar2 = lego::image::Image_LoadBMPScaled(stringParts[2],0,0); globs::interfaceGlobs.vehicleItemIcons_pr[i] = pIVar2; BVar3 = input::Key_Find(stringParts[3],&key); if (BVar3 != 0) { globs::interfaceGlobs.vehicleItemF2Keys[i] = key; } } i += 1; } while (i < globs::legoGlobs.vehicleCount); } globs::interfaceGlobs.buildingItemIcons = (Image **)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4); globs::interfaceGlobs.buildingItemIcons_no = (Image **)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4); globs::interfaceGlobs.buildingItemIcons_pr = (Image **)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4); i = 0; if (globs::legoGlobs.buildingCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (gameName,"InterfaceBuildImages",globs::legoGlobs.buildingName[i],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { globs::interfaceGlobs.buildingItemIcons[i] = NULL; globs::interfaceGlobs.buildingItemIcons_no[i] = NULL; globs::interfaceGlobs.buildingItemIcons_pr[i] = NULL; } else { util::Util_Tokenise(pcVar1,stringParts,":"); pIVar2 = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); globs::interfaceGlobs.buildingItemIcons[i] = pIVar2; pIVar2 = lego::image::Image_LoadBMPScaled(stringParts[1],0,0); globs::interfaceGlobs.buildingItemIcons_no[i] = pIVar2; pIVar2 = lego::image::Image_LoadBMPScaled(stringParts[2],0,0); globs::interfaceGlobs.buildingItemIcons_pr[i] = pIVar2; BVar3 = input::Key_Find(stringParts[3],&key); if (BVar3 != 0) { globs::interfaceGlobs.buildingItemF2Keys[i] = key; } } i += 1; } while (i < globs::legoGlobs.buildingCount); } return; } void __cdecl lego::front::Interface_LoadMenuItems(Config *config,char *gameName) { char cVar1; Interface_MenuItemType IVar2; char *pcVar3; Config *prop; BOOL BVar4; int iVar5; BoolTri BVar6; Image *pIVar7; uint uVar8; uint uVar9; uint uVar10; undefined4 *puVar11; char *pcVar12; undefined4 *puVar13; Keys8 local_47d; Interface_MenuItemType local_47c; char *local_478; char *local_474; char *stringParts [20]; char buff [1024]; pcVar3 = cfg::Config_BuildStringID(gameName,"InterfaceImages",0); prop = cfg::Config_FindArray(config,pcVar3); do { if (prop == NULL) { Interface_LoadBuildItems(config,gameName); Interface_LoadBackButton(config,gameName); return; } BVar4 = Interface_GetMenuItemType(prop->key,&local_47c); if (BVar4 != 0) { uVar8 = 0xffffffff; uVar10 = 0; pcVar3 = prop->value; do { pcVar12 = pcVar3; if (uVar8 == 0) break; uVar8 -= 1; pcVar12 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar12; } while (cVar1 != '\0'); uVar8 = ~uVar8; puVar11 = (undefined4 *)(pcVar12 + -uVar8); puVar13 = (undefined4 *)buff; for (uVar9 = uVar8 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar13 = *puVar11; puVar11 = puVar11 + 1; puVar13 = puVar13 + 1; } for (uVar8 &= 3; uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar13 = *(undefined *)puVar11; puVar11 = (undefined4 *)((int)puVar11 + 1); puVar13 = (undefined4 *)((int)puVar13 + 1); } iVar5 = util::Util_Tokenise(buff,stringParts,":"); if ((iVar5 == 7) && (BVar6 = util::Util_GetBoolFromString(stringParts[6]), BVar6 != BOOL3_ERROR)) { BVar6 = util::Util_GetBoolFromString(stringParts[6]); uVar10 = (uint)(BVar6 == BOOL3_TRUE); } globs::interfaceGlobs.menuItemUnkBools[local_47c] = uVar10; pIVar7 = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); globs::interfaceGlobs.menuItemIcons[local_47c] = pIVar7; pIVar7 = lego::image::Image_LoadBMPScaled(stringParts[1],0,0); globs::interfaceGlobs.menuItemIcons_no[local_47c] = pIVar7; pIVar7 = lego::image::Image_LoadBMPScaled(stringParts[2],0,0); globs::interfaceGlobs.menuItemIcons_pr[local_47c] = pIVar7; iVar5 = util::Util_Tokenise(stringParts[3],&local_478,"|"); IVar2 = local_47c; pcVar3 = util::Util_StrCpy(local_478); globs::interfaceGlobs.langMenuItemTexts[IVar2] = pcVar3; if (iVar5 == 2) { snd::SFX_GetType(local_474,globs::interfaceGlobs.sfxMenuItemTexts + IVar2); } iVar5 = util::Util_Tokenise(stringParts[4],&local_478,"|"); IVar2 = local_47c; pcVar3 = util::Util_StrCpy(local_478); globs::interfaceGlobs.langMenuItemTexts_no[IVar2] = pcVar3; if (iVar5 == 2) { snd::SFX_GetType(local_474,globs::interfaceGlobs.sfxMenuItemTexts_no + IVar2); } BVar4 = input::Key_Find(stringParts[5],&local_47d); if (BVar4 != 0) { globs::interfaceGlobs.menuItemF2keys[local_47c] = local_47d; } } prop = cfg::Config_GetNextItem(prop); } while( true ); } void __cdecl lego::front::Interface_LoadItemPanels(Config *config,char *gameName) { int value; char *pcVar1; int iVar2; Image *pIVar3; Image **ppIVar4; Image **ppIVar5; char local_64 [20]; char *stringParts [20]; value = 0; ppIVar4 = globs::interfaceGlobs.iconPanelImages; ppIVar5 = (Image **)&globs::interfaceGlobs.iconPanelIconOffsets[0].y; do { value += 1; std::itoa(value,local_64,10); pcVar1 = cfg::Config_BuildStringID(gameName,"InterfaceSurroundImages",local_64,0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { *ppIVar4 = NULL; } else { util::Util_Tokenise(pcVar1,stringParts,":"); iVar2 = std::_stricmp(stringParts[0],"NULL"); if (iVar2 != 0) { pIVar3 = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); *ppIVar4 = pIVar3; if (pIVar3 != NULL) { lego::image::Image_SetupTrans(pIVar3,0.0,0.0,0.0,0.0,0.0,0.0); } iVar2 = std::atoi(stringParts[1]); ppIVar5[-1] = (Image *)(float)iVar2; iVar2 = std::atoi(stringParts[2]); *ppIVar5 = (Image *)(float)iVar2; // surroundImageSizes iVar2 = std::atoi(stringParts[3]); ppIVar5[0x38] = (Image *)(float)iVar2; iVar2 = std::atoi(stringParts[4]); ppIVar5[0x39] = (Image *)(float)iVar2; } iVar2 = std::_stricmp(stringParts[5],"NULL"); if (iVar2 != 0) { pIVar3 = lego::image::Image_LoadBMPScaled(stringParts[5],0,0); ppIVar4[0x21] = pIVar3; if (pIVar3 != NULL) { lego::image::Image_SetupTrans(pIVar3,0.0,0.0,0.0,0.0,0.0,0.0); } // surroundBackImagePositions iVar2 = std::atoi(stringParts[6]); ppIVar5[0x20] = (Image *)(float)iVar2; iVar2 = std::atoi(stringParts[7]); ppIVar5[0x21] = (Image *)(float)iVar2; } } ppIVar5 = ppIVar5 + 2; ppIVar4 = ppIVar4 + 1; } while (ppIVar5 < globs::interfaceGlobs.iconPanelNoBackImages + 1); return; } void __cdecl lego::front::Interface_LoadBackButton(Config *config,char *gameName) { char *pcVar1; char *stringParts [20]; pcVar1 = cfg::Config_BuildStringID(gameName,"InterfaceBackButton",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { util::Util_Tokenise(pcVar1,stringParts,":"); globs::interfaceGlobs.backButtonSize.width = std::atoi(stringParts[0]); globs::interfaceGlobs.backButtonSize.height = std::atoi(stringParts[1]); globs::interfaceGlobs.backButtonImage_hl = lego::image::Image_LoadBMPScaled(stringParts[2],0,0); globs::interfaceGlobs.backButtonImage_pr = lego::image::Image_LoadBMPScaled(stringParts[3],0,0); globs::interfaceGlobs.backButtonText = util::Util_RemoveUnderscores(stringParts[4]); ToolTip_SetContent(ToolTip_InterfaceMenuBackButton,globs::interfaceGlobs.backButtonText); } return; } void __cdecl lego::front::Interface_LoadPlusMinusImages(char *plusName,char *minusName) { globs::interfaceGlobs.dependenciesPlusImage = lego::image::Image_LoadBMPScaled(plusName,0,0); if (globs::interfaceGlobs.dependenciesPlusImage != NULL) { lego::image::Image_SetupTrans (globs::interfaceGlobs.dependenciesPlusImage,0.0,0.0,0.0,0.0,0.0,0.0); } globs::interfaceGlobs.dependenciesMinusImage = lego::image::Image_LoadBMPScaled(minusName,0,0); if (globs::interfaceGlobs.dependenciesMinusImage != NULL) { lego::image::Image_SetupTrans (globs::interfaceGlobs.dependenciesMinusImage,0.0,0.0,0.0,0.0,0.0,0.0); } return; } void __cdecl lego::front::Interface_OpenMenu(Interface_MenuType menuType,Point2I *blockPos) { lrr::Lego_StopUserAction(); _Interface_OpenMenu_SelectBlock(menuType,blockPos); _Interface_OpenMenu_SetNext(menuType,blockPos); return; } void __cdecl lego::front::_Interface_OpenMenu_SelectBlock(Interface_MenuType menuType,Point2I *blockPos) { WallHighlightType currHighlight; Map3D *map; WallHighlightType oldHighlight; WallHighlightType newHighlight; WallHighlightType origHighlight; int bx; int by; if ((((globs::interfaceGlobs.nextMenuType == Interface_Menu_Ground) || (globs::interfaceGlobs.nextMenuType == Interface_Menu_Erode)) || (globs::interfaceGlobs.nextMenuType == Interface_Menu_Wall)) || (((globs::interfaceGlobs.nextMenuType == Interface_Menu_Rubble || (globs::interfaceGlobs.nextMenuType == Interface_Menu_PlaceFence)) || (globs::interfaceGlobs.nextMenuType == Interface_Menu_Construction)))) { by = globs::interfaceGlobs.highlightBlockPos.x; bx = globs::interfaceGlobs.highlightBlockPos.y; map = lrr::Lego_GetMap(); currHighlight = lego::map::Map3D_GetBlockHighlight(map,by,bx); if (currHighlight == WALLHIGHLIGHT_NONE) { globs::interfaceGlobs.origWallHighlight = WALLHIGHLIGHT_NONE; } else { by = globs::interfaceGlobs.highlightBlockPos.x; bx = globs::interfaceGlobs.highlightBlockPos.y; origHighlight = globs::interfaceGlobs.origWallHighlight; map = lrr::Lego_GetMap(); lego::map::Map3D_SetBlockHighlight(map,by,bx,origHighlight); } } if (((menuType == Interface_Menu_Ground) || (menuType == Interface_Menu_Erode)) || ((menuType == Interface_Menu_Wall || (((menuType == Interface_Menu_Rubble || (menuType == Interface_Menu_PlaceFence)) || (menuType == Interface_Menu_Construction)))))) { newHighlight = WALLHIGHLIGHT_SELECTED; by = blockPos->y; bx = blockPos->x; map = lrr::Lego_GetMap(); oldHighlight = lego::map::Map3D_SetBlockHighlight(map,bx,by,newHighlight); if (oldHighlight != WALLHIGHLIGHT_SELECTED) { globs::interfaceGlobs.origWallHighlight = oldHighlight; } } return; } uint __cdecl lego::front::Interface_GetBuildMenuIconCount(Interface_MenuType interfaceMenuType) { StatsFlags2 sflags2; StatsFlags3 sflags3; LegoObject_ID objID; uint iconCount; if (interfaceMenuType == Interface_Menu_BuildBuilding) { return globs::legoGlobs.buildingCount; } if (interfaceMenuType == Interface_Menu_BuildSmallVehicle) { iconCount = 0; objID = 0; if (globs::legoGlobs.vehicleCount != 0) { do { // if ((sflags2 & (STATS2_USESMALLTELEPORTER|STATS2_USEWATERTELEPORTER)) && // !(sflags3 & STATS3_CLASSASLARGE)) // { // iconCount++; // } sflags2 = stats::Stats_GetStatsFlags2(LegoObject_Vehicle,objID); if ((sflags2 & STATS2_USESMALLTELEPORTER) == STATS2_NONE) { sflags2 = stats::Stats_GetStatsFlags2(LegoObject_Vehicle,objID); if ((sflags2 & STATS2_USEWATERTELEPORTER) != STATS2_NONE) goto LAB_0041b335; } else { LAB_0041b335: sflags3 = stats::Stats_GetStatsFlags3(LegoObject_Vehicle,objID); if ((sflags3 & STATS3_CLASSASLARGE) == STATS3_NONE) { iconCount += 1; } } objID += 1; if (globs::legoGlobs.vehicleCount <= objID) { return iconCount; } } while( true ); } } else { if (interfaceMenuType != Interface_Menu_BuildLargeVehicle) { return globs::interfaceGlobs.menuList[interfaceMenuType].iconCount; } iconCount = 0; objID = 0; if (globs::legoGlobs.vehicleCount != 0) { do { // Because of water vehicles, we can choose to use either of these flags. // // if ((sflags2 & STATS2_USEBIGTELEPORTER) || (sflags3 & STATS3_CLASSASLARGE)) { // iconCount++; // } sflags2 = stats::Stats_GetStatsFlags2(LegoObject_Vehicle,objID); if ((sflags2 & STATS2_USEBIGTELEPORTER) == STATS2_NONE) { sflags3 = stats::Stats_GetStatsFlags3(LegoObject_Vehicle,objID); if ((sflags3 & STATS3_CLASSASLARGE) != STATS3_NONE) goto LAB_0041b385; } else { LAB_0041b385: iconCount += 1; } objID += 1; } while (objID < globs::legoGlobs.vehicleCount); } } return iconCount; } BOOL __cdecl lego::front::Interface_MenuTypeHasBackButton(Interface_MenuType interfaceMenuType) { if ((interfaceMenuType != Interface_Menu_Main) && (interfaceMenuType != Interface_Menu_FP)) { return TRUE; } return 0; } void __cdecl lego::front::Interface_FUN_0041b3c0(void) { uint uVar1; BOOL BVar2; Image *pIVar3; Interface_MenuItemFlags IVar4; Point2F destPos; if ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_4) == INTERFACE_GLOB_FLAG_NONE) { return; } uVar1 = Interface_GetBuildMenuIconCount(globs::interfaceGlobs.currMenuType); BVar2 = Interface_MenuTypeHasBackButton(globs::interfaceGlobs.currMenuType); if (BVar2 == 0) { pIVar3 = (Image *)(&globs::interfaceGlobs.iconPanelIconOffsets[10].y)[uVar1]; if (pIVar3 != NULL) { destPos.x = (float)globs::interfaceGlobs.iconPanelNoBackImages[uVar1 * 2 + 9] + globs::interfaceGlobs.currMenuPosition.x; destPos.y = (float)globs::interfaceGlobs.iconPanelNoBackImages[uVar1 * 2 + 10] + globs::interfaceGlobs.currMenuPosition.y; lego::image::Image_DisplayScaled(pIVar3,NULL,&destPos,NULL); } goto LAB_0041b52f; } if (globs::interfaceGlobs.iconPanelImages[uVar1 - 1] != NULL) { destPos.x = (float)globs::interfaceGlobs.iconPanelImages[uVar1 * 2 + 9] + globs::interfaceGlobs.currMenuPosition.x; destPos.y = (float)globs::interfaceGlobs.iconPanelImages[uVar1 * 2 + 10] + globs::interfaceGlobs.currMenuPosition.y; lego::image::Image_DisplayScaled (globs::interfaceGlobs.iconPanelImages[uVar1 - 1],NULL,&destPos,NULL); } IVar4 = globs::interfaceGlobs.menuItemFlags[0] & INTERFACE_MENUITEM_FLAG_FLASH; BVar2 = Interface_GetIconFlag8(Interface_MenuItem_Back); pIVar3 = globs::interfaceGlobs.backButtonImage_hl; if (BVar2 == 0) { if ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_4000) == INTERFACE_GLOB_FLAG_NONE) { if (IVar4 != INTERFACE_MENUITEM_FLAG_NONE) goto LAB_0041b47e; LAB_0041b48e: pIVar3 = NULL; } else { if (IVar4 != INTERFACE_MENUITEM_FLAG_NONE) { LAB_0041b47e: if (globs::interfaceGlobs.flashingState == 0) goto LAB_0041b48e; } } } else { pIVar3 = globs::interfaceGlobs.backButtonImage_pr; if ((IVar4 != INTERFACE_MENUITEM_FLAG_NONE) && (globs::interfaceGlobs.flashingState != 0)) { pIVar3 = globs::interfaceGlobs.backButtonImage_hl; } } if (pIVar3 != NULL) { destPos.x = globs::interfaceGlobs.iconPanelBackButtonOffsets[uVar1 - 1].x + globs::interfaceGlobs.currMenuPosition.x; destPos.y = globs::interfaceGlobs.iconPanelBackButtonOffsets[uVar1 - 1].y + globs::interfaceGlobs.currMenuPosition.y; lego::image::Image_DisplayScaled(pIVar3,NULL,&destPos,NULL); } Interface_FUN_0041c420(Interface_MenuItem_Back,LegoObject_None,0,NULL); Interface_SetIconFlag8(Interface_MenuItem_Back,FALSE); Interface_ChangeIconFlag1_FUN_0041c6e0(Interface_MenuItem_Back); LAB_0041b52f: destPos.x = globs::interfaceGlobs.currMenuPosition.x; destPos.y = globs::interfaceGlobs.currMenuPosition.y; Interface_FUN_0041b5b0 (globs::interfaceGlobs.currMenuType,Interface_Callback_FUN_0041b730,&destPos); if ((globs::interfaceGlobs.flags & (INTERFACE_GLOB_FLAG_UNK_200|INTERFACE_GLOB_FLAG_UNK_1000)) != INTERFACE_GLOB_FLAG_NONE) { Interface_DrawHoverOutline(&globs::interfaceGlobs.areaf_fb4); } if ((globs::interfaceGlobs.flags & (INTERFACE_GLOB_FLAG_UNK_1000|INTERFACE_GLOB_FLAG_UNK_2000)) != INTERFACE_GLOB_FLAG_NONE) { Interface_FUN_0041ebd0(globs::interfaceGlobs.areaf_fb4.x,globs::interfaceGlobs.areaf_fb4.y); return; } Interface_SetFloat1494To25_AndUnsetFlags800(); return; } BOOL __cdecl lego::front::Interface_FUN_0041b5b0(Interface_MenuType menuIcon,undefined *callback,void *context) { Interface_MenuItemType *pIVar1; int iVar2; StatsFlags2 SVar3; StatsFlags3 SVar4; Interface_MenuItemType IVar5; uint uVar6; LegoObject_ID LVar7; uVar6 = 0; if (menuIcon == Interface_Menu_BuildBuilding) { if (globs::legoGlobs.buildingCount != 0) { do { iVar2 = (*(code *)callback)(0x49,4,uVar6,context); if (iVar2 != 0) { return 1; } uVar6 += 1; } while (uVar6 < globs::legoGlobs.buildingCount); return 0; } } else { if (menuIcon == Interface_Menu_BuildSmallVehicle) { LVar7 = 0; if (globs::legoGlobs.vehicleCount != 0) { while (((SVar3 = stats::Stats_GetStatsFlags2(LegoObject_Vehicle,LVar7), (SVar3 & STATS2_USESMALLTELEPORTER) == STATS2_NONE && (SVar3 = stats::Stats_GetStatsFlags2(LegoObject_Vehicle,LVar7), (SVar3 & STATS2_USEWATERTELEPORTER) == STATS2_NONE)) || ((SVar4 = stats::Stats_GetStatsFlags3(LegoObject_Vehicle,LVar7), (SVar4 & STATS3_CLASSASLARGE) != STATS3_NONE || (iVar2 = (*(code *)callback)(0x49,1,LVar7,context), iVar2 == 0))))) { LVar7 += 1; if (globs::legoGlobs.vehicleCount <= LVar7) { return 0; } } return 1; } } else { if (menuIcon == Interface_Menu_BuildLargeVehicle) { LVar7 = 0; if (globs::legoGlobs.vehicleCount != 0) { while (((SVar3 = stats::Stats_GetStatsFlags2(LegoObject_Vehicle,LVar7), (SVar3 & STATS2_USEBIGTELEPORTER) == STATS2_NONE && (SVar4 = stats::Stats_GetStatsFlags3(LegoObject_Vehicle,LVar7), (SVar4 & STATS3_CLASSASLARGE) == STATS3_NONE)) || (iVar2 = (*(code *)callback)(0x49,1,LVar7,context), iVar2 == 0))) { LVar7 += 1; if (globs::legoGlobs.vehicleCount <= LVar7) { return 0; } } return TRUE; } } else { if (globs::interfaceGlobs.menuList[menuIcon].iconCount != 0) { while( true ) { pIVar1 = globs::interfaceGlobs.menuList[menuIcon].iconList; IVar5 = pIVar1[uVar6]; if ((IVar5 == Interface_MenuItem_PowerOn) || (IVar5 == Interface_MenuItem_PowerOff)) { IVar5 = Interface_GetPrimaryUnit_PowerIcon(pIVar1 + uVar6); } iVar2 = (*(code *)callback)(IVar5,0,0,context); if (iVar2 != 0) break; uVar6 += 1; if (globs::interfaceGlobs.menuList[menuIcon].iconCount <= uVar6) { return 0; } } return 1; } } } } return 0; } BOOL __cdecl lego::front::Interface_Callback_FUN_0041b730 (Interface_MenuItemType menuIcon,uint param_2,int param_3,float *param_4) { Interface_MenuItemType IVar1; Image *image; Interface_MenuItemFlags IVar2; IVar1 = menuIcon; if (menuIcon == Interface_MenuItem_Build) { Interface_ChangeObjectIconFlag1_FUN_0041c730(param_2,param_3); image = Interface_GetBuildImageByObjectType(param_2,param_3); if (param_2 == 1) { IVar2 = globs::interfaceGlobs.vehicleItemFlags[param_3] & INTERFACE_MENUITEM_FLAG_FLASH; } else { IVar2 = param_2; if (param_2 == 4) { IVar2 = globs::interfaceGlobs.buildingItemFlags[param_3] & INTERFACE_MENUITEM_FLAG_FLASH; } } Interface_SetObjectIconFlag8(param_2,param_3,0); } else { Interface_ChangeIconFlag1_FUN_0041c6e0(menuIcon); image = Interface_FUN_0041c9e0(menuIcon); IVar2 = globs::interfaceGlobs.menuItemFlags[menuIcon] & INTERFACE_MENUITEM_FLAG_FLASH; Interface_SetIconFlag8(menuIcon,0); } Interface_FUN_0041c420(menuIcon,param_2,param_3,param_4); if (image == NULL) { menuIcon = Interface_MenuItem_DeleteBuilding; } else { menuIcon = image->height; if ((IVar2 == INTERFACE_MENUITEM_FLAG_NONE) || (globs::interfaceGlobs.flashingState != 0)) { lego::image::Image_DisplayScaled(image,NULL,(Point2F *)param_4,NULL); } } if (IVar1 == Interface_MenuItem_TeleportMan) { param_3 = 0; param_2 = LegoObject_MiniFigure; } else { if (IVar1 != Interface_MenuItem_Build) goto LAB_0041b82e; } Interface_DrawTeleportQueueNumber(param_2,param_3,(Point2F *)param_4); LAB_0041b82e: param_4[1] = (float)(ulonglong)menuIcon + param_4[1]; return 0; } void __cdecl lego::front::Interface_FUN_0041b860(float elapsedAbs) { globs::interfaceGlobs.timer_fc8 = globs::interfaceGlobs.timer_fc8 - elapsedAbs; if (globs::interfaceGlobs.timer_fc8 < 0.0) { globs::interfaceGlobs.flashingState = ZEXT14(globs::interfaceGlobs.flashingState == 0); globs::interfaceGlobs.timer_fc8 = 15.0; } Interface_FUN_0041e9f0(elapsedAbs); if ((ushort)((ushort)(globs::interfaceGlobs.float_1494 < 0.0) << 8 | (ushort)(globs::interfaceGlobs.float_1494 == 0.0) << 0xe) == 0) { globs::interfaceGlobs.float_1494 = globs::interfaceGlobs.float_1494 - elapsedAbs; return; } globs::interfaceGlobs.flags = globs::interfaceGlobs.flags | INTERFACE_GLOB_FLAG_UNK_800; return; } BOOL __cdecl lego::front::Interface_GetFlashingState(void) { return globs::interfaceGlobs.flashingState; } // Result is same as final value of *ref_param_1 (param_1 may not be changed) Interface_MenuItemType __cdecl lego::front::Interface_GetPrimaryUnit_PowerIcon(Interface_MenuItemType *ref_menuIcon) { LegoObject *primaryUnit; primaryUnit = game::Message_GetPrimarySelectedUnit(); if (((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) == INTERFACE_GLOB_FLAG_NONE) && ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_100) != INTERFACE_GLOB_FLAG_NONE)) { return *ref_menuIcon; } if ((primaryUnit->flags3 & LIVEOBJ3_POWEROFF) != LIVEOBJ3_NONE) { *ref_menuIcon = Interface_MenuItem_PowerOn; return Interface_MenuItem_PowerOn; } *ref_menuIcon = Interface_MenuItem_PowerOff; return Interface_MenuItem_PowerOff; } void __cdecl lego::front::Interface_FUN_0041b940(float elapsedAbs) { SFX_ID SVar1; SVar1 = globs::interfaceGlobs.sfxType_149c; if (globs::interfaceGlobs.sfxType_149c != globs::interfaceGlobs.sfxType_14a4) { globals::g_Interface_TIMER_004a3b58 = 25.0; globs::interfaceGlobs.sfxType_149c = SFX_NULL; globs::interfaceGlobs.sfxType_14a4 = SVar1; globs::interfaceGlobs.sfxPlaying = 0; return; } globals::g_Interface_TIMER_004a3b58 = globals::g_Interface_TIMER_004a3b58 - elapsedAbs; if (((ushort)((ushort)(globals::g_Interface_TIMER_004a3b58 < 0.0) << 8 | (ushort)(globals::g_Interface_TIMER_004a3b58 == 0.0) << 0xe) != 0) && (globs::interfaceGlobs.sfxPlaying == 0)) { globs::interfaceGlobs.sfxPlaying = snd::SFX_Random_SetAndPlayGlobalSample(globs::interfaceGlobs.sfxType_149c,NULL); } globs::interfaceGlobs.sfxType_149c = SFX_NULL; return; } void __cdecl lego::front::Interface_SetSFX_004df1f4(SFX_ID sfxType) { globs::interfaceGlobs.sfxType_149c = sfxType; return; } BOOL __cdecl lego::front::Interface_DoSomethingWithRenameReplace (uint param_1,uint param_2,int param_3,int param_4,int param_5) { Image *pIVar1; char cVar2; Interface_GlobFlags IVar3; BOOL BVar4; char *pcVar5; LegoObject *pLVar6; uint uVar7; uint uVar8; uint uVar9; char *pcVar10; char **ppcVar11; Image *image; undefined4 *puVar12; int iVar13; char *pcVar14; undefined4 *puVar15; longlong lVar16; SFX_ID sfxType; Interface_MenuItemType local_a78; LegoObject_ID local_a74; uint local_a70; LegoObject_Type local_a6c; LegoObject_ID local_a68; LegoObject_Type local_a64; int local_a60; uint local_a5c; uint local_a58; uint local_a54; char *local_a50 [20]; char local_a00 [512]; char local_800 [512]; char local_600 [512]; char local_400 [1024]; pcVar10 = NULL; local_a70 = 0; local_a60 = 0; if (((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_4) == INTERFACE_GLOB_FLAG_NONE) || ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) == INTERFACE_GLOB_FLAG_NONE)) { globs::interfaceGlobs.flags = globs::interfaceGlobs.flags & ~(INTERFACE_GLOB_FLAG_UNK_200|INTERFACE_GLOB_FLAG_UNK_400|INTERFACE_GLOB_FLAG_UNK_1000| INTERFACE_GLOB_FLAG_UNK_2000|INTERFACE_GLOB_FLAG_UNK_4000); return 0; } globs::interfaceGlobs.flags = globs::interfaceGlobs.flags & ~(INTERFACE_GLOB_FLAG_UNK_200|INTERFACE_GLOB_FLAG_UNK_400|INTERFACE_GLOB_FLAG_UNK_1000| INTERFACE_GLOB_FLAG_UNK_2000|INTERFACE_GLOB_FLAG_UNK_4000); BVar4 = Interface_FUN_0041edb0 (param_1,param_2,globs::interfaceGlobs.areaf_fb4.x, globs::interfaceGlobs.areaf_fb4.y,&local_a64,&local_a68,&local_a5c); if (BVar4 != 0) { globs::interfaceGlobs.flags |= INTERFACE_GLOB_FLAG_UNK_1000; if (((param_3 == 0) && (param_5 == 0)) && (local_a64 != LegoObject_Type_Count)) { pcVar10 = globs::legoGlobs.langUpgradeLevel_name[local_a5c]; if (pcVar10 == NULL) { pcVar10 = game::Object_GetLangName(local_a64,local_a68); std::sprintf(local_800,"%s",pcVar10); } else { pcVar5 = game::Object_GetLangName(local_a64,local_a68); std::sprintf(local_800,"%s (%s)",pcVar5,pcVar10); } ToolTip_SetContent(ToolTip_InterfaceMenu,local_800); ToolTip_Activate(ToolTip_InterfaceMenu); ToolTip_ShowInstant(ToolTip_InterfaceMenu); if ((globs::legoGlobs.flags2 & GAME2_DISABLETOOLTIPSOUND) == GAME2_NONE) { Interface_SetSFX_004df1f4(globs::objectGlobs.objectTtSFX[local_a64][local_a68]); } } Interface_FUN_0041c610(Interface_MenuItem_Back,0,0,param_3,param_4); return TRUE; } BVar4 = Interface_FUN_0041c0f0(param_1,param_2,&local_a78,&local_a6c,&local_a74); if (BVar4 == 0) { uVar7 = Interface_GetBuildMenuIconCount(globs::interfaceGlobs.currMenuType); BVar4 = Interface_MenuTypeHasBackButton(globs::interfaceGlobs.currMenuType); if (BVar4 == 0) { image = (Image *)(&globs::interfaceGlobs.iconPanelIconOffsets[10].y)[uVar7]; lVar16 = __ftol((float10)(float)globs::interfaceGlobs.iconPanelNoBackImages[uVar7 * 2 + 9] + (float10)globs::interfaceGlobs.currMenuPosition.x); iVar13 = (int)lVar16; pIVar1 = globs::interfaceGlobs.iconPanelNoBackImages[uVar7 * 2 + 10]; } else { image = globs::interfaceGlobs.iconPanelImages[uVar7 - 1]; lVar16 = __ftol((float10)(float)globs::interfaceGlobs.iconPanelImages[uVar7 * 2 + 9] + (float10)globs::interfaceGlobs.currMenuPosition.x); iVar13 = (int)lVar16; pIVar1 = globs::interfaceGlobs.iconPanelImages[uVar7 * 2 + 10]; } lVar16 = __ftol((float10)(float)pIVar1 + (float10)globs::interfaceGlobs.currMenuPosition.y); if (image == NULL) { return local_a70; } BVar4 = lego::image::Image_GetPixel(image,param_1 - iVar13,param_2 - (int)lVar16,&local_a58); if (BVar4 == 0) { return local_a70; } if (local_a58 == 0) { return local_a70; } if (param_5 != 0) { lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); } return TRUE; } if (local_a78 == Interface_MenuItem_Back) { globs::interfaceGlobs.flags |= INTERFACE_GLOB_FLAG_UNK_4000; ToolTip_Activate(ToolTip_InterfaceMenuBackButton); goto LAB_0041bf5c; } if (local_a78 == Interface_MenuItem_Build) { globs::interfaceGlobs.flags = globs::interfaceGlobs.flags & 0xffff0000 | (uint)(ushort)(CONCAT11((char)((globs::interfaceGlobs.flags | INTERFACE_GLOB_FLAG_UNK_200) >> 8),(char)globs::interfaceGlobs.flags) | 0x400) | INTERFACE_GLOB_FLAG_UNK_2000; pcVar10 = game::Object_GetLangName(local_a6c,local_a74); std::sprintf(local_a00,"%s",pcVar10); if ((globs::legoGlobs.flags2 & GAME2_DISABLETOOLTIPSOUND) == GAME2_NONE) { Interface_SetSFX_004df1f4(globs::objectGlobs.objectTtSFX[local_a6c][local_a74]); pcVar5 = local_a00; } else { LAB_0041bec2: pcVar5 = local_a00; } } else { if ((local_a78 == Interface_MenuItem_LayPath) || (IVar3 = globs::interfaceGlobs.flags | INTERFACE_GLOB_FLAG_UNK_200, local_a78 == Interface_MenuItem_PlaceFence)) { IVar3 = globs::interfaceGlobs.flags | (INTERFACE_GLOB_FLAG_UNK_200|INTERFACE_GLOB_FLAG_UNK_2000); } globs::interfaceGlobs.flags = IVar3; BVar4 = Interface_GetIconUnk_FUN_0041c820(local_a78,0); if (BVar4 == 0) { pcVar5 = globs::interfaceGlobs.langMenuItemTexts[local_a78]; if ((pcVar5 != NULL) && (pcVar10 = pcVar5, (globs::legoGlobs.flags2 & GAME2_DISABLETOOLTIPSOUND) == GAME2_NONE)) { sfxType = globs::interfaceGlobs.sfxMenuItemTexts[local_a78]; LAB_0041bd3e: Interface_SetSFX_004df1f4(sfxType); pcVar10 = pcVar5; } } else { if (globs::interfaceGlobs.langMenuItemTexts_no[local_a78] != NULL) { pLVar6 = game::Message_GetPrimarySelectedUnit(); if (((((pLVar6 == NULL) || (local_a78 != Interface_MenuItem_UpgradeBuilding)) || (uVar7 = stats::Stats_GetLevels(pLVar6->type,pLVar6->id), uVar7 <= pLVar6->objLevel + 1 )) || ((uVar7 = game::Level_GetOreCount(0), (uint)globs::legoGlobs.BuildingUpgradeCostOre <= uVar7 || (uVar7 = game::Level_GetOreCount(1), (uint)globs::legoGlobs.BuildingUpgradeCostStuds <= uVar7)))) || (globs::objectGlobs.ToolTipIcon_Ore == NULL)) { pcVar10 = globs::interfaceGlobs.langMenuItemTexts_no[local_a78]; } else { if (globs::legoGlobs.langOreRequired_toolTip != NULL) { std::sprintf(local_400,"%s",globs::legoGlobs.langOreRequired_toolTip); pcVar10 = local_400; } local_a60 = game::Level_GetOreCount(0); local_a60 = globs::legoGlobs.BuildingUpgradeCostOre - local_a60; } if ((globs::legoGlobs.flags2 & GAME2_DISABLETOOLTIPSOUND) == GAME2_NONE) { sfxType = globs::interfaceGlobs.sfxMenuItemTexts_no[local_a78]; pcVar5 = pcVar10; goto LAB_0041bd3e; } } } pcVar5 = NULL; if (((pcVar10 != NULL) && (pcVar5 = pcVar10, globs::interfaceGlobs.menuItemUnkBools[local_a78] != 0)) && ((uVar7 = game::Message_GetNumSelectedUnits(), uVar7 == 1 && (((pLVar6 = game::Message_GetPrimarySelectedUnit(), pLVar6 != NULL && (pLVar6 = game::Message_GetPrimarySelectedUnit(), pLVar6->customName != NULL)) && (pLVar6 = game::Message_GetPrimarySelectedUnit(), *pLVar6->customName != '\0')))))) { uVar7 = 0xffffffff; pcVar5 = globs::legoGlobs.RenameReplace; do { pcVar14 = pcVar5; if (uVar7 == 0) break; uVar7 -= 1; pcVar14 = pcVar5 + 1; cVar2 = *pcVar5; pcVar5 = pcVar14; } while (cVar2 != '\0'); uVar7 = ~uVar7; puVar12 = (undefined4 *)(pcVar14 + -uVar7); puVar15 = (undefined4 *)local_800; for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar15 = *puVar12; puVar12 = puVar12 + 1; puVar15 = puVar15 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } uVar7 = 0xffffffff; do { pcVar5 = pcVar10; if (uVar7 == 0) break; uVar7 -= 1; pcVar5 = pcVar10 + 1; cVar2 = *pcVar10; pcVar10 = pcVar5; } while (cVar2 != '\0'); uVar7 = ~uVar7; puVar12 = (undefined4 *)(pcVar5 + -uVar7); puVar15 = (undefined4 *)local_600; for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar15 = *puVar12; puVar12 = puVar12 + 1; puVar15 = puVar15 + 1; } pcVar10 = local_800; for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } while (local_800[0] != '\0') { if (*pcVar10 == ' ') { *pcVar10 = '_'; } pcVar5 = pcVar10 + 1; pcVar10 = pcVar10 + 1; local_800[0] = *pcVar5; } local_a54 = util::Util_Tokenise(local_600,local_a50,local_800); uVar7 = 0; local_a00[0] = '\0'; if (local_a54 != 0) { local_a70 = local_a54 - 1; ppcVar11 = local_a50; do { uVar8 = 0xffffffff; pcVar10 = *ppcVar11; do { pcVar5 = pcVar10; if (uVar8 == 0) break; uVar8 -= 1; pcVar5 = pcVar10 + 1; cVar2 = *pcVar10; pcVar10 = pcVar5; } while (cVar2 != '\0'); uVar8 = ~uVar8; iVar13 = -1; pcVar10 = local_a00; do { pcVar14 = pcVar10; if (iVar13 == 0) break; iVar13 += -1; pcVar14 = pcVar10 + 1; cVar2 = *pcVar10; pcVar10 = pcVar14; } while (cVar2 != '\0'); puVar12 = (undefined4 *)(pcVar5 + -uVar8); puVar15 = (undefined4 *)(pcVar14 + -1); for (uVar9 = uVar8 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar12; puVar12 = puVar12 + 1; puVar15 = puVar15 + 1; } for (uVar8 &= 3; uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } if (uVar7 < local_a70) { pLVar6 = game::Message_GetPrimarySelectedUnit(); uVar8 = 0xffffffff; pcVar10 = pLVar6->customName; do { pcVar5 = pcVar10; if (uVar8 == 0) break; uVar8 -= 1; pcVar5 = pcVar10 + 1; cVar2 = *pcVar10; pcVar10 = pcVar5; } while (cVar2 != '\0'); uVar8 = ~uVar8; iVar13 = -1; pcVar10 = local_a00; do { pcVar14 = pcVar10; if (iVar13 == 0) break; iVar13 += -1; pcVar14 = pcVar10 + 1; cVar2 = *pcVar10; pcVar10 = pcVar14; } while (cVar2 != '\0'); puVar12 = (undefined4 *)(pcVar5 + -uVar8); puVar15 = (undefined4 *)(pcVar14 + -1); for (uVar9 = uVar8 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar12; puVar12 = puVar12 + 1; puVar15 = puVar15 + 1; } for (uVar8 &= 3; uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } } uVar7 += 1; ppcVar11 = ppcVar11 + 1; } while (uVar7 < local_a54); } goto LAB_0041bec2; } } if ((param_3 == 0) && (param_5 == 0)) { if (pcVar5 == NULL) { std::sprintf(local_a00,"Missing config for\n\'%s\'", globs::interfaceGlobs.menuItemName[local_a78]); ToolTip_SetContent(ToolTip_InterfaceMenu,local_a00); } else { ToolTip_SetContent(ToolTip_InterfaceMenu,pcVar5); for (iVar13 = local_a60; iVar13 != 0; iVar13 += -1) { ToolTip_AddIcon(ToolTip_InterfaceMenu,globs::objectGlobs.ToolTipIcon_Ore); } } ToolTip_Activate(ToolTip_InterfaceMenu); ToolTip_ShowInstant(ToolTip_InterfaceMenu); } else { Interface_SetSFX_004df1f4(SFX_NULL); } LAB_0041bf5c: BVar4 = Interface_FUN_0041c610(local_a78,local_a6c,local_a74,param_3,param_4); if ((BVar4 != 0) && (param_5 != 0)) { if (local_a78 == Interface_MenuItem_Build) { if ((globs::interfaceGlobs.currMenuType == Interface_Menu_BuildSmallVehicle) || (globs::interfaceGlobs.currMenuType == Interface_Menu_BuildLargeVehicle)) { globs::interfaceGlobs.vehicleItemClicks[local_a74] = globs::interfaceGlobs.vehicleItemClicks[local_a74] + 1; } else { if (globs::interfaceGlobs.currMenuType == Interface_Menu_BuildBuilding) { globs::interfaceGlobs.buildingItemClicks[local_a74] = globs::interfaceGlobs.buildingItemClicks[local_a74] + 1; } } } else { globs::interfaceGlobs.menuItemClicks[local_a78] = globs::interfaceGlobs.menuItemClicks[local_a78] + 1; } BVar4 = Interface_DoAction_FUN_0041dbd0(local_a78); lrr::Lego_SetPointerSFX((uint)(BVar4 == 0)); } return 1; } BOOL __cdecl lego::front::Interface_FUN_0041c0f0 (uint param_1,uint param_2,undefined4 *out_param_3,undefined4 *out_param_4, undefined4 *out_param_5) { float fVar1; float fVar2; float fVar3; uint uVar4; BOOL BVar5; uint local_1c; uint local_18; float local_14; float local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; uVar4 = Interface_GetBuildMenuIconCount(globs::interfaceGlobs.currMenuType); BVar5 = Interface_MenuTypeHasBackButton(globs::interfaceGlobs.currMenuType); if (BVar5 != 0) { fVar3 = (float)(ulonglong)param_1; fVar1 = globs::interfaceGlobs.iconPanelBackButtonOffsets[uVar4 - 1].x + globs::interfaceGlobs.currMenuPosition.x; fVar2 = globs::interfaceGlobs.iconPanelBackButtonOffsets[uVar4 - 1].y + globs::interfaceGlobs.currMenuPosition.y; if ((((fVar1 <= fVar3) && (fVar1 = (float)(ulonglong)(uint)globs::interfaceGlobs.backButtonSize.width + fVar1, (ushort)((ushort)(fVar3 < fVar1) << 8 | (ushort)(fVar3 == fVar1) << 0xe) != 0)) && (fVar1 = (float)(ulonglong)param_2, fVar2 <= fVar1)) && (fVar2 = (float)(ulonglong)(uint)globs::interfaceGlobs.backButtonSize.height + fVar2, (ushort)((ushort)(fVar1 < fVar2) << 8 | (ushort)(fVar1 == fVar2) << 0xe) != 0)) { *out_param_3 = 0; return TRUE; } } local_14 = globs::interfaceGlobs.currMenuPosition.x; local_1c = param_1; local_18 = param_2; local_10 = globs::interfaceGlobs.currMenuPosition.y; BVar5 = Interface_FUN_0041b5b0 (globs::interfaceGlobs.currMenuType,Interface_Callback_FUN_0041c240,&local_1c); if (BVar5 == 0) { return FALSE; } *out_param_3 = local_c; *out_param_4 = local_8; *out_param_5 = local_4; return TRUE; } BOOL __cdecl lego::front::Interface_Callback_FUN_0041c240 (Interface_MenuItemType menuIcon,LegoObject_Type objType,LegoObject_ID objID,uint *param_4 ) { Point2F *point; float fVar1; float fVar2; Image *pIVar3; uint uVar4; Interface_MenuItemType menuIcon_00; menuIcon_00 = menuIcon; if (menuIcon == Interface_MenuItem_Build) { pIVar3 = Interface_GetBuildImageByObjectType(objType,objID); } else { pIVar3 = Interface_FUN_0041c9e0(menuIcon); } if (pIVar3 == NULL) { uVar4 = 0x28; menuIcon = Interface_MenuItem_DeleteBuilding; } else { menuIcon = pIVar3->width; uVar4 = pIVar3->height; } point = (Point2F *)(param_4 + 2); fVar1 = (float)(ulonglong)*param_4; if ((((point->x <= fVar1) && (fVar2 = (float)(ulonglong)menuIcon + point->x, (ushort)((ushort)(fVar1 < fVar2) << 8 | (ushort)(fVar1 == fVar2) << 0xe) != 0)) && (fVar1 = (float)(ulonglong)param_4[1], (float)param_4[3] <= fVar1)) && ((ushort)((ushort)(fVar1 < (float)(ulonglong)uVar4 + (float)param_4[3]) << 8 | (ushort)(fVar1 == (float)(ulonglong)uVar4 + (float)param_4[3]) << 0xe) != 0)) { param_4[4] = menuIcon_00; Interface_SetDat_004decd8_004decdc(menuIcon_00,objType,objID); if (menuIcon_00 == Interface_MenuItem_Build) { param_4[5] = objType; param_4[6] = objID; } Interface_FUN_0041cc10(point,menuIcon + Interface_MenuItem_Type_Invalid,uVar4 - 1); return TRUE; } param_4[3] = (uint)((float)(ulonglong)uVar4 + (float)param_4[3]); return 0; } void __cdecl lego::front::Interface_DoF2InterfaceKeyAction(void) { // IsKeyDown(KEY_F2) (60) // "F2 configurable interface actions." if (((((byte)globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_4) != 0) && (((byte)globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) != 0)) && (globs::INPUT.Key_Map[60] != false)) { Interface_FUN_0041b5b0 (globs::interfaceGlobs.currMenuType,Interface_CallbackDoMenuIconKeyAction,NULL); } return; } BOOL __cdecl lego::front::Interface_CallbackDoMenuIconKeyAction (Interface_MenuItemType menuIcon,LegoObject_Type objType,LegoObject_ID objID) { Interface_MenuItemType menuIcon_00; menuIcon_00 = menuIcon; if (menuIcon == Interface_MenuItem_Build) { if (objType == LegoObject_Vehicle) { menuIcon = (Interface_MenuItemType)globs::interfaceGlobs.vehicleItemF2Keys[objID]; } else { if (objType == LegoObject_Building) { menuIcon = (Interface_MenuItemType)globs::interfaceGlobs.buildingItemF2Keys[objID]; } } } else { menuIcon = (Interface_MenuItemType)globs::interfaceGlobs.menuItemF2keys[menuIcon]; } if ((globs::INPUT.Key_Map[menuIcon & 0xff] != false) && (globs::INPUT.prevKey_Map[menuIcon & 0xff] != globs::INPUT.Key_Map[menuIcon & 0xff])) { Interface_SetDat_004decd8_004decdc(menuIcon_00,objType,objID); Interface_DoAction_FUN_0041dbd0(menuIcon_00); } return 0; } void __cdecl lego::front::Interface_FUN_0041c420 (Interface_MenuItemType menuIcon,LegoObject_Type objType,LegoObject_ID objID, float *param_4) { bool bVar1; bool bVar2; BOOL BVar3; uint uVar4; float local_18; float fStack20; Point2F origPos; bVar2 = false; if (((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_20) != INTERFACE_GLOB_FLAG_NONE) && (BVar3 = Advisor_IsAnimating(), BVar3 == 0)) { bVar1 = false; if (globs::interfaceGlobs.menuItemType_fd0 == Interface_MenuItem_Build) { if ((globs::interfaceGlobs.objType_fd4 == objType) && (globs::interfaceGlobs.objID_fd8 == objID)) { objType = (LegoObject_Type)Interface_GetBuildImageByObjectType(objType,objID); bVar1 = true; } } else { if (menuIcon == globs::interfaceGlobs.menuItemType_fd0) { if (menuIcon == Interface_MenuItem_Back) { bVar2 = true; bVar1 = true; } else { objType = (LegoObject_Type)Interface_FUN_0041c9e0(menuIcon); bVar1 = true; } } } if (bVar1) { if (bVar2) { uVar4 = Interface_GetBuildMenuIconCount(globs::interfaceGlobs.currMenuType); if ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) == INTERFACE_GLOB_FLAG_NONE) { local_18 = globs::interfaceGlobs.iconPanelBackButtonOffsets[uVar4 - 1].x + globs::interfaceGlobs.slideEndPosition.x; } else { local_18 = globs::interfaceGlobs.iconPanelBackButtonOffsets[uVar4 - 1].x + globs::interfaceGlobs.currMenuPosition.x; } local_18 = local_18 - (float)(ulonglong)(uint)globs::interfaceGlobs.backButtonSize.width * -0.5; fStack20 = (globs::interfaceGlobs.iconPanelBackButtonOffsets[uVar4 - 1].y + globs::interfaceGlobs.currMenuPosition.y) - (float)(ulonglong)(uint)globs::interfaceGlobs.backButtonSize.height * -0.5; } else { if ((Image *)objType == NULL) { uVar4 = 0x28; } else { uVar4 = *(uint *)(objType + 8); } local_18 = *param_4; if ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) == INTERFACE_GLOB_FLAG_NONE) { local_18 = globs::interfaceGlobs.slideEndPosition.x; } fStack20 = (float)(ulonglong)uVar4 * 0.5 + param_4[1]; } Advisor_GetOrigPos(globs::interfaceGlobs.advisorType_fcc,&origPos.x,&origPos.y); Advisor_SetParameters (globs::interfaceGlobs.advisorType_fcc,Panel_Type_Count,origPos.x + local_18, origPos.y + fStack20); Advisor_Start(globs::interfaceGlobs.advisorType_fcc, globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_40); globs::interfaceGlobs.flags &= ~INTERFACE_GLOB_FLAG_UNK_20; } } return; } BOOL __cdecl lego::front::Interface_FUN_0041c610 (Interface_MenuItemType menuIcon,int param_2,int param_3,BOOL param_4,BOOL param_5) { Interface_MenuItemType IVar1; IVar1 = globs::interfaceGlobs.menuItemType_fa8; if (param_4 == 0) { globs::interfaceGlobs.menuItemType_fa8 = Interface_MenuItem_Type_Count; } else { if ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_1000) == INTERFACE_GLOB_FLAG_NONE) { if (globs::interfaceGlobs.menuItemType_fa8 == Interface_MenuItem_Type_Count) { if (param_5 != 0) goto LAB_0041c6aa; globs::interfaceGlobs.menuItemType_fa8 = menuIcon; globs::interfaceGlobs.field_fac = param_2; globs::interfaceGlobs.field_fb0 = param_3; if (menuIcon == Interface_MenuItem_Build) { Interface_SetObjectIconFlag8(param_2,param_3,TRUE); goto LAB_0041c6aa; } } else { if (globs::interfaceGlobs.menuItemType_fa8 != menuIcon) goto LAB_0041c6aa; if (menuIcon == Interface_MenuItem_Build) { if ((globs::interfaceGlobs.field_fac == param_2) && (globs::interfaceGlobs.field_fb0 == param_3)) { Interface_SetObjectIconFlag8(param_2,param_3,TRUE); } goto LAB_0041c6aa; } } Interface_SetIconFlag8(menuIcon,TRUE); } } LAB_0041c6aa: if (IVar1 == menuIcon) { if (menuIcon != Interface_MenuItem_Build) { return TRUE; } if ((globs::interfaceGlobs.field_fac == param_2) && (globs::interfaceGlobs.field_fb0 == param_3) ) { return TRUE; } } return FALSE; } void __cdecl lego::front::Interface_ChangeIconFlag1_FUN_0041c6e0(Interface_MenuItemType menuIcon) { BOOL BVar1; Interface_MenuItemFlags IVar2; IVar2 = globs::interfaceGlobs.menuItemFlags[menuIcon]; if (((IVar2 & INTERFACE_MENUITEM_FLAG_UNK_2) == INTERFACE_MENUITEM_FLAG_NONE) && (((byte)globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) != 0)) { BVar1 = Interface_HandleMenuItem(menuIcon); IVar2 = globs::interfaceGlobs.menuItemFlags[menuIcon]; if (BVar1 != 0) { globs::interfaceGlobs.menuItemFlags[menuIcon] = IVar2 & ~INTERFACE_MENUITEM_FLAG_UNK_1; return; } } globs::interfaceGlobs.menuItemFlags[menuIcon] = IVar2 | INTERFACE_MENUITEM_FLAG_UNK_1; return; } void __cdecl lego::front::Interface_ChangeObjectIconFlag1_FUN_0041c730 (LegoObject_Type objType,LegoObject_ID objID) { BOOL BVar1; uint uVar2; int iVar3; Interface_MenuItemFlags IVar4; Interface_MenuItemFlags *pIVar5; if (objType == LegoObject_Vehicle) { IVar4 = globs::interfaceGlobs.vehicleItemFlags[objID]; pIVar5 = globs::interfaceGlobs.vehicleItemFlags; if (((IVar4 & INTERFACE_MENUITEM_FLAG_UNK_2) == INTERFACE_MENUITEM_FLAG_NONE) && (((byte)globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) != 0)) { BVar1 = Interface_HasTeleporterForObject(LegoObject_Vehicle,objID); if ((BVar1 != 0) && (BVar1 = game::Dependencies_Object_FUN_0040add0(LegoObject_Vehicle,objID,0), BVar1 != 0)) { uVar2 = stats::Stats_GetCostCrystal(LegoObject_Vehicle,objID,0); iVar3 = game::Level_GetCrystalCount(TRUE); if ((int)uVar2 <= iVar3) { globs::interfaceGlobs.vehicleItemFlags[objID] = globs::interfaceGlobs.vehicleItemFlags[objID] & ~INTERFACE_MENUITEM_FLAG_UNK_1; return; } } globs::interfaceGlobs.vehicleItemFlags[objID] = globs::interfaceGlobs.vehicleItemFlags[objID] | INTERFACE_MENUITEM_FLAG_UNK_1; return; } } else { if (objType != LegoObject_Building) { return; } IVar4 = globs::interfaceGlobs.buildingItemFlags[objID]; pIVar5 = globs::interfaceGlobs.buildingItemFlags; if (((IVar4 & INTERFACE_MENUITEM_FLAG_UNK_2) == INTERFACE_MENUITEM_FLAG_NONE) && (((byte)globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) != 0)) { BVar1 = Interface_HasTeleporterForObject(LegoObject_Building,objID); if ((BVar1 != 0) && (BVar1 = game::Dependencies_Object_FUN_0040add0(LegoObject_Building,objID,0), BVar1 != 0)) { globs::interfaceGlobs.buildingItemFlags[objID] = globs::interfaceGlobs.buildingItemFlags[objID] & ~INTERFACE_MENUITEM_FLAG_UNK_1; return; } globs::interfaceGlobs.buildingItemFlags[objID] = globs::interfaceGlobs.buildingItemFlags[objID] | INTERFACE_MENUITEM_FLAG_UNK_1; return; } } pIVar5[objID] = IVar4 | INTERFACE_MENUITEM_FLAG_UNK_1; return; } BOOL __cdecl lego::front::Interface_GetIconUnk_FUN_0041c820(Interface_MenuItemType menuIcon,BOOL param_2) { TutorialFlags tflags; if (menuIcon == Interface_MenuItem_Build) { return INTERFACE_MENUITEM_FLAG_NONE; } if ((globs::legoGlobs.flags1 & GAME1_LASERTRACKER) != GAME1_NONE) { return INTERFACE_MENUITEM_FLAG_UNK_1; } if (param_2 != 0) { tflags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((tflags & TUTORIAL_FLAG_NOICONS) != TUTORIAL_NONE) { return ~globs::interfaceGlobs.menuItemFlags[menuIcon] >> 2 & INTERFACE_MENUITEM_FLAG_UNK_1; } } return globs::interfaceGlobs.menuItemFlags[menuIcon] & INTERFACE_MENUITEM_FLAG_UNK_1; } BOOL __cdecl lego::front::Interface_GetObjectIconUnk_FUN_0041c880 (LegoObject_Type objType,LegoObject_ID objID,BOOL param_3) { TutorialFlags TVar1; if ((globs::legoGlobs.flags1 & GAME1_LASERTRACKER) != GAME1_NONE) { return INTERFACE_MENUITEM_FLAG_UNK_1; } if (param_3 != 0) { TVar1 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((TVar1 & TUTORIAL_FLAG_NOICONS) != TUTORIAL_NONE) { if (objType == LegoObject_Vehicle) { return ~globs::interfaceGlobs.vehicleItemFlags[objID] >> 2 & INTERFACE_MENUITEM_FLAG_UNK_1; } if (objType == LegoObject_Building) { return ~globs::interfaceGlobs.buildingItemFlags[objID] >> 2 & INTERFACE_MENUITEM_FLAG_UNK_1; } } } if (objType == LegoObject_Vehicle) { return globs::interfaceGlobs.vehicleItemFlags[objID] & INTERFACE_MENUITEM_FLAG_UNK_1; } if (objType == LegoObject_Building) { return globs::interfaceGlobs.buildingItemFlags[objID] & INTERFACE_MENUITEM_FLAG_UNK_1; } return INTERFACE_MENUITEM_FLAG_NONE; } void __cdecl lego::front::Interface_SetIconFlag8(Interface_MenuItemType menuIcon,BOOL on) { if (on != 0) { globs::interfaceGlobs.menuItemFlags[menuIcon] = globs::interfaceGlobs.menuItemFlags[menuIcon] | INTERFACE_MENUITEM_FLAG_UNK_8; return; } globs::interfaceGlobs.menuItemFlags[menuIcon] = globs::interfaceGlobs.menuItemFlags[menuIcon] & ~INTERFACE_MENUITEM_FLAG_UNK_8; return; } void __cdecl lego::front::Interface_SetObjectIconFlag8(LegoObject_Type objType,LegoObject_ID objID,BOOL on) { Interface_MenuItemFlags *pIVar1; pIVar1 = globs::interfaceGlobs.vehicleItemFlags; if ((objType == LegoObject_Vehicle) || (pIVar1 = globs::interfaceGlobs.buildingItemFlags, objType == LegoObject_Building)) { if (on != 0) { pIVar1[objID] = pIVar1[objID] | INTERFACE_MENUITEM_FLAG_UNK_8; return; } pIVar1[objID] = pIVar1[objID] & ~INTERFACE_MENUITEM_FLAG_UNK_8; } return; } BOOL __cdecl lego::front::Interface_GetIconFlag8(Interface_MenuItemType menuIcon) { return globs::interfaceGlobs.menuItemFlags[menuIcon] & INTERFACE_MENUITEM_FLAG_UNK_8; } BOOL __cdecl lego::front::Interface_GetObjectIconFlag8(LegoObject_Type objType,LegoObject_ID objID) { if (objType == LegoObject_Vehicle) { return globs::interfaceGlobs.vehicleItemFlags[objID] & INTERFACE_MENUITEM_FLAG_UNK_8; } if (objType == LegoObject_Building) { return globs::interfaceGlobs.buildingItemFlags[objID] & INTERFACE_MENUITEM_FLAG_UNK_8; } return INTERFACE_MENUITEM_FLAG_NONE; } Image * __cdecl lego::front::Interface_FUN_0041c9e0(Interface_MenuItemType menuIcon) { BOOL BVar1; BVar1 = Interface_GetIconUnk_FUN_0041c820(menuIcon,FALSE); if (BVar1 != 0) { return globs::interfaceGlobs.menuItemIcons_no[menuIcon]; } BVar1 = Interface_GetIconFlag8(menuIcon); if (BVar1 != 0) { return globs::interfaceGlobs.menuItemIcons_pr[menuIcon]; } return globs::interfaceGlobs.menuItemIcons[menuIcon]; } Image * __cdecl lego::front::Interface_GetBuildImageByObjectType(LegoObject_Type objType,LegoObject_ID objID) { BOOL BVar1; BVar1 = Interface_GetObjectIconUnk_FUN_0041c880(objType,objID,0); if (BVar1 == 0) { BVar1 = Interface_GetObjectIconFlag8(objType,objID); if (BVar1 == 0) { if (objType == LegoObject_Vehicle) { return globs::interfaceGlobs.vehicleItemIcons[objID]; } if (objType == LegoObject_Building) { return globs::interfaceGlobs.buildingItemIcons[objID]; } } else { if (objType == LegoObject_Vehicle) { return globs::interfaceGlobs.vehicleItemIcons_pr[objID]; } if (objType == LegoObject_Building) { return globs::interfaceGlobs.buildingItemIcons_pr[objID]; } } } else { if (objType == LegoObject_Vehicle) { return globs::interfaceGlobs.vehicleItemIcons_no[objID]; } if (objType == LegoObject_Building) { return globs::interfaceGlobs.buildingItemIcons_no[objID]; } } return NULL; } Image * __cdecl lego::front::Interface_GetObjectBuildImage(LegoObject_Type objType,LegoObject_ID objID,BOOL param_3) { if (param_3 == 0) { if (true) { switch(objType) { case LegoObject_Vehicle: return globs::interfaceGlobs.vehicleItemIcons_no[objID]; case LegoObject_MiniFigure: return globs::interfaceGlobs.menuItemIcons_no[1]; case LegoObject_Building: return globs::interfaceGlobs.buildingItemIcons_no[objID]; case LegoObject_ElectricFence: return globs::interfaceGlobs.menuItemIcons_no[14]; case LegoObject_Path: return globs::interfaceGlobs.menuItemIcons_no[5]; } } } else { if (true) { switch(objType) { case LegoObject_Vehicle: return globs::interfaceGlobs.vehicleItemIcons[objID]; case LegoObject_MiniFigure: return globs::interfaceGlobs.menuItemIcons[1]; case LegoObject_Building: return globs::interfaceGlobs.buildingItemIcons[objID]; case LegoObject_ElectricFence: return globs::interfaceGlobs.menuItemIcons[14]; case LegoObject_Path: return globs::interfaceGlobs.menuItemIcons[5]; } } } return NULL; } void __cdecl lego::front::Interface_SetDat_004decd8_004decdc (Interface_MenuItemType menuIcon,LegoObject_Type objType,LegoObject_ID objID) { if (menuIcon == Interface_MenuItem_Build) { globs::interfaceGlobs.objType_f80 = objType; globs::interfaceGlobs.objID_f84 = objID; return; } if (menuIcon == Interface_MenuItem_LayPath) { globs::interfaceGlobs.objType_f80 = LegoObject_Path; globs::interfaceGlobs.objID_f84 = 0; return; } if (menuIcon == Interface_MenuItem_PlaceFence) { globs::interfaceGlobs.objType_f80 = LegoObject_ElectricFence; globs::interfaceGlobs.objID_f84 = 0; } return; } void __cdecl lego::front::Interface_FUN_0041cc10(Point2F *point,uint unkWidth,uint unkHeight) { globs::interfaceGlobs.areaf_fb4.x = point->x; globs::interfaceGlobs.areaf_fb4.y = point->y; globs::interfaceGlobs.areaf_fb4.width = (float)(ulonglong)unkWidth; globs::interfaceGlobs.areaf_fb4.height = (float)(ulonglong)unkHeight; return; } // Draws a green 2-pixel width rectangle around the specified rect (drawing 1 and 2 pixels outside // of area). // // Passed area must subtract 1 from width/height so that there isn't a gap between the edge and the // start of the border on the bottom/right side. void __cdecl lego::front::Interface_DrawHoverOutline(Area2F *area) { Point2F rectLines [5]; if ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) { // Draw for rect expanded by 1 pixel. // Then draw for rect expanded by 2 pixels, for a 2-pixel-width rectangle outline. rectLines[0].x = area->x - 1.0; rectLines[0].y = area->y - 1.0; rectLines[2].y = (area->height + area->y) - -1.0; rectLines[1].x = (area->x + area->width) - -1.0; rectLines[1].y = rectLines[0].y; rectLines[2].x = rectLines[1].x; rectLines[3].x = rectLines[0].x; rectLines[3].y = rectLines[2].y; rectLines[4].x = rectLines[0].x; rectLines[4].y = rectLines[0].y; draw::Draw_LineListEx(rectLines,rectLines + 1,4,0.0,1.0,0.0,DrawEffect_None); rectLines[0].x = area->x - 2.0; rectLines[0].y = area->y - 2.0; rectLines[1].x = (area->x + area->width) - -2.0; rectLines[2].y = (area->height + area->y) - -2.0; rectLines[1].y = rectLines[0].y; rectLines[2].x = rectLines[1].x; rectLines[3].x = rectLines[0].x; rectLines[3].y = rectLines[2].y; rectLines[4].x = rectLines[0].x; rectLines[4].y = rectLines[0].y; draw::Draw_LineListEx(rectLines,rectLines + 1,4,0.0,1.0,0.0,DrawEffect_None); } return; } void __cdecl lego::front::Interface_ChangeMenu_IfVehicleMounted_IsLiveObject(LegoObject *liveObj) { uint uVar1; LegoObject **pSelectedObj; StatsFlags1 sflags1; uint uVar2; if (globs::interfaceGlobs.currMenuType == Interface_Menu_UnmannedVehicle) { uVar1 = game::Message_GetNumSelectedUnits(); pSelectedObj = game::Message_GetSelectedUnits(); for (uVar2 = uVar1; uVar2 != 0; uVar2 -= 1) { if (liveObj == *pSelectedObj) { if (uVar1 == 1) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && ((*(byte *)&liveObj->flags4 & LIVEOBJ4_DOCKOCCUPIED) == 0)) { Interface_OpenMenu(Interface_Menu_WaterVehicle,NULL); } else { Interface_OpenMenu(Interface_Menu_LandVehicle,NULL); } } else { Interface_BackToMain(); } } pSelectedObj = pSelectedObj + 1; } } return; } void __cdecl lego::front::Interface_ChangeMenu_IfPrimarySelectedVehicle_IsLiveObject(LegoObject *liveObj) { uint count; LegoObject **ppUnit; uint i; if (((globs::interfaceGlobs.currMenuType == Interface_Menu_LandVehicle) || (globs::interfaceGlobs.currMenuType == Interface_Menu_UpgradeVehicle)) || (globs::interfaceGlobs.currMenuType == Interface_Menu_WaterVehicle)) { count = game::Message_GetNumSelectedUnits(); ppUnit = game::Message_GetSelectedUnits(); for (i = count; i != 0; i -= 1) { if (liveObj->driveObject == *ppUnit) { if (count == 1) { Interface_OpenMenu(Interface_Menu_UnmannedVehicle,NULL); } else { Interface_BackToMain(); } } ppUnit = ppUnit + 1; } } return; } void __cdecl lego::front::Interface_BackToMain_IfSelectedWall_IsBlockPos(Point2I *blockPos) { if (((globs::interfaceGlobs.currMenuType == Interface_Menu_Wall) && (globs::interfaceGlobs.selBlockPos.x == blockPos->x)) && (globs::interfaceGlobs.selBlockPos.y == blockPos->y)) { Interface_BackToMain(); return; } return; } void __cdecl lego::front::Interface_BackToMain_IfSelectedGroundOrConstruction_IsBlockPos(Point2I *blockPos) { if ((((globs::interfaceGlobs.currMenuType == Interface_Menu_Ground) || (globs::interfaceGlobs.currMenuType == Interface_Menu_Construction)) && (globs::interfaceGlobs.selBlockPos.x == blockPos->x)) && (globs::interfaceGlobs.selBlockPos.y == blockPos->y)) { Interface_BackToMain(); return; } return; } void __cdecl lego::front::Interface_BackToMain_IfSelectedRubble_IsBlockPos(Point2I *blockPos) { if (((globs::interfaceGlobs.currMenuType == Interface_Menu_Rubble) && (globs::interfaceGlobs.selBlockPos.x == blockPos->x)) && (globs::interfaceGlobs.selBlockPos.y == blockPos->y)) { Interface_BackToMain(); return; } return; } void __cdecl lego::front::Interface_BackToMain_IfUnitIsSelected(LegoObject *liveObj) { BOOL BVar1; if (globs::legoGlobs.viewMode != ViewMode_FP) { BVar1 = game::Message_IsUnitSelected(liveObj,NULL); if (BVar1 != 0) { Interface_BackToMain(); return; } } return; } BOOL __cdecl lego::front::Interface_HandleMenuItem(Interface_MenuItemType menuIcon) { Interface_MenuItemType IVar1; LegoObject *liveObj; StatsFlags3 sflags3; StatsFlags1 sflags1; uint uVar2; BOOL BVar3; LegoObject_AbilityFlags LVar4; float10 fVar5; LegoObject_Type objType; code *callback; LegoObject_ToolType toolType; undefined *data; void *data_00; LegoObject_ID objID; int iVar6; LegoObject_Type local_8; int local_4; StatsFlags2 sflags2; Lego_SurfaceType8 terrain; liveObj = game::Message_GetPrimarySelectedUnit(); IVar1 = menuIcon; if (false) goto switchD_0041cf8b_caseD_2; switch(menuIcon) { case Interface_MenuItem_Back: if (globs::interfaceGlobs.nextMenuType == Interface_Menu_FP) { return 0; } break; case Interface_MenuItem_TeleportMan: lrr::Lego_GetObjectByName("Barracks",&local_8,&menuIcon,NULL); BVar3 = Interface_HasTeleporterForObject(LegoObject_MiniFigure,0); if (BVar3 == 0) { return 0; } BVar3 = game::Dependencies_Object_FUN_0040add0(LegoObject_MiniFigure,0,0); if (BVar3 == 0) { return 0; } BVar3 = game::LegoObject_CanSupportOxygenForType(LegoObject_MiniFigure,0,local_8,menuIcon); if (BVar3 == 0) { return 0; } break; case Interface_MenuItem_LayPath: BVar3 = game::Construction_Zone_ExistsAtBlock(&globs::interfaceGlobs.selBlockPos); if (BVar3 != 0) { return 0; } objID = game::Level_Block_IsPath(&globs::interfaceGlobs.selBlockPos); if (objID != 0) { return 0; } objType = LegoObject_Path; goto LAB_0041d8d5; case Interface_MenuItem_RemovePath: BVar3 = game::Level_Block_IsPath(&globs::interfaceGlobs.selBlockPos); if (BVar3 == 0) { return 0; } break; case Interface_MenuItem_RepairLava: BVar3 = game::Construction_Zone_ExistsAtBlock(&globs::interfaceGlobs.selBlockPos); if (BVar3 != 0) { return 0; } if ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::interfaceGlobs.selBlockPos.y + globs::interfaceGlobs.selBlockPos.x].terrain == Lego_SurfaceType8_Lava) { return 0; } break; case Interface_MenuItem_ClearRubble: BVar3 = game::Message_AnyUnitSelected(); if (BVar3 == 0) break; toolType = LegoObject_ToolType_Spade; goto LAB_0041d17f; case Interface_MenuItem_Dig: BVar3 = Interface_Block_FUN_0041f670(&globs::interfaceGlobs.selBlockPos); if (BVar3 == 0) { return 0; } BVar3 = game::Message_AnyUnitSelected(); if (BVar3 == 0) { BVar3 = Interface_ReqestDigBlock(&globs::interfaceGlobs.selBlockPos); if (BVar3 == 0) { return 0; } } else { BVar3 = ai::AITask_Game_SelectedUnits_UnkEquippedTool_FUN_00403110(LegoObject_ToolType_Drill); if ((BVar3 == 0) && (BVar3 = Interface_HasToolStore(), BVar3 == 0)) { return 0; } BVar3 = game::Level_FindSelectedUnit_BlockCheck_FUN_00431960 (globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y, FALSE); if (BVar3 == 0) { return 0; } } break; case Interface_MenuItem_Reinforce: BVar3 = Interface_Block_FUN_0041f670(&globs::interfaceGlobs.selBlockPos); if (BVar3 == 0) { return 0; } BVar3 = game::Level_Block_IsReinforced (globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y); if (BVar3 != 0) { return 0; } BVar3 = game::Level_Block_IsCorner (globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y); if (BVar3 != 0) { return 0; } BVar3 = game::LiveObject_CanReinforceBlock (NULL,globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y) ; if (BVar3 == 0) { return 0; } BVar3 = game::Message_AnyUnitSelected(); if (BVar3 == 0) { BVar3 = Interface_RequestReinforceBlock(&globs::interfaceGlobs.selBlockPos); if (BVar3 == 0) { return 0; } } else { BVar3 = ai::AITask_Game_SelectedUnits_UnkEquippedTool_FUN_00403110(LegoObject_ToolType_Hammer) ; if ((BVar3 == 0) && (BVar3 = Interface_HasToolStore(), BVar3 == 0)) { return 0; } BVar3 = game::Level_FindSelectedLiveObject_BlockReinforce_FUN_004319e0 (globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y); if (BVar3 == 0) { return 0; } } break; case Interface_MenuItem_Dynamite: BVar3 = Interface_Block_FUN_0041f670(&globs::interfaceGlobs.selBlockPos); if (BVar3 == 0) { return 0; } terrain = (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::interfaceGlobs.selBlockPos.y + globs::interfaceGlobs.selBlockPos.x].terrain; if (terrain == Lego_SurfaceType8_Immovable) { return 0; } if (terrain == Lego_SurfaceType8_RechargeSeam) { return 0; } BVar3 = game::Level_Block_IsWall (globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y); if (BVar3 == 0) { return 0; } BVar3 = game::Level_Block_IsBusy(&globs::interfaceGlobs.selBlockPos); if (BVar3 != 0) { return 0; } BVar3 = Interface_HasToolStore(); if (BVar3 == 0) { return 0; } BVar3 = Interface_HasObjectWithAbilities(ABILITY_FLAG_DYNAMITE); if (BVar3 != 0) break; BVar3 = Interface_HasObjectOfTypeID(LegoObject_MiniFigure,0); if (BVar3 == 0) { return 0; } sflags2 = STATS2_TRAINDYNAMITE; goto LAB_0041d599; case Interface_MenuItem_PlaceFence: BVar3 = game::Level_Block_IsFenceRequest (globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y); if (BVar3 != 0) { return 0; } BVar3 = game::ElectricFence_CanPlaceFenceAtBlock (globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y); if (BVar3 == 0) { return 0; } objID = 0; objType = LegoObject_ElectricFence; LAB_0041d8d5: BVar3 = game::Dependencies_Object_FUN_0040add0(objType,objID,objID); if (BVar3 == 0) { return 0; } break; case Interface_MenuItem_CancelConstruction: if (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::interfaceGlobs.selBlockPos.y + globs::interfaceGlobs.selBlockPos.x].flags1 & (BLOCK1_FOUNDATION|BLOCK1_LAYEDPATH)) == BLOCK1_NONE) { return 0; } BVar3 = game::Level_Block_IsPathBuilding(&globs::interfaceGlobs.selBlockPos); if (BVar3 != 0) { return 0; } BVar3 = game::Level_Block_IsPath(&globs::interfaceGlobs.selBlockPos); if (BVar3 != 0) { return 0; } BVar3 = game::Level_Block_IsSolidBuilding (globs::interfaceGlobs.selBlockPos.x,globs::interfaceGlobs.selBlockPos.y,TRUE) ; if (BVar3 != 0) { return 0; } break; case Interface_MenuItem_VehiclePickUp: case Interface_MenuItem_MinifigurePickUp: data_00 = NULL; callback = Interface_ObjectCallback_FUN_0041f400; goto LAB_0041d969; case Interface_MenuItem_UnLoadVehicle: case Interface_MenuItem_UnLoadMinifigure: if (((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && (liveObj->carriedObjects[0]->type == LegoObject_Barrier)) { return 0; } sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if (((sflags3 & STATS3_CARRYVEHICLES) != STATS3_NONE) && (BVar3 = game::LegoObject_UnkCarryingVehicle_FUN_00440080(liveObj), BVar3 == 0)) { return 0; } data_00 = NULL; callback = Interface_ObjectCallback_IsCarryingButNotStoring; goto LAB_0041d969; case Interface_MenuItem_GetIn: LVar4 = ABILITY_FLAG_SAILOR; sflags2 = STATS2_TRAINSAILOR; sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if ((sflags3 & STATS3_NEEDSPILOT) == STATS3_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CROSSLAND) != STATS1_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CROSSWATER) == STATS1_NONE) { LVar4 = ABILITY_FLAG_DRIVER; sflags2 = STATS2_TRAINDRIVER; } else { LVar4 = ABILITY_FLAG_PILOT; sflags2 = STATS2_TRAINPILOT; } } } else { LVar4 = ABILITY_FLAG_PILOT; sflags2 = STATS2_TRAINPILOT; } sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if (((sflags3 & STATS3_GETINATLAND) == STATS3_NONE) || ((*(byte *)&liveObj->flags4 & 0x40) != 0) ) { if ((LVar4 == ABILITY_FLAG_SAILOR) && ((*(byte *)&liveObj->flags4 & 0x40) == 0)) { return 0; } } else { BVar3 = game::LegoObject_CheckUnkGetInAtLand_FUN_0043a100(liveObj,NULL); if (BVar3 == 0) { return 0; } } if ((*(byte *)&liveObj->flags2 & LIVEOBJ2_UNK_10) != 0) { return 0; } BVar3 = Interface_HasObjectWithAbilities(LVar4); if (BVar3 != 0) break; BVar3 = Interface_HasObjectOfTypeID(LegoObject_MiniFigure,0); if (BVar3 == 0) { return 0; } goto LAB_0041d599; case Interface_MenuItem_GetOut: if ((*(byte *)&liveObj->flags1 & 1) != 0) { return 0; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) { return 0; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && (BVar3 = game::LegoObject_UnkGetTerrainGetOutAtLandBlock_FUN_0043a0d0(liveObj,NULL), BVar3 == 0)) && ((*(byte *)&liveObj->flags4 & LIVEOBJ4_DOCKOCCUPIED) == 0)) { return 0; } break; case Interface_MenuItem_GotoDock: if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_MOVING) != 0) { return 0; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) { return 0; } if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_DOCKOCCUPIED) != 0) { return 0; } iVar6 = game::LegoObject_Search_FUN_00438ca0(liveObj,TRUE); if (iVar6 == 0) { return 0; } break; case Interface_MenuItem_VehicleDig: if ((*(byte *)&liveObj->flags3 & LIVEOBJ3_CANDIG) == 0) { return 0; } if ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { return 0; } break; case Interface_MenuItem_LegoManDig: toolType = LegoObject_ToolType_Drill; LAB_0041d17f: BVar3 = ai::AITask_Game_SelectedUnits_UnkEquippedTool_FUN_00403110(toolType); if ((BVar3 == 0) && (BVar3 = Interface_HasToolStore(), BVar3 == 0)) { return 0; } break; case Interface_MenuItem_GoFeed: data_00 = NULL; callback = Interface_ObjectCallback_IsEnergyBelowMax; goto LAB_0041d969; case Interface_MenuItem_DropBirdScarer: data_00 = (void *)0x6; callback = Interface_ObjectCallback_HasToolEquipped_2; LAB_0041d969: BVar3 = Interface_DoSelectedUnits_Callback(callback,data_00); if (BVar3 == 0) { return 0; } break; case Interface_MenuItem_PowerOn: case Interface_MenuItem_PowerOff: sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_SELFPOWERED) != STATS2_NONE) { return 0; } if ((liveObj->flags3 & LIVEOBJ3_HASPOWER) == LIVEOBJ3_NONE) { return 0; } break; case Interface_MenuItem_Repair: BVar3 = Interface_DoSelectedUnits_Callback(Interface_ObjectCallback_IsHealthBelowMax,NULL); if (BVar3 == 0) { return 0; } BVar3 = Interface_HasObjectWithAbilities(ABILITY_FLAG_REPAIR); if (BVar3 != 0) break; BVar3 = Interface_HasObjectOfTypeID(LegoObject_MiniFigure,0); if (BVar3 == 0) { return 0; } sflags2 = STATS2_TRAINREPAIR; LAB_0041d599: BVar3 = Interface_HasStatsFlags2(sflags2); if (BVar3 == 0) { return 0; } break; case Interface_MenuItem_MakeTeleporterPrimary: BVar3 = game::LegoObject_IsSmallTeleporter(liveObj); if (((BVar3 == 0) && (BVar3 = game::LegoObject_IsBigTeleporter(liveObj), BVar3 == 0)) && (BVar3 = game::LegoObject_IsWaterTeleporter(liveObj), BVar3 == 0)) { return 0; } break; case Interface_MenuItem_EjectCrystal: BVar3 = game::LegoObject_CanSpawnCarryableObject(liveObj,LegoObject_PowerCrystal,0); if (BVar3 == 0) { return 0; } case Interface_MenuItem_EjectOre: BVar3 = game::LegoObject_CanSpawnCarryableObject(liveObj,LegoObject_Ore,0); if (BVar3 == 0) { return 0; } break; case Interface_MenuItem_DeleteVehicle: game::LegoObject_GetBlockPos(liveObj,(int *)&local_8,&local_4); if ((liveObj->driveObject != NULL) && (iVar6 = game::Lego_GetCrossTerrainType (liveObj->driveObject,local_8,local_4,local_8,local_4,TRUE), iVar6 == 0)) { return 0; } sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if (((((sflags3 & STATS3_CARRYVEHICLES) != STATS3_NONE) && ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) && (liveObj->carriedObjects[0] != NULL)) && (iVar6 = game::Lego_GetCrossTerrainType (liveObj->carriedObjects[0],local_8,local_4,local_8,local_4,TRUE), iVar6 == 0)) { return 0; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && ((*(byte *)&liveObj->flags4 & 0x40) == 0)) { return 0; } break; case Interface_MenuItem_GotoFirstPerson: if ((liveObj == globs::legoGlobs.objectFP) && ((globs::legoGlobs.cameraFP)->trackFPCameraFrame == 0)) { return 0; } break; case Interface_MenuItem_GotoSecondPerson: if ((liveObj == globs::legoGlobs.objectFP) && ((globs::legoGlobs.cameraFP)->trackFPCameraFrame == 1)) { return 0; } break; case Interface_MenuItem_GetTool: goto switchD_0041cf8b_caseD_30; case Interface_MenuItem_GetDrill: data = NULL; goto LAB_0041d741; case Interface_MenuItem_GetSpade: data = (undefined *)LegoObject_ToolType_Spade; goto LAB_0041d741; case Interface_MenuItem_GetHammer: data = (undefined *)LegoObject_ToolType_Hammer; goto LAB_0041d741; case Interface_MenuItem_GetSpanner: data = (undefined *)LegoObject_ToolType_Spanner; goto LAB_0041d741; case Interface_MenuItem_GetLaser: data = &DAT_00000004; goto LAB_0041d741; case Interface_MenuItem_GetPusherGun: data = &DAT_00000005; goto LAB_0041d741; case Interface_MenuItem_GetFreezerGun: data = &DAT_00000007; goto LAB_0041d741; case Interface_MenuItem_GetBirdScarer: data = (undefined *)LegoObject_ToolType_BirdScarer; LAB_0041d741: BVar3 = Interface_DoSelectedUnits_Callback (Interface_ObjectCallback_DoesNotHaveToolEquipped,data); if (BVar3 == 0) { return 0; } switchD_0041cf8b_caseD_30: BVar3 = Interface_HasToolStore(); if (BVar3 == 0) { return 0; } break; case Interface_MenuItem_TrainSkill: BVar3 = Interface_HasStatsFlags2 (STATS2_TRAINPILOT|STATS2_TRAINSAILOR|STATS2_TRAINDRIVER|STATS2_TRAINDYNAMITE| STATS2_TRAINREPAIR|STATS2_TRAINSCANNER); if (BVar3 == 0) { return 0; } LVar4 = liveObj->abilityFlags; if (((((LVar4 & ABILITY_FLAG_PILOT) != ABILITY_FLAG_NONE) && ((LVar4 & ABILITY_FLAG_SAILOR) != ABILITY_FLAG_NONE)) && (((LVar4 & ABILITY_FLAG_DRIVER) != ABILITY_FLAG_NONE && (((LVar4 & ABILITY_FLAG_DYNAMITE) != ABILITY_FLAG_NONE && ((LVar4 & ABILITY_FLAG_REPAIR) != ABILITY_FLAG_NONE)))))) && ((LVar4 & ABILITY_FLAG_SCANNER) != ABILITY_FLAG_NONE)) { return 0; } break; case Interface_MenuItem_TrainDriver: BVar3 = Interface_CheckPrimaryUnitHasAbility(ABILITY_FLAG_DRIVER); if (BVar3 != 0) { return 0; } sflags2 = STATS2_TRAINDRIVER; goto LAB_0041d829; case Interface_MenuItem_TrainEngineer: BVar3 = Interface_CheckPrimaryUnitHasAbility(ABILITY_FLAG_REPAIR); if (BVar3 != 0) { return 0; } sflags2 = STATS2_TRAINREPAIR; goto LAB_0041d829; case Interface_MenuItem_TrainGeologist: BVar3 = Interface_CheckPrimaryUnitHasAbility(ABILITY_FLAG_SCANNER); if (BVar3 != 0) { return 0; } sflags2 = STATS2_TRAINSCANNER; goto LAB_0041d829; case Interface_MenuItem_TrainPilot: BVar3 = Interface_CheckPrimaryUnitHasAbility(ABILITY_FLAG_PILOT); if (BVar3 != 0) { return 0; } sflags2 = STATS2_TRAINPILOT; LAB_0041d829: iVar6 = Interface_HasStatsFlags2(sflags2); joined_r0x0041d86f: if (iVar6 == 0) { return 0; } fVar5 = lrr::Lego_GetTrainTime(); if ((ushort)((ushort)(fVar5 < (float10)liveObj->elapsedTime1) << 8 | (ushort)(fVar5 == (float10)liveObj->elapsedTime1) << 0xe) == 0) { return 0; } break; case Interface_MenuItem_TrainSailor: BVar3 = Interface_CheckPrimaryUnitHasAbility(ABILITY_FLAG_SAILOR); if (BVar3 != 0) { return 0; } sflags2 = STATS2_TRAINSAILOR; goto LAB_0041d865; case Interface_MenuItem_TrainDynamite: BVar3 = Interface_CheckPrimaryUnitHasAbility(ABILITY_FLAG_DYNAMITE); if (BVar3 != 0) { return 0; } sflags2 = STATS2_TRAINDYNAMITE; LAB_0041d865: iVar6 = Interface_HasStatsFlags2(sflags2); goto joined_r0x0041d86f; case Interface_MenuItem_UpgradeMan: uVar2 = stats::Stats_GetLevels(liveObj->type,liveObj->id); if (uVar2 <= liveObj->objLevel + 1) { return 0; } if ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { return 0; } goto switchD_0041cf8b_caseD_30; case Interface_MenuItem_UpgradeBuilding: BVar3 = game::LegoObject_GetBuildingUpgradeCost(liveObj,NULL); if (BVar3 == 0) { return 0; } break; case Interface_MenuItem_UpgradeVehicle: BVar3 = Interface_HasUpgradeStation(); if (BVar3 == 0) { return 0; } BVar3 = game::LegoObject_HasEnoughOreToUpgrade(liveObj,1); if (((BVar3 != 0) || (BVar3 = game::LegoObject_HasEnoughOreToUpgrade(liveObj,0), BVar3 != 0)) || (BVar3 = game::LegoObject_HasEnoughOreToUpgrade(liveObj,2), BVar3 != 0)) break; goto LAB_0041da08; case Interface_MenuItem_UpgradeEngine: BVar3 = Interface_HasUpgradeStation(); if (BVar3 == 0) { return 0; } iVar6 = 1; goto LAB_0041da0a; case Interface_MenuItem_UpgardeDrill: BVar3 = Interface_HasUpgradeStation(); if (BVar3 == 0) { return 0; } iVar6 = 0; goto LAB_0041da0a; case Interface_MenuItem_UpgardeScan: BVar3 = Interface_HasUpgradeStation(); if (BVar3 == 0) { return 0; } iVar6 = 2; goto LAB_0041da0a; case Interface_MenuItem_UpgardeCarry: BVar3 = Interface_HasUpgradeStation(); if (BVar3 == 0) { return 0; } LAB_0041da08: iVar6 = 3; LAB_0041da0a: BVar3 = game::LegoObject_HasEnoughOreToUpgrade(liveObj,iVar6); if (BVar3 == 0) { return 0; } } switchD_0041cf8b_caseD_2: if (((byte)globs::legoGlobs.flags3 & 6) == 0) { if (((byte)globs::legoGlobs.flags3 & 0x18) == 0) { if ((((byte)globs::legoGlobs.flags3 & 0x60) != 0) && (IVar1 != Interface_MenuItem_Back)) { if ((int)IVar1 < 0x1d) { return 0; } if (0x1e < (int)IVar1) { return 0; } } } else { if (IVar1 != Interface_MenuItem_Back) { if ((int)IVar1 < 0x14) { return 0; } if (0x15 < (int)IVar1) { return 0; } } } } else { if ((IVar1 != Interface_MenuItem_Back) && (((int)IVar1 < 0x1b || (0x1c < (int)IVar1)))) { return 0; } } return TRUE; } BOOL __cdecl lego::front::Interface_DoAction_FUN_0041dbd0(Interface_MenuItemType menuIcon) { LegoObject *pLVar1; BOOL BVar2; Map3D *map; StatsFlags1 sflags1; Lego_Level *level; int iVar3; StatsFlags3 sflags3; GameFlags3 gflags3; int iVar4; undefined4 argument2; WallHighlightType highlightType; uint newObjLevel; LegoObject_Type objType; pLVar1 = game::Message_GetPrimarySelectedUnit(); BVar2 = Interface_GetIconUnk_FUN_0041c820(menuIcon,TRUE); if (BVar2 != 0) { return 0; } if (false) goto switchD_0041dbfa_caseD_8; switch(menuIcon) { case Interface_MenuItem_Back: if (0xf < (int)globs::interfaceGlobs.currMenuType) { if ((int)globs::interfaceGlobs.currMenuType < 0x12) { Interface_OpenMenu(Interface_Menu_LegoMan,NULL); return TRUE; } if (globs::interfaceGlobs.currMenuType == Interface_Menu_UpgradeVehicle) { sflags1 = stats::StatsObject_GetStatsFlags1(pLVar1); if (((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && ((*(byte *)&pLVar1->flags4 & LIVEOBJ4_DOCKOCCUPIED) == 0)) { Interface_OpenMenu(Interface_Menu_WaterVehicle,NULL); return TRUE; } Interface_OpenMenu(Interface_Menu_LandVehicle,NULL); return TRUE; } } break; case Interface_MenuItem_TeleportMan: game::Lego_TryTeleportObject(LegoObject_MiniFigure,0); Interface_BackToMain(); return TRUE; case Interface_MenuItem_BuildBuilding: Interface_OpenMenu(Interface_Menu_BuildBuilding,NULL); return TRUE; case Interface_MenuItem_BuildSmallVehicle: Interface_OpenMenu(Interface_Menu_BuildSmallVehicle,NULL); return TRUE; case Interface_MenuItem_BuildLargeVehicle: Interface_OpenMenu(Interface_Menu_BuildLargeVehicle,NULL); return TRUE; case Interface_MenuItem_LayPath: case Interface_MenuItem_RepairLava: game::Construction_Zone_StartPath(&globs::interfaceGlobs.selBlockPos); Interface_BackToMain(); return TRUE; case Interface_MenuItem_RemovePath: ai::AITask_DoClearTypeAction(&globs::interfaceGlobs.selBlockPos,Message_ClearRemovePathComplete) ; level = lrr::Lego_GetLevel(); iVar3 = level->width * globs::interfaceGlobs.selBlockPos.y + globs::interfaceGlobs.selBlockPos.x ; level = lrr::Lego_GetLevel(); level->blocks[iVar3].flags1 = level->blocks[iVar3].flags1 & ~BLOCK1_PATH; game::Level_BlockUpdateSurface (globs::legoGlobs.currLevel,globs::interfaceGlobs.selBlockPos.x, globs::interfaceGlobs.selBlockPos.y,0); Interface_BackToMain(); return TRUE; case Interface_MenuItem_ClearRubble: ai::AITask_FUN_00401f40(AITask_Type_Clear,NULL,&globs::interfaceGlobs.selBlockPos); Interface_BackToMain(); return TRUE; case Interface_MenuItem_Dig: ai::AITask_DoDig_AtBlockPos(&globs::interfaceGlobs.selBlockPos,FALSE,TRUE); goto LAB_0041de87; case Interface_MenuItem_Reinforce: ai::AITask_DoReinforce_AtBlockPos(&globs::interfaceGlobs.selBlockPos); goto LAB_0041de87; case Interface_MenuItem_Dynamite: ai::AITask_DoDynamite_AtBlockPos(&globs::interfaceGlobs.selBlockPos,FALSE); LAB_0041de87: iVar3 = globs::interfaceGlobs.selBlockPos.x; iVar4 = globs::interfaceGlobs.selBlockPos.y; map = lrr::Lego_GetMap(); globs::interfaceGlobs.origWallHighlight = lego::map::Map3D_GetBlockHighlight(map,iVar3,iVar4); Interface_BackToMain(); return TRUE; case Interface_MenuItem_PlaceFence: ai::AITask_DoElecFence(&globs::interfaceGlobs.selBlockPos); Interface_BackToMain(); return TRUE; case Interface_MenuItem_DeselectDig: ai::AITask_RemoveDigReferences(&globs::interfaceGlobs.selBlockPos,FALSE); globs::interfaceGlobs.origWallHighlight = WALLHIGHLIGHT_NONE; highlightType = WALLHIGHLIGHT_SELECTED; iVar3 = globs::interfaceGlobs.selBlockPos.x; iVar4 = globs::interfaceGlobs.selBlockPos.y; map = lrr::Lego_GetMap(); lego::map::Map3D_SetBlockHighlight(map,iVar3,iVar4,highlightType); Interface_BackToMain(); return TRUE; case Interface_MenuItem_CancelConstruction: if (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::interfaceGlobs.selBlockPos.y + globs::interfaceGlobs.selBlockPos.x].flags1 & BLOCK1_LAYEDPATH) == BLOCK1_NONE) { game::Construction_Zone_CancelBuilding(&globs::interfaceGlobs.selBlockPos); Interface_BackToMain(); return TRUE; } game::Construction_Zone_CancelPath(&globs::interfaceGlobs.selBlockPos); Interface_BackToMain(); return TRUE; case Interface_MenuItem_SelectMan: game::Message_PostEvent(Message_ClearSelection,0,0,NULL); game::Message_PostEvent(Message_Select,pLVar1,0,NULL); Interface_OpenMenu(Interface_Menu_LegoMan,NULL); return TRUE; case Interface_MenuItem_SelectVehicle: game::Message_PostEvent(Message_ClearSelection,0,0,NULL); game::Message_PostEvent(Message_Select,pLVar1,0,NULL); sflags1 = stats::StatsObject_GetStatsFlags1(pLVar1); if (((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && ((*(byte *)&pLVar1->flags4 & 0x40) == 0)) { Interface_OpenMenu(Interface_Menu_WaterVehicle,NULL); return TRUE; } LAB_0041df4c: Interface_OpenMenu(Interface_Menu_LandVehicle,NULL); return TRUE; case Interface_MenuItem_SelectBuilding: game::Message_PostEvent(Message_ClearSelection,0,0,NULL); game::Message_PostEvent(Message_Select,pLVar1,0,NULL); Interface_OpenMenu(Interface_Menu_Building,NULL); return TRUE; case Interface_MenuItem_VehiclePickUp: sflags3 = stats::StatsObject_GetStatsFlags3(pLVar1); if ((sflags3 & STATS3_CARRYVEHICLES) != STATS3_NONE) { ai::AITask_DoFindLoad(pLVar1); return TRUE; } gflags3 = GAME3_LOADVEHICLE; if ((globs::legoGlobs.flags3 & GAME3_LOADVEHICLE) != GAME3_NONE) { lrr::Lego_StopUserAction(); return TRUE; } goto LAB_0041e4b7; case Interface_MenuItem_MinifigurePickUp: gflags3 = GAME3_PICKUPOBJECT; if ((globs::legoGlobs.flags3 & GAME3_PICKUPOBJECT) != GAME3_NONE) { lrr::Lego_StopUserAction(); return TRUE; } goto LAB_0041e4b7; case Interface_MenuItem_UnLoadVehicle: case Interface_MenuItem_UnLoadMinifigure: Interface_DoSelectedUnits_Callback(Interface_ObjectCallback_FUN_0041f5f0,NULL); return TRUE; case Interface_MenuItem_GetIn: game::Message_ClearSelectedUnits(); ai::AITask_DoFindDriver_Target(pLVar1); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetOut: game::LegoObject_FUN_00440470(pLVar1,FALSE); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GotoDock: game::LegoObject_FUN_00440470(pLVar1,TRUE); Interface_BackToMain(); return TRUE; case Interface_MenuItem_LegoManGoto: gflags3 = GAME3_LEGOMANGOTO; if ((globs::legoGlobs.flags3 & GAME3_LEGOMANGOTO) != GAME3_NONE) { lrr::Lego_StopUserAction(); return TRUE; } goto LAB_0041e4b7; case Interface_MenuItem_VehicleGoto: gflags3 = GAME3_VEHICLEGOTO; if ((globs::legoGlobs.flags3 & GAME3_VEHICLEGOTO) != GAME3_NONE) { lrr::Lego_StopUserAction(); return TRUE; } goto LAB_0041e4b7; case Interface_MenuItem_VehicleDig: gflags3 = GAME3_VEHICLEDIG; goto LAB_0041e4a1; case Interface_MenuItem_LegoManDig: gflags3 = GAME3_LEGOMANDIG; LAB_0041e4a1: if (((byte)globs::legoGlobs.flags3 & (byte)gflags3) != 0) { lrr::Lego_StopUserAction(); return TRUE; } LAB_0041e4b7: lrr::Lego_StopUserAction(); globs::legoGlobs.flags3 = globs::legoGlobs.flags3 | gflags3; return TRUE; case Interface_MenuItem_GoFeed: Interface_DoSelectedUnits_Callback(Interface_ObjectCallback_GoEatIfEnergyBelowMax,NULL); Interface_BackToMain(); return TRUE; case Interface_MenuItem_DeleteMan: case Interface_MenuItem_DeleteBuilding: case Interface_MenuItem_DeleteVehicle: case Interface_MenuItem_DeleteElectricFence: Interface_DoSelectedUnits_Callback(Interface_ObjectCallback_SetFlags4_8_HealthM1,NULL); Interface_BackToMain(); return TRUE; case Interface_MenuItem_DropBirdScarer: Interface_DoSelectedUnits_Callback(Interface_ObjectCallback_PlaceBirdScarerIfEquipped,NULL); Interface_BackToMain(); return TRUE; case Interface_MenuItem_PowerOn: BVar2 = 1; goto LAB_0041e51b; case Interface_MenuItem_PowerOff: BVar2 = 0; LAB_0041e51b: game::LegoObject_SetPowerOn(pLVar1,BVar2); break; case Interface_MenuItem_Repair: Interface_DoSelectedUnits_Callback(Interface_ObjectCallback_RequestRepairIfHealthBelowMax,NULL); Interface_BackToMain(); return TRUE; case Interface_MenuItem_MakeTeleporterPrimary: BVar2 = game::LegoObject_IsSmallTeleporter(pLVar1); if (BVar2 != 0) { globs::legoGlobs.placeDestSmallTeleporter = pLVar1; Interface_BackToMain(); return TRUE; } BVar2 = game::LegoObject_IsBigTeleporter(pLVar1); if (BVar2 != 0) { globs::legoGlobs.placeDestBigTeleporter = pLVar1; Interface_BackToMain(); return TRUE; } BVar2 = game::LegoObject_IsWaterTeleporter(pLVar1); if (BVar2 != 0) { globs::legoGlobs.placeDestWaterTeleporter = pLVar1; Interface_BackToMain(); return TRUE; } break; case Interface_MenuItem_EjectCrystal: game::LegoObject_SpawnCarryableObject(pLVar1,LegoObject_PowerCrystal,0,0); Interface_BackToMain(); return TRUE; case Interface_MenuItem_EjectOre: game::LegoObject_SpawnCarryableObject(pLVar1,LegoObject_Ore,LegoObject_ID_Ore,0); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GotoTopView: game::Message_PostEvent(Message_TopView,0,0,NULL); objType = pLVar1->type; if (objType == LegoObject_Vehicle) { sflags1 = stats::StatsObject_GetStatsFlags1(pLVar1); if (((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && ((*(byte *)&pLVar1->flags4 & LIVEOBJ4_DOCKOCCUPIED) == 0)) { Interface_OpenMenu(Interface_Menu_WaterVehicle,NULL); return TRUE; } goto LAB_0041df4c; } if (objType == LegoObject_MiniFigure) { Interface_OpenMenu(Interface_Menu_LegoMan,NULL); return TRUE; } if (objType == LegoObject_Building) { Interface_OpenMenu(Interface_Menu_Building,NULL); return TRUE; } break; case Interface_MenuItem_GotoFirstPerson: argument2 = 0; goto LAB_0041deb2; case Interface_MenuItem_GotoSecondPerson: argument2 = 1; LAB_0041deb2: game::Message_PostEvent(Message_FirstPerson,0,argument2,NULL); Interface_OpenMenu(Interface_Menu_FP,NULL); return TRUE; case Interface_MenuItem_TrackObject: lrr::Lego_TrackObjectInRadar(pLVar1); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetTool: Interface_OpenMenu(Interface_Menu_GetTool,NULL); return TRUE; case Interface_MenuItem_GetDrill: Interface_DoSelectedUnits_Callback(Interface_ObjectCallback_GoGetToolIfNotEquipped,NULL); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetSpade: Interface_DoSelectedUnits_Callback (Interface_ObjectCallback_GoGetToolIfNotEquipped,(void *)LegoObject_ToolType_Spade); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetHammer: Interface_DoSelectedUnits_Callback (Interface_ObjectCallback_GoGetToolIfNotEquipped,(void *)LegoObject_ToolType_Hammer); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetSpanner: Interface_DoSelectedUnits_Callback (Interface_ObjectCallback_GoGetToolIfNotEquipped,(void *)LegoObject_ToolType_Spanner); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetLaser: Interface_DoSelectedUnits_Callback (Interface_ObjectCallback_GoGetToolIfNotEquipped,&DAT_00000004); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetPusherGun: Interface_DoSelectedUnits_Callback (Interface_ObjectCallback_GoGetToolIfNotEquipped,&DAT_00000005); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetFreezerGun: Interface_DoSelectedUnits_Callback (Interface_ObjectCallback_GoGetToolIfNotEquipped,&DAT_00000007); Interface_BackToMain(); return TRUE; case Interface_MenuItem_GetBirdScarer: Interface_DoSelectedUnits_Callback (Interface_ObjectCallback_GoGetToolIfNotEquipped, (void *)LegoObject_ToolType_BirdScarer); Interface_BackToMain(); return TRUE; case Interface_MenuItem_TrainSkill: Interface_OpenMenu(Interface_Menu_TrainSkill,NULL); return TRUE; case Interface_MenuItem_TrainDriver: case Interface_MenuItem_TrainEngineer: case Interface_MenuItem_TrainGeologist: case Interface_MenuItem_TrainPilot: case Interface_MenuItem_TrainSailor: case Interface_MenuItem_TrainDynamite: switch(menuIcon) { case Interface_MenuItem_TrainDriver: menuIcon = ABILITY_FLAG_DRIVER; break; case Interface_MenuItem_TrainEngineer: menuIcon = ABILITY_FLAG_REPAIR; break; case Interface_MenuItem_TrainGeologist: menuIcon = ABILITY_FLAG_SCANNER; break; case Interface_MenuItem_TrainPilot: menuIcon = ABILITY_FLAG_PILOT; break; case Interface_MenuItem_TrainSailor: menuIcon = ABILITY_FLAG_SAILOR; break; case Interface_MenuItem_TrainDynamite: menuIcon = ABILITY_FLAG_DYNAMITE; } pLVar1 = (LegoObject *)game::LegoObject_Search_FUN_00439110(pLVar1,NULL,menuIcon); if (pLVar1 == NULL) { return 0; } ai::AITask_DoTrain_Target(pLVar1,menuIcon,TRUE); Interface_BackToMain(); return TRUE; case Interface_MenuItem_UpgradeMan: ai::AITask_DoUpgrade(pLVar1,0); Interface_BackToMain(); return TRUE; case Interface_MenuItem_UpgradeBuilding: game::LegoObject_UpgradeBuilding(pLVar1); Interface_BackToMain(); return TRUE; case Interface_MenuItem_UpgradeVehicle: Interface_OpenMenu(Interface_Menu_UpgradeVehicle,NULL); return TRUE; case Interface_MenuItem_UpgradeEngine: newObjLevel = LegoObject_UpgradeType_Speed; goto LAB_0041e4f4; case Interface_MenuItem_UpgardeDrill: newObjLevel = LegoObject_UpgradeType_Drill; goto LAB_0041e4f4; case Interface_MenuItem_UpgardeScan: newObjLevel = LegoObject_UpgradeType_Scan; goto LAB_0041e4f4; case Interface_MenuItem_UpgardeCarry: newObjLevel = LegoObject_UpgradeType_Carry; LAB_0041e4f4: ai::AITask_DoUpgrade(pLVar1,newObjLevel); pLVar1->elapsedTime2 = 0.0; Interface_BackToMain(); return TRUE; case Interface_MenuItem_Encyclopedia: if ((globs::legoGlobs.flags3 & GAME3_ENCYCLOPEDIA) == GAME3_NONE) { lrr::Lego_StopUserAction(); globs::legoGlobs.flags3 |= GAME3_ENCYCLOPEDIA; Encyclopedia_ClearSelection(); Interface_BackToMain(); return TRUE; } lrr::Lego_StopUserAction(); Interface_BackToMain(); return TRUE; case Interface_MenuItem_ClearSelection: game::Message_PostEvent(Message_ClearSelection,0,0,NULL); Interface_BackToMain(); return TRUE; case Interface_MenuItem_Build: BVar2 = Interface_GetObjectIconUnk_FUN_0041c880 (globs::interfaceGlobs.objType_f80,globs::interfaceGlobs.objID_f84,TRUE); if (BVar2 != 0) { return 0; } game::Lego_TryTeleportObject(globs::interfaceGlobs.objType_f80,globs::interfaceGlobs.objID_f84); if (globs::interfaceGlobs.objType_f80 == LegoObject_Building) { return TRUE; } } switchD_0041dbfa_caseD_8: Interface_BackToMain(); return TRUE; } void __cdecl lego::front::Interface_BackToMain(void) { game::Message_PostEvent(Message_ClearSelection,0,FALSE,NULL); Interface_OpenMenu(Interface_Menu_Main,NULL); return; } void __cdecl lego::front::Interface_SetIconFlash(Interface_MenuItemType menuIcon,BOOL flash) { if (flash != 0) { globs::interfaceGlobs.menuItemFlags[menuIcon] = globs::interfaceGlobs.menuItemFlags[menuIcon] | INTERFACE_MENUITEM_FLAG_FLASH; return; } globs::interfaceGlobs.menuItemFlags[menuIcon] = globs::interfaceGlobs.menuItemFlags[menuIcon] & ~INTERFACE_MENUITEM_FLAG_FLASH; return; } void __cdecl lego::front::Interface_SetSubmenuIconFlash(LegoObject_Type objType,LegoObject_ID objID,BOOL flash) { Interface_MenuItemFlags *pIVar1; pIVar1 = globs::interfaceGlobs.vehicleItemFlags; if ((objType == LegoObject_Vehicle) || (pIVar1 = globs::interfaceGlobs.buildingItemFlags, objType == LegoObject_Building)) { if (flash != 0) { pIVar1[objID] = pIVar1[objID] | INTERFACE_MENUITEM_FLAG_FLASH; return; } pIVar1[objID] = pIVar1[objID] & ~INTERFACE_MENUITEM_FLAG_FLASH; } return; } LegoObject * __cdecl lego::front::Interface_GetPrimarySelectedUnit(void) { return (LegoObject *) (-(uint)(globs::messageGlobs.selectedUnitCount != 0) & (uint)globs::messageGlobs.selectedUnitList[0]); } // Sets click COUNT // returns previous COUNT int __cdecl lego::front::Interface_SetIconClicked(Interface_MenuItemType menuIcon,int clickedCount) { uint lastCount; lastCount = globs::interfaceGlobs.menuItemClicks[menuIcon]; globs::interfaceGlobs.menuItemClicks[menuIcon] = clickedCount; return lastCount; } // Gets click COUNT int __cdecl lego::front::Interface_GetIconClicked(Interface_MenuItemType menuIcon) { return globs::interfaceGlobs.menuItemClicks[menuIcon]; } // Sets click COUNT // returns previous COUNT int __cdecl lego::front::Interface_SetSubmenuIconClicked (LegoObject_Type objType,LegoObject_ID objID,int clickedCount) { uint lastCount; lastCount = 0; if (objType == LegoObject_Vehicle) { lastCount = globs::interfaceGlobs.vehicleItemClicks[objID]; globs::interfaceGlobs.vehicleItemClicks[objID] = clickedCount; return lastCount; } if (objType == LegoObject_Building) { lastCount = globs::interfaceGlobs.buildingItemClicks[objID]; globs::interfaceGlobs.buildingItemClicks[objID] = clickedCount; } return lastCount; } // Gets click COUNT int __cdecl lego::front::Interface_GetSubmenuIconClicked(LegoObject_Type objType,LegoObject_ID objID) { if (objType == LegoObject_Vehicle) { return globs::interfaceGlobs.vehicleItemClicks[objID]; } if (objType == LegoObject_Building) { return globs::interfaceGlobs.buildingItemClicks[objID]; } return 0; } // Always returns true BOOL __cdecl lego::front::Interface_SetAdvisorPointToFashingIcon(Interface_MenuItemType menuIcon,BOOL setFlag40) { Interface_GlobFlags IVar1; IVar1 = globs::interfaceGlobs.flags | INTERFACE_GLOB_FLAG_UNK_20; if (setFlag40 != 0) { IVar1 = globs::interfaceGlobs.flags | (INTERFACE_GLOB_FLAG_UNK_20|INTERFACE_GLOB_FLAG_UNK_40); } globs::interfaceGlobs.flags = IVar1; globs::interfaceGlobs.advisorType_fcc = Interface_GetAdvisorType_FromIcon(menuIcon); globs::interfaceGlobs.menuItemType_fd0 = menuIcon; return TRUE; } Advisor_Type __cdecl lego::front::Interface_GetAdvisorType_FromIcon(Interface_MenuItemType menuIcon) { if (true) { switch(menuIcon) { case Interface_MenuItem_Back: return Advisor_IconPoint_BackButton; case Interface_MenuItem_TeleportMan: case Interface_MenuItem_BuildBuilding: case Interface_MenuItem_LayPath: case Interface_MenuItem_RemovePath: case Interface_MenuItem_ClearRubble: case Interface_MenuItem_Dig: case Interface_MenuItem_Reinforce: case Interface_MenuItem_PlaceFence: case Interface_MenuItem_VehiclePickUp: case Interface_MenuItem_UnLoadVehicle: case Interface_MenuItem_UnLoadMinifigure: case Interface_MenuItem_GetIn: case Interface_MenuItem_GoFeed: case Interface_MenuItem_PowerOn: case Interface_MenuItem_Repair: case Interface_MenuItem_DeleteVehicle: case Interface_MenuItem_DeleteElectricFence: case Interface_MenuItem_Attack: case Interface_MenuItem_GotoTopView: case Interface_MenuItem_GotoSecondPerson: case Interface_MenuItem_TrackObject: case Interface_MenuItem_GetDrill: case Interface_MenuItem_GetSpade: case Interface_MenuItem_TrainDriver: case Interface_MenuItem_TrainEngineer: case Interface_MenuItem_UpgradeEngine: case Interface_MenuItem_UpgardeDrill: return Advisor_IconPoint_TopButtons; } } return Advisor_IconPoint_Normal; } BOOL __cdecl lego::front::Interface_GetObjectBool_FUN_0041e8c0(LegoObject_Type objType,LegoObject_ID objID) { TutorialFlags tflags; tflags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((tflags & TUTORIAL_FLAG_NOMAP) != TUTORIAL_NONE) { return *(BOOL *)(objID * 4 + 0x4ded34 + objType * 0x3c); } return TRUE; } void __cdecl lego::front::Interface_SetScrollParameters (uint xEnd,uint yEnd,uint xStart,uint yStart,float timerFloat_750) { globs::interfaceGlobs.slideStartPosition.x = (float)(ulonglong)xStart; globs::interfaceGlobs.slideStartPosition.y = (float)(ulonglong)yStart; globs::interfaceGlobs.slideEndPosition.x = (float)(ulonglong)xEnd; globs::interfaceGlobs.slideEndPosition.y = (float)(ulonglong)yEnd; globs::interfaceGlobs.slideSpeed = timerFloat_750 * 0.04; return; } void __cdecl lego::front::_Interface_OpenMenu_SetNext(Interface_MenuType menuType,Point2I *opt_blockPos) { if (((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) == INTERFACE_GLOB_FLAG_NONE) || (globs::interfaceGlobs.currMenuType != menuType)) { globs::interfaceGlobs.flags = globs::interfaceGlobs.flags & ~INTERFACE_GLOB_FLAG_UNK_80 | INTERFACE_GLOB_FLAG_UNK_100; snd::SFX_Random_PlaySoundNormal(SFX_InterfaceSlideOffScreen,FALSE); } else { globs::interfaceGlobs.currMenuType = menuType; if (opt_blockPos == NULL) { globs::interfaceGlobs.nextMenuType = menuType; return; } globs::interfaceGlobs.selBlockPos.x = opt_blockPos->x; globs::interfaceGlobs.selBlockPos.y = opt_blockPos->y; } if (opt_blockPos != NULL) { globs::interfaceGlobs.highlightBlockPos.x = opt_blockPos->x; globs::interfaceGlobs.highlightBlockPos.y = opt_blockPos->y; } globs::interfaceGlobs.nextMenuType = menuType; return; } void __cdecl lego::front::Interface_FUN_0041e9f0(float elapsedAbs) { if ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_80) == INTERFACE_GLOB_FLAG_NONE) { if ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_100) == INTERFACE_GLOB_FLAG_NONE) { if ((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_4) != INTERFACE_GLOB_FLAG_NONE) { globs::interfaceGlobs.currMenuPosition.x = globs::interfaceGlobs.currMenuPosition.x - elapsedAbs * globs::interfaceGlobs.slideSpeed; if ((ushort)((ushort)(globs::interfaceGlobs.currMenuPosition.x < globs::interfaceGlobs.slideEndPosition.x) << 8 | (ushort)(globs::interfaceGlobs.currMenuPosition.x == globs::interfaceGlobs.slideEndPosition.x) << 0xe) != 0) { globs::interfaceGlobs.flags |= INTERFACE_GLOB_FLAG_UNK_80; globs::interfaceGlobs.currMenuPosition.x = globs::interfaceGlobs.slideEndPosition.x; } } } else { globs::interfaceGlobs.currMenuPosition.x = elapsedAbs * globs::interfaceGlobs.slideSpeed + globs::interfaceGlobs.currMenuPosition.x; if ((globs::interfaceGlobs.currMenuType == Interface_Menu_Type_Count) && (((byte)globs::panelGlobs.panelTable[8].flags & PANEL_FLAG_OPEN) != 0)) { Panel_ToggleOpenClosed(Panel_PriorityList); Panel_Button_SetToggled(Panel_TopPanel,1,FALSE); globs::interfaceGlobs.currMenuPosition.x = globs::interfaceGlobs.slideStartPosition.x; } if (globs::interfaceGlobs.slideStartPosition.x <= globs::interfaceGlobs.currMenuPosition.x) { globs::interfaceGlobs.flags &= ~INTERFACE_GLOB_FLAG_UNK_100; globs::interfaceGlobs.currMenuPosition.x = globs::interfaceGlobs.slideStartPosition.x; snd::SFX_Random_PlaySoundNormal(SFX_InterfaceSlideOnScreen,FALSE); if (globs::interfaceGlobs.nextMenuType == Interface_Menu_Type_Count) { globs::interfaceGlobs.flags = globs::interfaceGlobs.flags & ~INTERFACE_GLOB_FLAG_UNK_4 | INTERFACE_GLOB_FLAG_UNK_80 ; Panel_ToggleOpenClosed(Panel_PriorityList); Panel_PriorityList_ResetButtons(); globs::panelGlobs.flags |= PANEL_GLOB_FLAG_PRIORITIES_TOP; } else { if (globs::interfaceGlobs.nextMenuType == Interface_Menu_Encyclopedia) { globs::interfaceGlobs.flags = globs::interfaceGlobs.flags & ~INTERFACE_GLOB_FLAG_UNK_4 | INTERFACE_GLOB_FLAG_UNK_80; Panel_ToggleOpenClosed(Panel_Encyclopedia); globs::legoGlobs.flags3 |= GAME3_ENCYCLOPEDIA; Encyclopedia_ClearSelection(); } else { globs::interfaceGlobs.flags |= INTERFACE_GLOB_FLAG_UNK_4; } } globs::interfaceGlobs.selBlockPos.x = globs::interfaceGlobs.highlightBlockPos.x; globs::interfaceGlobs.selBlockPos.y = globs::interfaceGlobs.highlightBlockPos.y; globs::interfaceGlobs.currMenuType = globs::interfaceGlobs.nextMenuType; return; } } } return; } void __cdecl lego::front::Interface_DrawTeleportQueueNumber (LegoObject_Type objType,LegoObject_ID objID,Point2F *screenPt) { LegoObject_Type *pObjTeleQueue; int y; uint count; int numQueued; longlong lVar1; char *msg; numQueued = 0; if (globs::legoGlobs.objTeleportQueue_COUNT != 0) { pObjTeleQueue = globs::legoGlobs.objTeleportQueueTypes_TABLE; count = globs::legoGlobs.objTeleportQueue_COUNT; do { // if (objTeleportQueueTypes_TABLE[i] == objType && objTeleportQueueIDs_TABLE[i] == // objID) if ((*pObjTeleQueue == objType) && (pObjTeleQueue[0x14] == objID)) { numQueued += 1; } pObjTeleQueue = pObjTeleQueue + 1; count -= 1; } while (count != 0); } if (numQueued != 0) { msg = "%i"; lVar1 = __ftol((float10)screenPt->y); y = (int)lVar1 + 3; lVar1 = __ftol((float10)screenPt->x); lego::image::Font_PrintF(globs::interfaceGlobs.font,(int)lVar1 + 3,y,msg,numQueued); } return; } void __cdecl lego::front::Interface_FUN_0041ebd0(float xScreen,float yScreen) { BOOL BVar1; Image *image; int y; uint uVar2; longlong lVar3; char *msg; char *pcVar4; DependencyRequirement *local_10; uint local_c; Point2F local_8; if ((globals::g_Interface_UINT_004a3b5c != globs::interfaceGlobs.objType_f80) || (INTObjectIndex_004ddd50 != globs::interfaceGlobs.objID_f84)) { Interface_SetFloat1494To25_AndUnsetFlags800(); globals::g_Interface_UINT_004a3b5c = globs::interfaceGlobs.objType_f80; INTObjectIndex_004ddd50 = globs::interfaceGlobs.objID_f84; } if (((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_800) != INTERFACE_GLOB_FLAG_NONE) && (game::Dependencies_Object_GetRequirements (globs::interfaceGlobs.objType_f80,globs::interfaceGlobs.objID_f84,0,&local_10, &local_c), local_c != 0)) { local_8.x = xScreen - 15.0; uVar2 = 0; local_8.y = yScreen; if (local_c != 0) { do { if (uVar2 == 0) { if (globs::interfaceGlobs.dependenciesMinusImage == NULL) { LAB_0041ecb4: local_8.x = local_8.x - 20.0; } else { local_8.x = local_8.x - (float)(globs::interfaceGlobs.dependenciesMinusImage)->width; lego::image::Image_DisplayScaled (globs::interfaceGlobs.dependenciesMinusImage,NULL,&local_8,NULL); } } else { if (globs::interfaceGlobs.dependenciesPlusImage == NULL) goto LAB_0041ecb4; local_8.x = local_8.x - (float)(globs::interfaceGlobs.dependenciesPlusImage)->width; lego::image::Image_DisplayScaled (globs::interfaceGlobs.dependenciesPlusImage,NULL,&local_8,NULL); } BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts (game::Dependencies_LiveObject_CallbackCheck_FUN_0040ae70,local_10 + uVar2 ); image = Interface_GetObjectBuildImage (local_10[uVar2].objType,local_10[uVar2].objID,(uint)(BVar1 != 0)); if (image == NULL) { local_8.x = local_8.x - 40.0; } else { local_8.x = local_8.x - (float)image->width; lego::image::Image_DisplayScaled(image,NULL,&local_8,NULL); if ((local_10[uVar2].hasLevel != 0) && (local_10[uVar2].objLevel != 0)) { pcVar4 = globs::legoGlobs.langUpgradeLevel_name[local_10[uVar2].objLevel]; msg = "%s"; lVar3 = __ftol((float10)local_8.y); y = (int)lVar3 + 3; lVar3 = __ftol((float10)local_8.x); lego::image::Font_PrintF(globs::interfaceGlobs.font,(int)lVar3 + 3,y,msg,pcVar4); } } uVar2 += 1; } while (uVar2 < local_c); } } return; } void __cdecl lego::front::Interface_SetFloat1494To25_AndUnsetFlags800(void) { globs::interfaceGlobs.float_1494 = 25.0; globs::interfaceGlobs.flags = globs::interfaceGlobs.flags & ~INTERFACE_GLOB_FLAG_UNK_800; return; } BOOL __cdecl lego::front::Interface_FUN_0041edb0 (uint param_1,uint param_2,float x,float y,LegoObject_Type *out_objType, LegoObject_ID *out_objID,uint *out_objLevel) { float fVar1; float fVar2; Image *pIVar3; uint uVar4; uint uVar5; uint requirementCount; DependencyRequirement *requirements; float local_38; undefined4 uStack52; uint local_30; undefined4 uStack44; uint local_28; undefined4 uStack36; uint local_20; undefined4 uStack28; uint local_18; undefined4 uStack20; uint local_10; undefined4 uStack12; uint local_8; undefined4 uStack4; if (((globs::interfaceGlobs.flags & INTERFACE_GLOB_FLAG_UNK_800) != INTERFACE_GLOB_FLAG_NONE) && (game::Dependencies_Object_GetRequirements (globs::interfaceGlobs.objType_f80,globs::interfaceGlobs.objID_f84,0,&requirements, &requirementCount), requirementCount != 0)) { local_38 = x - 15.0; fVar2 = (float)(ulonglong)param_1; if ((local_38 <= fVar2) && ((((ushort)((ushort)(fVar2 < local_38 - -15.0) << 8 | (ushort)(fVar2 == local_38 - -15.0) << 0xe) != 0 && (fVar1 = (float)(ulonglong)param_2, y <= fVar1)) && ((ushort)((ushort)(fVar1 < y - -40.0) << 8 | (ushort)(fVar1 == y - -40.0) << 0xe) != 0)))) { *out_objType = LegoObject_Type_Count; return TRUE; } uStack52 = 0; uVar5 = 0; if (requirementCount != 0) { do { pIVar3 = globs::interfaceGlobs.dependenciesMinusImage; if (uVar5 != 0) { pIVar3 = globs::interfaceGlobs.dependenciesPlusImage; } if (pIVar3 == NULL) { local_30 = 0x14; uVar4 = 0x28; } else { local_30 = pIVar3->width; uVar4 = pIVar3->height; } uStack44 = 0; local_38 = local_38 - (float)(ulonglong)local_30; if ((local_38 <= fVar2) && (fVar1 = local_38 + (float)(ulonglong)local_30, (ushort)((ushort)(fVar2 < fVar1) << 8 | (ushort)(fVar2 == fVar1) << 0xe) != 0)) { local_28 = param_2; uStack36 = 0; fVar1 = (float)(ulonglong)param_2; if ((y <= fVar1) && (uStack28 = 0, local_20 = uVar4, (ushort)((ushort)(fVar1 < (float)(ulonglong)uVar4 + y) << 8 | (ushort)(fVar1 == (float)(ulonglong)uVar4 + y) << 0xe) != 0)) { *out_objType = LegoObject_Type_Count; return TRUE; } } pIVar3 = Interface_GetObjectBuildImage (requirements[uVar5].objType,requirements[uVar5].objID,0); if (pIVar3 == NULL) { local_18 = 0x28; uVar4 = 0x28; } else { local_18 = pIVar3->width; uVar4 = pIVar3->height; } uStack20 = 0; local_38 = local_38 - (float)(ulonglong)local_18; if ((local_38 <= fVar2) && (fVar1 = local_38 + (float)(ulonglong)local_18, (ushort)((ushort)(fVar2 < fVar1) << 8 | (ushort)(fVar2 == fVar1) << 0xe) != 0)) { local_10 = param_2; uStack12 = 0; fVar1 = (float)(ulonglong)param_2; if ((y <= fVar1) && (uStack4 = 0, local_8 = uVar4, (ushort)((ushort)(fVar1 < (float)(ulonglong)uVar4 + y) << 8 | (ushort)(fVar1 == (float)(ulonglong)uVar4 + y) << 0xe) != 0)) { *out_objType = requirements[uVar5].objType; *out_objID = requirements[uVar5].objID; *out_objLevel = requirements[uVar5].objLevel; return TRUE; } } uVar5 += 1; if (requirementCount <= uVar5) { return FALSE; } } while( true ); } } return FALSE; } BOOL __cdecl lego::front::Interface_HasTeleporterForObject(LegoObject_Type objType,LegoObject_ID objID) { StatsFlags2 sflags2; BOOL BVar1; SearchInterfaceFindObject search; search.objID = 0; search.statsFlags1 = STATS1_NONE; search.objType = LegoObject_None; search.statsFlags2 = STATS2_NONE; search.abilityFlags = ABILITY_FLAG_NONE; search.flags = 0; sflags2 = stats::Stats_GetStatsFlags2(objType,objID); if ((sflags2 & STATS2_USESMALLTELEPORTER) == STATS2_NONE) { if ((sflags2 & STATS2_USEBIGTELEPORTER) == STATS2_NONE) { if ((sflags2 & STATS2_USEWATERTELEPORTER) == STATS2_NONE) { if ((sflags2 & STATS2_USELEGOMANTELEPORTER) == STATS2_NONE) { return TRUE; } search.statsFlags1 = STATS1_MANTELEPORTER; } else { search.statsFlags1 = STATS1_WATERTELEPORTER; } } else { search.statsFlags1 = STATS1_BIGTELEPORTER; } } else { search.statsFlags1 = STATS1_SMALLTELEPORTER; } BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts(Interface_Callback_HasObject,&search); return BVar1; } // Does not return object, only checks if a match exists. BOOL __cdecl lego::front::Interface_Callback_HasObject(LegoObject *liveObj,SearchInterfaceFindObject *search) { BOOL BVar1; StatsFlags1 sflags1; StatsFlags2 sflags2; if ((liveObj->type == LegoObject_Building) && (BVar1 = game::LegoObject_IsActive(liveObj,FALSE), BVar1 == 0)) { return 0; } if ((search->flags & 1) != 0) { if (liveObj->type != search->objType) { return 0; } if (liveObj->id != search->objID) { return 0; } } if (((search->flags & 2) != 0) && ((search->abilityFlags & liveObj->abilityFlags) == ABILITY_FLAG_NONE)) { return 0; } if ((search->statsFlags1 != STATS1_NONE) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (search->statsFlags1 & sflags1) == STATS1_NONE)) { return 0; } if ((search->statsFlags2 != STATS2_NONE) && (sflags2 = stats::StatsObject_GetStatsFlags2(liveObj), (search->statsFlags2 & sflags2) == STATS2_NONE)) { return 0; } return TRUE; } BOOL __cdecl lego::front::Interface_HasUpgradeStation(void) { BOOL BVar1; SearchInterfaceFindObject search; search.objID = 0; search.statsFlags1 = STATS1_NONE; search.objType = LegoObject_None; search.abilityFlags = ABILITY_FLAG_NONE; search.statsFlags2 = STATS2_UPGRADEBUILDING; search.flags = 0; BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts(Interface_Callback_HasObject,&search); return BVar1; } BOOL __cdecl lego::front::Interface_HasStatsFlags2(StatsFlags2 statsFlags2) { BOOL BVar1; SearchInterfaceFindObject search; search.objID = 0; search.statsFlags1 = STATS1_NONE; search.abilityFlags = ABILITY_FLAG_NONE; search.objType = LegoObject_None; search.flags = 0; search.statsFlags2 = statsFlags2; BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts(Interface_Callback_HasObject,&search); return BVar1; } BOOL __cdecl lego::front::Interface_HasToolStore(void) { BOOL BVar1; SearchInterfaceFindObject search; search.objID = 0; search.statsFlags2 = STATS2_NONE; search.objType = LegoObject_None; search.abilityFlags = ABILITY_FLAG_NONE; search.statsFlags1 = STATS1_TOOLSTORE; search.flags = 0; BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts(Interface_Callback_HasObject,&search); return BVar1; } BOOL __cdecl lego::front::Interface_HasObjectOfTypeID(LegoObject_Type objType,LegoObject_ID objID) { BOOL BVar1; SearchInterfaceFindObject search; search.statsFlags1 = STATS1_NONE; search.statsFlags2 = STATS2_NONE; search.abilityFlags = ABILITY_FLAG_NONE; // Flag 0x1 to search for objectType/ID. search.flags = 1; search.objType = objType; search.objID = objID; BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts(Interface_Callback_HasObject,&search); return BVar1; } BOOL __cdecl lego::front::Interface_HasObjectWithAbilities(LegoObject_AbilityFlags abilityFlags) { BOOL BVar1; SearchInterfaceFindObject search; search.objID = 0; search.statsFlags1 = STATS1_NONE; search.statsFlags2 = STATS2_NONE; // Flag 0x2 to check abilities. search.flags = 2; search.objType = LegoObject_None; search.abilityFlags = abilityFlags; BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts(Interface_Callback_HasObject,&search); return BVar1; } BOOL __cdecl lego::front::Interface_Callback_ReqestDigBlock(LegoObject *liveObj,Point2I *blockPos) { BOOL BVar1; BVar1 = game::LiveObject_BlockCheck_FUN_004326a0(liveObj,blockPos->x,blockPos->y,FALSE,FALSE); return (uint)(BVar1 != 0); } BOOL __cdecl lego::front::Interface_ReqestDigBlock(Point2I *blockPos) { BOOL BVar1; BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts (Interface_Callback_ReqestDigBlock,blockPos); return BVar1; } BOOL __cdecl lego::front::Interface_Callback_RequestReinforceBlock(LegoObject *liveObj,Point2I *blockPos) { BOOL BVar1; BVar1 = game::LiveObject_CanReinforceBlock(liveObj,blockPos->x,blockPos->y); return (uint)(BVar1 != 0); } BOOL __cdecl lego::front::Interface_RequestReinforceBlock(Point2I *blockPos) { BOOL BVar1; BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts (Interface_Callback_RequestReinforceBlock,blockPos); return BVar1; } BOOL __cdecl lego::front::Interface_DoSelectedUnits_Callback (LegoObject_RunThroughListsCallback callback,void *data) { uint uVar1; LegoObject **pSelectedObj; BOOL BVar2; uint i; uVar1 = game::Message_GetNumSelectedUnits(); pSelectedObj = game::Message_GetSelectedUnits(); i = 0; if (uVar1 == 0) { return 0; } do { BVar2 = (*callback)(*pSelectedObj,data); if (BVar2 != 0) { return TRUE; } i += 1; pSelectedObj = pSelectedObj + 1; } while (i < uVar1); return FALSE; } BOOL __cdecl lego::front::Interface_ObjectCallback_IsCarryingButNotStoring(LegoObject *liveObj,void *unused) { if (((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && ((liveObj->flags1 & LIVEOBJ1_STORING) == LIVEOBJ1_NONE)) { return TRUE; } return FALSE; } BOOL __cdecl lego::front::Interface_ObjectCallback_IsEnergyBelowMax(LegoObject *liveObj,void *unused) { if (liveObj->energy < 100.0) { return TRUE; } return FALSE; } BOOL __cdecl lego::front::Interface_ObjectCallback_IsHealthBelowMax(LegoObject *liveObj,void *unused) { if (liveObj->health < 100.0) { return TRUE; } return FALSE; } BOOL __cdecl lego::front::Interface_ObjectCallback_FUN_0041f400(LegoObject *liveObj,void *unused) { StatsFlags3 sflags3; Container *cont; Map3D *map; BOOL BVar1; int iVar2; uint uVar3; uint uVar4; int *out_bx; int *out_by; int local_14; int local_10; Vector3F local_c; sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if ((sflags3 & STATS3_CARRYVEHICLES) == STATS3_NONE) { if (liveObj->type == LegoObject_MiniFigure) { if ((((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) && ((liveObj->flags3 & LIVEOBJ3_CANCARRY) != LIVEOBJ3_NONE)) && ((liveObj->flags3 & LIVEOBJ3_CANPICKUP) != LIVEOBJ3_NONE)) { return 1; } } else { if (((liveObj->flags3 & LIVEOBJ3_CANCARRY) != LIVEOBJ3_NONE) && ((liveObj->flags3 & LIVEOBJ3_CANPICKUP) != LIVEOBJ3_NONE)) { uVar4 = liveObj->carryNullFrames; uVar3 = stats::StatsObject_GetMaxCarry(liveObj); if (uVar3 <= uVar4) { uVar4 = stats::StatsObject_GetMaxCarry(liveObj); } if (liveObj->numCarriedObjects < uVar4) { return 1; } } } } else { if ((((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) && ((liveObj->flags4 & LIVEOBJ4_UNK_10000) == LIVEOBJ4_NONE)) && (cont = game::LegoObject_GetDepositNull(liveObj), cont != NULL)) { gfx::Container_GetPosition(cont,NULL,&local_c); out_by = &local_10; out_bx = &local_14; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ(map,local_c.x,local_c.y,out_bx,out_by); if ((BVar1 != 0) && (iVar2 = game::Lego_GetCrossTerrainType(NULL,local_14,local_10,local_14,local_10,TRUE), iVar2 != 0)) { return 1; } } } return 0; } BOOL __cdecl lego::front::Interface_ObjectCallback_SetFlags4_8_HealthM1(LegoObject *liveObj,void *unused) { liveObj->health = -1.0; liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_UNK_8; return 0; } BOOL __cdecl lego::front::Interface_ObjectCallback_GoEatIfEnergyBelowMax(LegoObject *liveObj,void *unused) { if (liveObj->energy < 100.0) { game::LegoObject_GoEat_unk(liveObj); } return 0; } BOOL __cdecl lego::front::Interface_ObjectCallback_RequestRepairIfHealthBelowMax (LegoObject *liveObj,void *unused) { if (liveObj->health < 100.0) { ai::AITask_DoRepair_Target(liveObj,FALSE); } return 0; } BOOL __cdecl lego::front::Interface_ObjectCallback_DoesNotHaveToolEquipped (LegoObject *liveObj,LegoObject_ToolType toolType) { BOOL BVar1; BVar1 = game::LegoObject_HasToolEquipped(liveObj,toolType); return (uint)(BVar1 == 0); } BOOL __cdecl lego::front::Interface_ObjectCallback_GoGetToolIfNotEquipped (LegoObject *liveObj,LegoObject_ToolType toolType) { BOOL BVar1; BVar1 = game::LegoObject_HasToolEquipped(liveObj,toolType); if (BVar1 == 0) { ai::AITask_DoGetTool(toolType); } return 0; } BOOL __cdecl lego::front::Interface_ObjectCallback_FUN_0041f5f0(LegoObject *liveObj,void *unused) { StatsFlags3 SVar1; SVar1 = stats::StatsObject_GetStatsFlags3(liveObj); if ((SVar1 & STATS3_CARRYVEHICLES) == STATS3_NONE) { if (((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) || (liveObj->carriedObjects[0]->type != LegoObject_Barrier)) { game::LegoObject_DropCarriedObject(liveObj,FALSE); } } else { if (((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && (liveObj->carriedObjects[0] != NULL)) { game::LegoObject_FUN_0043fee0(liveObj->carriedObjects[0]); return 0; } } return 0; } BOOL __cdecl lego::front::Interface_CheckPrimaryUnitHasAbility(LegoObject_AbilityFlags abilityFlag) { LegoObject *liveObj; liveObj = game::Message_GetPrimarySelectedUnit(); return (uint)((liveObj->abilityFlags & abilityFlag) != ABILITY_FLAG_NONE); } BOOL __cdecl lego::front::Interface_Block_FUN_0041f670(Point2I *blockPos) { BOOL BVar1; uint uVar2; int iVar3; int *piVar4; int local_20 [5]; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_20[4] = 0xffffffff; local_4 = 0xffffffff; uVar2 = 0; local_20[0] = 1; local_20[1] = 0; local_20[2] = 0; local_20[3] = 1; local_c = 0; local_8 = 0; BVar1 = game::Level_Block_IsCorner(blockPos->x,blockPos->y); if (BVar1 == 0) { piVar4 = local_20; do { BVar1 = game::Level_Block_IsSolidBuilding(blockPos->x + *piVar4,piVar4[1] + blockPos->y,1); if (BVar1 != 0) { return 0; } uVar2 += 1; piVar4 = piVar4 + 2; } while (uVar2 < 4); return 1; } uVar2 = 0; piVar4 = local_20; iVar3 = 4; do { BVar1 = game::Level_Block_IsSolidBuilding(blockPos->x + *piVar4,piVar4[1] + blockPos->y,1); if (BVar1 != 0) { uVar2 += 1; } piVar4 = piVar4 + 2; iVar3 += -1; } while (iVar3 != 0); if (1 < uVar2) { return 0; } return 1; } BOOL __cdecl lego::front::Interface_ObjectCallback_HasToolEquipped_2 (LegoObject *liveObj,LegoObject_ToolType toolType) { BOOL BVar1; BVar1 = game::LegoObject_HasToolEquipped(liveObj,toolType); return (uint)(BVar1 != 0); } BOOL __cdecl lego::front::Interface_ObjectCallback_PlaceBirdScarerIfEquipped(LegoObject *liveObj,void *unused) { BOOL BVar1; BVar1 = game::LegoObject_HasToolEquipped(liveObj,LegoObject_ToolType_BirdScarer); if (BVar1 != 0) { game::LegoObject_PlaceBirdScarer_AndTickDown(liveObj); } return 0; } void __cdecl lego::game::Level_IncCrystalsStored(void) { if (globs::legoGlobs.currLevel != NULL) { (globs::legoGlobs.currLevel)->crystals = (globs::legoGlobs.currLevel)->crystals + 1; } return; } void __cdecl lego::game::Level_SubtractCrystalsStored(int crystalAmount) { if (globs::legoGlobs.currLevel != NULL) { (globs::legoGlobs.currLevel)->crystals = (globs::legoGlobs.currLevel)->crystals - crystalAmount; } return; } void __cdecl lego::game::Level_AddCrystalsDrained(int crystalDrainedAmount) { if (globs::legoGlobs.currLevel != NULL) { (globs::legoGlobs.currLevel)->crystalsDrained = (globs::legoGlobs.currLevel)->crystalsDrained + crystalDrainedAmount; } return; } void __cdecl lego::game::Level_ResetCrystalsDrained(void) { if (globs::legoGlobs.currLevel != NULL) { (globs::legoGlobs.currLevel)->crystalsDrained = 0; } return; } // FALSE - GetCrystalsFree (not powering buildings) // TRUE - GetCrystalsStored (total) int __cdecl lego::game::Level_GetCrystalCount(BOOL includeDrained) { int in_EAX; if ((globs::legoGlobs.currLevel != NULL) && (in_EAX = (globs::legoGlobs.currLevel)->crystals, includeDrained == FALSE)) { in_EAX -= (globs::legoGlobs.currLevel)->crystalsDrained; } // Undefined return value if not currently in level. But that's okay...-ish... return in_EAX; } // FALSE : GetOreStored (normal ore) // TRUE : GetProcessedOreStored (studs) int __cdecl lego::game::Level_GetOreCount(BOOL isProcessed) { Lego_Level *level; level = globs::legoGlobs.currLevel; if (globs::legoGlobs.currLevel != NULL) { if (isProcessed != 0) { // return (globs::legoGlobs.currLevel)->studs; return (int)(Lego_Level *)(globs::legoGlobs.currLevel)->studs; } // return (globs::legoGlobs.currLevel)->ore; level = (Lego_Level *)(globs::legoGlobs.currLevel)->ore; } return (int)level; } void __cdecl lego::game::Level_AddStolenCrystals(int stolenCrystalAmount) { if (globs::legoGlobs.currLevel != NULL) { (globs::legoGlobs.currLevel)->crystalsStolen = (globs::legoGlobs.currLevel)->crystalsStolen + stolenCrystalAmount; } return; } void __cdecl lego::game::Lego_SetRadarNoTrackObject(BOOL noTrackObj) { if (noTrackObj != 0) { globs::legoGlobs.flags1 = globs::legoGlobs.flags1 | GAME1_RADAR_NOTRACKOBJECT; return; } globs::legoGlobs.flags1 = globs::legoGlobs.flags1 & ~GAME1_RADAR_NOTRACKOBJECT; return; } BOOL __cdecl lego::game::Lego_IsNoclipOn(void) { return globs::legoGlobs.flags1 & GAME1_DEBUG_NOCLIP_FPS; } void __cdecl lego::game::Level_IncCrystalsPickedUp(void) { if (globs::legoGlobs.currLevel != NULL) { (globs::legoGlobs.currLevel)->crystalsPickedUp = (globs::legoGlobs.currLevel)->crystalsPickedUp + 1; } return; } void __cdecl lego::game::Level_IncOrePickedUp(void) { if (globs::legoGlobs.currLevel != NULL) { (globs::legoGlobs.currLevel)->orePickedUp = (globs::legoGlobs.currLevel)->orePickedUp + 1; } return; } void __cdecl lego::game::Level_IncOreStored(BOOL isProcessed) { if (globs::legoGlobs.currLevel != NULL) { if (isProcessed == 0) { (globs::legoGlobs.currLevel)->ore = (globs::legoGlobs.currLevel)->ore + 1; } else { (globs::legoGlobs.currLevel)->studs = (globs::legoGlobs.currLevel)->studs + 1; } } if (isProcessed != 0) { front::Panel_CryOreSideBar_ChangeOreMeter(TRUE,5); return; } front::Panel_CryOreSideBar_ChangeOreMeter(TRUE,1); return; } void __cdecl lego::game::Level_SubtractOreStored(BOOL isProcessed,int oreAmount) { if (globs::legoGlobs.currLevel != NULL) { if (isProcessed == 0) { (globs::legoGlobs.currLevel)->ore = (globs::legoGlobs.currLevel)->ore - oreAmount; } else { (globs::legoGlobs.currLevel)->studs = (globs::legoGlobs.currLevel)->studs - oreAmount; } } if (isProcessed != 0) { // VISUAL BUG: This doesn't account for a value greater than one... front::Panel_CryOreSideBar_ChangeOreMeter(FALSE,5); return; } front::Panel_CryOreSideBar_ChangeOreMeter(FALSE,oreAmount); return; } BOOL __cdecl lego::Gods_Go(char *programName) { BOOL BVar1; int iVar2; Lego_Globs *pLVar3; Main_State mainState; // std::memset(&legoGlobs, 0, sizeof(legoGlobs)); // 0xef8 pLVar3 = &globs::legoGlobs; for (iVar2 = 0x3be; iVar2 != 0; iVar2 += -1) { pLVar3->config = NULL; pLVar3 = (Lego_Globs *)&pLVar3->gameName; } globs::legoGlobs.gameName = programName; main::Main_SetTitle(programName); mainState.Initialise = lrr::Lego_Initialise; mainState.MainLoop = lrr::Lego_MainLoop; mainState.Shutdown = lrr::Lego_Shutdown_Full; if (globs::mainGlobs.programmerLevel != PROGRAMMER_MODE_10) { // Full shutdown with proper cleanup. mainState.Shutdown = lrr::Lego_Shutdown_Quick; } BVar1 = main::Main_SetState(&mainState); return BVar1; } void __cdecl lego::lrr::Lego_QuitLevel(void) { Lego_GetLevel(); if ((globs::legoGlobs.flags1 & GAME1_LEVELENDING) == GAME1_NONE) { // table[REWARDTYPE_FIGURES] globs::rewardGlobs.current.items[5].numDestroyed = nerps::NERPsRuntime_GetPreviousLevelObjectsBuilt("Pilot",0); globs::legoGlobs.flags1 |= GAME1_LEVELENDING; game::Construction_DisableCryOreDrop(TRUE); game::LegoObject_SetLevelEnding(TRUE); unk::Teleporter_Start(TELEPORT_SERVIVE_VEHICLE,1,1); unk::Teleporter_Start(TELEPORT_SERVIVE_MINIFIGURE,1,1); unk::Teleporter_Start(TELEPORT_SERVIVE_BUILDING,1,1); unk::Teleporter_Start(TELEPORT_SERVIVE_ELECTRICFENCE,1,1); Lego_SetPaused(FALSE,FALSE); front::Interface_BackToMain(); // panelGlobs.panelTable[Panel_Radar] if (((byte)globs::panelGlobs.panelTable[0].flags & PANEL_FLAG_OPEN) != 0) { front::Panel_ToggleOpenClosed(Panel_Radar); front::Panel_ToggleOpenClosed(Panel_RadarFill); } } return; } float10 __cdecl lego::game::Lego_GetGameSpeed(void) { return (float10)globs::legoGlobs.gameSpeed; } BOOL __cdecl lego::lrr::Lego_Initialise(void) { char *pcVar1; BOOL BVar2; uint uVar3; uint uVar4; char *pcVar5; ProgrammerMode PVar6; char *pcVar7; byte *input; BoolTri BVar8; int iVar9; Config *config; float10 fVar10; float10 fVar11; float10 fVar12; int iVar13; float *out_r; float red; ColourRGBF *pCVar14; float *pfVar15; float green; float *pfVar16; float blue; char *MinEnergyForEat_str; char *HighPolyRange_str; char *MedPolyRange_str; char *ReinforceHits_str; char *DrainTime_str; char *MiniFigureRunAway_str; char *HPBlocks_str; char *CDTracks_str; char *CDStartTrack_str; char *BirdScarerRadius_str; char *DynamiteWakeRadius_str; char *DynamiteMaxDamage_str; char *DynamiteDamageRadius_str; char *tvclipdist_str; char *maxdist_str; char *mindist_str; char *MouseScrollBorder_str; char *MaxReturnedCrystals_str; char *RollOffFor3DSounds_str; char *MaxDistFor3DSounds_str; char *MinDistFor3DSoundsOnTopView_str; char *MouseScrollIndent_str; char *CameraAcceleration_str; char *CameraDropOff_str; char *CameraSpeed_str; char *LoaderProfile_filename; char *TextPauseTime_str; char *TextureUsage_str; char *BuildingUpgradeCostStuds_str; char *BuildingUpgradeCostOre_str; char *startLevelName; Point2F Dialog_center; char *Window_stringParts [4]; int Window_numParts; Area2F Window_rect; Config *Pointers_cfgProp; float CameraDropOff; float CameraSpeed; float MaxDistFor3DSounds; float RollOffFor3DSounds; int MouseScrollIndent; float CameraAcceleration; float MinDistFor3DSoundsOnTopView; char *Button_lpstr; char *Button_stringParts [10]; char Button_buffer [128]; char *Button_filename; char *SharedSizes_str; char *LoadScreen; char *ProgressBar; char *ProgressWindow; char *LoadingText; char *ShutdownScreen; Direction ProgressBar_direction; Area2F ProgressWindow_rect; char *ProgressWindow_stringParts [10]; char *StartMessage; char *Version; Area2F MsgPanel_rect1; Area2F MsgPanel_rect2; float local_5c; Area2F fontRender84_rect; Area2F fontRender80_rect; uint TextureUsage; uint videoMemFree; uint videoMemTotal; char *RenameReplace_ptr; float ToolTipRGB_g; float ToolTipRGB_r; float ToolTipRGB_b; float maxdist; float mindist; Config *legoConfig; uint surfaceIdx_unused; float maxtilt; float mintilt; globs::legoGlobs.DragBoxRGB.red = 0.2; globs::legoGlobs.DragBoxRGB.green = 0.7; globs::legoGlobs.DragBoxRGB.blue = 1.0; globs::legoGlobs.surfaceName[0] = "Lego_SurfaceType_Tunnel"; globs::legoGlobs.surfaceName[1] = "Lego_SurfaceType_Immovable"; globs::legoGlobs.surfaceName[2] = "Lego_SurfaceType_Hard"; globs::legoGlobs.surfaceName[3] = "Lego_SurfaceType_Medium"; globs::legoGlobs.surfaceName[4] = "Lego_SurfaceType_Loose"; globs::legoGlobs.surfaceName[5] = "Lego_SurfaceType_Soil"; globs::legoGlobs.surfaceName[6] = "Lego_SurfaceType_Lava"; globs::legoGlobs.surfaceName[7] = "Lego_SurfaceType_Water"; globs::legoGlobs.surfaceName[8] = "Lego_SurfaceType_OreSeam"; globs::legoGlobs.surfaceName[9] = "Lego_SurfaceType_Lake"; globs::legoGlobs.surfaceName[10] = "Lego_SurfaceType_CrystalSeam"; globs::legoGlobs.surfaceName[11] = "Lego_SurfaceType_RechargeSeam"; globs::legoGlobs.surfaceName[12] = "Lego_SurfaceType_Rubble"; globs::legoGlobs.surfaceName[13] = "Lego_SurfaceType_Reinforcement"; globs::legoGlobs.surfaceName[14] = "Lego_SurfaceType_Path"; globs::legoGlobs.surfaceName[15] = "Lego_SurfaceType_SlugHole"; globs::legoGlobs.surfaceName[16] = "Lego_SurfaceType_Undiscovered"; globs::legoGlobs.surfaceName[17] = "Lego_SurfaceType_Cavern"; for (surfaceIdx_unused = 0; surfaceIdx_unused < 0x12; surfaceIdx_unused += 1) { } Lego_SetGameSpeed(1.0); lego::input::Keys_Initialise(); lego::view::Viewport_Initialise(); game::LegoObject_Initialise(); lego::image::Image_Initialise(); // No argument actually passed, just problem with variadic functions not allowing zero // args util::logf_removed(); game::RadarMap_Initialise(); front::Panel_Initialise(); ai::AITask_Initialise(); game::Message_Initialise(); effect::Smoke_Initialise(); front::Pointer_Initialise(); front::Bubble_Initialise(); globs::legoGlobs.fontStandard = lego::image::Font_Load("Interface\\Fonts\\FONT5_HI.bmp"); globs::legoGlobs.fontToolTip = lego::image::Font_Load("Interface\\Fonts\\ToolTipFont.bmp"); globs::legoGlobs.fontTallYellow = lego::image::Font_Load("Interface\\Fonts\\DeskTopFont.bmp"); globs::legoGlobs.fontTextWindow = lego::image::Font_Load("Interface\\Fonts\\font5_HI.bmp"); globs::legoGlobs.fontBriefingLo = lego::image::Font_Load("Interface\\Fonts\\MBriefFONT.bmp"); globs::legoGlobs.fontBriefingHi = lego::image::Font_Load("Interface\\Fonts\\MBriefFONT2.bmp"); globs::legoGlobs.fontCredits = lego::image::Font_Load("Interface\\Fonts\\RSFont.bmp"); front::Info_Initialise(globs::legoGlobs.fontStandard); front::Interface_Initialise(565,18,globs::legoGlobs.fontToolTip); globs::legoGlobs.rootCont = gfx::Container_Initialise(globs::legoGlobs.gameName); if (globs::legoGlobs.rootCont == NULL) { return 0; } gfx::Container_SetTriggerFrameCallback(game::LegoObject_TriggerFrameCallback,NULL); globs::legoGlobs.config = cfg::Config_Load("Lego.cfg"); legoConfig = globs::legoGlobs.config; if (globs::legoGlobs.config == NULL) goto LAB_0042274b; pfVar16 = &ToolTipRGB_b; pfVar15 = &ToolTipRGB_g; out_r = &ToolTipRGB_r; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","ToolTipRGB",0); BVar2 = cfg::Config_GetRGBValue(legoConfig,pcVar1,out_r,pfVar15,pfVar16); if (BVar2 == 0) { ToolTipRGB_b = 0.3254902; ToolTipRGB_g = 0.3254902; ToolTipRGB_r = 0.3254902; } iVar13 = 32; red = ToolTipRGB_r; green = ToolTipRGB_g; blue = ToolTipRGB_b; uVar3 = main::appHeight(); uVar4 = main::appWidth(); front::ToolTip_Initialise(globs::legoGlobs.fontToolTip,2,1,1.0,uVar4,uVar3,iVar13,red,green,blue); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CreditsTextFile",0); globs::legoGlobs.CreditsTextFile = cfg::Config_GetStringValue(legoConfig,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CreditsBackAVI",0); globs::legoGlobs.CreditsBackAVI = cfg::Config_GetStringValue(legoConfig,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","BuildingUpgradeCostOre",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { BuildingUpgradeCostOre_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","BuildingUpgradeCostOre",0); BuildingUpgradeCostOre_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } globs::legoGlobs.BuildingUpgradeCostOre = std::atoi(BuildingUpgradeCostOre_str); if (globs::legoGlobs.BuildingUpgradeCostOre == 0) { globs::legoGlobs.BuildingUpgradeCostOre = 5; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","BuildingUpgradeCostStuds",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { BuildingUpgradeCostStuds_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"Main","BuildingUpgradeCostStuds",0); BuildingUpgradeCostStuds_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } globs::legoGlobs.BuildingUpgradeCostStuds = std::atoi(BuildingUpgradeCostStuds_str); if (globs::legoGlobs.BuildingUpgradeCostStuds == 0) { globs::legoGlobs.BuildingUpgradeCostStuds = 1; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","RenameReplace",0); globs::legoGlobs.RenameReplace = cfg::Config_GetStringValue(legoConfig,pcVar1); pcVar1 = globs::legoGlobs.RenameReplace; if (globs::legoGlobs.RenameReplace != NULL) { while (RenameReplace_ptr = pcVar1, *RenameReplace_ptr != '\0') { if (*RenameReplace_ptr == '_') { *RenameReplace_ptr = ' '; } pcVar1 = RenameReplace_ptr + 1; } } BVar2 = ddraw::DirectDraw_GetAvailTextureMem(&videoMemTotal,&videoMemFree); if (BVar2 != 0) { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","TextureUsage",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { TextureUsage_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","TextureUsage",0); TextureUsage_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } TextureUsage = std::atoi(TextureUsage_str); if ((TextureUsage != 0) && (ddraw::DirectDraw_AdjustTextureUsage(&TextureUsage), TextureUsage <= videoMemFree)) { main::Main_DisableTextureManagement(); } } fontRender80_rect.x = 55.0; fontRender80_rect.y = 435.0; fontRender80_rect.width = 325.0; fontRender80_rect.height = 42.0; globs::legoGlobs.textOnlyWindow = front::TextWindow_Create(globs::legoGlobs.fontTextWindow,&fontRender80_rect,0x400); fontRender84_rect.x = 55.0; fontRender84_rect.y = 435.0; fontRender84_rect.width = 260.0; fontRender84_rect.height = 42.0; globs::legoGlobs.textImageWindow = front::TextWindow_Create(globs::legoGlobs.fontTextWindow,&fontRender84_rect,0x400); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","TextPauseTime",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { TextPauseTime_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","TextPauseTime",0); TextPauseTime_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(TextPauseTime_str); front::Text_Load(globs::legoGlobs.textOnlyWindow,globs::legoGlobs.textImageWindow,0x13c,0x1a9, (float)(fVar10 * (float10)25.0)); MsgPanel_rect1.x = 55.0; MsgPanel_rect1.y = 435.0; MsgPanel_rect1.width = 325.0; MsgPanel_rect1.height = 42.0; MsgPanel_rect2.x = 55.0; MsgPanel_rect2.y = 363.0; MsgPanel_rect2.width = 325.0; MsgPanel_rect2.height = 140.0; front::Text_Initialise ("Interface\\MessagePanel\\MsgPanel.bmp",0x2a,0x199,0x152,&MsgPanel_rect1, &MsgPanel_rect2,20.0); if ((globs::mainGlobs.flags & MAIN_FLAG_SHOWVERSION) != MAIN_FLAG_NONE) { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","StartMessage",0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); pcVar5 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","Version",0); pcVar5 = cfg::Config_GetTempStringValue(legoConfig,pcVar5); if (pcVar1 != NULL) { pcVar1 = front::Front_Util_StringReplaceChar(pcVar1,'_',' '); if (pcVar5 == NULL) { front::TextWindow_PrintF(globs::legoGlobs.textOnlyWindow,"\n%s",pcVar1); } else { front::TextWindow_PrintF(globs::legoGlobs.textOnlyWindow,"\n%s (%s)",pcVar1,pcVar5); } util::free2(pcVar1); } } BVar2 = front::Front_IsFrontEndEnabled(); if ((BVar2 != 0) && (BVar2 = front::Front_IsIntrosEnabled(), BVar2 != 0)) { PVar6 = main::Main_ProgrammerMode(); front::Front_PlayIntroMovie("LegoAvi",(uint)(PVar6 != PROGRAMMER_OFF)); front::Front_PlayIntroSplash("DDILogo",TRUE,"DDILogoTime"); front::Front_PlayIntroMovie("DDIAvi",TRUE); front::Front_PlayIntroMovie("RRAvi",TRUE); pcVar1 = "LMILogoTime"; PVar6 = main::Main_ProgrammerMode(); front::Front_PlayIntroSplash("LMILogo",(uint)(PVar6 != PROGRAMMER_OFF),pcVar1); } snd::SFX_Initialise(); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","ProgressBar",0); ProgressBar = cfg::Config_GetTempStringValue(legoConfig,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","LoadScreen",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); pcVar5 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","ShutdownScreen",0); pcVar5 = cfg::Config_GetTempStringValue(legoConfig,pcVar5); pcVar7 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","ProgressWindow",0); input = (byte *)cfg::Config_GetStringValue(legoConfig,pcVar7); pcVar7 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","LoadingText",0); pcVar7 = cfg::Config_GetTempStringValue(legoConfig,pcVar7); if (input == NULL) { ProgressBar = NULL; } else { iVar13 = std::toupper((uint)*input); *input = (byte)iVar13; if (false) { LAB_004203f0: ProgressBar_direction = DIRECTION__COUNT; } else { switch(*input) { case 0x44: ProgressBar_direction = DIRECTION_DOWN; break; default: goto LAB_004203f0; case 0x4c: ProgressBar_direction = DIRECTION_LEFT; break; case 0x52: ProgressBar_direction = DIRECTION_RIGHT; break; case 0x55: ProgressBar_direction = DIRECTION_UP; } } iVar13 = util::Util_Tokenise((char *)input,ProgressWindow_stringParts,","); if (((iVar13 == 4) && (input[1] == 0x3a)) && (ProgressBar_direction != DIRECTION__COUNT)) { iVar13 = std::atoi(ProgressWindow_stringParts[0] + 2); ProgressWindow_rect.x = (float)iVar13; iVar13 = std::atoi(ProgressWindow_stringParts[1]); ProgressWindow_rect.y = (float)iVar13; iVar13 = std::atoi(ProgressWindow_stringParts[2]); ProgressWindow_rect.width = (float)iVar13; iVar13 = std::atoi(ProgressWindow_stringParts[3]); ProgressWindow_rect.height = (float)iVar13; } } util::free2(input); BVar2 = snd::Sound_IsInitialised(); if (BVar2 == 0) { LoaderProfile_filename = "LoaderProfileNoSound.txt"; } else { LoaderProfile_filename = "LoaderProfile.txt"; } front::Loader_Initialise (pcVar1,pcVar5,globs::legoGlobs.fontStandard,LoaderProfile_filename, ProgressBar_direction,ProgressBar,&ProgressWindow_rect,pcVar7); front::Loader_display_loading_bar("Game Data"); globs::legoGlobs.cameraMain = lego::view::Camera_Create(globs::legoGlobs.rootCont,LegoCamera_Top); if (((globs::legoGlobs.cameraMain == NULL) || (globs::legoGlobs.cameraFP = lego::view::Camera_Create(globs::legoGlobs.rootCont,LegoCamera_FP), globs::legoGlobs.cameraFP == NULL)) || ((globs::legoGlobs.cameraTrack = lego::view::Camera_Create(globs::legoGlobs.rootCont,LegoCamera_Radar), globs::legoGlobs.cameraTrack == NULL || ((globs::legoGlobs.viewMain = lego::view::Viewport_Create(0.0,0.0,1.0,1.0,(globs::legoGlobs.cameraMain)->contCam), globs::legoGlobs.viewMain == NULL || (globs::legoGlobs.viewTrack = lego::view::Viewport_CreatePixel (0x10,0xd,0x97,0x97,(globs::legoGlobs.cameraTrack)->contCam), globs::legoGlobs.viewTrack == NULL)))))) goto LAB_0042274b; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","StreamNERPSSpeach",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags1 |= GAME1_STREAMNERPSSPEACH; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","ShowDebugToolTips",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if ((BVar8 == BOOL3_TRUE) || (PVar6 = main::Main_ProgrammerMode(), PVar6 != PROGRAMMER_OFF)) { globs::legoGlobs.flags2 |= GAME2_SHOWDEBUGTOOLTIPS; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","AllowDebugKeys",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if ((BVar8 == BOOL3_TRUE) || (PVar6 = main::Main_ProgrammerMode(), PVar6 != PROGRAMMER_OFF)) { globs::legoGlobs.flags2 |= GAME2_ALLOWDEBUGKEYS; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","AllowEditMode",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if ((BVar8 == BOOL3_TRUE) || (PVar6 = main::Main_ProgrammerMode(), PVar6 != PROGRAMMER_OFF)) { globs::legoGlobs.flags2 |= GAME2_ALLOWEDITMODE; } pfVar15 = &globs::legoGlobs.PowerCrystalRGB.blue; pfVar16 = &globs::legoGlobs.PowerCrystalRGB.green; pCVar14 = &globs::legoGlobs.PowerCrystalRGB; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","PowerCrystalRGB",0); cfg::Config_GetRGBValue(legoConfig,pcVar1,&pCVar14->red,pfVar16,pfVar15); pfVar15 = &globs::legoGlobs.UnpoweredCrystalRGB.blue; pfVar16 = &globs::legoGlobs.UnpoweredCrystalRGB.green; pCVar14 = &globs::legoGlobs.UnpoweredCrystalRGB; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","UnpoweredCrystalRGB",0); cfg::Config_GetRGBValue(legoConfig,pcVar1,&pCVar14->red,pfVar16,pfVar15); Lego_LoadSamples(legoConfig, (uint)((globs::mainGlobs.flags & MAIN_FLAG_REDUCESAMPLES) == MAIN_FLAG_NONE)); Lego_LoadSurfaceTypeDescriptions_sound(legoConfig,globs::legoGlobs.gameName); ai::Priorities_LoadPositions(legoConfig,globs::legoGlobs.gameName); ai::Priorities_LoadImages(legoConfig,globs::legoGlobs.gameName); Lego_LoadToolTipInfos(legoConfig,globs::legoGlobs.gameName); game::Object_LoadToolNames(legoConfig,globs::legoGlobs.gameName); front::Panel_RotationControl_Initialise(legoConfig,globs::legoGlobs.gameName); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","SharedObjects",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); gfx::Lws_Initialise(pcVar1,snd::SFX_GetType,snd::SFX_Random_PlaySound3DOnFrame,snd::SFX_IsSoundOn) ; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","SharedTextures",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 != NULL) { gfx::Container_SetSharedTextureDirectory(pcVar1); } gfx::Mesh_Initialise(pcVar1); iVar13 = main::appHeight(); iVar9 = main::appWidth(); std::sprintf(Button_buffer,"NextButton%ix%i",iVar9,iVar13); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",Button_buffer,0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (globs::legoGlobs.NextButtonImage = lego::image::Image_LoadBMPScaled(pcVar1,0,0), globs::legoGlobs.NextButtonImage != NULL)) { lego::image::Image_SetupTrans(globs::legoGlobs.NextButtonImage,0.0,0.0,0.0,0.0,0.0,0.0); iVar13 = main::appHeight(); iVar9 = main::appWidth(); std::sprintf(Button_buffer,"NextButtonPos%ix%i",iVar9,iVar13); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",Button_buffer,0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); if (pcVar1 != NULL) { iVar13 = util::Util_Tokenise(pcVar1,Button_stringParts,","); if (iVar13 == 2) { fVar10 = std::atof(Button_stringParts[0]); globs::legoGlobs.NextButtonPos.x = (float)fVar10; fVar10 = std::atof(Button_stringParts[1]); globs::legoGlobs.NextButtonPos.y = (float)fVar10; } util::free2(pcVar1); } } iVar13 = main::appHeight(); iVar9 = main::appWidth(); std::sprintf(Button_buffer,"BackButton%ix%i",iVar9,iVar13); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",Button_buffer,0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (globs::legoGlobs.RepeatButtonImage = lego::image::Image_LoadBMPScaled(pcVar1,0,0), globs::legoGlobs.RepeatButtonImage != NULL)) { lego::image::Image_SetupTrans(globs::legoGlobs.RepeatButtonImage,0.0,0.0,0.0,0.0,0.0,0.0); iVar13 = main::appHeight(); iVar9 = main::appWidth(); std::sprintf(Button_buffer,"BackButtonPos%ix%i",iVar9,iVar13); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main",Button_buffer,0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); if (pcVar1 != NULL) { iVar13 = util::Util_Tokenise(pcVar1,Button_stringParts,","); if (iVar13 == 2) { fVar10 = std::atof(Button_stringParts[0]); globs::legoGlobs.RepeatButtonPos.x = (float)fVar10; fVar10 = std::atof(Button_stringParts[1]); globs::legoGlobs.RepeatButtonPos.y = (float)fVar10; } util::free2(pcVar1); } } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","BackArrow",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (globs::legoGlobs.BackArrowImage = lego::image::Image_LoadBMPScaled(pcVar1,0,0), globs::legoGlobs.BackArrowImage != NULL)) { lego::image::Image_SetupTrans(globs::legoGlobs.BackArrowImage,0.0,0.0,0.0,0.0,0.0,0.0); } nerps::NERPs_SetHasNextButton((uint)(globs::legoGlobs.NextButtonImage != NULL)); BVar2 = Lego_LoadLighting(); if (((((BVar2 != 0) && (BVar2 = Lego_LoadGraphicsSettings(), BVar2 != 0)) && (BVar2 = Lego_LoadUpgradeTypes(), BVar2 != 0)) && ((BVar2 = Lego_LoadVehicleTypes(), BVar2 != 0 && (BVar2 = Lego_LoadMiniFigureTypes(), BVar2 != 0)))) && ((BVar2 = Lego_LoadRockMonsterTypes(), BVar2 != 0 && (BVar2 = Lego_LoadBuildingTypes(), BVar2 != 0)))) { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CameraSpeed",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { CameraSpeed_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CameraSpeed",0); CameraSpeed_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(CameraSpeed_str); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CameraDropOff",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { CameraDropOff_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CameraDropOff",0); CameraDropOff_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar11 = std::atof(CameraDropOff_str); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CameraAcceleration",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { CameraAcceleration_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CameraAcceleration",0); CameraAcceleration_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar12 = std::atof(CameraAcceleration_str); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MouseScrollIndent",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { MouseScrollIndent_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MouseScrollIndent",0); MouseScrollIndent_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } iVar13 = std::atoi(MouseScrollIndent_str); lego::view::Camera_InitCameraMovements((float)fVar10,(float)fVar11,(float)fVar12,iVar13); pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"Main","MinDistFor3DSoundsOnTopView",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { MinDistFor3DSoundsOnTopView_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"Main","MinDistFor3DSoundsOnTopView",0); MinDistFor3DSoundsOnTopView_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(MinDistFor3DSoundsOnTopView_str); globs::legoGlobs.MinDistFor3DSoundsOnTopView = (float)fVar10; if (fVar10 == (float10)0.0) { globs::legoGlobs.MinDistFor3DSoundsOnTopView = 150.0; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MaxDistFor3DSounds",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { MaxDistFor3DSounds_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MaxDistFor3DSounds",0); MaxDistFor3DSounds_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(MaxDistFor3DSounds_str); if (fVar10 != (float10)0.0) { snd::Sound3D_SetMaxDist((float)fVar10); } snd::Sound3D_SetRollOffFactor(1.0); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","RollOffFor3DSounds",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { RollOffFor3DSounds_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","RollOffFor3DSounds",0); RollOffFor3DSounds_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(RollOffFor3DSounds_str); if (fVar10 != (float10)0.0) { snd::Sound3D_SetRollOffFactor((float)fVar10); } globs::legoGlobs.selectPlace = gfx::SelectPlace_Create(globs::legoGlobs.rootCont,5.0); gfx::SelectPlace_Hide(globs::legoGlobs.selectPlace,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MaxReturnedCrystals",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { MaxReturnedCrystals_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MaxReturnedCrystals",0); MaxReturnedCrystals_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } globs::legoGlobs.MaxReturnedCrystals = std::atoi(MaxReturnedCrystals_str); if (globs::legoGlobs.MaxReturnedCrystals == 0) { globs::legoGlobs.MaxReturnedCrystals = 10; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MouseScrollBorder",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { MouseScrollBorder_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MouseScrollBorder",0); MouseScrollBorder_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } globs::legoGlobs.MouseScrollBorder = std::atoi(MouseScrollBorder_str); if (globs::legoGlobs.MouseScrollBorder == 0) { globs::legoGlobs.MouseScrollBorder = 5; } Lego_LoadObjectNames(legoConfig); Lego_LoadObjectTheNames(legoConfig); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","HelpWindowOn",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_TRUE) { front::HelpWindow_SetFont(globs::legoGlobs.fontBriefingHi); front::HelpWindow_Initialise(legoConfig,globs::legoGlobs.gameName); } front::ObjInfo_Initialise(legoConfig,globs::legoGlobs.gameName); light::LightEffects_Load(legoConfig,globs::legoGlobs.gameName); stats::Stats_Initialise(legoConfig,globs::legoGlobs.gameName); game::Dependencies_Initialise(legoConfig,globs::legoGlobs.gameName); front::Bubble_LoadBubbles(legoConfig); front::Encyclopedia_Initialise(legoConfig,globs::legoGlobs.gameName); front::LegoObject_LoadObjTtsSFX(legoConfig,globs::legoGlobs.gameName); tools::Weapon_Initialise(legoConfig,globs::legoGlobs.gameName); globs::legoGlobs.viewMode = ViewMode_Top; snd::Sound3D_MakeListener((globs::legoGlobs.cameraMain)->contListener->masterFrame); snd::Sound3D_SetMinDistForAtten(globs::legoGlobs.MinDistFor3DSoundsOnTopView); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","mindist",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { mindist_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","mindist",0); mindist_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(mindist_str); mindist = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","maxdist",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { maxdist_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","maxdist",0); maxdist_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(maxdist_str); maxdist = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","mintilt",0); fVar10 = cfg::Config_GetAngle(legoConfig,pcVar1); mintilt = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","maxtilt",0); fVar10 = cfg::Config_GetAngle(legoConfig,pcVar1); maxtilt = (float)fVar10; lego::view::Camera_SetZoomRange(globs::legoGlobs.cameraMain,mindist,maxdist); lego::view::Camera_SetTiltRange(globs::legoGlobs.cameraMain,mintilt,maxtilt); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","tvclipdist",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { tvclipdist_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","tvclipdist",0); tvclipdist_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(tvclipdist_str); globs::legoGlobs.TVClipDist = (float)fVar10; lego::view::Viewport_SetBackClip(globs::legoGlobs.viewMain,globs::legoGlobs.TVClipDist); lego::view::Viewport_SetBackClip(globs::legoGlobs.viewTrack,globs::legoGlobs.TVClipDist); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DynamiteDamageRadius",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { DynamiteDamageRadius_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DynamiteDamageRadius",0); DynamiteDamageRadius_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(DynamiteDamageRadius_str); globs::legoGlobs.DynamiteDamageRadius = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DynamiteMaxDamage",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { DynamiteMaxDamage_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DynamiteMaxDamage",0); DynamiteMaxDamage_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(DynamiteMaxDamage_str); globs::legoGlobs.DynamiteMaxDamage = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DynamiteWakeRadius",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { DynamiteWakeRadius_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DynamiteWakeRadius",0); DynamiteWakeRadius_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(DynamiteWakeRadius_str); globs::legoGlobs.DynamiteWakeRadius = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","BirdScarerRadius",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { BirdScarerRadius_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","BirdScarerRadius",0); BirdScarerRadius_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(BirdScarerRadius_str); globs::legoGlobs.BirdScarerRadius = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MusicOn",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags2 |= GAME2_MUSICREADY; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CDStartTrack",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { CDStartTrack_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CDStartTrack",0); CDStartTrack_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } globs::legoGlobs.CDStartTrack = std::atoi(CDStartTrack_str); if (globs::legoGlobs.CDStartTrack == 0) { globs::legoGlobs.CDStartTrack = 2; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CDTracks",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { CDTracks_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","CDTracks",0); CDTracks_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } globs::legoGlobs.CDTracks = std::atoi(CDTracks_str); if (globs::legoGlobs.CDTracks == 0) { globs::legoGlobs.flags2 &= ~GAME2_MUSICREADY; globs::legoGlobs.CDTracks = 1; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","SoundOn",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags1 |= GAME1_USESFX; } globs::legoGlobs.flags1 |= GAME1_USEDETAIL|GAME1_DDRAWCLEAR|GAME1_RENDERPANELS|GAME1_DYNAMICPM; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","Clear",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_FALSE) { globs::legoGlobs.flags1 &= ~GAME1_DDRAWCLEAR; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","Panels",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_FALSE) { globs::legoGlobs.flags1 &= ~GAME1_RENDERPANELS; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","WallProMeshes",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_FALSE) { globs::legoGlobs.flags1 &= ~GAME1_USEDETAIL; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DynamicPM",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_FALSE) { globs::legoGlobs.flags1 &= ~GAME1_DYNAMICPM; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","HPBlocks",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { HPBlocks_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","HPBlocks",0); HPBlocks_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } globs::legoGlobs.HPBlocks = std::atoi(HPBlocks_str); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","OnlyBuildOnPaths",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags1 |= GAME1_ONLYBUILDONPATHS; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","AlwaysRockFall",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags1 |= GAME1_ALWAYSROCKFALL; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MiniFigureRunAway",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { MiniFigureRunAway_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MiniFigureRunAway",0); MiniFigureRunAway_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(MiniFigureRunAway_str); globs::legoGlobs.MiniFigureRunAway = (float)fVar10; if (fVar10 == (float10)0.0) { globs::legoGlobs.MiniFigureRunAway = 10.0; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DrainTime",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { DrainTime_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DrainTime",0); DrainTime_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(DrainTime_str); globs::legoGlobs.DrainTime = (float)fVar10; if (fVar10 == (float10)0.0) { globs::legoGlobs.DrainTime = 10.0; } globs::legoGlobs.DrainTime = globs::legoGlobs.DrainTime * 25.0; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","ReinforceHits",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { ReinforceHits_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","ReinforceHits",0); ReinforceHits_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } globs::legoGlobs.ReinforceHits = std::atoi(ReinforceHits_str); if (globs::legoGlobs.ReinforceHits == 0) { globs::legoGlobs.ReinforceHits = 4; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MedPolyRange",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { MedPolyRange_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MedPolyRange",0); MedPolyRange_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(MedPolyRange_str); globs::legoGlobs.MedPolyRange = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","HighPolyRange",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { HighPolyRange_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","HighPolyRange",0); HighPolyRange_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(HighPolyRange_str); globs::legoGlobs.HighPolyRange = (float)fVar10; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MinEnergyForEat",0); pcVar1 = cfg::Config_GetTempStringValue(legoConfig,pcVar1); if (pcVar1 == NULL) { MinEnergyForEat_str = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MinEnergyForEat",0); MinEnergyForEat_str = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } fVar10 = std::atof(MinEnergyForEat_str); globs::legoGlobs.MinEnergyForEat = (float)fVar10; Lego_LoadMiscObjects(legoConfig); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Pointers",0); config = cfg::Config_FindArray(legoConfig,pcVar1); front::Pointer_Load(config); front::Pointer_SetCurrent_IfTimerFinished(Pointer_Standard); if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) { game::Message_RegisterHotKeyEvent(KEY_ONE,Message_FirstPerson,NULL,FALSE,NULL); game::Message_RegisterHotKeyEvent(KEY_TWO,Message_FirstPerson,NULL,TRUE,NULL); game::Message_RegisterHotKeyEvent(KEY_FOUR,Message_TrackObject,NULL,FALSE,NULL); game::Message_RegisterHotKeyEvent(KEY_THREE,Message_TopView,NULL,FALSE,NULL); } effect::Smoke_LoadTextures("MiscAnims\\Smoke","Smoke",3); effect::DamageFont_LoadFrames("Interface\\FONTS\\HealthFont","a000_"); Dialog_center.x = 0.0; Dialog_center.y = 0.0; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Dialog","Image",0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (globs::legoGlobs.DialogImage = lego::image::Image_LoadBMPScaled(pcVar1,0,0), globs::legoGlobs.DialogImage != NULL)) { lego::image::Image_SetupTrans(globs::legoGlobs.DialogImage,0.0,0.0,0.0,0.0,0.0,0.0); iVar13 = main::appWidth(); Dialog_center.x = (float)(iVar13 / 2) - (float)((globs::legoGlobs.DialogImage)->width >> 1); iVar13 = main::appHeight(); Dialog_center.y = (float)(iVar13 / 2) - (float)((globs::legoGlobs.DialogImage)->height >> 1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Dialog","TitleWindow",0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (iVar13 = util::Util_Tokenise(pcVar1,Window_stringParts,"|"), iVar13 == 4)) { iVar13 = std::atoi(Window_stringParts[0]); Window_rect.x = (float)iVar13 + Dialog_center.x; iVar13 = std::atoi(Window_stringParts[1]); Window_rect.y = (float)iVar13 + Dialog_center.y; iVar13 = std::atoi(Window_stringParts[2]); Window_rect.width = (float)iVar13; iVar13 = std::atoi(Window_stringParts[3]); Window_rect.height = (float)iVar13; globs::legoGlobs.DialogTextWndTitle = front::TextWindow_Create(globs::legoGlobs.fontBriefingHi,&Window_rect,0x400); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Dialog","TextWindow",0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (iVar13 = util::Util_Tokenise(pcVar1,Window_stringParts,"|"), iVar13 == 4)) { iVar13 = std::atoi(Window_stringParts[0]); Window_rect.x = (float)iVar13 + Dialog_center.x; iVar13 = std::atoi(Window_stringParts[1]); Window_rect.y = (float)iVar13 + Dialog_center.y; iVar13 = std::atoi(Window_stringParts[2]); Window_rect.width = (float)iVar13; iVar13 = std::atoi(Window_stringParts[3]); Window_rect.height = (float)iVar13; globs::legoGlobs.DialogTextWndMessage = front::TextWindow_Create(globs::legoGlobs.fontBriefingLo,&Window_rect,0x400); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Dialog","OkWindow",0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (iVar13 = util::Util_Tokenise(pcVar1,Window_stringParts,"|"), iVar13 == 4)) { iVar13 = std::atoi(Window_stringParts[0]); Window_rect.x = (float)iVar13 + Dialog_center.x; iVar13 = std::atoi(Window_stringParts[1]); Window_rect.y = (float)iVar13 + Dialog_center.y; iVar13 = std::atoi(Window_stringParts[2]); Window_rect.width = (float)iVar13; iVar13 = std::atoi(Window_stringParts[3]); Window_rect.height = (float)iVar13; globs::legoGlobs.DialogTextWndOK = front::TextWindow_Create(globs::legoGlobs.fontBriefingLo,&Window_rect,0x400); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Dialog","CancelWindow",0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (iVar13 = util::Util_Tokenise(pcVar1,Window_stringParts,"|"), iVar13 == 4)) { iVar13 = std::atoi(Window_stringParts[0]); Window_rect.x = (float)iVar13 + Dialog_center.x; iVar13 = std::atoi(Window_stringParts[1]); Window_rect.y = (float)iVar13 + Dialog_center.y; iVar13 = std::atoi(Window_stringParts[2]); Window_rect.width = (float)iVar13; iVar13 = std::atoi(Window_stringParts[3]); Window_rect.height = (float)iVar13; globs::legoGlobs.DialogTextWndCancel = front::TextWindow_Create(globs::legoGlobs.fontBriefingLo,&Window_rect,0x400); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Dialog","ContrastOverlay",0); pcVar1 = cfg::Config_GetStringValue(legoConfig,pcVar1); if ((pcVar1 != NULL) && (globs::legoGlobs.DialogContrastOverlay = lego::image::Image_LoadBMPScaled(pcVar1,0,0), globs::legoGlobs.DialogContrastOverlay != NULL)) { lego::image::Image_SetupTrans(globs::legoGlobs.DialogContrastOverlay,0.0,0.0,0.0,0.0,0.0,0.0); } globs::legoGlobs.flags1 |= GAME1_RADARON|GAME1_RADAR_TRACKOBJECTVIEW; util::logf_removed((char *)globs::legoGlobs.rootCont,"animtex\\dirt"); globs::legoGlobs.radarZoom = 15.0; globs::legoGlobs.radarScreenRect.x = 16.0; globs::legoGlobs.radarScreenRect.y = 13.0; globs::legoGlobs.radarScreenRect.width = 151.0; globs::legoGlobs.radarScreenRect.height = 151.0; effect::Effect_Load_RockFallStylesAll (legoConfig,globs::legoGlobs.gameName,globs::legoGlobs.rootCont); Lego_LoadToolTips(legoConfig); game::Object_LoadToolTipIcons(legoConfig); Lego_LoadUpgradeNames(legoConfig); Lego_LoadInfoMessages(legoConfig); front::Info_SetOverFlowImageFile("Interface\\MessageTabs\\infoOverFlow.bmp"); Lego_LoadTextMessages(legoConfig); uVar3 = main::appHeight(); uVar4 = main::appWidth(); Lego_LoadPanels(legoConfig,uVar4,uVar3); front::Panel_Crystals_Initialise ("Interface\\RightPanel\\SmallCrystal.bmp","Interface\\RightPanel\\UsedCrystal.bmp", "Interface\\RightPanel\\NoSmallCrystal.bmp"); front::Panel_AirMeter_Initialise ("Interface\\AirMeter\\msgpanel_air_juice.bmp",85,6,236, "Interface\\AirMeter\\msgpanel_noair.bmp",21,0); front::Panel_CryOreSideBar_Initialise ("Interface\\RightPanel\\crystalsidebar_ore.bmp",615,434,423); uVar3 = main::appHeight(); uVar4 = main::appWidth(); Lego_LoadPanelButtons(legoConfig,uVar4,uVar3); Lego_LoadTutorialIcon(legoConfig); front::Interface_InitBuildItems(); front::Interface_LoadMenuItems(legoConfig,globs::legoGlobs.gameName); front::Interface_LoadItemPanels(legoConfig,globs::legoGlobs.gameName); front::Interface_LoadPlusMinusImages ("Interface\\Dependencies\\+.bmp","Interface\\Dependencies\\=.bmp"); reward::Reward_LoadGraphics(legoConfig,globs::legoGlobs.gameName); reward::Reward_Initialise(); front::Panel_LoadInterfaceButtons_ScrollInfo(); front::Panel_Button_Hide(Panel_Radar,PanelButton_Radar_ZoomIn,TRUE); front::Panel_Button_Hide(Panel_Radar,PanelButton_Radar_ZoomOut,TRUE); save::Front_ResetSaveNumber(); BVar2 = front::Front_IsFrontEndEnabled(); if (BVar2 != 0) { front::Front_Initialise(globs::legoGlobs.config); } front::Advisor_Initialise (globs::legoGlobs.gameName,globs::legoGlobs.cameraMain,globs::legoGlobs.viewMain); front::Advisor_InitViewport(200.0); front::Advisor_LoadAnims(legoConfig,globs::legoGlobs.gameName); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","DisplayAdvisor",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 == BOOL3_TRUE) { iVar13 = main::appHeight(); iVar9 = main::appWidth(); front::Advisor_LoadPositions(legoConfig,globs::legoGlobs.gameName,iVar9,iVar13); } if ((globs::legoGlobs.flags1 & GAME1_USESFX) != GAME1_NONE) { Lego_SetSoundOn(TRUE); } PVar6 = main::Main_ProgrammerMode(); if (PVar6 < PROGRAMMER_MODE_3) { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","FrontEnd",0); BVar8 = cfg::Config_GetBoolValue(legoConfig,pcVar1); if (BVar8 != BOOL3_TRUE) goto LAB_004226cc; front::Loader_display_loading_bar(NULL); front::Front_RunScreenMenuType(Menu_Screen_Title); BVar2 = front::Front_IsTriggerAppQuit(); if (BVar2 != 0) { return 0; } startLevelName = front::Front_GetSelectedLevel(); } else { LAB_004226cc: startLevelName = main::Main_GetStartLevel(); if (startLevelName == NULL) { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","startlevel",0); startLevelName = cfg::Config_GetTempStringValue(legoConfig,pcVar1); } } front::Front_LoadOptionParameters(TRUE,FALSE); BVar2 = Lego_LoadLevel(startLevelName); if (BVar2 != 0) { snd::SFX_Random_PlaySoundNormal(SFX_AmbientLoop,TRUE); return TRUE; } } cfg::Config_Free(legoConfig); LAB_0042274b: gfx::Container_Shutdown(); return 0; } void __cdecl lego::lrr::Lego_LoadMiscObjects(Config *config) { char *pcVar1; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","Boulder",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contBoulder = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWO",TRUE); if (globs::legoGlobs.contBoulder == NULL) { globs::legoGlobs.contBoulder = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"MESH",TRUE) ; } gfx::Container_Hide(globs::legoGlobs.contBoulder,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","BoulderExplodeIce",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contBoulderExplodeIce = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",TRUE); gfx::Container_Hide(globs::legoGlobs.contBoulderExplodeIce,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","BoulderExplode",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contBoulderExplode = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",TRUE); gfx::Container_Hide(globs::legoGlobs.contBoulderExplode,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","SmashPath",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contSmashPath = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",TRUE); gfx::Container_Hide(globs::legoGlobs.contSmashPath,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","Explosion",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); effect::Effect_Load_Explosion(globs::legoGlobs.rootCont,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","Crystal",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contCrystal = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWO",TRUE); if (globs::legoGlobs.contCrystal == NULL) { globs::legoGlobs.contCrystal = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"MESH",TRUE) ; } gfx::Container_Hide(globs::legoGlobs.contCrystal,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","Dynamite",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contDynamite = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"ACT",TRUE); gfx::Container_Hide(globs::legoGlobs.contDynamite,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","OohScary",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contOohScary = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"ACT",TRUE); gfx::Container_Hide(globs::legoGlobs.contOohScary,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","Barrier",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contBarrier = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"ACT",TRUE); gfx::Container_Hide(globs::legoGlobs.contBarrier,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","Ore",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contOresTable[0] = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWO",TRUE); if (globs::legoGlobs.contOresTable[0] == NULL) { globs::legoGlobs.contOresTable[0] = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"MESH",TRUE); } gfx::Container_Hide(globs::legoGlobs.contOresTable[0],TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","ProcessedOre",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contOresTable[1] = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWO",TRUE); if (globs::legoGlobs.contOresTable[1] == NULL) { globs::legoGlobs.contOresTable[1] = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"MESH",TRUE); } gfx::Container_Hide(globs::legoGlobs.contOresTable[1],TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","ElectricFence",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contElectricFence = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWO",TRUE); gfx::Container_Hide(globs::legoGlobs.contElectricFence,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","ElectricFenceStud",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contElectricFenceStud = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",TRUE); gfx::Container_Hide(globs::legoGlobs.contElectricFenceStud,TRUE); pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"MiscObjects","ShortElectricFenceBeam",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); effect::Effect_Load_ElectricFenceBeam(globs::legoGlobs.rootCont,pcVar1,FALSE); pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"MiscObjects","LongElectricFenceBeam",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); effect::Effect_Load_ElectricFenceBeam(globs::legoGlobs.rootCont,pcVar1,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","SpiderWeb",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contSpiderWeb = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"ACT",TRUE); gfx::Container_Hide(globs::legoGlobs.contSpiderWeb,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","RechargeSparkle",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contRechargeSparkle = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",TRUE); gfx::Container_Hide(globs::legoGlobs.contRechargeSparkle,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","MiniTeleportUp",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contMiniTeleportUp = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",FALSE); gfx::Container_Hide(globs::legoGlobs.contMiniTeleportUp,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","IceCube",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contIceCube = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"ACT",TRUE); gfx::Container_Hide(globs::legoGlobs.contIceCube,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","Pusher",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contPusher = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",TRUE); gfx::Container_Hide(globs::legoGlobs.contPusher,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","Freezer",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contFreezer = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",TRUE); gfx::Container_Hide(globs::legoGlobs.contFreezer,TRUE); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiscObjects","LaserShot",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::legoGlobs.contLaserShot = gfx::Container_Load(globs::legoGlobs.rootCont,pcVar1,"LWS",TRUE); gfx::Container_Hide(globs::legoGlobs.contLaserShot,TRUE); effect::Effect_Initialise(config,globs::legoGlobs.gameName,globs::legoGlobs.rootCont); return; } Container * __cdecl lego::lrr::Lego_GetCurrentCamera_Container(void) { Container *cont; if (globs::legoGlobs.viewMode == ViewMode_Top) { return (globs::legoGlobs.cameraMain)->contCam; } cont = (Container *)globs::legoGlobs.viewMode; if (globs::legoGlobs.viewMode == ViewMode_FP) { cont = (globs::legoGlobs.cameraFP)->contCam; } return cont; } float10 __cdecl lego::lrr::Lego_GetElapsedAbs(void) { return (float10)globs::legoGlobs.elapsedAbs; } void __cdecl lego::lrr::Lego_DrawRenameInput(float elapsedAbs) { uint uVar1; uint uVar2; LegoObject *pLVar3; char *pcVar4; uint uVar5; char *pcVar6; char *pcVar7; int iVar8; longlong lVar9; globs::updateGlobs.renameInputTimer = globs::updateGlobs.renameInputTimer - elapsedAbs; if ((ushort)((ushort)(globs::updateGlobs.renameInputTimer < 0.0) << 8 | (ushort)(globs::updateGlobs.renameInputTimer == 0.0) << 0xe) != 0) { globs::updateGlobs.renameInputTimer = globs::updateGlobs.renameInputTimer - -12.5; globs::gamectrlGlobs.renameUseQuotes = ZEXT14(globs::gamectrlGlobs.renameUseQuotes == 0); } if (globs::legoGlobs.renameInput != NULL) { lVar9 = __ftol((float10)globs::legoGlobs.renamePosition.x); iVar8 = (int)lVar9; uVar1 = lego::image::Font_GetHeight(globs::legoGlobs.fontToolTip); lVar9 = __ftol((float10)globs::legoGlobs.renamePosition.y); uVar2 = lego::image::Font_GetCharWidth(globs::legoGlobs.fontToolTip,'\"'); pcVar4 = globs::legoGlobs.renameInput; if ((*globs::legoGlobs.renameInput == '\0') && (pLVar3 = game::Message_GetPrimarySelectedUnit(), pcVar4 = globs::legoGlobs.renameInput, pLVar3 != NULL)) { pLVar3 = game::Message_GetPrimarySelectedUnit(); pcVar4 = game::LegoObject_GetLangName(pLVar3); } uVar5 = lego::image::Font_GetStringWidth(globs::legoGlobs.fontToolTip,"\"%s\"",pcVar4); if (globs::mainGlobs.appWidth - 40 < iVar8 + uVar5) { iVar8 -= uVar5; } pcVar7 = "\""; if (globs::gamectrlGlobs.renameUseQuotes == 0) { pcVar7 = ____EMPTYSTR__; } pcVar6 = "\""; if (globs::gamectrlGlobs.renameUseQuotes == 0) { pcVar6 = ____EMPTYSTR__; } lego::image::Font_PrintF (globs::legoGlobs.fontToolTip, (~-(uint)(globs::gamectrlGlobs.renameUseQuotes != 0) & uVar2) + iVar8, (int)lVar9 - (uVar1 >> 1),"%s%s%s",pcVar6,pcVar4,pcVar7); } return; } // This function also has the essential behaviour of clearing INPUT.Key_Map. // Which prevents any functions called after this during the main loop from // triggering debug keys. void __cdecl lego::lrr::Lego_HandleRenameInput(float elapsedAbs) { char cVar1; uint uVar2; uint inputLength; int iVar3; Keys32 diKey; undefined4 *puVar4; char *pcVar5; undefined4 *puVar6; if (globs::legoGlobs.renameInput != NULL) { // inputLength = std::strlen(legoGlobs.renameInput) uVar2 = 0xffffffff; pcVar5 = globs::legoGlobs.renameInput; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); inputLength = ~uVar2 - 1; // 1 = DIK_ESCAPE, 14 = DIK_BACK (backspace), 28 = DIK_RETURN (enter) // IsTypingKeyUp(KEY_BACKSPACE) (14) if ((globs::INPUT.Key_Map[14] == false) || (globs::gamectrlGlobs.typingState_Map[14] == globs::INPUT.Key_Map[14])) { // Escape can also be used to end (accept) renaming input. Just not to start it. // // IsTypingKeyReleased(KEY_RETURN) || (28) // IsTypingKeyReleased(KEY_ESCAPE) (1) if (((globs::INPUT.Key_Map[28] == false) && (globs::gamectrlGlobs.typingState_Map[28] != false)) || ((globs::INPUT.Key_Map[1] == false && (globs::gamectrlGlobs.typingState_Map[1] != false)))) { globs::legoGlobs.renameInput = NULL; Lego_SetPaused(FALSE,FALSE); } else { diKey = KEY__NONE; do { // 11 is the maximum number of characters per name. // // if (iVar3 < 11 && IsTypingKeyDown(diKey)) if ((((inputLength < 0xb) && (globs::INPUT.Key_Map[diKey] != false)) && (globs::gamectrlGlobs.typingState_Map[diKey] != globs::INPUT.Key_Map[diKey])) && (uVar2 = front::Front_Input_GetKeyCharacter(diKey), uVar2 != 0)) { iVar3 = std::toupper(uVar2); globs::legoGlobs.renameInput[inputLength] = (char)iVar3; inputLength += 1; globs::legoGlobs.renameInput[inputLength] = '\0'; } diKey += KEY_ESCAPE; } while (diKey < 0x100); } } else { if (inputLength != 0) { globs::legoGlobs.renameInput[~uVar2 - 2] = '\0'; } } // std::memcpy(gamectrlGlobs.typingState_Map, INPUT.Key_Map, sizeof(INPUT.Key_Map)); // std::memset(INPUT.Key_Map, 0, sizeof(INPUT.Key_Map)); puVar4 = (undefined4 *)globs::INPUT.Key_Map; puVar6 = (undefined4 *)globs::gamectrlGlobs.typingState_Map; for (iVar3 = 0x40; iVar3 != 0; iVar3 += -1) { *puVar6 = *puVar4; puVar4 = puVar4 + 1; puVar6 = puVar6 + 1; } puVar4 = (undefined4 *)globs::INPUT.Key_Map; for (iVar3 = 0x40; iVar3 != 0; iVar3 += -1) { *puVar4 = 0; puVar4 = puVar4 + 1; } } return; } // Returning FALSE will naturally exit the program. BOOL __cdecl lego::lrr::Lego_MainLoop(float elapsed) { float fVar1; LegoObject *pLVar2; BOOL hasNextLevel; Lego_Level *level; BOOL dontExit; char *pcVar3; BOOL BVar4; uint uVar5; LegoObject **ppLVar6; UpgradesModel *pUVar7; float crystals; float elapsedGame_00; uint objLevel; int inRadarMapView; int iVar8; float10 fVar9; longlong lVar10; Text_Type textType; float fVar12; ulonglong uVar11; float local_34; SFX_ID local_30; float elapsedGame; Vector4F local_28; BOOL modifierDownAddSelection; BOOL keyDownR; BOOL keyDownT; Vector3F local_c; fVar1 = elapsed; local_30 = SFX_NULL; if ((globs::mainGlobs.programmerLevel == PROGRAMMER_MODE_10) && (hasNextLevel = Lego_EndLevel(), hasNextLevel == 0)) { // ProgrammerMode 10 has finished cycling through every level. Now quit the game. return FALSE; } if ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) != GAME1_NONE) { elapsed = 0.0; } Lego_HandleRenameInput(fVar1); globs::legoGlobs.elapsedAbs = elapsed; if ((globs::legoGlobs.viewMode == ViewMode_FP) && (globs::mainGlobs.programmerLevel < PROGRAMMER_MODE_2)) { // In first person view, game speed is locked at 100% elapsedGame = elapsed; } else { fVar9 = game::Lego_GetGameSpeed(); elapsedGame = (float)(fVar9 * (float10)elapsed); } elapsedGame_00 = elapsedGame; unk::Teleporter_Update(elapsedGame); Lego_UnkTeleporterInit_FUN_00435980(); fVar12 = elapsed; level = Lego_GetLevel(); game::Level_Emerge_FUN_0042c370(level,fVar12); Lego_UpdateFallins(elapsedGame_00); Lego_UpdateSlug_FUN_004260f0(elapsedGame_00); if ((globs::legoGlobs.flags2 & GAME2_CALLTOARMS) == GAME2_NONE) { if (((globs::legoGlobs.cameraFP != NULL) && ((globs::legoGlobs.cameraFP)->contCam != NULL)) && (globs::legoGlobs.dirLightCallToArms != NULL)) { gfx::Container_Hide(globs::legoGlobs.dirLightCallToArms,TRUE); } } else { if (((globs::legoGlobs.cameraFP != NULL) && ((globs::legoGlobs.cameraFP)->contCam != NULL)) && ((globs::legoGlobs.dirLightCallToArms != NULL && ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE)))) { gfx::Container_Hide(globs::legoGlobs.dirLightCallToArms,FALSE); gfx::Container_AddRotation (globs::legoGlobs.dirLightCallToArms,Container_Combine_After,0.0,1.0,0.0, elapsed * 0.1); } } if (((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) && (((globs::legoGlobs.flags1 & GAME1_CAMERAGOTO) != GAME1_NONE || (globs::legoGlobs.gotoSmooth != 0)))) { if (globs::legoGlobs.gotoSmooth != 0) { local_28.x = (1.0 / elapsed) * 5.0; gfx::Container_GetPosition((globs::legoGlobs.cameraMain)->cont3,NULL,&local_c); globs::legoGlobs.gotoNewPos.x = (local_28.x * local_c.x + globs::legoGlobs.gotoTargetPos.x) / (local_28.x - -1.0); globs::legoGlobs.gotoNewPos.y = (local_28.x * local_c.y + globs::legoGlobs.gotoTargetPos.y) / (local_28.x - -1.0); local_28.x = globs::legoGlobs.gotoNewPos.x - local_c.x; local_28.y = globs::legoGlobs.gotoNewPos.y - local_c.y; if (SQRT(local_28.y * local_28.y + local_28.x * local_28.x) < 2.0) { globs::legoGlobs.gotoSmooth = 0; } } lego::view::Camera_SetTopdownPosition (globs::legoGlobs.cameraMain,globs::legoGlobs.gotoNewPos.x, globs::legoGlobs.gotoNewPos.y); globs::legoGlobs.flags1 &= ~GAME1_CAMERAGOTO; } if ((globs::legoGlobs.flags1 & GAME1_LEVELSTART) != GAME1_NONE) { elapsedGame = 1.0; globs::legoGlobs.flags1 &= ~GAME1_LEVELSTART; elapsedGame_00 = 1.0; } dontExit = Lego_HandleKeys(elapsedGame_00,elapsed,&keyDownT,&keyDownR,&modifierDownAddSelection); if (dontExit == 0) { return FALSE; } if ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) { Lego_HandleRadarInput(); } ai::AITask_UpdateAll(elapsedGame_00); game::Level_UpdateEffects(globs::legoGlobs.currLevel,elapsedGame_00); effect::DamageFont_UpdateAll(elapsed); game::LegoObject_UpdateAll(elapsedGame_00); tools::Weapon_Update(elapsedGame_00); game::Erode_Update(elapsedGame_00); game::Level_BlockActivity_UpdateAll(globs::legoGlobs.currLevel,elapsedGame_00); game::Message_Update(); lego::view::Camera_Update (globs::legoGlobs.cameraMain,globs::legoGlobs.currLevel,elapsed,elapsedGame_00); lego::view::Camera_Update (globs::legoGlobs.cameraTrack,globs::legoGlobs.currLevel,elapsed,elapsedGame_00); lego::view::Camera_Update (globs::legoGlobs.cameraFP,globs::legoGlobs.currLevel,elapsed,elapsedGame_00); game::Construction_UpdateAll(elapsedGame_00); front::Interface_FUN_0041b940(fVar1); Lego_UnkUpdateMapsWorldUnk_FUN_004290d0(elapsed,FALSE); game::LegoObject_HideAllCertainObjects(); game::ElectricFence_UpdateAll(elapsedGame_00); Lego_HandleWorld(fVar1,elapsed,keyDownT,keyDownR,modifierDownAddSelection); lego::map::Map3D_Update((globs::legoGlobs.currLevel)->map,elapsedGame_00); game::Water_Update(globs::legoGlobs.currLevel,elapsedGame_00); snd::Sound3D_UpdateListener(); effect::Smoke_Update(elapsedGame_00); game::SpiderWeb_Update(elapsedGame_00); light::LightEffects_Update(elapsedGame_00); front::Info_FUN_0041a1f0(fVar1); if (globs::legoGlobs.IsFallinsEnabled != 0) { game::Fallin_Update(elapsedGame_00); } // IsKeyPressed(KEY_F6) (64) // "Toggles fallin mode." if ((((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) && (globs::INPUT.Key_Map[64] != false)) && (globs::INPUT.prevKey_Map[64] != globs::INPUT.Key_Map[64])) { globs::legoGlobs.IsFallinsEnabled = ZEXT14(globs::legoGlobs.IsFallinsEnabled == 0); pcVar3 = "On"; if (globs::legoGlobs.IsFallinsEnabled == 0) { pcVar3 = "Off"; } front::TextWindow_PrintF(globs::legoGlobs.textOnlyWindow,"\nFallin Mode %s",pcVar3); } gfx::Container_Hide(globs::legoGlobs.ambientLight,FALSE); if (globs::legoGlobs.viewMode == ViewMode_Top) { if ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) { gfx::Container_Hide(globs::legoGlobs.rootSpotlight,FALSE); } gfx::Container_Hide(globs::legoGlobs.spotlightTop,FALSE); lego::view::Viewport_Clear(globs::legoGlobs.viewMain,TRUE); lego::view::Viewport_Render(globs::legoGlobs.viewMain,globs::legoGlobs.rootCont,elapsed); gfx::Container_Hide(globs::legoGlobs.spotlightTop,TRUE); gfx::Container_Hide(globs::legoGlobs.rootSpotlight,TRUE); } else { if (globs::legoGlobs.viewMode == ViewMode_FP) { game::Roof_Hide(0); game::Roof_Update(); game::LegoObject_FP_SetRanges (globs::legoGlobs.objectFP,(globs::legoGlobs.cameraFP)->contCam, globs::legoGlobs.MedPolyRange,globs::legoGlobs.HighPolyRange,TRUE); BVar4 = 1; uVar5 = lego::view::Camera_GetFPCameraFrame(globs::legoGlobs.cameraFP); game::LegoObject_SwapPolyFP(globs::legoGlobs.objectFP,uVar5,BVar4); Lego_UpdateSceneFog(TRUE,elapsedGame_00); if (((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) && (gfx::Container_Hide(globs::legoGlobs.pointLightFP,0), globs::legoGlobs.dirLightFP != NULL) ) { gfx::Container_AddRotation (globs::legoGlobs.dirLightFP,Container_Combine_After,0.0,1.0,0.0,elapsed * 0.01); gfx::Container_Hide(globs::legoGlobs.dirLightFP,FALSE); } lego::view::Viewport_Clear(globs::legoGlobs.viewMain,TRUE); lego::view::Viewport_Render(globs::legoGlobs.viewMain,globs::legoGlobs.rootCont,elapsed); gfx::Container_Hide(globs::legoGlobs.pointLightFP,TRUE); if (globs::legoGlobs.dirLightFP != NULL) { gfx::Container_Hide(globs::legoGlobs.dirLightFP,TRUE); } Lego_UpdateSceneFog(0,elapsedGame_00); BVar4 = 0; uVar5 = lego::view::Camera_GetFPCameraFrame(globs::legoGlobs.cameraFP); game::LegoObject_SwapPolyFP(globs::legoGlobs.objectFP,uVar5,BVar4); game::LegoObject_FP_SetRanges(globs::legoGlobs.objectFP,NULL,0.0,0.0,0); game::Roof_HideAllVisibleBlocks(); game::Roof_Hide(TRUE); game::Level_RemoveAll_ProMeshes(); } } gfx::Container_Hide(globs::legoGlobs.ambientLight,TRUE); BVar4 = front::Panel_IsFullyOpen(Panel_Radar); if (BVar4 == 0) { globs::legoGlobs.flags1 &= ~GAME1_RADARON; } else { globs::legoGlobs.flags1 |= GAME1_RADARON; } if (globs::legoGlobs.viewMode == ViewMode_Top) { Lego_DrawAllSelectedUnitBoxes(globs::legoGlobs.viewMain); Lego_DrawAllLaserTrackerBoxes(globs::legoGlobs.viewMain); front::Encyclopedia_DrawSelectBox(globs::legoGlobs.viewMain); } Lego_DrawDragSelectionBox(globs::legoGlobs.currLevel); if ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) { front::Bubble_DrawAllObjInfos(elapsed); } if ((((globs::legoGlobs.flags1 & GAME1_RADARON) != GAME1_NONE) && ((globs::legoGlobs.flags1 & GAME1_RADAR_TRACKOBJECTVIEW) != GAME1_NONE)) && (lego::view::Viewport_Clear(globs::legoGlobs.viewTrack,TRUE), (globs::legoGlobs.flags1 & GAME1_RADAR_NOTRACKOBJECT) == GAME1_NONE)) { Lego_UnkUpdateMapsWorldUnk_FUN_004290d0(elapsedGame_00,TRUE); game::LegoObject_HideAllCertainObjects(); gfx::Container_Hide(globs::legoGlobs.spotlightTrack,FALSE); if (((globs::legoGlobs.cameraFP != NULL) && ((globs::legoGlobs.cameraFP)->contCam != NULL)) && (globs::legoGlobs.dirLightCallToArms != NULL)) { gfx::Container_Hide(globs::legoGlobs.dirLightCallToArms,TRUE); } lego::view::Viewport_Render(globs::legoGlobs.viewTrack,globs::legoGlobs.rootCont,elapsed); gfx::Container_Hide(globs::legoGlobs.spotlightTrack,TRUE); lego::map::Map3D_HideVisibleBlocksList((globs::legoGlobs.currLevel)->map); } main::Main_Finalise3D(); effect::Smoke_HideAll(TRUE); snd::SFX_Update(fVar1); if ((globs::legoGlobs.viewMode == ViewMode_Top) && ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE)) { game::Level_UpdateTutorialBlockFlashing (globs::legoGlobs.currLevel,globs::legoGlobs.viewMain,elapsedGame_00,elapsed); nerps::NERPsRuntime_DrawTutorialIcon (globs::legoGlobs.currLevel,globs::legoGlobs.viewMain,elapsedGame_00,elapsed); } lego::map::Map3D_HideVisibleBlocksList((globs::legoGlobs.currLevel)->map); if (((globs::legoGlobs.flags1 & GAME1_RADARON) == GAME1_NONE) || ((globs::legoGlobs.flags1 & GAME1_RADAR_MAPVIEW) == GAME1_NONE)) { inRadarMapView = FALSE; } else { inRadarMapView = TRUE; } if (inRadarMapView != 0) { Lego_DrawRadarMap(); } game::LegoObject_UpdateAllRadarSurvey(elapsedGame_00,inRadarMapView); if ((globs::legoGlobs.flags1 & GAME1_RENDERPANELS) != GAME1_NONE) { if ((globs::legoGlobs.flags1 & GAME1_RADARON) == GAME1_NONE) { front::Panel_Draw(Panel_RadarFill,elapsed); } front::Panel_Draw(Panel_Radar,elapsed); if ((((globs::legoGlobs.flags1 & GAME1_RADARON) != GAME1_NONE) && ((globs::legoGlobs.flags1 & GAME1_RADAR_TRACKOBJECTVIEW) != GAME1_NONE)) && ((globs::legoGlobs.flags1 & GAME1_RADAR_NOTRACKOBJECT) == GAME1_NONE)) { front::Panel_Draw(Panel_RadarOverlay,elapsed); } front::Panel_Draw(Panel_MessagesSide,elapsed); front::Panel_Draw(Panel_CameraControl,elapsed); front::Panel_Draw(Panel_TopPanel,elapsed); front::Panel_Draw(Panel_PriorityList,elapsed); ai::Priorities_Draw(); front::Panel_Draw(Panel_Encyclopedia,elapsed); front::Encyclopedia_Update(elapsed); if ((globs::legoGlobs.flags2 & GAME2_INMENU) == GAME2_NONE) { front::Interface_FUN_0041b3c0(); } front::Interface_FUN_0041b860(elapsed); front::Panel_Draw(Panel_CrystalSideBar,elapsed); crystals = elapsed; fVar12 = elapsed; if (globs::legoGlobs.currLevel != NULL) { crystals = (float)(globs::legoGlobs.currLevel)->crystals; fVar12 = (float)((globs::legoGlobs.currLevel)->crystals - (globs::legoGlobs.currLevel)->crystalsDrained); } front::Panel_Crystals_Draw((uint)crystals,(uint)fVar12,elapsedGame_00); front::Panel_CryOreSideBar_Draw(); front::Panel_PrintF(5,globs::legoGlobs.fontToolTip,0x10,0x1d5,1,"%i", (globs::legoGlobs.currLevel)->ore + (globs::legoGlobs.currLevel)->studs * 5) ; front::Panel_Draw(Panel_Information,elapsed); front::ScrollInfo_Update(FALSE); front::Info_DrawPanel(elapsed); front::Panel_Draw(Panel_InfoDock,elapsed); front::Info_Draw(elapsed); } front::HelpWindow_FUN_00418930(); BVar4 = game::Objective_IsShowing(); fVar12 = elapsed; if (BVar4 != 0) { fVar12 = fVar1; } front::Advisor_Update(fVar12); snd::Sound_Update(globs::legoGlobs.flags1 & GAME1_MUSICPLAYING); if ((globs::legoGlobs.flags1 & GAME1_DEBUG_NONERPS) == GAME1_NONE) { nerps::NERPsRuntime_Execute(elapsed); } game::Objective_Update (globs::legoGlobs.textOnlyWindow,globs::legoGlobs.currLevel,elapsedGame_00,fVar1); if (globs::mainGlobs.programmerLevel < PROGRAMMER_MODE_2) { if (((globs::legoGlobs.currLevel)->MaxStolen != 0.0) && ((uint)(globs::legoGlobs.currLevel)->MaxStolen <= (uint)(globs::legoGlobs.currLevel)->crystalsStolen)) { game::Objective_SetStatus(LEVELSTATUS_FAILED_CRYSTALS); } uVar5 = game::LegoObject_GetLevelObjectsBuilt(LegoObject_Path,0,0,TRUE); if (uVar5 == 0) { objLevel = 0; iVar8 = 0; uVar5 = stats::Stats_GetLevels(LegoObject_MiniFigure,0); if (uVar5 != 0) { do { uVar5 = game::LegoObject_GetLevelObjectsBuilt(LegoObject_MiniFigure,0,objLevel,TRUE); iVar8 += uVar5; objLevel += 1; uVar5 = stats::Stats_GetLevels(LegoObject_MiniFigure,0); } while (objLevel < uVar5); } if ((iVar8 == 0) && (level = Lego_GetLevel(), level->status == LEVELSTATUS_INCOMPLETE)) { game::Objective_SetStatus(LEVELSTATUS_FAILED); } } } front::Text_Update(elapsed); if (((globs::legoGlobs.flags2 & GAME2_MENU_HASNEXT) != GAME2_NONE) && (globs::legoGlobs.NextButtonImage != NULL)) { lego::image::Image_DisplayScaled (globs::legoGlobs.NextButtonImage,NULL,&globs::legoGlobs.menuNextPoint,NULL); } if (((globs::legoGlobs.flags2 & GAME2_MENU_HASPREVIOUS) != GAME2_NONE) && (globs::legoGlobs.BackArrowImage != NULL)) { lego::image::Image_DisplayScaled (globs::legoGlobs.BackArrowImage,NULL,&globs::legoGlobs.menuPrevPoint,NULL); } if ((((globs::legoGlobs.flags2 & GAME2_MESSAGE_HASNEXT) != GAME2_NONE) && (globs::legoGlobs.NextButtonImage != NULL)) && (((globs::legoGlobs.flags2 & GAME2_CAMERAMOVING) == GAME2_NONE || (BVar4 = front::Interface_GetFlashingState(), BVar4 != 0)))) { lego::image::Image_DisplayScaled (globs::legoGlobs.NextButtonImage,NULL,&globs::legoGlobs.NextButtonPos,NULL); } if (((globs::legoGlobs.flags2 & GAME2_MESSAGE_HASREPEAT) != GAME2_NONE) && (globs::legoGlobs.RepeatButtonImage != NULL)) { lego::image::Image_DisplayScaled (globs::legoGlobs.RepeatButtonImage,NULL,&globs::legoGlobs.RepeatButtonPos,NULL); } if ((((globs::legoGlobs.flags2 & GAME2_INOPTIONSMENU) != GAME2_NONE) && (BVar4 = front::Front_IsFrontEndEnabled(), BVar4 != 0)) && (BVar4 = front::Front_Options_Update(elapsed,Menu_Modal_Options), BVar4 != 0)) { globs::legoGlobs.flags2 &= ~GAME2_INOPTIONSMENU; BVar4 = game::Objective_IsShowing(); if (BVar4 == 0) { Lego_SetPaused(0,0); } else { globs::legoGlobs.flags1 |= GAME1_PAUSED; } } Lego_DrawRenameInput(fVar1); if ((globs::legoGlobs.flags1 & GAME1_PAUSED) == GAME1_NONE) { front::Pointer_Update(fVar1); if (globs::legoGlobs.renameInput == NULL) goto LAB_00423e04; } else { BVar4 = front::Front_IsFrontEndEnabled(); if ((BVar4 == 0) || (BVar4 = front::Front_Options_Update(elapsed,Menu_Modal_Paused), BVar4 == 0) ) { front::Pointer_Update(fVar1); LAB_00423e04: front::Pointer_DrawPointer(globs::INPUT.msx,globs::INPUT.msy); } else { globs::legoGlobs.flags1 ^= GAME1_PAUSED; BVar4 = front::Front_IsTriggerMissionQuit(); if (BVar4 == 0) { BVar4 = game::Objective_IsShowing(); if (BVar4 == 0) { Lego_SetPaused(0,0); } } else { Lego_QuitLevel(); level = Lego_GetLevel(); level->status = LEVELSTATUS_FAILED_CRYSTALS; reward::RewardQuota_CountUnits(); if ((globs::legoGlobs.flags1 & GAME1_MUSICPLAYING) != GAME1_NONE) { globs::legoGlobs.flags2 |= GAME2_MUSICREADY; Lego_SetMusicPlaying(FALSE); } } } } BVar4 = front::Front_IsTriggerMissionRestart(); if ((BVar4 == 1) || (globs::mainGlobs.programmerLevel == PROGRAMMER_MODE_11)) { front::Front_RestartLevel(); } if ((globs::legoGlobs.flags1 & GAME1_DEBUG_SHOWVERTEXMODE) != GAME1_NONE) { pcVar3 = "Vertex"; if ((globs::legoGlobs.flags1 & GAME1_VERTEXMODE) == GAME1_NONE) { pcVar3 = "Block"; } lego::image::Font_PrintF(globs::legoGlobs.fontTallYellow,10,10,"%s mode",pcVar3); } if (((globs::legoGlobs.flags1 & GAME1_VERTEXMODE) != GAME1_NONE) && (globs::legoGlobs.digVertexShowPointer != 0)) { lego::map::Map3D_GetBlockFirstVertexPosition ((globs::legoGlobs.currLevel)->map,globs::legoGlobs.digVertexBlockPos.x, globs::legoGlobs.digVertexBlockPos.y,&local_c); lego::view::Viewport_Transform(globs::legoGlobs.viewMain,&local_28,&local_c); local_28.x = local_28.x / local_28.w; local_28.y = local_28.y / local_28.w; front::Pointer_SetCurrent_IfTimerFinished(Pointer_Drill); lVar10 = __ftol((float10)local_28.y); uVar5 = (uint)lVar10; lVar10 = __ftol((float10)local_28.x); front::Pointer_DrawPointer((uint)lVar10,uVar5); globs::legoGlobs.flags1 &= ~GAME1_VERTEXLOCKONPOINTER; } front::ToolTip_Update(globs::INPUT.msx,globs::INPUT.msy,fVar1); if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) { // IsKeyPressed(KEY_FIVE) (6) // "Set selected unit model to first upgrade code." // IsKeyPressed(KEY_SIX) (7) // "Set selected unit model to second upgrade code." // IsKeyPressed(KEY_SEVEN) (8) // "Set selected unit model to third upgrade code." // IsKeyPressed(KEY_EIGHT) (9) // "Set selected unit model to fourth upgrade code." if (((((globs::INPUT.Key_Map[6] != false) && (globs::INPUT.prevKey_Map[6] != globs::INPUT.Key_Map[6])) || ((globs::INPUT.Key_Map[7] != false && (globs::INPUT.prevKey_Map[7] != globs::INPUT.Key_Map[7])))) || ((globs::INPUT.Key_Map[8] != false && (globs::INPUT.prevKey_Map[8] != globs::INPUT.Key_Map[8])))) || ((globs::INPUT.Key_Map[9] != false && (globs::INPUT.prevKey_Map[9] != globs::INPUT.Key_Map[9])))) { globs::gamectrlGlobs.dbgUpgradeChangeTimer = 1.0; } if ((ushort)((ushort)(globs::gamectrlGlobs.dbgUpgradeChangeTimer < 0.0) << 8 | (ushort)(globs::gamectrlGlobs.dbgUpgradeChangeTimer == 0.0) << 0xe) == 0) { ppLVar6 = game::Message_GetSelectedUnits2((uint *)&local_28); if (local_28.x != 0.0) { pLVar2 = *ppLVar6; if (pLVar2->type == LegoObject_Building) { pUVar7 = &pLVar2->building->upgrades; } else { if (pLVar2->type == LegoObject_Vehicle) { pUVar7 = &pLVar2->vehicle->upgrades; } else { pUVar7 = NULL; } } if (pUVar7 != NULL) { uVar5 = pUVar7->currentLevel; uVar11 = CONCAT44(uVar5,uVar5 >> 1) & 0x100000001; lego::image::Font_PrintF (globs::legoGlobs.fontStandard,0,0,"Upgrade - (%i%i%i%i)",uVar5 >> 3 & 1, uVar5 >> 2 & 1,(uint)uVar11,(uint)(uVar11 >> 0x20)); } } globs::gamectrlGlobs.dbgUpgradeChangeTimer = globs::gamectrlGlobs.dbgUpgradeChangeTimer - 0.1; } } if (globs::updateGlobs.dripSFXTimer < 0.0) { snd::SFX_Random_PlaySoundNormal(SFX_Drip,FALSE); fVar9 = math::Maths_RandRange(75.0,125.0); globs::updateGlobs.dripSFXTimer = (float)fVar9; } if (globs::updateGlobs.ambientSFXTimer < 0.0) { snd::SFX_Random_PlaySoundNormal(SFX_Ambient,FALSE); fVar9 = math::Maths_RandRange(250.0,750.0); globs::updateGlobs.ambientSFXTimer = (float)fVar9; } globs::updateGlobs.dripSFXTimer = globs::updateGlobs.dripSFXTimer - elapsed; globs::updateGlobs.ambientSFXTimer = globs::updateGlobs.ambientSFXTimer - elapsed; if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) { // IsKeyUp(KEYPAD_9) (73) if (globs::INPUT.Key_Map[73] == false) { local_34 = -1.0; // IsKeyUp(KEYPAD_8) (72) if (globs::INPUT.Key_Map[72] == false) { local_34 = 0.0; } } else { local_34 = 1.0; } if (local_34 != 0.0) { globs::gamectrlGlobs.dbgSpeedChangeTimer = 25.0; fVar9 = game::Lego_GetGameSpeed(); Lego_SetGameSpeed((float)((float10)local_34 * (float10)elapsed * (float10)0.01 + fVar9)); fVar9 = game::Lego_GetGameSpeed(); if ((ushort)((ushort)(fVar9 < (float10)3.0) << 8 | (ushort)(fVar9 == (float10)3.0) << 0xe) == 0) { Lego_SetGameSpeed(3.0); } fVar9 = game::Lego_GetGameSpeed(); if (fVar9 < (float10)0.0) { Lego_SetGameSpeed(0.0); } } if ((ushort)((ushort)(globs::gamectrlGlobs.dbgSpeedChangeTimer < 0.0) << 8 | (ushort)(globs::gamectrlGlobs.dbgSpeedChangeTimer == 0.0) << 0xe) == 0) { fVar9 = game::Lego_GetGameSpeed(); lego::image::Font_PrintF (globs::legoGlobs.fontStandard,10,0x50,"Game Speed %0.0f%%", (double)(fVar9 * (float10)100.0)); } globs::gamectrlGlobs.dbgSpeedChangeTimer = globs::gamectrlGlobs.dbgSpeedChangeTimer - elapsed; } if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) == GAME2_NONE) goto LAB_0042427c; if (globs::updateGlobs.dbgRollOffFactorValue == -1.0) { fVar9 = snd::Sound3D_SetRollOffFactor(-1.0); globs::updateGlobs.dbgRollOffFactorValue = (float)fVar9; } if (globs::INPUT.Key_Map[10] == false) { if (globs::INPUT.Key_Map[11] != false) { globs::updateGlobs.dbgRollOffFactorValue = globs::updateGlobs.dbgRollOffFactorValue - -0.05; goto LAB_0042421e; } } else { globs::updateGlobs.dbgRollOffFactorValue = globs::updateGlobs.dbgRollOffFactorValue - 0.05; LAB_0042421e: fVar9 = snd::Sound3D_SetRollOffFactor(globs::updateGlobs.dbgRollOffFactorValue); globs::updateGlobs.dbgRollOffFactorValue = (float)fVar9; globs::gamectrlGlobs.dbgRollOffChangeTimer = 25.0; } if ((ushort)((ushort)(globs::gamectrlGlobs.dbgRollOffChangeTimer < 0.0) << 8 | (ushort)(globs::gamectrlGlobs.dbgRollOffChangeTimer == 0.0) << 0xe) == 0) { lego::image::Font_PrintF (globs::legoGlobs.fontStandard,10,0x50,"3D sound fall off: %f", (double)globs::updateGlobs.dbgRollOffFactorValue); } globs::gamectrlGlobs.dbgRollOffChangeTimer = globs::gamectrlGlobs.dbgRollOffChangeTimer - elapsed; LAB_0042427c: if ((globs::legoGlobs.flags1 & GAME1_DEBUG_NONERPS) == GAME1_NONE) { nerps::NERPsRuntime_UpdateTimers(elapsed); } else { lego::image::Font_PrintF(globs::legoGlobs.fontStandard,0,0,"NoNERPS"); } if ((ushort)((ushort)((globs::legoGlobs.currLevel)->oxygenLevel < 0.0) << 8 | (ushort)((globs::legoGlobs.currLevel)->oxygenLevel == 0.0) << 0xe) == 0) { fVar1 = (globs::legoGlobs.currLevel)->oxygenLevel; if ((globs::legoGlobs.currLevel)->oxygenLevelMessage - 5.0 <= (globs::legoGlobs.currLevel)->oxygenLevel) { if ((ushort)((ushort)(fVar1 < (globs::legoGlobs.currLevel)->oxygenLevelMessage) << 8 | (ushort)(fVar1 == (globs::legoGlobs.currLevel)->oxygenLevelMessage) << 0xe) == 0) { // 100.0f if ((undefined *)(globs::legoGlobs.currLevel)->oxygenLevel == &DAT_42c80000) { front::Info_Send(Info_AirRestored,NULL,NULL,NULL); } (globs::legoGlobs.currLevel)->oxygenLevelMessage = (globs::legoGlobs.currLevel)->oxygenLevel ; } } else { if ((ushort)((ushort)(fVar1 < 10.0) << 8 | (ushort)(fVar1 == 10.0) << 0xe) == 0) { front::Info_Send(Info_AirDepleting,NULL,NULL,NULL); textType = Text_AirSupplyRunningOut; } else { front::Info_Send(Info_AirLow,NULL,NULL,NULL); textType = Text_AirSupplyLow; } front::Text_DisplayMessage(textType,1,0); (globs::legoGlobs.currLevel)->oxygenLevelMessage = (globs::legoGlobs.currLevel)->oxygenLevel; } } else { front::Info_Send(Info_AirOut,NULL,NULL,NULL); } if ((ushort)((ushort)((globs::legoGlobs.currLevel)->oxygenLevel < 10.0) << 8 | (ushort)((globs::legoGlobs.currLevel)->oxygenLevel == 10.0) << 0xe) == 0) { if ((globs::panelGlobs.airMeterOxygenLow != 0) && (BVar4 = snd::SFX_GetType("SND_AirBeat",&local_30), BVar4 != 0)) { iVar8 = snd::SFX_Random_GetSound3DHandle(local_30); snd::SFX_Sound3D_StopSound(iVar8); } BVar4 = 0; } else { if ((globs::panelGlobs.airMeterOxygenLow == 0) && (BVar4 = snd::SFX_GetType("SND_AirBeat",&local_30), BVar4 != 0)) { snd::SFX_Random_PlaySoundNormal(local_30,TRUE); } BVar4 = snd::SFX_GetType("SND_AirBeat",&local_30); if (BVar4 != 0) { iVar8 = snd::Sound3D_MinVolume(); lVar10 = __ftol((float10)(globs::legoGlobs.currLevel)->oxygenLevel * (float10)0.1 * (float10)iVar8 * (float10)0.1); iVar8 = snd::SFX_Random_GetBufferVolume(local_30); if ((int)lVar10 != iVar8) { snd::SFX_Random_SetBufferVolume(local_30,(int)lVar10); } } BVar4 = 1; } front::Panel_AirMeter_SetOxygenLow(BVar4); globs::legoGlobs.timerGame_e3c = globs::legoGlobs.timerGame_e3c - elapsedGame; return TRUE; } void __cdecl lego::game::Level_ConsumeObjectOxygen(LegoObject *liveObj,float elapsed) { float10 fVar1; Lego_Level *level; level = globs::legoGlobs.currLevel; fVar1 = stats::StatsObject_GetOxygenCoef(liveObj); if ((liveObj->type != LegoObject_Building) || ((liveObj->flags3 & LIVEOBJ3_HASPOWER) != LIVEOBJ3_NONE)) { fVar1 = (float10)elapsed * (float10)0.04 * (float10)level->OxygenRate * fVar1 + (float10)level->oxygenLevel; level->oxygenLevel = (float)fVar1; if ((ushort)((ushort)(fVar1 < (float10)100.0) << 8 | (ushort)(fVar1 == (float10)100.0) << 0xe) == 0) { level->oxygenLevel = (float)&DAT_42c80000; } if (((ushort)((ushort)(level->oxygenLevel < 0.0) << 8 | (ushort)(level->oxygenLevel == 0.0) << 0xe) != 0) && (level->oxygenLevel = 0.0, (globs::legoGlobs.flags1 & GAME1_LEVELENDING) == GAME1_NONE)) { Objective_SetStatus(LEVELSTATUS_FAILED); return; } } return; } void __cdecl lego::game::Level_UpdateEffects(Lego_Level *level,float elapsedGame) { BlockFlags1 *pBVar1; uint numRockFalls; int idx; uint i; uint bx; uint *unused_rockFallSubtypes; uint *unused_rockFallTypes; Point2I blockPos; numRockFalls = effect::Effect_UpdateAll (elapsedGame,&unused_rockFallTypes,&unused_rockFallSubtypes); i = 0; if (numRockFalls != 0) { do { effect::Effect_GetBlockPos_RockFall (unused_rockFallTypes[i],unused_rockFallSubtypes[i],&bx,(uint *)&elapsedGame); blockPos.x = bx; blockPos.y = (int)elapsedGame; idx = (globs::legoGlobs.currLevel)->width * (int)elapsedGame + bx; (globs::legoGlobs.currLevel)->blocks[idx].flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1 & ~BLOCK1_ROCKFALLFX; if (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * (int)elapsedGame + bx].flags1 & BLOCK1_LANDSLIDING ) == BLOCK1_NONE) { Message_PostEvent(Message_RockFallComplete,0,0,&blockPos); } idx = (globs::legoGlobs.currLevel)->width * (int)elapsedGame + bx; (globs::legoGlobs.currLevel)->blocks[idx].flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1 & ~BLOCK1_LANDSLIDING; pBVar1 = &(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos.y + blockPos.x].flags1; i += 1; *pBVar1 = *pBVar1 & ~BLOCK1_BUSY_WALL; } while (i < numRockFalls); } return; } void __cdecl lego::lrr::Lego_UpdateSceneFog(BOOL fogEnabled,float elapsed) { uint uVar1; uint uVar2; float10 delta; float10 waveDelta; float10 range; ColourRGBF fogRGB; if ((globs::legoGlobs.flags1 & GAME1_FOGCOLOURRGB) != GAME1_NONE) { gfx::Container_EnableFog(fogEnabled); if ((fogEnabled != 0) && ((globs::legoGlobs.flags1 & GAME1_HIGHFOGCOLOURRGB) != GAME1_NONE)) { delta = ((float10)6.283185 / (float10)globs::legoGlobs.FogRate) * (float10)elapsed + (float10)globs::gamectrlGlobs.sceneFogDelta; globs::gamectrlGlobs.sceneFogDelta = (float)delta; waveDelta = (float10)fsin(delta); uVar1 = 0; do { uVar2 = uVar1 + 4; // (legoGlobs.HighFogColourRGB.channels[i] - legoGlobs.FogColourRGB.channels[i]) * 0.5f; range = ((float10)*(float *)((int)globs::legoGlobs.objTeleportQueueTypes_TABLE + (uVar1 - 0x5c)) - (float10)*(float *)((int)globs::legoGlobs.recordObjs + uVar1 + 0x54)) * (float10)0.5 ; // fogRGB.channels[i] = legoGlobs.FogColourRGB.channels[i] + fVar4 * fVar3; // // difference * delta *(float *)((int)&fogRGB.red + uVar1) = (float)(range + (float10)*(float *)((int)globs::legoGlobs.recordObjs + uVar1 + 0x54) + range * waveDelta); uVar1 = uVar2; } while (uVar2 < 0xc); gfx::Container_SetFogColour(fogRGB.red,fogRGB.green,fogRGB.blue); } } return; } BOOL __cdecl lego::lrr::Lego_Callback_DrawObjectLaserTrackerBox(LegoObject *liveObj,Viewport *viewMain) { if ((liveObj->flags4 & LIVEOBJ4_LASERTRACKERMODE) != LIVEOBJ4_NONE) { Lego_DrawObjectSelectionBox(liveObj,viewMain,1.0,0.0,0.0); } return 0; } void __cdecl lego::lrr::Lego_DrawAllLaserTrackerBoxes(Viewport *viewMain) { game::LegoObject_RunThroughListsSkipUpgradeParts(Lego_Callback_DrawObjectLaserTrackerBox,viewMain) ; return; } void __cdecl lego::lrr::Lego_DrawAllSelectedUnitBoxes(Viewport *viewMain) { uint uVar1; LegoObject **ppLVar2; uint index; uVar1 = game::Message_GetNumSelectedUnits(); ppLVar2 = game::Message_GetSelectedUnits(); for (index = 0; index < uVar1; index += 1) { if (index == 0) { // Primary selected unit has a green box Lego_DrawObjectSelectionBox(*ppLVar2,viewMain,0.0,1.0,0.0); } else { // All remaining selected units have a yellow box Lego_DrawObjectSelectionBox(ppLVar2[index],viewMain,1.0,1.0,0.0); } } return; } void __cdecl lego::lrr::Lego_DrawObjectSelectionBox(LegoObject *liveObj,Viewport *view,float r,float g,float b) { float fVar1; BOOL BVar2; Map3D *map; int iVar3; uint uVar4; float10 fVar5; longlong lVar6; char *msg; Point2F linePts1 [8]; Vector3F local_a8; Vector3F local_9c; Point2F linePts2 [8]; Vector3F local_4c; Point2F local_40 [2]; Vector4F local_30; Vector3F local_20; Vector3F local_14; float local_8; local_4c.x = 0.0; local_4c.y = 1.0; local_4c.z = 0.0; BVar2 = game::LegoObject_IsHidden(liveObj); if (BVar2 == 0) { if ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) != GAME1_NONE) { r = r * 0.3; g = g * 0.3; b = b * 0.3; } game::LegoObject_GetPosition(liveObj,&local_a8.x,&local_a8.y); map = Lego_GetMap(); fVar5 = lego::map::Map3D_GetWorldZ(map,local_a8.x,local_a8.y); local_a8.z = (float)fVar5; fVar5 = stats::StatsObject_GetCollHeight(liveObj); local_a8.z = (float)((float10)local_a8.z - fVar5 / (float10)2.0); lego::view::Viewport_WorldToScreen(view,(Point2F *)&local_30,&local_a8); if ((0.0 <= local_30.x) && (0.0 <= local_30.y)) { iVar3 = main::appWidth(); if (local_30.x <= (float)iVar3) { iVar3 = main::appHeight(); if (local_30.y <= (float)iVar3) { local_30.z = 0.0; local_30.w = 1.0; lego::view::Viewport_InverseTransform(view,&local_9c,&local_30); math::Maths_Vector3DSubtract(&local_14,&local_a8,&local_9c); math::Maths_Vector3DNormalize(&local_14); math::Maths_Vector3DCrossProduct(&local_20,&local_14,&local_4c); math::Maths_Vector3DNormalize(&local_20); fVar5 = stats::StatsObject_GetPickSphere(liveObj); math::Maths_Vector3DScale(&local_20,&local_20,(float)fVar5); math::Maths_Vector3DAdd(&local_a8,&local_a8,&local_20); lego::view::Viewport_WorldToScreen(view,local_40,&local_a8); fVar5 = math::Maths_Vector2DDistance((Point2F *)&local_30,local_40); fVar1 = (float)(fVar5 / (float10)2.5); local_8 = (float)((fVar5 / (float10)2.5) / (float10)5.0 + (float10)3.0); linePts1[0].x = local_30.x - fVar1; linePts1[0].y = (local_30.y - fVar1) + local_8; linePts2[0].x = local_30.x - fVar1; linePts2[0].y = local_30.y - fVar1; linePts1[1].x = (local_30.x - fVar1) + 1.0; linePts1[1].y = local_30.y - fVar1; linePts2[1].x = (local_30.x - fVar1) + local_8; linePts2[1].y = local_30.y - fVar1; linePts1[2].x = (local_30.x + fVar1) - local_8; linePts1[2].y = local_30.y - fVar1; linePts2[2].x = local_30.x + fVar1; linePts2[2].y = local_30.y - fVar1; linePts1[3].x = local_30.x + fVar1; linePts1[3].y = (local_30.y - fVar1) + 1.0; linePts2[3].x = local_30.x + fVar1; linePts2[3].y = (local_30.y - fVar1) + local_8; linePts1[4].x = local_30.x + fVar1; linePts1[4].y = (local_30.y + fVar1) - local_8; linePts2[4].x = local_30.x + fVar1; linePts2[4].y = local_30.y + fVar1; linePts1[5].x = (local_30.x + fVar1) - 1.0; linePts1[5].y = local_30.y + fVar1; linePts2[5].x = (local_30.x + fVar1) - local_8; linePts2[5].y = local_30.y + fVar1; linePts1[6].x = (local_30.x - fVar1) + local_8; linePts1[6].y = local_30.y + fVar1; linePts2[6].x = local_30.x - fVar1; linePts2[6].y = local_30.y + fVar1; linePts1[7].x = local_30.x - fVar1; linePts1[7].y = (local_30.y + fVar1) - 1.0; linePts2[7].x = local_30.x - fVar1; linePts2[7].y = (local_30.y + fVar1) - local_8; draw::Draw_LineListEx(linePts1,linePts2,8,r,g,b,DrawEffect_None); if ((((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) && (liveObj->customName != NULL)) && (*liveObj->customName != '\0')) { msg = liveObj->customName; lVar6 = __ftol((float10)local_30.y - (float10)fVar1); uVar4 = lego::image::Font_GetHeight(globs::legoGlobs.fontToolTip); iVar3 = (int)lVar6 - uVar4; lVar6 = __ftol((float10)local_30.x - (float10)fVar1); lego::image::Font_PrintF(globs::legoGlobs.fontToolTip,(int)lVar6,iVar3,msg); } } } } } return; } // Simply halts music playback, then calls std::exit(0); void __cdecl lego::lrr::Lego_Shutdown_Quick(void) { Lego_Exit(); return; } // This is only called as a ProgrammerMode_10 setting, // where proper cleanup is performed. void __cdecl lego::lrr::Lego_Shutdown_Full(void) { BOOL BVar1; char *filename; uint uVar2; int iVar3; front::Loader_display_shutdown(); reward::Reward_Shutdown(); Lego_SetMusicPlaying(FALSE); Lego_SetSoundOn(FALSE); game::Level_Free(); front::Interface_Shutdown(); cfg::Config_Free(globs::legoGlobs.config); lego::view::Viewport_Remove(globs::legoGlobs.viewMain); gfx::Container_Remove(globs::legoGlobs.rootCont); lego::view::Camera_Free(globs::legoGlobs.cameraMain); lego::view::Camera_Free(globs::legoGlobs.cameraTrack); lego::view::Camera_Free(globs::legoGlobs.cameraFP); uVar2 = 0; if (globs::legoGlobs.vehicleCount != 0) { iVar3 = 0; do { gfx::Vehicle_Remove((VehicleModel *) ((int)(globs::legoGlobs.vehicleData)->contWheels + iVar3 + -0x10)); io::Mem_Free(globs::legoGlobs.vehicleName[uVar2]); uVar2 += 1; iVar3 += 0x1ec; } while (uVar2 < globs::legoGlobs.vehicleCount); } io::Mem_Free(globs::legoGlobs.vehicleName); io::Mem_Free(globs::legoGlobs.langVehicle_name); io::Mem_Free(globs::legoGlobs.vehicleData); uVar2 = 0; if (globs::legoGlobs.miniFigureCount != 0) { iVar3 = 0; do { gfx::Creature_Remove ((CreatureModel *)((globs::legoGlobs.miniFigureData)->reserved1 + iVar3 + -8)); io::Mem_Free(globs::legoGlobs.miniFigureName[uVar2]); uVar2 += 1; iVar3 += 0x74; } while (uVar2 < globs::legoGlobs.miniFigureCount); } io::Mem_Free(globs::legoGlobs.miniFigureName); io::Mem_Free(globs::legoGlobs.langMiniFigure_name); io::Mem_Free(globs::legoGlobs.miniFigureData); uVar2 = 0; if (globs::legoGlobs.rockMonsterCount != 0) { iVar3 = 0; do { gfx::Creature_Remove ((CreatureModel *)((globs::legoGlobs.rockMonsterData)->reserved1 + iVar3 + -8)); io::Mem_Free(globs::legoGlobs.rockMonsterName[uVar2]); uVar2 += 1; iVar3 += 0x74; } while (uVar2 < globs::legoGlobs.rockMonsterCount); } io::Mem_Free(globs::legoGlobs.rockMonsterName); io::Mem_Free(globs::legoGlobs.langRockMonster_name); io::Mem_Free(globs::legoGlobs.rockMonsterData); uVar2 = 0; if (globs::legoGlobs.upgradeCount != 0) { iVar3 = 0; do { gfx::Upgrade_Part_Remove ((Upgrade_PartModel *)((int)&(globs::legoGlobs.upgradeData)->objID + iVar3)); io::Mem_Free(globs::legoGlobs.upgradeName[uVar2]); uVar2 += 1; iVar3 += 0x10; } while (uVar2 < globs::legoGlobs.upgradeCount); } io::Mem_Free(globs::legoGlobs.upgradeName); io::Mem_Free(globs::legoGlobs.langUpgrade_name); io::Mem_Free(globs::legoGlobs.upgradeData); uVar2 = 0; if (globs::legoGlobs.buildingCount != 0) { iVar3 = 0; do { gfx::Building_Remove ((BuildingModel *)((int)(globs::legoGlobs.buildingData)->carryNulls + iVar3 + -0x28) ); io::Mem_Free(globs::legoGlobs.buildingName[uVar2]); uVar2 += 1; iVar3 += 0x14c; } while (uVar2 < globs::legoGlobs.buildingCount); } io::Mem_Free(globs::legoGlobs.buildingName); io::Mem_Free(globs::legoGlobs.langBuilding_name); io::Mem_Free(globs::legoGlobs.buildingData); io::Mem_Free(globs::legoGlobs.langPowerCrystal_name); io::Mem_Free(globs::legoGlobs.langOre_name); io::Mem_Free(globs::legoGlobs.langProcessedOre_name); io::Mem_Free(globs::legoGlobs.langDynamite_name); io::Mem_Free(globs::legoGlobs.langBarrier_name); io::Mem_Free(globs::legoGlobs.langElectricFence_name); io::Mem_Free(globs::legoGlobs.langSpiderWeb_name); io::Mem_Free(globs::legoGlobs.langOohScary_name); io::Mem_Free(globs::legoGlobs.langPath_name); front::TextWindow_Remove(globs::legoGlobs.textOnlyWindow); lego::image::Font_Remove(globs::legoGlobs.fontStandard); lego::image::Font_Remove(globs::legoGlobs.fontToolTip); effect::Effect_RemoveAll_RockFall(); ai::AITask_Shutdown(); game::LegoObject_Shutdown(); gfx::Container_Shutdown(); lego::view::Viewport_Shutdown(); if (globs::mainGlobs.programmerLevel == PROGRAMMER_MODE_10) { BVar1 = snd::Sound_IsInitialised(); filename = "LoaderProfile.txt"; if (BVar1 == 0) { filename = "LoaderProfileNoSound.txt"; } } else { filename = NULL; } front::Loader_Shutdown(filename); util::logf_removed(); lego::image::Image_Shutdown(); gfx::Lws_Shutdown(); snd::Sound3D_ShutDown(); ddraw::DirectDraw_Clear(NULL,0); return; } void __cdecl lego::lrr::Lego_Exit(void) { Lego_SetMusicPlaying(FALSE); std::exit(0); return; } // Returning FALSE will naturally exit the program (as handled by Lego_MainLoop). // // keyDownT is unused, and no keybinds exist. // keyDownR is unused, but debug keybinds exist for the rewards screen. // keyDownAddSelection is only needed by Lego_HandleWorld(). BOOL __cdecl lego::lrr::Lego_HandleKeys (float elapsedGame,float elapsedInterface,BOOL *out_keyDownT,BOOL *out_keyDownR, BOOL *out_keyDownAddSelection) { LegoObject *pLVar1; Container *cont; BOOL BVar2; BOOL hasNextLevel; TutorialFlags tutFlags; BOOL hasNextLevel_; char *pcVar3; BOOL nextKeyPressed; BoolTri BVar4; bool bVar5; float10 fVar6; Activity_Type activityType; uint repeatCount; Point2F local_14; Vector3F local_c; BOOL *out_keyDownR_00; BOOL *out_keyDownShift_00; BOOL *out_keyDownT_00; // IsKeyReleased(KEY_RETURN) (28) // "Submit unit rename input." if ((((((globs::legoGlobs.flags2 & GAME2_ALLOWRENAME) != GAME2_NONE) && (globs::INPUT.Key_Map[28] == false)) && (globs::INPUT.prevKey_Map[28] != false)) && (((globs::legoGlobs.viewMode == ViewMode_Top && ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE)) && ((pLVar1 = game::Message_GetPrimarySelectedUnit(), pLVar1 != NULL && (pLVar1->type == LegoObject_MiniFigure)))))) && ((pLVar1->abilityFlags != ABILITY_FLAG_NONE || (pLVar1->objLevel != 0)))) { cont = game::LegoObject_GetActivityContainer(pLVar1); gfx::Container_GetPosition(cont,NULL,&local_c); fVar6 = stats::StatsObject_GetCollHeight(pLVar1); local_c.z = (float)((float10)local_c.z - fVar6 * (float10)0.5); lego::view::Viewport_WorldToScreen(globs::legoGlobs.viewMain,&local_14,&local_c); if ((40.0 <= local_14.x) && (((40.0 <= local_14.y && ((ushort)((ushort)(local_14.x < (float)globs::mainGlobs.appWidth - 40.0) << 8 | (ushort)(local_14.x == (float)globs::mainGlobs.appWidth - 40.0) << 0xe) != 0)) && ((ushort)((ushort)(local_14.y < (float)globs::mainGlobs.appHeight - 80.0) << 8 | (ushort)(local_14.y == (float)globs::mainGlobs.appHeight - 80.0) << 0xe) != 0)))) { Lego_SetPaused(FALSE,TRUE); if (pLVar1->customName == NULL) { game::LegoObject_SetCustomName(pLVar1,"Object"); *pLVar1->customName = '\0'; } globs::legoGlobs.renameInput = pLVar1->customName; globs::legoGlobs.renamePosition.x = local_14.x; globs::legoGlobs.renamePosition.y = local_14.y; } } // IsKeyDown(KEY_ESCAPE) (1) if (globs::INPUT.Key_Map[1] != false) { if ((((globs::legoGlobs.flags2 & GAME2_INOPTIONSMENU) == GAME2_NONE) && (BVar2 = front::HelpWindow_IsEnabled_AndFlags_3_AndNoTutorialFlags(), BVar2 == 0)) && ((BVar2 = game::Objective_IsShowing(), BVar2 == 0 && ((globs::legoGlobs.flags1 & GAME1_LEVELENDING) == GAME1_NONE)))) { if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) { // IsKeyUp(KEY_SPACE) (57) if (globs::INPUT.Key_Map[57] == false) { // IsKeyDown(KEY_RETURN) (28) if (globs::INPUT.Key_Map[28] != false) { return FALSE; } } else { snd::Sound3D_ShutDown(); Lego_Exit(); } } Lego_SetPaused(FALSE,TRUE); globs::legoGlobs.flags1 |= GAME1_PAUSED; } else { // UNREACHABLE CODE: Condition is identical to condition for above block. // // IsKeyDown(KEY_ESCAPE) (1) if (((globs::INPUT.Key_Map[1] != false) && ((globs::legoGlobs.flags2 & GAME2_INOPTIONSMENU) == GAME2_NONE)) && ((BVar2 = front::HelpWindow_IsEnabled_AndFlags_3_AndNoTutorialFlags(), BVar2 == 0 && ((BVar2 = game::Objective_IsShowing(), BVar2 == 0 && ((globs::legoGlobs.flags1 & GAME1_LEVELENDING) == GAME1_NONE)))))) { snd::Sound3D_ShutDown(); Lego_Exit(); } } } if ((globs::legoGlobs.flags2 & GAME2_LEVELEXITING) != GAME2_NONE) { BVar2 = front::Front_IsFrontEndEnabled(); // IsKeyDown(KEY_SPACE) (57) if ((BVar2 == 0) || (globs::INPUT.Key_Map[57] != false)) { snd::Sound3D_ShutDown(); Lego_Exit(); } else { // IsKeyDown(KEY_RETURN) (28) if (globs::INPUT.Key_Map[28] != false) { return FALSE; } // Complete the end of the level. WHY IS THIS IN HANDLEKEYS!?? hasNextLevel = Lego_EndLevel(); if (hasNextLevel == 0) { return FALSE; } } } out_keyDownShift_00 = out_keyDownAddSelection; out_keyDownR_00 = out_keyDownR; out_keyDownT_00 = out_keyDownT; *out_keyDownT = 0; *out_keyDownR = 0; *out_keyDownAddSelection = 0; if ((globs::legoGlobs.flags1 & (GAME1_FREEZEINTERFACE|GAME1_LEVELENDING)) == GAME1_NONE) { front::Interface_DoF2InterfaceKeyAction(); // IsKeyPressed(KEY_SPACE) (57) // "Toggle unit info bubbles/HUDs visibility." if ((globs::INPUT.Key_Map[57] != false) && (globs::INPUT.prevKey_Map[57] != globs::INPUT.Key_Map[57])) { front::Bubble_ToggleObjectUIsAlwaysVisible(); } // IsKeyDown(KEY_LEFTSHIFT) (42) || IsKeyDown(KEY_RIGHTSHIFT) (54) if ((globs::INPUT.Key_Map[42] != false) || (globs::INPUT.Key_Map[54] != false)) { *out_keyDownShift_00 = TRUE; } if ((globs::legoGlobs.viewMode == ViewMode_Top) && (tutFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL), (tutFlags & TUTORIAL_FLAG_NOCAMERA) == TUTORIAL_NONE)) { // IsKeyDown(KEY_CURSORDOWN) (208) // "Topdown view: Pitch lower (around center)." if (globs::INPUT.Key_Map[208] != false) { lego::view::Camera_AddTilt(globs::legoGlobs.cameraMain,elapsedInterface * 0.02); } // IsKeyDown(KEY_CURSORUP) (200) // "Topdown view: Pitch raise (around center)." if (globs::INPUT.Key_Map[200] != false) { lego::view::Camera_AddTilt(globs::legoGlobs.cameraMain,elapsedInterface * -0.02); } // IsKeyDown(KEY_CURSORLEFT) (203) // "Topdown view: Rotate clockwise (around center)." if (globs::INPUT.Key_Map[203] != false) { lego::view::Camera_AddRotation(globs::legoGlobs.cameraMain,elapsedInterface * 0.02); } // IsKeyDown(KEY_CURSORRIGHT) (205) // "Topdown view: Rotate counter-clockwise (around center)." if (globs::INPUT.Key_Map[205] != false) { lego::view::Camera_AddRotation(globs::legoGlobs.cameraMain,elapsedInterface * -0.02); } // IsKeyDown(KEY_MINUS) (12) // "Topdown view: Zoom out." if (globs::INPUT.Key_Map[12] != false) { lego::view::Camera_AddZoom(globs::legoGlobs.cameraMain,elapsedInterface * 3.0); } // IsKeyDown(KEY_EQUALS) (13) "+""Topdown view: Zoom in." if (globs::INPUT.Key_Map[13] != false) { lego::view::Camera_AddZoom(globs::legoGlobs.cameraMain,elapsedInterface * -3.0); } } if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) { // IsKeyDown(KEYPAD_7) (71) // "Set game speed to 300%." if (globs::INPUT.Key_Map[71] != false) { Lego_SetGameSpeed(3.0); } // IsKeyDown(KEY_T) (20) if (globs::INPUT.Key_Map[20] != false) { *out_keyDownT_00 = TRUE; } // IsKeyDown(KEY_R) (19) if (globs::INPUT.Key_Map[19] != false) { *out_keyDownR_00 = TRUE; } // IsKeyPressed(KEY_L) (38) if (((globs::INPUT.Key_Map[38] != false) && (globs::INPUT.prevKey_Map[38] != globs::INPUT.Key_Map[38])) && (hasNextLevel_ = Lego_EndLevel(), hasNextLevel_ == 0)) { return FALSE; } // IsKeyDown(KEY_LEFTCTRL) (29) && IsKeyPressed(KEY_F) (33) // "Toggle framerate monitor." if (((globs::INPUT.Key_Map[29] != false) && (globs::INPUT.Key_Map[33] != false)) && (globs::INPUT.prevKey_Map[33] != globs::INPUT.Key_Map[33])) { if ((globs::legoGlobs.flags1 & GAME1_SHOWFPS) == GAME1_NONE) { globs::legoGlobs.flags1 |= GAME1_SHOWFPS; } else { globs::legoGlobs.flags1 &= ~GAME1_SHOWFPS; } pcVar3 = "ON"; if ((globs::legoGlobs.flags1 & GAME1_SHOWFPS) == GAME1_NONE) { pcVar3 = "OFF"; } front::TextWindow_PrintF(globs::legoGlobs.textOnlyWindow,"\nFrame Rate Monitor: %s",pcVar3); } // IsKeyPressed(KEY_TAB) (15) // "Toggle between Radar Map/Track Object View." if ((((globs::legoGlobs.flags1 & GAME1_RADARON) != GAME1_NONE) && (globs::INPUT.Key_Map[15] != false)) && (globs::INPUT.prevKey_Map[15] != globs::INPUT.Key_Map[15])) { bVar5 = (globs::legoGlobs.flags1 & GAME1_RADAR_TRACKOBJECTVIEW) == GAME1_NONE; if (bVar5) { // legoGlobs.flags1 &= ~GAME1_RADAR_MAPVIEW; // legoGlobs.flags1 |= GAME1_RADAR_TRACKOBJECTVIEW; globs::legoGlobs.flags1 = globs::legoGlobs.flags1 & (GAME1_HIGHFOGCOLOURRGB|GAME1_RADAR_NOTRACKOBJECT|GAME1_VERTEXMODE|GAME1_DYNAMICPM| GAME1_FREEZEINTERFACE|GAME1_CAMERAGOTO|GAME1_ONLYBUILDONPATHS|GAME1_ALWAYSROCKFALL| GAME1_DEBUG_NONERPS|GAME1_PAUSED|GAME1_STREAMNERPSSPEACH|GAME1_LEVELENDING| GAME1_LASERTRACKER|GAME1_DEBUG_SHOWVERTEXMODE|GAME1_DEBUG_NOCLIP_FPS| GAME1_VERTEXLOCKONPOINTER) | (ushort)((ushort)globs::legoGlobs.flags1 | 0x2000) & ~GAME1_RADAR_MAPVIEW; front::Panel_Button_Hide(Panel_Radar,2,TRUE); } else { // legoGlobs.flags1 &= ~GAME1_RADAR_TRACKOBJECTVIEW; // legoGlobs.flags1 |= GAME1_RADAR_MAPVIEW; globs::legoGlobs.flags1 = globs::legoGlobs.flags1 & ~GAME1_RADAR_TRACKOBJECTVIEW | GAME1_RADAR_MAPVIEW; front::Panel_Button_Hide(Panel_Radar,2,FALSE); } front::Panel_Button_Hide(Panel_Radar,3,(uint)bVar5); } // IsKeyDown(KEY_LEFTCTRL) (29) if (globs::INPUT.Key_Map[29] != false) { // IsKeyPressed(KEY_G) (34) // "Toggle memory monitor." if ((globs::INPUT.Key_Map[34] != false) && (globs::INPUT.prevKey_Map[34] != globs::INPUT.Key_Map[34])) { if ((globs::legoGlobs.flags1 & GAME1_SHOWMEMORY) == GAME1_NONE) { globs::legoGlobs.flags1 |= GAME1_SHOWMEMORY; } else { globs::legoGlobs.flags1 &= ~GAME1_SHOWMEMORY; } pcVar3 = "ON"; if ((globs::legoGlobs.flags1 & GAME1_SHOWMEMORY) == GAME1_NONE) { pcVar3 = "OFF"; } front::TextWindow_PrintF(globs::legoGlobs.textOnlyWindow,"\nMemory Monitor: %s",pcVar3); } // IsKeyDown(KEY_LEFTCTRL) (29) && IsKeyPressed(KEY_RETURN) (28) // "Toggle Noclip in first/second person view." if (((globs::INPUT.Key_Map[29] != false) && (globs::INPUT.Key_Map[28] != false)) && (globs::INPUT.prevKey_Map[28] != globs::INPUT.Key_Map[28])) { if ((globs::legoGlobs.flags1 & GAME1_DEBUG_NOCLIP_FPS) == GAME1_NONE) { globs::legoGlobs.flags1 |= GAME1_DEBUG_NOCLIP_FPS; } else { globs::legoGlobs.flags1 &= ~GAME1_DEBUG_NOCLIP_FPS; } } } } if ((globs::legoGlobs.viewMode == ViewMode_FP) && ((*(byte *)&(globs::legoGlobs.objectFP)->flags2 & LIVEOBJ2_THROWING) == 0)) { // First person view controls // IsKeyDown(KEY_CURSORUP) (200) // "First person view: Move forward." if (globs::INPUT.Key_Map[200] != false) { game::LegoObject_FP_Move(globs::legoGlobs.objectFP,1,0,0.0); } // IsKeyDown(KEY_CURSORDOWN) (208) // "First person view: Move back." if (globs::INPUT.Key_Map[208] != false) { game::LegoObject_FP_Move(globs::legoGlobs.objectFP,-1,0,0.0); } // IsKeyDown(KEY_CURSORLEFT) (203) // "First person view: Turn left." if (globs::INPUT.Key_Map[203] != false) { game::LegoObject_FP_Move(globs::legoGlobs.objectFP,0,0,-0.05); } // IsKeyDown(KEY_CURSORRIGHT) (205) // "First person view: Turn right." if (globs::INPUT.Key_Map[205] != false) { game::LegoObject_FP_Move(globs::legoGlobs.objectFP,0,0,0.05); } // IsKeyDown(KEY_Z) (44) // "First person view: Strafe left." if (globs::INPUT.Key_Map[44] != false) { game::LegoObject_FP_Move(globs::legoGlobs.objectFP,0,-1,0.0); } // IsKeyDown(KEY_X) (45) // "First person view: Strafe right." if (globs::INPUT.Key_Map[45] != false) { game::LegoObject_FP_Move(globs::legoGlobs.objectFP,0,1,0.0); } } if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) { // IsKeyPressed(KEY_S) (31) // "Toggle sound On/Off." if ((globs::INPUT.Key_Map[31] != false) && (globs::INPUT.prevKey_Map[31] != globs::INPUT.Key_Map[31])) { if ((globs::legoGlobs.flags1 & GAME1_USESFX) == GAME1_NONE) { Lego_SetSoundOn(TRUE); snd::SFX_Random_PlaySoundNormal(SFX_AmbientLoop,TRUE); } else { Lego_SetSoundOn(FALSE); } pcVar3 = "ON"; if ((globs::legoGlobs.flags1 & GAME1_USESFX) == GAME1_NONE) { pcVar3 = "OFF"; } front::TextWindow_PrintF(globs::legoGlobs.textOnlyWindow,"\nSound Effects: %s",pcVar3); } // IsKeyPressed(KEY_M) (55) // "Toggle music On/Off." if ((globs::INPUT.Key_Map[50] != false) && (globs::INPUT.prevKey_Map[50] != globs::INPUT.Key_Map[50])) { Lego_SetMusicPlaying((uint)((globs::legoGlobs.flags1 & GAME1_MUSICPLAYING) == GAME1_NONE)); pcVar3 = "ON"; if ((globs::legoGlobs.flags1 & GAME1_MUSICPLAYING) == GAME1_NONE) { pcVar3 = "OFF"; } front::TextWindow_PrintF(globs::legoGlobs.textOnlyWindow,"\nMusic: %s",pcVar3); } } // IsKeyPressed(KEYPAD_0) (82) if ((((globs::legoGlobs.flags2 & GAME2_ALLOWEDITMODE) != GAME2_NONE) && (globs::INPUT.Key_Map[82] != false)) && (globs::INPUT.prevKey_Map[82] != globs::INPUT.Key_Map[82])) { lego::view::Camera_EnableFreeMovement(globs::legoGlobs.cameraMain,FALSE); gfx::SelectPlace_Hide(globs::legoGlobs.selectPlace,TRUE); } // IsKeyPressed(KEY_Z) (44) // "Make primary selected unit eat." if ((((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) && (globs::INPUT.Key_Map[44] != false)) && (globs::INPUT.prevKey_Map[44] != globs::INPUT.Key_Map[44])) { lego::view::Camera_Shake(globs::legoGlobs.cameraMain,5.0,25.0); pLVar1 = game::Message_GetPrimarySelectedUnit(); if (pLVar1 != NULL) { pLVar1 = game::Message_GetPrimarySelectedUnit(); repeatCount = 0; activityType = Activity_Eat; pLVar1->flags1 = pLVar1->flags1 | LIVEOBJ1_EATING; pLVar1 = game::Message_GetPrimarySelectedUnit(); game::LegoObject_SetActivity(pLVar1,activityType,repeatCount); pLVar1 = game::Message_GetPrimarySelectedUnit(); game::LegoObject_UpdateActivityChange(pLVar1); pLVar1 = game::Message_GetPrimarySelectedUnit(); ai::AITask_DoAnimationWait(pLVar1); } } } BVar2 = 0; elapsedInterface = 0.0; if ((globs::gamectrlGlobs.handleKeysLastLeftMouseButtonDown != 0) && (globs::INPUT.mslb == 0)) { BVar2 = TRUE; } // IsKeyUp(KEY_SPACE) || !IsKeyChanged(KEY_SPACE) (57) if ((globs::INPUT.Key_Map[57] == false) || (globs::INPUT.prevKey_Map[57] == globs::INPUT.Key_Map[57])) { nextKeyPressed = 0; } else { nextKeyPressed = TRUE; } BVar2 = game::Objective_HandleKeys(nextKeyPressed,BVar2,(BOOL *)&elapsedInterface); if ((((BVar2 == 0) && (BVar2 = front::HelpWindow_IsEnabled_AndFlags_3_AndNoTutorialFlags(), BVar2 == 0)) && (BVar2 = game::Objective_IsShowing(), BVar2 == 0)) && (((globs::legoGlobs.flags1 & GAME1_LEVELENDING) == GAME1_NONE && ((globs::legoGlobs.flags2 & GAME2_INOPTIONSMENU) == GAME2_NONE)))) { // IsKeyPressed(KEY_P) (25) // "Pause/unpause the game." if ((globs::INPUT.Key_Map[25] != false) && (globs::INPUT.prevKey_Map[25] != globs::INPUT.Key_Map[25])) { Lego_SetPaused(TRUE,FALSE); globs::legoGlobs.flags1 ^= GAME1_PAUSED; } if (globs::mainGlobs.active == 0) { pcVar3 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","LoseFocusAndPause",0); BVar4 = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar3); if (((BVar4 == BOOL3_TRUE) && ((globs::legoGlobs.flags1 & GAME1_LEVELENDING) == GAME1_NONE)) && (Lego_SetPaused(FALSE,TRUE), (globs::legoGlobs.flags1 & GAME1_PAUSED) == GAME1_NONE)) { globs::legoGlobs.flags1 |= GAME1_PAUSED; } } } globs::gamectrlGlobs.handleKeysLastLeftMouseButtonDown = globs::INPUT.mslb; if (elapsedInterface != 0.0) { return 0; } if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) { // IsKeyUp(KEY_LEFTSHIFT) (42) if (globs::INPUT.Key_Map[42] == false) { // IsKeyDown(KEY_FIVE) (6) if (globs::INPUT.Key_Map[6] != false) { globs::updateGlobs.currentBaseLightLevel = globs::updateGlobs.currentBaseLightLevel - 0.02; gfx::Container_Light_SetSpotPenumbra (globs::legoGlobs.rootSpotlight,globs::updateGlobs.currentBaseLightLevel); } // IsKeyDown(KEY_SIX) (7) if (globs::INPUT.Key_Map[7] != false) { globs::gamectrlGlobs.dbgCursorLightLevel = globs::gamectrlGlobs.dbgCursorLightLevel - 0.02; goto LAB_004259b9; } } else { // IsKeyDown(KEY_FIVE) (6) if (globs::INPUT.Key_Map[6] != false) { globs::updateGlobs.currentBaseLightLevel = globs::updateGlobs.currentBaseLightLevel - -0.02; gfx::Container_Light_SetSpotPenumbra (globs::legoGlobs.rootSpotlight,globs::updateGlobs.currentBaseLightLevel); } // IsKeyDown(KEY_SIX) (7) if (globs::INPUT.Key_Map[7] != false) { globs::gamectrlGlobs.dbgCursorLightLevel = globs::gamectrlGlobs.dbgCursorLightLevel - -0.02; LAB_004259b9: gfx::Container_Light_SetSpotUmbra (globs::legoGlobs.rootSpotlight,globs::gamectrlGlobs.dbgCursorLightLevel); } } if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) goto LAB_004259d8; } if ((globs::mainGlobs.flags & MAIN_FLAG_DEBUGCOMPLETE) == MAIN_FLAG_NONE) { return 1; } LAB_004259d8: // IsKeyDown(KEY_LEFTCTRL) (29) if (globs::INPUT.Key_Map[29] != false) { // IsKeyPressed(KEY_D) (32) // "Instantly fails the current level." if ((globs::INPUT.Key_Map[32] != false) && (globs::INPUT.prevKey_Map[32] != globs::INPUT.Key_Map[32])) { nerps::funcs::NERPFunc__SetLevelFail(NULL); } // IsKeyPressed(KEY_S) (31) // "Instantly completes the current level." if ((globs::INPUT.Key_Map[31] != false) && (globs::INPUT.prevKey_Map[31] != globs::INPUT.Key_Map[31])) { nerps::funcs::NERPFunc__SetLevelCompleted(NULL); } } // IsKeyDown(KEY_RIGHTCTRL) (157) && IsKeyPressed(KEY_S) (31) // "Instantly fails the current level with reason, too many crystals stolen." if (((globs::INPUT.Key_Map[157] != false) && (globs::INPUT.Key_Map[31] != false)) && (globs::INPUT.prevKey_Map[31] != globs::INPUT.Key_Map[31])) { game::Objective_SetStatus(LEVELSTATUS_FAILED_CRYSTALS); } // IsKeyDown(KEY_O) (24) // "Decreases oxygen level." if (globs::INPUT.Key_Map[24] != false) { (globs::legoGlobs.currLevel)->oxygenLevel = (globs::legoGlobs.currLevel)->oxygenLevel - 1.0; } return TRUE; } BOOL __cdecl lego::lrr::Lego_UpdateAll3DSounds(BOOL stopAll) { BOOL BVar1; BVar1 = game::LegoObject_RunThroughListsSkipUpgradeParts(Lego_UpdateObject3DSounds,&stopAll); return BVar1; } BOOL __cdecl lego::lrr::Lego_UpdateObject3DSounds(LegoObject *liveObj,BOOL *pStopAll) { Container *cont; SFX_ID sfxId; int drillPlayHandle; SFX_ID playHandle; BOOL loop; BOOL onCont; Vector3F *opt_wPos; cont = game::LegoObject_GetActivityContainer(liveObj); if (cont != NULL) { if ((liveObj->flags4 & LIVEOBJ4_UNK_20000) == LIVEOBJ4_NONE) { if (*pStopAll != 0) { snd::SFX_Sound3D_StopSound(liveObj->drillSoundHandle); } if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_DRILLING) != 0) { opt_wPos = NULL; onCont = TRUE; loop = TRUE; sfxId = stats::StatsObject_GetDrillSoundType(liveObj,FALSE); drillPlayHandle = snd::SFX_Random_PlaySound3DOnContainer(cont,sfxId,loop,onCont,opt_wPos); liveObj->drillSoundHandle = drillPlayHandle; liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_DRILLSOUNDPLAYING; } } if (*pStopAll != 0) { snd::SFX_Sound3D_StopSound(liveObj->engineSoundHandle); } sfxId = stats::StatsObject_GetEngineSound(liveObj); if (sfxId != SFX_NULL) { playHandle = snd::SFX_Random_PlaySound3DOnContainer(cont,sfxId,TRUE,TRUE,NULL); liveObj->engineSoundHandle = playHandle; liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_ENGINESOUNDPLAYING; } } return 0; } void __cdecl lego::lrr::Lego_SetPaused(BOOL checkCamDisableFlag,BOOL paused) { if ((globs::legoGlobs.flags2 & GAME2_LEVELEXITING) == GAME2_NONE) { if (checkCamDisableFlag != 0) { // param_2 = (gameGlobs.flags1 & GAME1_CAMERADISABLED) == GAME1_NONE; paused = ~globs::legoGlobs.flags1 >> 20 & 1; } if (paused != 0) { if ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) { snd::Sound3D_StopAllSounds(); } globs::legoGlobs.flags1 = globs::legoGlobs.flags1 | GAME1_FREEZEINTERFACE; globs::legoGlobs.flags2 = globs::legoGlobs.flags2 | GAME2_INMENU; return; } Lego_UpdateAll3DSounds(FALSE); snd::SFX_Random_PlaySoundNormal(SFX_AmbientLoop,TRUE); globs::legoGlobs.flags1 &= ~GAME1_FREEZEINTERFACE; globs::legoGlobs.flags2 &= ~GAME2_INMENU; } return; } // When set to TRUE, game speed can only be lowered, not raised. void __cdecl lego::lrr::Lego_LockGameSpeed(BOOL locked) { globs::gamectrlGlobs.isGameSpeedLocked = locked; return; } // Set new game speed and update front end speed slider. // If GameSpeedLocked global is true, game speed can only be lowered, not raised. void __cdecl lego::lrr::Lego_SetGameSpeed(float newGameSpeed) { if ((globs::legoGlobs.gameSpeed <= newGameSpeed) || (globs::gamectrlGlobs.isGameSpeedLocked == 0)) { front::Front_UpdateSliderGameSpeed(); globs::legoGlobs.gameSpeed = newGameSpeed; if (newGameSpeed < 0.0) { globs::legoGlobs.gameSpeed = 0.0; } // Debug mode allows game speeds up to 300% // // if (gameGlobs.gameSpeed > 3.0f) // gameGlobs.gameSpeed = 3.0f; if ((ushort)((ushort)(globs::legoGlobs.gameSpeed < 3.0) << 8 | (ushort)(globs::legoGlobs.gameSpeed == 3.0) << 0xe) == 0) { globs::legoGlobs.gameSpeed = 3.0; } } return; } void __cdecl lego::lrr::Lego_TrackObjectInRadar(LegoObject *liveObj) { float10 fVar1; float trackTilt; float trackRotationSpeed; trackRotationSpeed = 0.01; trackTilt = 0.7; fVar1 = stats::StatsObject_GetTrackDist(liveObj); lego::view::Camera_TrackObject (globs::legoGlobs.cameraTrack,liveObj,2.0,(float)fVar1,trackTilt,trackRotationSpeed); return; } BOOL __cdecl lego::lrr::Lego_IsFirstPersonView(void) { return (uint)(globs::legoGlobs.viewMode == ViewMode_FP); } void __cdecl lego::lrr::Lego_HandleRadarInput(void) { TutorialFlags TVar1; BOOL BVar2; float fVar3; int iVar4; char *pcVar5; SFX_ID sfxType; BlockFlags1 BVar6; float10 fVar7; float trackRotationSpeed; ToolTip_Type toolTipType; LegoObject *local_30; Point2F local_2c; int local_24; int local_20; Point2I local_1c; Point2F local_10; Point2F local_8; Lego_Level *level; level = globs::legoGlobs.currLevel; if ((globs::legoGlobs.flags1 & GAME1_RADARON) == GAME1_NONE) { return; } if ((globs::legoGlobs.flags1 & GAME1_RADAR_MAPVIEW) == GAME1_NONE) { return; } if ((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) != GAME1_NONE) { return; } local_1c.x = (int)((float)globs::INPUT.msx - (float)globs::gamectrlGlobs.msx_Last_1); local_10.x = (float)globs::gamectrlGlobs.msy_Last_1; local_10.y = 0.0; local_1c.y = (int)((float)globs::INPUT.msy - (float)globs::gamectrlGlobs.msy_Last_1); front::Pointer_SetCurrent_IfTimerFinished(Pointer_Standard); TVar1 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((TVar1 & TUTORIAL_FLAG_NOCAMERA) == TUTORIAL_NONE) { globs::gamectrlGlobs.mslb_Last_3 = (BOOL)(SQRT((float)local_1c.y * (float)local_1c.y + (float)local_1c.x * (float)local_1c.x) + (float)globs::gamectrlGlobs.mslb_Last_3); } if ((((globs::gamectrlGlobs.mslb_Last_5 != 0) && (globs::INPUT.mslb != 0)) && (4.0 <= (float)globs::gamectrlGlobs.mslb_Last_3)) && (BVar2 = game::RadarMap_ScreenToWorldBlockPos (level->radarMap,globs::INPUT.msx,globs::INPUT.msy,&local_10, (int *)&local_2c,(int *)&local_2c.y), BVar2 != 0)) { lego::view::Camera_GetTopdownPosition(globs::legoGlobs.cameraMain,&local_1c); fVar3 = (float)lego::view::Camera_GetMouseScrollIndent(); if (((uint)local_2c.x < (uint)fVar3) || (iVar4 = lego::view::Camera_GetMouseScrollIndent(), level->map->blockWidth - iVar4 <= (uint)local_2c.x)) { local_10.x = (float)local_1c.x; } fVar3 = (float)lego::view::Camera_GetMouseScrollIndent(); if (((uint)local_2c.y < (uint)fVar3) || (iVar4 = lego::view::Camera_GetMouseScrollIndent(), level->map->blockHeight - iVar4 <= (uint)local_2c.y)) { local_10.y = (float)local_1c.y; } if (globs::legoGlobs.viewMode == ViewMode_Top) { lego::view::Camera_SetTopdownPosition(globs::legoGlobs.cameraMain,local_10.x,local_10.y); } front::Pointer_SetCurrent_IfTimerFinished(Pointer_RadarPan); globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; } BVar2 = game::RadarMap_InsideRadarScreen(level->radarMap,globs::INPUT.msx,globs::INPUT.msy); if (((BVar2 != 0) && (globs::INPUT.mslb != 0)) && (globs::gamectrlGlobs.mslb_Last_4 == 0)) { globs::gamectrlGlobs.mslb_Last_5 = 1; } if (4.0 <= (float)globs::gamectrlGlobs.mslb_Last_3) goto LAB_004260b6; BVar2 = game::RadarMap_TrySelectObject (level->radarMap,globs::INPUT.msx,globs::INPUT.msy,&local_30,&local_8); if (BVar2 == 0) { if (globs::INPUT.mslb != 0) goto LAB_004260b6; if (globs::gamectrlGlobs.mslb_Last_4 != 0) { BVar2 = game::RadarMap_ScreenToWorldBlockPos (level->radarMap,globs::INPUT.msx,globs::INPUT.msy, &globs::legoGlobs.radarCenter,&local_20,&local_24); if (BVar2 != 0) { globs::legoGlobs.flags1 |= GAME1_RADAR_TRACKOBJECTLOST; } goto LAB_004260b6; } if ((false) || (BVar2 = game::RadarMap_ScreenToWorldBlockPos (level->radarMap,globs::INPUT.msx,globs::INPUT.msy,NULL,(int *)&local_2c, (int *)&local_2c.y), BVar2 == 0)) goto LAB_004260b6; if ((globs::gamectrlGlobs.pointf_144.x == local_2c.x) && (globs::gamectrlGlobs.pointf_144.y == local_2c.y)) { if (((uint)local_2c.x < (globs::legoGlobs.currLevel)->width - 1) && ((uint)local_2c.y < (globs::legoGlobs.currLevel)->height - 1)) { BVar6 = (globs::legoGlobs.currLevel)->blocks [(int)local_2c.y * (globs::legoGlobs.currLevel)->width + (int)local_2c.x].flags1 & BLOCK1_SURVEYED; } else { BVar6 = BLOCK1_NONE; } if (BVar6 != BLOCK1_NONE) { local_1c.x = (int)local_2c.x; local_1c.y = (int)local_2c.y; Lego_ShowBlockToolTip(&local_1c,FALSE,TRUE,TRUE); } goto LAB_004260b6; } globs::gamectrlGlobs.pointf_144.x = local_2c.x; globs::gamectrlGlobs.pointf_144.y = local_2c.y; toolTipType = ToolTip_Null; } else { if (globs::INPUT.mslb != 0) goto LAB_004260b6; if (globs::gamectrlGlobs.mslb_Last_4 != 0) { if (globs::legoGlobs.viewMode == ViewMode_Top) { lego::view::Camera_SetTopdownPosition(globs::legoGlobs.cameraMain,local_8.x,local_8.y); } trackRotationSpeed = 0.01; fVar3 = 0.7; fVar7 = stats::StatsObject_GetTrackDist(local_30); lego::view::Camera_TrackObject (globs::legoGlobs.cameraTrack,local_30,2.0,(float)fVar7,fVar3,trackRotationSpeed); globs::legoGlobs.flags1 &= ~GAME1_RADAR_TRACKOBJECTLOST; goto LAB_004260b6; } front::Pointer_SetCurrent_IfTimerFinished(Pointer_TrackObject); pcVar5 = game::LegoObject_GetLangName(local_30); front::ToolTip_SetContent(ToolTip_UnitSelect,"%s",pcVar5); sfxType = game::LegoObject_GetObjTtSFX(local_30); front::ToolTip_SetSFX(ToolTip_UnitSelect,sfxType); toolTipType = ToolTip_UnitSelect; } front::ToolTip_Activate(toolTipType); LAB_004260b6: if (globs::INPUT.mslb == 0) { globs::gamectrlGlobs.mslb_Last_3 = globs::INPUT.mslb; globs::gamectrlGlobs.mslb_Last_5 = globs::INPUT.mslb; } globs::gamectrlGlobs.msy_Last_1 = globs::INPUT.msy; globs::gamectrlGlobs.msx_Last_1 = globs::INPUT.msx; globs::gamectrlGlobs.mslb_Last_4 = globs::INPUT.mslb; return; } void __cdecl lego::lrr::Lego_UpdateSlug_FUN_004260f0(float elapsedGame) { int iVar1; // 20 == OBJECTS_SUBTYPES_COUNT, meaning Slug objIndex is invalid if (((globs::legoGlobs.currLevel)->Slug != 0x14) && (globs::legoGlobs.InitialSlugTime = globs::legoGlobs.InitialSlugTime - elapsedGame, globs::legoGlobs.InitialSlugTime < 0.0)) { iVar1 = game::LegoObject_Search_FUN_00438c20(NULL,FALSE); if (iVar1 != 0) { game::LegoObject_TryGenerateSlug(NULL,(globs::legoGlobs.currLevel)->Slug); } globs::legoGlobs.InitialSlugTime = (globs::legoGlobs.currLevel)->SlugTime; } return; } void __cdecl lego::lrr::Lego_GetMouseWorldPosition(Vector3F *out_mouseWorldPos) { out_mouseWorldPos->x = globs::legoGlobs.mouseWorldPos.x; out_mouseWorldPos->y = globs::legoGlobs.mouseWorldPos.y; out_mouseWorldPos->z = globs::legoGlobs.mouseWorldPos.z; return; } void __cdecl lego::lrr::Lego_DrawRadarMap(void) { Point2F radarCenterPos; if ((globs::legoGlobs.cameraTrack)->trackObj == NULL) { globs::legoGlobs.flags1 |= GAME1_RADAR_TRACKOBJECTLOST; } if ((globs::legoGlobs.flags1 & GAME1_RADAR_TRACKOBJECTLOST) == GAME1_NONE) { game::LegoObject_GetPosition ((globs::legoGlobs.cameraTrack)->trackObj,&radarCenterPos.x,&radarCenterPos.y); } else { radarCenterPos.x = globs::legoGlobs.radarCenter.x; radarCenterPos.y = globs::legoGlobs.radarCenter.y; } game::RadarMap_SetZoom((globs::legoGlobs.currLevel)->radarMap,globs::legoGlobs.radarZoom); game::RadarMap_Draw((globs::legoGlobs.currLevel)->radarMap,&radarCenterPos); return; } void __cdecl lego::lrr::Lego_SetMenuNextPosition(Point2F *position) { if (position != NULL) { globs::legoGlobs.flags2 = globs::legoGlobs.flags2 | GAME2_MENU_HASNEXT; globs::legoGlobs.menuNextPoint.x = position->x; globs::legoGlobs.menuNextPoint.y = position->y; return; } globs::legoGlobs.flags2 = globs::legoGlobs.flags2 & ~GAME2_MENU_HASNEXT; return; } void __cdecl lego::lrr::Lego_SetMenuPreviousPosition(Point2F *position) { if (position != NULL) { globs::legoGlobs.flags2 = globs::legoGlobs.flags2 | GAME2_MENU_HASPREVIOUS; globs::legoGlobs.menuPrevPoint.x = position->x; globs::legoGlobs.menuPrevPoint.y = position->y; return; } globs::legoGlobs.flags2 = globs::legoGlobs.flags2 & ~GAME2_MENU_HASPREVIOUS; return; } void __cdecl lego::lrr::Lego_SetFlags2_40_And_2_unkCamera(BOOL onFlag40,BOOL onFlag2) { GameFlags2 flags2; if (onFlag40 == 0) { flags2 = globs::legoGlobs.flags2 & ~GAME2_MESSAGE_HASNEXT; } else { flags2 = globs::legoGlobs.flags2 | GAME2_MESSAGE_HASNEXT; } if (onFlag2 != 0) { globs::legoGlobs.flags2 = flags2 | GAME2_CAMERAMOVING; return; } globs::legoGlobs.flags2 = flags2 & ~GAME2_CAMERAMOVING; return; } void __cdecl lego::lrr::Lego_SetFlags2_80(BOOL state) { if (state != 0) { globs::legoGlobs.flags2 = globs::legoGlobs.flags2 | GAME2_MESSAGE_HASREPEAT; return; } globs::legoGlobs.flags2 = globs::legoGlobs.flags2 & ~GAME2_MESSAGE_HASREPEAT; return; } void __cdecl lego::lrr::Lego_UnkObjective_CompleteSub_FUN_004262f0(void) { int msgPermit; msgPermit = TRUE; globs::textGlobs.jankCounter = 0; nerps::funcs::NERPFunc__SetMessagePermit(&msgPermit); globs::textGlobs.float_488 = 0.0; front::TextWindow_Clear(globs::legoGlobs.textOnlyWindow); Lego_SetFlags2_40_And_2_unkCamera(FALSE,FALSE); Lego_SetFlags2_80(FALSE); return; } void __cdecl lego::lrr::Lego_UpdateTopdownCamera(float elapsedAbs) { TutorialFlags tutFlags; Vector3F mouseWorldPos; Vector3F camWorldPos; Vector3F mouseCamWorldPos; if (globs::legoGlobs.viewMode == ViewMode_Top) { tutFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((tutFlags & TUTORIAL_FLAG_NOCAMERA) == TUTORIAL_NONE) { if ((((globs::legoGlobs.MouseScrollBorder <= globs::INPUT.msx) && (globs::legoGlobs.MouseScrollBorder <= globs::INPUT.msy)) && (globs::INPUT.msx <= (int)(globs::mainGlobs.appWidth - globs::legoGlobs.MouseScrollBorder) )) && (globs::INPUT.msy <= (int)(globs::mainGlobs.appHeight - globs::legoGlobs.MouseScrollBorder))) { // Stop camera moving if mouse isn't in the scroll indent region around the window // border.; lego::view::Camera_StopMovement(globs::legoGlobs.cameraMain); return; } lego::view::Camera_GetTopdownWorldPos (globs::legoGlobs.cameraMain,(globs::legoGlobs.currLevel)->map,&camWorldPos); Lego_MainView_MouseTransform (globs::INPUT.msx,globs::INPUT.msy,&mouseWorldPos.x,&mouseWorldPos.y); mouseCamWorldPos.x = mouseWorldPos.x - camWorldPos.x; mouseCamWorldPos.y = mouseWorldPos.y - camWorldPos.y; camWorldPos.z = 0.0; mouseWorldPos.z = 0.0; mouseCamWorldPos.z = 0.0; lego::view::Camera_Move(globs::legoGlobs.cameraMain,&mouseCamWorldPos,elapsedAbs); } } return; } void __cdecl lego::lrr::Lego_HandleWorld (float elapsedGame,float elapsedAbs,BOOL keyDownT,BOOL keyDownR,BOOL keyDownAddSelection) { char cVar1; LegoObject_Type LVar2; float fVar3; Pointer_Type PVar4; LegoObject *pLVar5; StatsFlags3 sflags3; StatsFlags1 sflags1; LegoObject *pLVar6; int iVar7; BlockFlags1 bflags1; TutorialFlags tutFlags; float fVar8; LegoObject_AbilityFlags LVar9; BOOL BVar10; bool bVar11; uint uVar12; uint uVar13; uint uVar14; Interface_MenuType menuType; uint uVar15; Pointer_Type pointerType; PointerSFX_Type pointerSFXType; Point2F *opt_blockPos; float fVar16; BOOL leftReleased; LegoObject *mouseObj; int mouseBlockY; int mouseBlockX; BOOL rightReleased; int local_2c; int local_28; Point2F local_24; Point2F local_1c; Point2F local_14; Vector3F mouseWorldPos; Lego_Level *level; level = globs::legoGlobs.currLevel; globs::legoGlobs.flags2 &= ~GAME2_MOUSE_INSIDEGAMEVIEW; BVar10 = 0; mouseObj = NULL; local_28 = 0; local_2c = 0; leftReleased = 0; rightReleased = 0; gfx::SelectPlace_Hide(globs::legoGlobs.selectPlace,TRUE); if ((globs::INPUT.mslb == 0) && (globs::INPUT.msrb == 0)) { globs::gamectrlGlobs.handleWorldNoMouseButtonsElapsed = globs::gamectrlGlobs.handleWorldNoMouseButtonsElapsed + elapsedGame; } else { globs::gamectrlGlobs.handleWorldNoMouseButtonsElapsed = 0.0; } if (globs::gamectrlGlobs.mslb_Last_0 != 0) { if (globs::INPUT.mslb == 0) { if ((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) { BVar10 = TRUE; leftReleased = TRUE; } } else { globs::gamectrlGlobs.mslb_Last_6 = TRUE; } } if (globs::INPUT.mslb == 0) { globs::gamectrlGlobs.mslb_Last_6 = 0; } if ((globs::gamectrlGlobs.mslr_Last_0 != 0) && (globs::INPUT.msrb == 0)) { rightReleased = TRUE; } if (globs::gamectrlGlobs.mslb_Last_6 == 0) { globs::gamectrlGlobs.pointf_8.y = 0.0; globs::gamectrlGlobs.pointf_8.x = 0.0; } else { globs::gamectrlGlobs.pointf_8.x = (float)((globs::INPUT.diffx ^ globs::INPUT.diffx >> 0x1f) - (globs::INPUT.diffx >> 0x1f)) + globs::gamectrlGlobs.pointf_8.x; local_24.x = (float)((globs::INPUT.diffy ^ globs::INPUT.diffy >> 0x1f) - (globs::INPUT.diffy >> 0x1f)); globs::gamectrlGlobs.pointf_8.y = (float)(int)local_24.x + globs::gamectrlGlobs.pointf_8.y; } front::HelpWindow_FUN_00418cd0 (globs::INPUT.msx,globs::INPUT.msy,globs::INPUT.mslb,globs::gamectrlGlobs.mslb_Last_0, BVar10,elapsedGame); if ((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) != GAME1_NONE) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_Standard); globs::gamectrlGlobs.mslb_Last_0 = globs::INPUT.mslb; globs::gamectrlGlobs.mslr_Last_0 = globs::INPUT.msrb; globs::gamectrlGlobs.bool_160 = TRUE; globs::legoGlobs.flags1 = globs::legoGlobs.flags1 & ~(GAME1_MULTISELECTING|GAME1_MOUSEBUSY); return; } if (globs::gamectrlGlobs.bool_160 != 0) { globs::gamectrlGlobs.mslb_Last_0 = 0; globs::gamectrlGlobs.mslr_Last_0 = 0; globs::gamectrlGlobs.mslb_Last_6 = 0; leftReleased = 0; rightReleased = 0; globs::gamectrlGlobs.bool_160 = 0; } BVar10 = lego::map::Map3D_GetIntersections ((globs::legoGlobs.currLevel)->map,globs::legoGlobs.viewMain,globs::INPUT.msx, globs::INPUT.msy,(uint *)&mouseBlockX,(uint *)&mouseBlockY,&mouseWorldPos); bVar11 = BVar10 == 0; if (!bVar11) { elapsedGame = (float)(level->blocks + level->width * mouseBlockY + mouseBlockX); gfx::Container_SetPosition (globs::legoGlobs.rootLight,NULL,mouseWorldPos.x,mouseWorldPos.y, mouseWorldPos.z - 250.0); } light::LightEffects_SetDimmerMode((uint)bVar11); if ((globs::legoGlobs.flags1 & GAME1_LEVELENDING) != GAME1_NONE) { Lego_UpdateTopdownCamera(elapsedAbs); front::Pointer_SetCurrent_IfTimerFinished(Pointer_Standard); globs::legoGlobs.flags1 = globs::legoGlobs.flags1 & ~(GAME1_MULTISELECTING|GAME1_MOUSEBUSY); return; } PVar4 = front::Pointer_GetCurrentType(); if (((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) && (BVar10 = game::Message_AnyUnitSelected(), BVar10 != 0)) { pointerType = Pointer_Selected; } else { pointerType = Pointer_Standard; } front::Pointer_SetCurrent_IfTimerFinished(pointerType); if (((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) && (BVar10 = front::Panel_CheckCollision (elapsedAbs,globs::INPUT.msx,globs::INPUT.msy,globs::INPUT.mslb, globs::gamectrlGlobs.mslb_Last_0,&local_2c), BVar10 != 0)) { Lego_UpdateTopdownCamera(elapsedAbs); globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; goto LAB_00427c9c; } Lego_UpdateTopdownCamera(elapsedAbs); if ((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) { BVar10 = ai::Priorities_HandleInput (globs::INPUT.msx,globs::INPUT.msy,globs::INPUT.mslb, globs::gamectrlGlobs.mslb_Last_0,leftReleased); if (BVar10 != 0) { globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; goto LAB_00427c9c; } if ((((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) && ((globs::legoGlobs.flags2 & GAME2_INMENU) == GAME2_NONE)) && (BVar10 = front::Interface_DoSomethingWithRenameReplace (globs::INPUT.msx,globs::INPUT.msy,globs::INPUT.mslb, globs::gamectrlGlobs.mslb_Last_0,leftReleased), BVar10 != 0)) { globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; goto LAB_00427c9c; } if (((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) != GAME1_NONE) || (BVar10 = front::Info_Update_FUN_0041a0d0(globs::INPUT.msx,globs::INPUT.msy,leftReleased), BVar10 == 0)) goto LAB_0042682b; globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; if (leftReleased == 0) goto LAB_00427c9c; pointerSFXType = PointerSFX_Okay; LAB_00427c94: Lego_SetPointerSFX(pointerSFXType); goto LAB_00427c9c; } LAB_0042682b: if (globs::legoGlobs.viewMode == ViewMode_FP) { globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; goto LAB_00427c9c; } if ((((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) && ((globs::legoGlobs.flags1 & GAME1_RADARON) != GAME1_NONE)) && (BVar10 = game::RadarMap_InsideRadarScreen(level->radarMap,globs::INPUT.msx,globs::INPUT.msy), BVar10 != 0)) { if (leftReleased != 0) { Lego_SetPointerSFX(PointerSFX_Okay); } if ((globs::legoGlobs.flags1 & GAME1_RADAR_TRACKOBJECTVIEW) == GAME1_NONE) { front::Pointer_SetCurrent_IfTimerFinished(PVar4); } goto LAB_00427c9c; } if (local_2c != 0) { bVar11 = false; if ((globs::legoGlobs.NextButtonImage != NULL) && ((globs::legoGlobs.flags2 & GAME2_MESSAGE_HASNEXT) != GAME2_NONE)) { fVar16 = (float)globs::INPUT.msx; fVar8 = (float)(globs::legoGlobs.NextButtonImage)->height; if ((((ushort)((ushort)(fVar16 < globs::legoGlobs.NextButtonPos.x) << 8 | (ushort)(fVar16 == globs::legoGlobs.NextButtonPos.x) << 0xe) == 0) && (((fVar3 = (float)globs::INPUT.msy, (ushort)((ushort)(fVar3 < globs::legoGlobs.NextButtonPos.y) << 8 | (ushort)(fVar3 == globs::legoGlobs.NextButtonPos.y) << 0xe) == 0 && (local_24.y = 0.0, local_24.x = (float)(globs::legoGlobs.NextButtonImage)->width, fVar16 < (float)(ulonglong)(globs::legoGlobs.NextButtonImage)->width + globs::legoGlobs.NextButtonPos.x)) && (local_24.y = 0.0, local_24.x = fVar8, fVar3 < (float)(ulonglong)(uint)fVar8 + globs::legoGlobs.NextButtonPos.y)))) && (front::ToolTip_Activate(ToolTip_NextMessage), leftReleased != 0)) { nerps::NERPsRuntime_AdvanceMessage(); bVar11 = true; } } if ((globs::legoGlobs.RepeatButtonImage != NULL) && ((globs::legoGlobs.flags2 & GAME2_MESSAGE_HASREPEAT) != GAME2_NONE)) { fVar16 = (float)globs::INPUT.msx; fVar8 = (float)(globs::legoGlobs.RepeatButtonImage)->height; if ((((ushort)((ushort)(fVar16 < globs::legoGlobs.RepeatButtonPos.x) << 8 | (ushort)(fVar16 == globs::legoGlobs.RepeatButtonPos.x) << 0xe) == 0) && ((fVar3 = (float)globs::INPUT.msy, (ushort)((ushort)(fVar3 < globs::legoGlobs.RepeatButtonPos.y) << 8 | (ushort)(fVar3 == globs::legoGlobs.RepeatButtonPos.y) << 0xe) == 0 && (local_24.y = 0.0, local_24.x = (float)(globs::legoGlobs.RepeatButtonImage)->width, fVar16 < (float)(ulonglong)(globs::legoGlobs.RepeatButtonImage)->width + globs::legoGlobs.RepeatButtonPos.x)))) && (local_24.y = 0.0, local_24.x = fVar8, fVar3 < (float)(ulonglong)(uint)fVar8 + globs::legoGlobs.RepeatButtonPos.y)) { front::ToolTip_Activate(ToolTip_PreviousMessage); if (leftReleased == 0) goto LAB_00427c9c; nerps::NERPsRuntime_RepeatMessage(); bVar11 = true; } } if ((leftReleased == 0) || (bVar11)) goto LAB_00427c9c; pointerSFXType = PointerSFX_NotOkay; goto LAB_00427c94; } if (bVar11) goto LAB_00427c9c; globs::legoGlobs.mouseWorldPos.y = mouseWorldPos.y; globs::legoGlobs.mouseWorldPos.x = mouseWorldPos.x; globs::legoGlobs.mouseWorldPos.z = mouseWorldPos.z; globs::legoGlobs.flags2 |= GAME2_MOUSE_INSIDEGAMEVIEW; globs::legoGlobs.mouseBlockPos.x = mouseBlockX; globs::legoGlobs.mouseBlockPos.y = mouseBlockY; if (((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) || ((globs::legoGlobs.flags3 & (GAME3_ENCYCLOPEDIA|GAME3_PLACEBUILDING)) != GAME3_NONE)) { if ((globs::legoGlobs.flags3 & GAME3_PLACEBUILDING) == GAME3_NONE) { BVar10 = game::LegoObject_DoPickSphereSelection(globs::INPUT.msx,globs::INPUT.msy,&mouseObj); if (BVar10 == 0) { if ((globs::legoGlobs.flags1 & GAME1_LASERTRACKER) != GAME1_NONE) { if ((((uint)mouseBlockX < (globs::legoGlobs.currLevel)->width - 1) && ((uint)mouseBlockY < (globs::legoGlobs.currLevel)->height - 1)) && ((bflags1 = (globs::legoGlobs.currLevel)->blocks [mouseBlockY * (globs::legoGlobs.currLevel)->width + mouseBlockX].flags1, (bflags1 & BLOCK1_WALL) != BLOCK1_NONE && ((bflags1 & BLOCK1_FLOOR) == BLOCK1_NONE)))) { bVar11 = true; } else { bVar11 = false; } if (bVar11) { game::Level_SetPointer_FromSurfaceType((uint)*(byte *)((int)elapsedGame + 2)); } goto LAB_0042797a; } if (leftReleased != 0) { *(int *)((int)elapsedGame + 0x28) = *(int *)((int)elapsedGame + 0x28) + 1; } if (((globs::legoGlobs.flags3 & GAME3_PICKUPOBJECT) != GAME3_NONE) || ((globs::legoGlobs.flags3 & GAME3_LOADVEHICLE) != GAME3_NONE)) { if ((globs::legoGlobs.flags3 & GAME3_PICKUPOBJECT) == GAME3_NONE) { PVar4 = Pointer_VehicleCantPickUp; } else { PVar4 = Pointer_LegoManCantPickUp; } goto LAB_00427972; } if (((globs::legoGlobs.flags3 & GAME3_LEGOMANDIG) == GAME3_NONE) && ((globs::legoGlobs.flags3 & GAME3_VEHICLEDIG) == GAME3_NONE)) { if (((globs::legoGlobs.flags3 & GAME3_LEGOMANGOTO) == GAME3_NONE) && ((globs::legoGlobs.flags3 & GAME3_VEHICLEGOTO) == GAME3_NONE)) { if ((globs::legoGlobs.flags3 & GAME3_ENCYCLOPEDIA) == GAME3_NONE) { if (((uint)mouseBlockX < (globs::legoGlobs.currLevel)->width - 1) && ((uint)mouseBlockY < (globs::legoGlobs.currLevel)->height - 1)) { bflags1 = (globs::legoGlobs.currLevel)->blocks [mouseBlockY * (globs::legoGlobs.currLevel)->width + mouseBlockX].flags1 & BLOCK1_SURVEYED; } else { bflags1 = BLOCK1_NONE; } if (bflags1 != BLOCK1_NONE) { if (((((uint)mouseBlockX < (globs::legoGlobs.currLevel)->width - 1) && ((uint)mouseBlockY < (globs::legoGlobs.currLevel)->height - 1)) && (bflags1 = (globs::legoGlobs.currLevel)->blocks [mouseBlockY * (globs::legoGlobs.currLevel)->width + mouseBlockX]. flags1, (bflags1 & BLOCK1_WALL) != BLOCK1_NONE)) && ((bflags1 & BLOCK1_FLOOR) == BLOCK1_NONE)) { bVar11 = true; } else { bVar11 = false; } if ((bVar11) && (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::legoGlobs.mouseBlockPos.y + globs::legoGlobs.mouseBlockPos.x].terrain == Lego_SurfaceType8_Immovable || ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::legoGlobs.mouseBlockPos.y + globs::legoGlobs.mouseBlockPos.x].terrain == Lego_SurfaceType8_RechargeSeam))) ) { if ((*(byte *)((int)elapsedGame + 8) & 8) == 0) { game::Level_SetPointer_FromSurfaceType((uint)*(byte *)((int)elapsedGame + 2)); } if (globs::gamectrlGlobs.mslb_Last_6 == 0) { Lego_ShowBlockToolTip(&globs::legoGlobs.mouseBlockPos,TRUE,TRUE,FALSE); } if (leftReleased != 0) { Lego_SetPointerSFX(PointerSFX_NotOkay_ImmovableRock); } } else { fVar8 = 0.0; elapsedAbs = 0.0; if ((*(byte *)((int)elapsedGame + 8) & 8) == 0) { game::Level_SetPointer_FromSurfaceType((uint)*(byte *)((int)elapsedGame + 2)); } if (globs::gamectrlGlobs.mslb_Last_6 == 0) { Lego_ShowBlockToolTip(&globs::legoGlobs.mouseBlockPos,TRUE,TRUE,FALSE); } BVar10 = game::Message_AnyUnitSelected(); if (BVar10 != 0) { if ((globs::legoGlobs.flags1 & GAME1_VERTEXMODE) == GAME1_NONE) { if (((*(byte *)((int)elapsedGame + 8) & 8) == 0) && (BVar10 = game::Level_FindSelectedUnit_BlockCheck_FUN_00431960 (mouseBlockX,mouseBlockY,0), BVar10 != 0)) { pLVar6 = game::Message_GetPrimarySelectedUnit(); if (pLVar6->type == LegoObject_MiniFigure) { PVar4 = Pointer_LegoManCantDig; } else { PVar4 = Pointer_VehicleCantDig; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); front::Text_DisplayMessage(Text_NoDrill,0,0); cVar1 = *(char *)((int)elapsedGame + 2); if ((((cVar1 != '\x01') && (cVar1 != '\t')) && (cVar1 != '\v')) && ((*(byte *)((int)elapsedGame + 8) & 0x40) == 0)) { // = 1; fVar8 = 1.401298e-45; elapsedAbs = 1.401298e-45; pLVar6 = game::Message_GetPrimarySelectedUnit(); if (pLVar6->type == LegoObject_MiniFigure) { PVar4 = Pointer_LegoManDig; } else { PVar4 = Pointer_VehicleDig; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); front::Text_DisplayMessage(Text_Drill,FALSE,FALSE); if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck (&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { ai::AITask_DoDig_AtBlockPos(&globs::legoGlobs.mouseBlockPos,0,TRUE); ai::AITask_FUN_00401f40 (AITask_Type_Dig,NULL,&globs::legoGlobs.mouseBlockPos); goto LAB_004271d4; } } } } else { if ((*(char *)elapsedGame == '\x01') || (BVar10 = game::Level_FindSelectedUnit_BlockCheck_FUN_00431960 (mouseBlockX,mouseBlockY,1), BVar10 == 0)) { globs::legoGlobs.digVertexShowPointer = 0; } else { globs::legoGlobs.digVertexBlockPos.y = mouseBlockY; // = 1 fVar8 = 1.401298e-45; globs::legoGlobs.digVertexBlockPos.x = mouseBlockX; elapsedAbs = 1.401298e-45; globs::legoGlobs.digVertexShowPointer = 1; if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck(&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { ai::AITask_DoDig_AtBlockPos(&globs::legoGlobs.mouseBlockPos,1,1); LAB_004271d4: elapsedAbs = 1.401298e-45; fVar8 = 1.401298e-45; Lego_SetPointerSFX(PointerSFX_Okay); front::Interface_BackToMain(); } } } if ((fVar8 == 0.0) && ((*(uint *)((int)elapsedGame + 8) & 8) != 0)) { // !(block[...].flags2 & BLOCK2_TOOLSTORE) if ((((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * mouseBlockY + mouseBlockX].flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * mouseBlockY + mouseBlockX].flags2 & 4) == 0)) { bVar11 = false; } else { bVar11 = true; } if ((!bVar11) && ((*(byte *)((int)elapsedGame + 0xc) & 0x20) == 0)) { if ((*(uint *)((int)elapsedGame + 8) & 0x200000) == 0) { pLVar6 = game::Message_GetPrimarySelectedUnit(); sflags1 = stats::StatsObject_GetStatsFlags1(pLVar6); if ((sflags1 & STATS1_CANCLEARRUBBLE) != STATS1_NONE) { BVar10 = FALSE; uVar12 = mouseBlockX; uVar13 = mouseBlockY; uVar14 = mouseBlockX; uVar15 = mouseBlockY; pLVar6 = game::Message_GetPrimarySelectedUnit(); iVar7 = game::Lego_GetCrossTerrainType (pLVar6,uVar12,uVar13,uVar14,uVar15,BVar10); if (iVar7 != 0) { // = 1 fVar8 = 1.401298e-45; elapsedAbs = 1.401298e-45; pLVar6 = game::Message_GetPrimarySelectedUnit(); if (pLVar6->type == LegoObject_MiniFigure) { PVar4 = Pointer_LegoManClear; } else { PVar4 = Pointer_VehicleClear; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck (&globs::legoGlobs.mouseBlockPos), BVar10 == 0) ) { game::Message_PostEvent (Message_UserGoto,0,0,&globs::legoGlobs.mouseBlockPos); ai::AITask_FUN_00401f40 (AITask_Type_Clear,NULL,&globs::legoGlobs.mouseBlockPos); Lego_SetPointerSFX(PointerSFX_Okay); front::Interface_BackToMain(); } } } } if (fVar8 != 0.0) goto LAB_0042797a; uVar12 = mouseBlockX; uVar13 = mouseBlockY; uVar14 = mouseBlockX; uVar15 = mouseBlockY; fVar16 = fVar8; pLVar6 = game::Message_GetPrimarySelectedUnit(); iVar7 = game::Lego_GetCrossTerrainType (pLVar6,uVar12,uVar13,uVar14,uVar15,(BOOL)fVar16); if (iVar7 != 0) { // = 1 fVar8 = 1.401298e-45; elapsedAbs = 1.401298e-45; pLVar6 = game::Message_GetPrimarySelectedUnit(); if (pLVar6->type == LegoObject_MiniFigure) { PVar4 = Pointer_LegoManGo; } else { PVar4 = Pointer_VehicleGo; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); front::Text_DisplayMessage(Text_Walk,FALSE,FALSE); if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck (&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { game::Message_PostEvent (Message_UserGoto,0,0,&globs::legoGlobs.mouseBlockPos); Lego_SetPointerSFX(PointerSFX_Okay); front::Interface_BackToMain(); } } } } } if (fVar8 == 0.0) { // !(block[...].flags2 & BLOCK2_TOOLSTORE) if ((((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * mouseBlockY + mouseBlockX].flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * mouseBlockY + mouseBlockX] .flags2 & 4) == 0)) { bVar11 = false; } else { bVar11 = true; } if ((((!bVar11) && (cVar1 = *(char *)((int)elapsedGame + 2), cVar1 != '\x06')) && (cVar1 != '\t')) && ((*(byte *)((int)elapsedGame + 0xc) & 0x20) == 0)) { if ((*(uint *)((int)elapsedGame + 8) & 8) != 0) { if (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::legoGlobs.mouseBlockPos.y + globs::legoGlobs.mouseBlockPos.x].flags1 & BLOCK1_ERODEACTIVE) != BLOCK1_NONE) { // = 1 fVar8 = 1.401298e-45; elapsedAbs = 1.401298e-45; if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck (&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { game::Message_PostEvent(Message_ClearSelection,0,0,NULL); Lego_SetPointerSFX(PointerSFX_Okay_Floor); front::Interface_OpenMenu (Interface_Menu_Erode,&globs::legoGlobs.mouseBlockPos); } } if (((fVar8 == 0.0) && ((*(uint *)((int)elapsedGame + 8) & 0x8000) != 0)) && (elapsedAbs = 1.401298e-45, leftReleased != 0)) { Lego_SetPointerSFX(PointerSFX_NotOkay); } if ((((*(uint *)((int)elapsedGame + 8) & 0x100000) != 0) || (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::legoGlobs.mouseBlockPos.y + globs::legoGlobs.mouseBlockPos.x]. flags1 & BLOCK1_LAYEDPATH) != BLOCK1_NONE)) && (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::legoGlobs.mouseBlockPos.y + globs::legoGlobs.mouseBlockPos.x].flags1 & BLOCK1_BUILDINGPATH) == BLOCK1_NONE)) { if (((globs::legoGlobs.mouseBlockPos.x < 0) || (globs::legoGlobs.mouseBlockPos.y < 0)) || (((int)(globs::legoGlobs.currLevel)->width <= globs::legoGlobs.mouseBlockPos.x || ((int)(globs::legoGlobs.currLevel)->height <= globs::legoGlobs.mouseBlockPos.y)))) { bflags1 = BLOCK1_NONE; } else { bflags1 = (globs::legoGlobs.currLevel)->blocks [globs::legoGlobs.mouseBlockPos.y * (globs::legoGlobs.currLevel)->width + globs::legoGlobs.mouseBlockPos.x].flags1 & BLOCK1_PATH; } if (((bflags1 == BLOCK1_NONE) && (elapsedAbs = 1.401298e-45, leftReleased != 0)) && (BVar10 = game::Level_BlockPointerCheck (&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { Lego_SetPointerSFX(PointerSFX_Okay_Floor); front::Interface_OpenMenu (Interface_Menu_Construction,&globs::legoGlobs.mouseBlockPos); } } if (elapsedAbs != 0.0) goto LAB_0042797a; if (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * globs::legoGlobs.mouseBlockPos.y + globs::legoGlobs.mouseBlockPos.x].flags1 & BLOCK1_LAYEDPATH) == BLOCK1_NONE) { if (((globs::legoGlobs.mouseBlockPos.x < 0) || (globs::legoGlobs.mouseBlockPos.y < 0)) || (((int)(globs::legoGlobs.currLevel)->width <= globs::legoGlobs.mouseBlockPos.x || ((int)(globs::legoGlobs.currLevel)->height <= globs::legoGlobs.mouseBlockPos.y)))) { bflags1 = BLOCK1_NONE; } else { bflags1 = (globs::legoGlobs.currLevel)->blocks [globs::legoGlobs.mouseBlockPos.y * (globs::legoGlobs.currLevel)->width + globs::legoGlobs.mouseBlockPos.x].flags1 & BLOCK1_PATH; } fVar8 = elapsedAbs; if (bflags1 != BLOCK1_NONE) goto LAB_004275d9; } else { LAB_004275d9: fVar8 = 1.401298e-45; if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck (&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { game::Message_PostEvent(Message_ClearSelection,0,0,NULL); Lego_SetPointerSFX(PointerSFX_Okay_Floor); front::Interface_OpenMenu (Interface_Menu_Ground,&globs::legoGlobs.mouseBlockPos); } } if (fVar8 == 0.0) { if ((((*(uint *)((int)elapsedGame + 8) & 0x200000) != 0) && (fVar8 = 1.401298e-45, leftReleased != 0)) && (BVar10 = game::Level_BlockPointerCheck (&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { game::Message_PostEvent(Message_ClearSelection,0,0,NULL); Lego_SetPointerSFX(PointerSFX_Okay_Floor); front::Interface_OpenMenu (Interface_Menu_Ground,&globs::legoGlobs.mouseBlockPos); } if (fVar8 == 0.0) { if ((((*(uint *)((int)elapsedGame + 8) & 0x200000) != 0) || (fVar8 = 1.401298e-45, leftReleased == 0)) || (BVar10 = game::Level_BlockPointerCheck (&globs::legoGlobs.mouseBlockPos), BVar10 != 0)) goto LAB_00427713; game::Message_PostEvent(Message_ClearSelection,0,0,NULL); Lego_SetPointerSFX(PointerSFX_Okay_Floor); menuType = Interface_Menu_Rubble; goto LAB_0042770b; } } goto LAB_0042797a; } if (((cVar1 == '\x01') || ((*(uint *)((int)elapsedGame + 8) & 0x40) != 0)) || ((fVar8 = 1.401298e-45, leftReleased == 0 || (BVar10 = game::Level_BlockPointerCheck(&globs::legoGlobs.mouseBlockPos), BVar10 != 0)))) goto LAB_00427713; game::Message_PostEvent(Message_ClearSelection,0,0,NULL); Lego_SetPointerSFX(PointerSFX_Okay_Wall); menuType = Interface_Menu_Wall; LAB_0042770b: fVar8 = 1.401298e-45; front::Interface_OpenMenu(menuType,&globs::legoGlobs.mouseBlockPos); } LAB_00427713: if (fVar8 == 0.0) goto LAB_0042771b; } } goto LAB_0042797a; } } else { globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; front::Pointer_SetCurrent_IfTimerFinished(Pointer_CantHelp); front::Text_DisplayMessage(Text_Encyclopedia,FALSE,FALSE); } LAB_0042771b: if (leftReleased != 0) { LAB_00427727: Lego_SetPointerSFX(PointerSFX_NotOkay); } } else { if ((globs::legoGlobs.flags3 & GAME3_LEGOMANGOTO) == GAME3_NONE) { PVar4 = Pointer_VehicleCantGo; } else { PVar4 = Pointer_LegoManCantGo; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); if (((*(byte *)((int)elapsedGame + 8) & 8) != 0) && (BVar10 = game::Message_AnyUnitSelected(), BVar10 != 0)) { BVar10 = FALSE; uVar12 = mouseBlockX; uVar13 = mouseBlockY; uVar14 = mouseBlockX; uVar15 = mouseBlockY; pLVar6 = game::Message_GetPrimarySelectedUnit(); iVar7 = game::Lego_GetCrossTerrainType(pLVar6,uVar12,uVar13,uVar14,uVar15,BVar10); if (iVar7 != 0) { if ((globs::legoGlobs.flags3 & GAME3_LEGOMANGOTO) == GAME3_NONE) { PVar4 = Pointer_VehicleGo; } else { PVar4 = Pointer_LegoManGo; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); front::Text_DisplayMessage(Text_Walk,0,0); if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck(&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { game::Message_PostEvent(Message_UserGoto,0,0,&globs::legoGlobs.mouseBlockPos); Lego_SetPointerSFX(PointerSFX_Okay); front::Interface_BackToMain(); } } } } } else { if ((globs::legoGlobs.flags3 & GAME3_LEGOMANDIG) == GAME3_NONE) { PVar4 = Pointer_VehicleCantDig; } else { PVar4 = Pointer_LegoManCantDig; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); front::Text_DisplayMessage(Text_NoDrill,0,0); if ((globs::legoGlobs.flags1 & GAME1_VERTEXMODE) == GAME1_NONE) { if ((((((*(uint *)((int)elapsedGame + 8) & 8) == 0) && (cVar1 = *(char *)((int)elapsedGame + 2), cVar1 != '\x01')) && (cVar1 != '\t')) && ((cVar1 != '\v' && ((*(uint *)((int)elapsedGame + 8) & 0x40) == 0)))) && ((BVar10 = game::Message_AnyUnitSelected(), BVar10 == 0 || (BVar10 = game::Level_FindSelectedUnit_BlockCheck_FUN_00431960 (mouseBlockX,mouseBlockY,FALSE), BVar10 != 0)))) { if ((globs::legoGlobs.flags3 & GAME3_LEGOMANDIG) == GAME3_NONE) { PVar4 = Pointer_VehicleDig; } else { PVar4 = Pointer_LegoManDig; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); front::Text_DisplayMessage(Text_Drill,0,0); if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck(&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { ai::AITask_DoDig_AtBlockPos(&globs::legoGlobs.mouseBlockPos,0,TRUE); goto LAB_00427954; } } } else { if ((*(char *)elapsedGame == '\x01') || ((BVar10 = game::Message_AnyUnitSelected(), BVar10 != 0 && (BVar10 = game::Level_FindSelectedUnit_BlockCheck_FUN_00431960 (mouseBlockX,mouseBlockY,TRUE), BVar10 == 0)))) { globs::legoGlobs.digVertexShowPointer = FALSE; } else { globs::legoGlobs.digVertexBlockPos.y = mouseBlockY; globs::legoGlobs.digVertexBlockPos.x = mouseBlockX; globs::legoGlobs.digVertexShowPointer = TRUE; if ((leftReleased != 0) && (BVar10 = game::Level_BlockPointerCheck(&globs::legoGlobs.mouseBlockPos), BVar10 == 0)) { ai::AITask_DoDig_AtBlockPos(&globs::legoGlobs.mouseBlockPos,TRUE,TRUE); Lego_SetPointerSFX(PointerSFX_Okay); front::Interface_BackToMain(); } } } } } else { if ((mouseObj->type == LegoObject_MiniFigure) && (mouseObj->driveObject != NULL)) { mouseObj = mouseObj->driveObject; } if (mouseObj->carryingThisObject != NULL) { mouseObj = mouseObj->carryingThisObject; } if (((mouseObj->type == LegoObject_Vehicle) && (BVar10 = game::Message_AnyUnitSelected(), BVar10 != 0)) && (pLVar5 = game::Message_GetPrimarySelectedUnit(), pLVar6 = mouseObj, pLVar5->type == LegoObject_MiniFigure)) { pLVar5 = game::Message_GetPrimarySelectedUnit(); LVar9 = ABILITY_FLAG_SAILOR; sflags3 = stats::StatsObject_GetStatsFlags3(pLVar6); if ((sflags3 & STATS3_NEEDSPILOT) == STATS3_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(pLVar6); if ((sflags1 & STATS1_CROSSLAND) != STATS1_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(pLVar6); LVar9 = (-(uint)((sflags1 & STATS1_CROSSWATER) != STATS1_NONE) & 0xfffffffd) + ABILITY_FLAG_DRIVER; } } else { LVar9 = ABILITY_FLAG_PILOT; } if ((pLVar5->abilityFlags & LVar9) != ABILITY_FLAG_NONE) { if (leftReleased == 0) { PVar4 = Pointer_GetIn; goto LAB_00427972; } ai::AITask_DoFindDriver_Target(pLVar6); Lego_SetPointerSFX(PointerSFX_Okay); front::Interface_BackToMain(); } } else { if (((globs::legoGlobs.flags3 & GAME3_LEGOMANDIG) == GAME3_NONE) && ((globs::legoGlobs.flags3 & GAME3_VEHICLEDIG) == GAME3_NONE)) { if (((globs::legoGlobs.flags3 & GAME3_PICKUPOBJECT) == GAME3_NONE) && ((globs::legoGlobs.flags3 & GAME3_LOADVEHICLE) == GAME3_NONE)) { if (((globs::legoGlobs.flags3 & GAME3_LEGOMANGOTO) != GAME3_NONE) || ((globs::legoGlobs.flags3 & GAME3_VEHICLEGOTO) != GAME3_NONE)) { if ((globs::legoGlobs.flags3 & GAME3_LEGOMANGOTO) == GAME3_NONE) { PVar4 = Pointer_VehicleCantGo; } else { PVar4 = Pointer_LegoManCantGo; } goto LAB_00427972; } if ((globs::legoGlobs.flags3 & GAME3_ENCYCLOPEDIA) == GAME3_NONE) { BVar10 = game::LegoObject_IsActive(mouseObj,TRUE); if (BVar10 != 0) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_Selected); if (globs::gamectrlGlobs.mslb_Last_6 == 0) { Lego_ShowObjectToolTip(mouseObj); } if (leftReleased == 0) { pLVar6 = game::Message_GetPrimarySelectedUnit(); if ((pLVar6 != NULL) && ((mouseObj->type == LegoObject_PowerCrystal || (mouseObj->type == LegoObject_Ore)))) { game::LegoObject_GetBlockPos(mouseObj,(int *)&local_24,(int *)&local_24.y); iVar7 = game::Lego_GetCrossTerrainType (pLVar6,(int)local_24.x,(int)local_24.y,(int)local_24.x, (int)local_24.y,FALSE); if (iVar7 != 0) { if (mouseObj->type == LegoObject_Ore) { PVar4 = Pointer_PickUpOre; } else { if (pLVar6->type == LegoObject_MiniFigure) { PVar4 = Pointer_LegoManPickUp; } else { if (pLVar6->type != LegoObject_Vehicle) goto LAB_0042797a; PVar4 = Pointer_VehiclePickUp; } } LAB_00427972: front::Pointer_SetCurrent_IfTimerFinished(PVar4); } } } else { tutFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (((tutFlags & TUTORIAL_FLAG_NOOBJECTS) != TUTORIAL_NONE) || ((tutFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL), tutFlags != TUTORIAL_NONE && (mouseObj->bool_3f8 == 0)))) goto LAB_00427727; BVar10 = front::Interface_GetObjectBool_FUN_0041e8c0 (mouseObj->type,mouseObj->id); if (((BVar10 != 0) && (((mouseObj->flags2 & LIVEOBJ2_THROWN) == LIVEOBJ2_NONE && ((LVar2 = mouseObj->type, LVar2 != LegoObject_Vehicle || ((mouseObj->flags1 & LIVEOBJ1_CLEARING) == LIVEOBJ1_NONE)))))) && (((globs::legoGlobs.flags1 & GAME1_LASERTRACKER) == GAME1_NONE || ((*(byte *)&mouseObj->flags4 & 1) != 0)))) { if ((((LVar2 == LegoObject_Vehicle) || (LVar2 == LegoObject_Building)) || (LVar2 == LegoObject_MiniFigure)) || ((LVar2 == LegoObject_ElectricFence && ((mouseObj->flags2 & LIVEOBJ2_ACTIVEELECTRICFENCE) != LIVEOBJ2_NONE)))) { Lego_SetPointerSFX(PointerSFX_Okay); if (((keyDownAddSelection == 0) && (game::Message_PostEvent(Message_ClearSelection,0,0,NULL), true)) || (BVar10 = game::Message_IsUnitSelected(mouseObj,NULL), BVar10 == 0)) { game::Message_PostEvent(Message_Select,mouseObj,0,NULL); game::Message_PostEvent(Message_ReduceSelection,0,0,NULL); } } else { if ((LVar2 == LegoObject_PowerCrystal) || (LVar2 == LegoObject_Ore)) { pLVar6 = game::Message_GetPrimarySelectedUnit(); if (pLVar6 != NULL) { game::LegoObject_GetBlockPos (mouseObj,(int *)&local_24,(int *)&local_24.y); iVar7 = game::Lego_GetCrossTerrainType (pLVar6,(int)local_24.x,(int)local_24.y, (int)local_24.x,(int)local_24.y,FALSE); if (iVar7 != 0) { opt_blockPos = &local_24; goto LAB_00426def; } } } else { Lego_SetPointerSFX(PointerSFX_NotOkay); } } } } } } else { globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; front::Pointer_SetCurrent_IfTimerFinished(Pointer_Help); front::Text_DisplayMessage(Text_Encyclopedia,FALSE,FALSE); if (leftReleased != 0) { Lego_SetPointerSFX(PointerSFX_Okay); front::Encyclopedia_SelectObject(mouseObj); } } } else { if ((globs::legoGlobs.flags3 & GAME3_PICKUPOBJECT) == GAME3_NONE) { PVar4 = Pointer_VehicleCantPickUp; } else { PVar4 = Pointer_LegoManCantPickUp; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); LVar2 = mouseObj->type; if ((((LVar2 == LegoObject_Ore) || (LVar2 == LegoObject_PowerCrystal)) || ((LVar2 == LegoObject_ElectricFence && ((mouseObj->flags2 & LIVEOBJ2_ACTIVEELECTRICFENCE) == LIVEOBJ2_NONE)))) || ((LVar2 == LegoObject_Dynamite && ((mouseObj->flags3 & LIVEOBJ3_UNK_10000) == LIVEOBJ3_NONE)))) { BVar10 = FALSE; uVar12 = mouseBlockX; uVar13 = mouseBlockY; uVar14 = mouseBlockX; uVar15 = mouseBlockY; pLVar6 = game::Message_GetPrimarySelectedUnit(); iVar7 = game::Lego_GetCrossTerrainType(pLVar6,uVar12,uVar13,uVar14,uVar15,BVar10); if (iVar7 != 0) { if (mouseObj->type == LegoObject_Ore) { PVar4 = Pointer_PickUpOre; } else { if ((globs::legoGlobs.flags3 & GAME3_PICKUPOBJECT) == GAME3_NONE) { PVar4 = Pointer_VehiclePickUp; } else { PVar4 = Pointer_LegoManPickUp; } } front::Pointer_SetCurrent_IfTimerFinished(PVar4); if (leftReleased != 0) { opt_blockPos = (Point2F *)&globs::legoGlobs.mouseBlockPos; LAB_00426def: game::Message_PostEvent(Message_UserGoto,0,0,(Point2I *)opt_blockPos); ai::AITask_LiveObject_FUN_004025f0(mouseObj); ai::AITask_FUN_00401f40(AITask_Type_Collect,mouseObj,NULL); LAB_00427954: Lego_SetPointerSFX(PointerSFX_Okay); front::Interface_BackToMain(); } } } } } else { if ((globs::legoGlobs.flags3 & GAME3_LEGOMANDIG) == GAME3_NONE) { PVar4 = Pointer_VehicleCantDig; } else { PVar4 = Pointer_LegoManCantDig; } front::Pointer_SetCurrent_IfTimerFinished(PVar4); front::Text_DisplayMessage(Text_NoDrill,FALSE,FALSE); } } } } else { local_1c.x = mouseWorldPos.x; local_1c.y = mouseWorldPos.y; local_28 = 1; BVar10 = game::LegoObject_UpdateBuildingPlacement (globs::legoGlobs.placeObjType,globs::legoGlobs.placeObjID,leftReleased, FALSE,&local_1c,mouseBlockX,mouseBlockY,TRUE,globs::legoGlobs.selectPlace) ; if (BVar10 == 0) { globs::legoGlobs.flags3 &= ~GAME3_PLACEBUILDING; } if (leftReleased != 0) { *(int *)((int)elapsedGame + 0x28) = *(int *)((int)elapsedGame + 0x28) + 1; } } } LAB_0042797a: if ((((globs::legoGlobs.flags3 & GAME3_PLACEBUILDING) == GAME3_NONE) && ((globs::legoGlobs.flags1 & GAME1_LASERTRACKER) == GAME1_NONE)) && (tutFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL), (tutFlags & TUTORIAL_FLAG_NOMULTISELECT) == TUTORIAL_NONE)) { if (globs::INPUT.mslb == 0) { if ((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) { globs::legoGlobs.vectorDragStartUnk_a4.x = mouseWorldPos.x; globs::legoGlobs.vectorDragStartUnk_a4.y = mouseWorldPos.y; globs::legoGlobs.vectorDragStartUnk_a4.z = mouseWorldPos.z; } else { local_24.x = (float)globs::INPUT.msx; local_24.y = (float)globs::INPUT.msy; tutFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((tutFlags & TUTORIAL_FLAG_NOOBJECTS) == TUTORIAL_NONE) { if (keyDownAddSelection == 0) { game::Message_PostEvent(Message_ClearSelection,0,0,NULL); } lego::view::Viewport_WorldToScreen (globs::legoGlobs.viewMain,&local_14,&globs::legoGlobs.vectorDragStartUnk_a4); game::LegoObject_DoDragSelection(globs::legoGlobs.viewMain,&local_14,&local_24); Lego_SetPointerSFX(PointerSFX_Okay); } } globs::legoGlobs.float_b0 = (float)(ulonglong)(uint)mouseBlockX; local_24.x = (float)mouseBlockY; local_24.y = 0.0; globs::legoGlobs.float_b4 = (float)(ulonglong)(uint)mouseBlockY; } if (((globs::gamectrlGlobs.mslb_Last_6 != 0) && ((globs::legoGlobs.flags2 & GAME2_NOMULTISELECT) == GAME2_NONE)) && ((globs::legoGlobs.flags1 & GAME1_MOUSEBUSY) == GAME1_NONE)) { if (((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) == GAME1_NONE) && (fVar8 = SQRT(globs::gamectrlGlobs.pointf_8.y * globs::gamectrlGlobs.pointf_8.y + globs::gamectrlGlobs.pointf_8.x * globs::gamectrlGlobs.pointf_8.x), (ushort)((ushort)(fVar8 < 10.0) << 8 | (ushort)(fVar8 == 10.0) << 0xe) == 0)) { globs::legoGlobs.flags1 |= GAME1_MULTISELECTING; } globs::legoGlobs.float_b8 = (float)(ulonglong)(uint)mouseBlockX; local_24.x = (float)mouseBlockY; local_24.y = 0.0; globs::legoGlobs.float_bc = (float)(ulonglong)(uint)mouseBlockY; } } if ((globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != GAME2_NONE) { Lego_HandleWorldDebugKeys (mouseBlockX,mouseBlockY,mouseObj, globs::gamectrlGlobs.handleWorldNoMouseButtonsElapsed); } LAB_00427c9c: if (((local_28 == 0) && ((globs::legoGlobs.flags3 & GAME3_PLACEBUILDING) != GAME3_NONE)) && (BVar10 = game::LegoObject_UpdateBuildingPlacement (globs::legoGlobs.placeObjType,globs::legoGlobs.placeObjID,leftReleased, rightReleased,NULL,mouseBlockX,mouseBlockY,FALSE, globs::legoGlobs.selectPlace), BVar10 == 0)) { globs::legoGlobs.flags3 &= ~GAME3_PLACEBUILDING; } if (globs::gamectrlGlobs.mslb_Last_6 == 0) { globs::legoGlobs.flags1 &= ~(GAME1_MULTISELECTING|GAME1_MOUSEBUSY); } globs::gamectrlGlobs.mslb_Last_0 = globs::INPUT.mslb; globs::gamectrlGlobs.mslr_Last_0 = globs::INPUT.msrb; return; } void __cdecl lego::lrr::Lego_LoadToolTipInfos(Config *config,char *gameName_unused) { char *pcVar1; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","HealthText",0); globs::legoGlobs.langHealth_toolTip = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","EnergyText",0); globs::legoGlobs.langEnergy_toolTip = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","CrystalsText",0); globs::legoGlobs.langCrystals_toolTip = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","OreText",0); globs::legoGlobs.langOre_toolTip = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","StudsText",0); globs::legoGlobs.langStuds_toolTip = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","ToolsText",0); globs::legoGlobs.langTools_toolTip = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","CarryObjectText",0); globs::legoGlobs.langCarryObject_toolTip = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","DrivenByText",0); globs::legoGlobs.langDrivenBy_toolTip = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipInfo","OreRequiredText",0); globs::legoGlobs.langOreRequired_toolTip = cfg::Config_GetStringValue(config,pcVar1); return; } void __cdecl lego::lrr::Lego_LoadUpgradeNames(Config *config) { char cVar1; char *pcVar2; Config *prop; int iVar3; uint uVar4; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"UpgradeNames",0); prop = cfg::Config_FindArray(config,pcVar2); do { if (prop == NULL) { return; } uVar4 = 0xffffffff; pcVar2 = "Level"; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); iVar3 = std::_strnicmp("Level",prop->key,~uVar4 - 1); if (iVar3 == 0) { uVar4 = 0xffffffff; pcVar2 = "Level"; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); uVar4 = std::atoi(prop->key + (~uVar4 - 1)); if (uVar4 < 0x10) { pcVar2 = util::Util_StrCpy(prop->value); globs::legoGlobs.langUpgradeLevel_name[uVar4] = pcVar2; } } prop = cfg::Config_GetNextItem(prop); } while( true ); } void __cdecl lego::lrr::Lego_ShowObjectToolTip(LegoObject *liveObj) { char cVar1; LegoObject_Type LVar2; Image *opt_image; char *pcVar3; BOOL BVar4; undefined4 uVar5; SFX_ID sfxType; int iVar6; uint uVar7; uint uVar8; undefined4 *puVar9; Image **ppIVar10; byte bVar11; char *pcVar12; char *pcVar13; undefined4 *puVar14; LegoObject_ToolType *pLVar15; longlong lVar16; char buff2 [128]; char buff1 [256]; pcVar3 = game::LegoObject_GetLangName(liveObj); if (pcVar3 != NULL) { pcVar3 = game::LegoObject_GetLangName(liveObj); iVar6 = -1; do { if (iVar6 == 0) break; iVar6 += -1; cVar1 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar1 != '\0'); if (iVar6 != -2) { if (globs::gamectrlGlobs.toolTipObject != liveObj) { globs::gamectrlGlobs.toolTipObject = liveObj; return; } if ((liveObj->customName != NULL) && (*liveObj->customName == '\0')) { game::LegoObject_SetCustomName(liveObj,NULL); } pcVar3 = liveObj->customName; if (pcVar3 == NULL) { pcVar3 = game::LegoObject_GetLangName(liveObj); } uVar7 = 0xffffffff; do { pcVar12 = pcVar3; if (uVar7 == 0) break; uVar7 -= 1; pcVar12 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar12; } while (cVar1 != '\0'); uVar7 = ~uVar7; puVar9 = (undefined4 *)(pcVar12 + -uVar7); puVar14 = (undefined4 *)buff1; for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar14 = *puVar9; puVar9 = puVar9 + 1; puVar14 = puVar14 + 1; } LVar2 = liveObj->type; for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar14 = *(undefined *)puVar9; puVar9 = (undefined4 *)((int)puVar9 + 1); puVar14 = (undefined4 *)((int)puVar14 + 1); } if ((LVar2 == LegoObject_Building) && (globs::legoGlobs.langUpgradeLevel_name[liveObj->objLevel] != NULL)) { std::sprintf(buff2," (%s)",globs::legoGlobs.langUpgradeLevel_name[liveObj->objLevel]); uVar7 = 0xffffffff; pcVar3 = buff2; do { pcVar12 = pcVar3; if (uVar7 == 0) break; uVar7 -= 1; pcVar12 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar12; } while (cVar1 != '\0'); uVar7 = ~uVar7; iVar6 = -1; pcVar3 = buff1; do { pcVar13 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar13 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar13; } while (cVar1 != '\0'); puVar9 = (undefined4 *)(pcVar12 + -uVar7); puVar14 = (undefined4 *)(pcVar13 + -1); for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar14 = *puVar9; puVar9 = puVar9 + 1; puVar14 = puVar14 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar14 = *(undefined *)puVar9; puVar9 = (undefined4 *)((int)puVar9 + 1); puVar14 = (undefined4 *)((int)puVar14 + 1); } } if (((((liveObj->flags3 & LIVEOBJ3_CANDAMAGE) != LIVEOBJ3_NONE) && (BVar4 = front::DamageFont_LiveObject_CheckCanShowDamage_Unk(liveObj), BVar4 != 0)) && (liveObj->type != LegoObject_MiniFigure)) && (liveObj->type != LegoObject_RockMonster)) { if (0.0 <= liveObj->health) { lVar16 = __ftol((float10)liveObj->health); uVar5 = (undefined4)lVar16; } else { uVar5 = 0; } std::sprintf(buff2,"\n%s: %i",globs::legoGlobs.langEnergy_toolTip,uVar5); uVar7 = 0xffffffff; pcVar3 = buff2; do { pcVar12 = pcVar3; if (uVar7 == 0) break; uVar7 -= 1; pcVar12 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar12; } while (cVar1 != '\0'); uVar7 = ~uVar7; iVar6 = -1; pcVar3 = buff1; do { pcVar13 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar13 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar13; } while (cVar1 != '\0'); puVar9 = (undefined4 *)(pcVar12 + -uVar7); puVar14 = (undefined4 *)(pcVar13 + -1); for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar14 = *puVar9; puVar9 = puVar9 + 1; puVar14 = puVar14 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar14 = *(undefined *)puVar9; puVar9 = (undefined4 *)((int)puVar9 + 1); puVar14 = (undefined4 *)((int)puVar14 + 1); } } if (((liveObj->type == LegoObject_Vehicle) && (liveObj->driveObject != NULL)) && ((pcVar3 = liveObj->driveObject->customName, pcVar3 != NULL && ((*pcVar3 != '\0' && (globs::legoGlobs.langDrivenBy_toolTip != NULL)))))) { std::sprintf(buff2,"\n%s: %s",globs::legoGlobs.langDrivenBy_toolTip,pcVar3); uVar7 = 0xffffffff; pcVar3 = buff2; do { pcVar12 = pcVar3; if (uVar7 == 0) break; uVar7 -= 1; pcVar12 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar12; } while (cVar1 != '\0'); uVar7 = ~uVar7; iVar6 = -1; pcVar3 = buff1; do { pcVar13 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar13 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar13; } while (cVar1 != '\0'); puVar9 = (undefined4 *)(pcVar12 + -uVar7); puVar14 = (undefined4 *)(pcVar13 + -1); for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar14 = *puVar9; puVar9 = puVar9 + 1; puVar14 = puVar14 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar14 = *(undefined *)puVar9; puVar9 = (undefined4 *)((int)puVar9 + 1); puVar14 = (undefined4 *)((int)puVar14 + 1); } } front::ToolTip_SetContent(ToolTip_UnitSelect,buff1); sfxType = game::LegoObject_GetObjTtSFX(liveObj); front::ToolTip_SetSFX(ToolTip_UnitSelect,sfxType); if (liveObj->type == LegoObject_MiniFigure) { uVar7 = 0; if (liveObj->numCarriedTools != 0) { pLVar15 = liveObj->carriedTools; do { if (globs::objectGlobs.ToolTipIcons_Tools[*pLVar15] != NULL) { front::ToolTip_AddIcon (ToolTip_UnitSelect,globs::objectGlobs.ToolTipIcons_Tools[*pLVar15]); } uVar7 += 1; pLVar15 = pLVar15 + 1; } while (uVar7 < liveObj->numCarriedTools); } uVar8 = stats::StatsObject_GetNumOfToolsCanCarry(liveObj); if (uVar7 < uVar8) { do { if (globs::objectGlobs.ToolTipIcon_Blank != NULL) { front::ToolTip_AddIcon(ToolTip_UnitSelect,globs::objectGlobs.ToolTipIcon_Blank); } uVar7 += 1; uVar8 = stats::StatsObject_GetNumOfToolsCanCarry(liveObj); } while (uVar7 < uVar8); } if (liveObj->abilityFlags != ABILITY_FLAG_NONE) { front::ToolTip_AddIcon(ToolTip_UnitSelect,NULL); bVar11 = 0; ppIVar10 = globs::objectGlobs.ToolTipIcons_Abilities; do { opt_image = globs::objectGlobs.ToolTipIcon_Blank; if ((liveObj->abilityFlags & 1 << (bVar11 & 0x1f)) != ABILITY_FLAG_NONE) { opt_image = *ppIVar10; } if (opt_image != NULL) { front::ToolTip_AddIcon(ToolTip_UnitSelect,opt_image); } ppIVar10 = ppIVar10 + 1; bVar11 += 1; } while (ppIVar10 < globs::objectGlobs.ToolTipIcons_Tools); } } front::ToolTip_Activate(ToolTip_UnitSelect); } } return; } void __cdecl lego::lrr::Lego_ShowBlockToolTip (Point2I *mouseBlockPos,BOOL showConstruction,BOOL playSound,BOOL showCavern) { char cVar1; int iVar2; BlockFlags1 BVar3; Construction_ZoneFlags CVar4; bool bVar5; char *pcVar6; uint uVar7; uint uVar8; uint uVar9; uint uVar10; char *pcVar11; BlockFlags1 BVar12; uint uVar13; uint uVar14; int iVar15; undefined4 *puVar16; char *pcVar17; undefined4 *puVar18; Lego_SurfaceType LVar19; char buff2 [128]; char buff1 [128]; Lego_Block *block; Construction_Zone *construct; iVar15 = mouseBlockPos->y; iVar2 = mouseBlockPos->x; block = (globs::legoGlobs.currLevel)->blocks + (globs::legoGlobs.currLevel)->width * iVar15 + iVar2; if ((globs::s_ShowBlockToolTip_MousePos.x != iVar2) || (globs::s_ShowBlockToolTip_MousePos.y != iVar15)) { globs::s_ShowBlockToolTip_MousePos.x = mouseBlockPos->x; globs::s_ShowBlockToolTip_MousePos.y = mouseBlockPos->y; return; } BVar3 = block->flags1; pcVar6 = (char *)(BVar3 & BLOCK1_FOUNDATION); if ((((pcVar6 != NULL) && (((globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * iVar15 + iVar2]. flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE)) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * iVar15 + iVar2].flags2 & BLOCK2_TOOLSTORE) == 0)) && ((BVar3 & BLOCK1_BUILDINGPATH) == BLOCK1_NONE)) { construct = block->construct; CVar4 = construct->flags; pcVar6 = game::Object_GetLangName(LegoObject_Building,construct->objID); uVar13 = 0xffffffff; do { pcVar11 = pcVar6; if (uVar13 == 0) break; uVar13 -= 1; pcVar11 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar11; } while (cVar1 != '\0'); uVar13 = ~uVar13; puVar16 = (undefined4 *)(pcVar11 + -uVar13); puVar18 = (undefined4 *)buff1; for (uVar14 = uVar13 >> 2; uVar14 != 0; uVar14 -= 1) { *puVar18 = *puVar16; puVar16 = puVar16 + 1; puVar18 = puVar18 + 1; } for (uVar13 &= 3; uVar13 != 0; uVar13 -= 1) { *(undefined *)puVar18 = *(undefined *)puVar16; puVar16 = (undefined4 *)((int)puVar16 + 1); puVar18 = (undefined4 *)((int)puVar18 + 1); } if (showConstruction != 0) { uVar7 = game::Construction_Zone_CountOfResourcePlaced(construct,LegoObject_PowerCrystal,0); uVar8 = stats::Stats_GetCostCrystal(LegoObject_Building,construct->objID,0); uVar13 = game::Construction_Zone_CountOfResourcePlaced (construct,LegoObject_Ore,LegoObject_ID_Ore); uVar14 = stats::Stats_GetCostOre(LegoObject_Building,construct->objID,0); uVar9 = game::Construction_Zone_CountOfResourcePlaced (construct,LegoObject_Ore,LegoObject_ID_ProcessedOre); uVar10 = stats::Stats_GetCostRefinedOre(LegoObject_Building,construct->objID,0); if (uVar8 != 0) { std::sprintf(buff2,"\n%s: %i/%i",globs::legoGlobs.langCrystals_toolTip,uVar7,uVar8); uVar7 = 0xffffffff; pcVar6 = buff2; do { pcVar11 = pcVar6; if (uVar7 == 0) break; uVar7 -= 1; pcVar11 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar11; } while (cVar1 != '\0'); uVar7 = ~uVar7; iVar15 = -1; pcVar6 = buff1; do { pcVar17 = pcVar6; if (iVar15 == 0) break; iVar15 += -1; pcVar17 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar17; } while (cVar1 != '\0'); puVar16 = (undefined4 *)(pcVar11 + -uVar7); puVar18 = (undefined4 *)(pcVar17 + -1); for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar18 = *puVar16; puVar16 = puVar16 + 1; puVar18 = puVar18 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar18 = *(undefined *)puVar16; puVar16 = (undefined4 *)((int)puVar16 + 1); puVar18 = (undefined4 *)((int)puVar18 + 1); } } pcVar6 = globs::legoGlobs.langOre_toolTip; if ((CVar4 & CONSTRUCTION_FLAG_USESTUDS) != CONSTRUCTION_FLAG_NONE) { uVar13 = uVar9; uVar14 = uVar10; pcVar6 = globs::legoGlobs.langStuds_toolTip; } if (uVar14 != 0) { std::sprintf(buff2,"\n%s: %i/%i",pcVar6,uVar13,uVar14); uVar13 = 0xffffffff; pcVar6 = buff2; do { pcVar11 = pcVar6; if (uVar13 == 0) break; uVar13 -= 1; pcVar11 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar11; } while (cVar1 != '\0'); uVar13 = ~uVar13; iVar15 = -1; pcVar6 = buff1; do { pcVar17 = pcVar6; if (iVar15 == 0) break; iVar15 += -1; pcVar17 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar17; } while (cVar1 != '\0'); puVar16 = (undefined4 *)(pcVar11 + -uVar13); puVar18 = (undefined4 *)(pcVar17 + -1); for (uVar14 = uVar13 >> 2; uVar14 != 0; uVar14 -= 1) { *puVar18 = *puVar16; puVar16 = puVar16 + 1; puVar18 = puVar18 + 1; } for (uVar13 &= 3; uVar13 != 0; uVar13 -= 1) { *(undefined *)puVar18 = *(undefined *)puVar16; puVar16 = (undefined4 *)((int)puVar16 + 1); puVar18 = (undefined4 *)((int)puVar18 + 1); } } } front::ToolTip_SetContent(ToolTip_Construction,buff1); front::ToolTip_SetSFX(ToolTip_Construction,SFX_NULL); front::ToolTip_Activate(ToolTip_Construction); return; } bVar5 = false; if ((BVar3 & BLOCK1_FLOOR) == BLOCK1_NONE) { if (((BVar3 & BLOCK1_WALL) == BLOCK1_NONE) && ((BVar3 & BLOCK1_HIDDEN) != BLOCK1_NONE)) { pcVar6 = game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType_Undiscovered); LVar19 = Lego_SurfaceType_Undiscovered; } else { if ((BVar3 & BLOCK1_REINFORCED) == BLOCK1_NONE) { LVar19 = (Lego_SurfaceType)block->terrain; goto LAB_00428649; } pcVar6 = game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType_Reinforcement); LVar19 = Lego_SurfaceType_Reinforcement; } } else { if ((BVar3 & BLOCK1_ERODEACTIVE) == BLOCK1_NONE) { if ((BVar3 & BLOCK1_CLEARED) == BLOCK1_NONE) { pcVar6 = game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType_Rubble); pcVar11 = (char *)game::Lego_GetSurfaceTypeSFX(Lego_SurfaceType_Rubble); bVar5 = true; } else { if ((*(byte *)&block->flags2 & BLOCK2_SLUGHOLE_EXPOSED) == 0) { if (((iVar2 < 0) || (iVar15 < 0)) || (((int)(globs::legoGlobs.currLevel)->width <= iVar2 || ((int)(globs::legoGlobs.currLevel)->height <= iVar15)))) { BVar12 = BLOCK1_NONE; } else { BVar12 = (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * iVar15 + iVar2].flags1 & BLOCK1_PATH; } if ((BVar12 == BLOCK1_NONE) && ((BVar3 & BLOCK1_BUILDINGPATH) == BLOCK1_NONE)) { pcVar11 = pcVar6; if (((((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * iVar15 + iVar2].flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * iVar15 + iVar2].flags2 & BLOCK2_TOOLSTORE) == 0)) && (pcVar6 == NULL)) { if (showCavern == 0) goto LAB_004285a8; pcVar6 = game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType_Cavern); pcVar11 = (char *)game::Lego_GetSurfaceTypeSFX(Lego_SurfaceType_Cavern); bVar5 = true; } } else { pcVar6 = game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType_Path); pcVar11 = (char *)game::Lego_GetSurfaceTypeSFX(Lego_SurfaceType_Path); bVar5 = true; } } else { pcVar6 = game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType_SlugHole); pcVar11 = (char *)game::Lego_GetSurfaceTypeSFX(Lego_SurfaceType_SlugHole); bVar5 = true; } } } else { LAB_004285a8: pcVar6 = game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType_Tunnel); pcVar11 = (char *)game::Lego_GetSurfaceTypeSFX(Lego_SurfaceType_Tunnel); bVar5 = true; } if (block->terrain == Lego_SurfaceType8_Lake) { LVar19 = Lego_SurfaceType_Lake; LAB_00428649: pcVar6 = game::Lego_GetSurfaceTypeDescription(LVar19); LVar19 = (Lego_SurfaceType)block->terrain; } else { if (block->terrain != Lego_SurfaceType8_Lava) goto LAB_00428668; pcVar6 = game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType_Lava); LVar19 = (Lego_SurfaceType)block->terrain; } } pcVar11 = (char *)game::Lego_GetSurfaceTypeSFX(LVar19); bVar5 = true; LAB_00428668: if (bVar5) { front::ToolTip_SetContent(ToolTip_MapBlock,"%s",pcVar6); if (playSound == 0) { pcVar11 = NULL; } front::ToolTip_SetSFX(ToolTip_MapBlock,(SFX_ID)pcVar11); front::ToolTip_Activate(ToolTip_MapBlock); } return; } BOOL __cdecl lego::game::Level_BlockPointerCheck(Point2I *blockPos) { uint uVar1; int iVar2; int iVar3; TutorialFlags TVar4; Lego_Level *level; TVar4 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (TVar4 != TUTORIAL_NONE) { TVar4 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((TVar4 & TUTORIAL_FLAG_NOOBJECTS) == TUTORIAL_NONE) { TVar4 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((TVar4 & TUTORIAL_FLAG_NOMAP) == TUTORIAL_NONE) { return TRUE; } } } TVar4 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((TVar4 & TUTORIAL_FLAG_NOBLOCKACTION) != TUTORIAL_NONE) { level = lrr::Lego_GetLevel(); uVar1 = level->width; iVar2 = blockPos->y; iVar3 = blockPos->x; level = lrr::Lego_GetLevel(); if (level->blocks[uVar1 * iVar2 + iVar3].blockpointer == 0) { return TRUE; } } return 0; } // Sets the current combination pointer/hover SFX, with a pointer duration of 12.5. void __cdecl lego::lrr::Lego_SetPointerSFX(PointerSFX_Type pointerSFXType) { BOOL origQueueMode; SFX_ID sfxID; origQueueMode = snd::SFX_IsQueueMode(); snd::SFX_SetQueueMode(FALSE,FALSE); switch(pointerSFXType) { case PointerSFX_Okay: front::Pointer_SetCurrent(Pointer_Okay,12.5); sfxID = SFX_Okay; break; case PointerSFX_NotOkay: front::Pointer_SetCurrent(Pointer_NotOkay,12.5); sfxID = SFX_NotOkay; break; case PointerSFX_NotOkay_ImmovableRock: front::Pointer_SetCurrent(Pointer_NotOkay,12.5); sfxID = SFX_ImmovableRock; break; case PointerSFX_Okay_TopPriority: front::Pointer_SetCurrent(Pointer_Okay,12.5); sfxID = SFX_TopPriority; break; case PointerSFX_Okay_Wall: front::Pointer_SetCurrent(Pointer_Okay,12.5); sfxID = SFX_Wall; break; case PointerSFX_Okay_Floor: front::Pointer_SetCurrent(Pointer_Okay,12.5); sfxID = SFX_Floor; break; default: goto switchD_00428751_caseD_6; } snd::SFX_Random_PlaySoundNormal(sfxID,FALSE); switchD_00428751_caseD_6: snd::SFX_SetQueueMode(origQueueMode,FALSE); return; } // bx,by : mouse-over block position. // liveObj : mouse-over object. void __cdecl lego::lrr::Lego_HandleWorldDebugKeys(int bx,int by,LegoObject *liveObj,float noMouseButtonsElapsed) { Lego_Level *pLVar1; BOOL BVar2; LegoObject *primaryObj; BOOL canUpgDrill; BOOL canUpgSpeed; BOOL canUpgScan; BOOL canUpgCarry; LegoObject *liveObj_00; Container_Texture *contTexture; uint uVar3; LegoObject **ppLVar4; UpgradesModel *upgrades; LegoObject_UpgradeFlags upgradeLvl; float dirz; LegoObject_UpgradeType LVar5; LegoObject_UpgradeFlags local_18; LegoObject **selectedUnits; Point2F local_10; Point2I mouseBlockPos; LegoObject *registeredVehicle; LegoObject *firstObj; mouseBlockPos.x = bx; mouseBlockPos.y = by; // IsKeyPressed(KEY_A) (30) // "Creates a landslide at mousepoint.""Causes unit at mousepoint to slip." // The DIRECTION_FLAG_N here is probably why the landslide debug key is so finicky. if (((globs::INPUT.Key_Map[30] != false) && (globs::INPUT.prevKey_Map[30] != globs::INPUT.Key_Map[30])) && (game::Fallin_Block_FUN_0040f260(&mouseBlockPos,DIRECTION_FLAG_N,TRUE), liveObj != NULL)) { ai::LegoObject_DoSlip(liveObj); } // IsKeyPressed(KEY_END) (207) // "Toggles power Off/On for currently selected building" if (((globs::INPUT.Key_Map[207] != false) && (globs::INPUT.prevKey_Map[207] != globs::INPUT.Key_Map[207])) && (BVar2 = game::Message_AnyUnitSelected(), BVar2 != 0)) { primaryObj = game::Message_GetPrimarySelectedUnit(); debug::StatsObject_Debug_ToggleSelfPowered(primaryObj); } // IsKeyPressed(KEY_E) (18) // "Makes a monster emerge from a diggable wall at mousepoint." if ((globs::INPUT.Key_Map[18] != false) && (globs::INPUT.prevKey_Map[18] != globs::INPUT.Key_Map[18])) { game::LegoObject_TryGenerateRMonster (globs::legoGlobs.rockMonsterData + (globs::legoGlobs.currLevel)->EmergeCreature, LegoObject_RockMonster,(globs::legoGlobs.currLevel)->EmergeCreature,bx,by); } // IsKeyDown(KEY_W) (17) // "Performs unknown behavior with the unfinished 'flood water' surface." if (globs::INPUT.Key_Map[17] != false) { debug::Level_Debug_WKey_NeedsBlockFlags1_8_FUN_004303a0(globs::legoGlobs.currLevel,0,bx,by); } // IsKeyPressed(KEY_C) (46) // "Tell selected unit to carried dynamite drop where they are and set it off." if (globs::INPUT.Key_Map[46] != false) { if ((globs::INPUT.prevKey_Map[46] != globs::INPUT.Key_Map[46]) && (BVar2 = game::Message_AnyUnitSelected(), BVar2 != 0)) { primaryObj = game::Message_GetPrimarySelectedUnit(); debug::LegoObject_Debug_DropActivateDynamite(primaryObj); } // IsKeyPressed(KEY_C) (46) // "Simply calling the same debug C key function again... no idea why." if (((globs::INPUT.Key_Map[46] != false) && (globs::INPUT.prevKey_Map[46] != globs::INPUT.Key_Map[46])) && (BVar2 = game::Message_AnyUnitSelected(), BVar2 != 0)) { primaryObj = game::Message_GetPrimarySelectedUnit(); debug::LegoObject_Debug_DropActivateDynamite(primaryObj); } } // IsKeyPressed(KEY_F12) (88) // "Disables all NERPs functions (toggle)." if ((globs::INPUT.Key_Map[88] != false) && (globs::INPUT.prevKey_Map[88] != globs::INPUT.Key_Map[88])) { if ((globs::legoGlobs.flags1 & GAME1_DEBUG_NONERPS) == GAME1_NONE) { selectedUnits = NULL; globs::legoGlobs.flags1 |= GAME1_DEBUG_NONERPS; nerps::funcs::NERPFunc__SetTutorialFlags((int *)&selectedUnits); } else { globs::legoGlobs.flags1 &= ~GAME1_DEBUG_NONERPS; } } // IsKeyPressed(KEY_F11) (87) // "Disables all building and vehicle prerequisites." if ((globs::INPUT.Key_Map[87] != false) && (globs::INPUT.prevKey_Map[87] != globs::INPUT.Key_Map[87])) { debug::Dependencies_SetEnabled(FALSE); } // IsKeyPressed(KEY_F10) (68) // "Inverts the direction of lighting." if ((globs::INPUT.Key_Map[68] != false) && (globs::INPUT.prevKey_Map[68] != globs::INPUT.Key_Map[68])) { globs::gamectrlGlobs.dbgF10InvertLighting = ZEXT14(globs::gamectrlGlobs.dbgF10InvertLighting == 0); if (globs::gamectrlGlobs.dbgF10InvertLighting == 0) { gfx::Container_SetPosition (globs::legoGlobs.spotlightTop,(globs::legoGlobs.cameraMain)->cont3,200.0,140.0, -130.0); dirz = 0.75; } else { gfx::Container_SetPosition (globs::legoGlobs.spotlightTop,(globs::legoGlobs.cameraMain)->cont3,250.0,190.0,20.0 ); dirz = 0.0; } gfx::Container_SetOrientation (globs::legoGlobs.spotlightTop,(globs::legoGlobs.cameraMain)->cont3,-1.0,-0.8,dirz,0.0 ,1.0,0.0); light::LightEffects_InvalidatePosition(); } // IsKeyPressed(KEY_F9) (67) // "Toggle spotlight effects." if ((globs::INPUT.Key_Map[67] != false) && (globs::INPUT.prevKey_Map[67] != globs::INPUT.Key_Map[67])) { globs::gamectrlGlobs.dbgF9DisableLightEffects = ZEXT14(globs::gamectrlGlobs.dbgF9DisableLightEffects == 0); light::LightEffects_SetDisabled(globs::gamectrlGlobs.dbgF9DisableLightEffects); } BVar2 = game::Message_AnyUnitSelected(); // IsKeyPressed(KEY_FIVE) (6) || IsKeyPressed(KEY_SIX) (7) || // IsKeyPressed(KEY_SEVEN) (8) || IsKeyPressed(KEY_EIGHT) (9) // "Change selected unit visual upgrade parts. Respectively: Carry, Scan, Speed, Drill" if ((BVar2 != 0) && ((((((globs::INPUT.Key_Map[6] != false && (globs::INPUT.prevKey_Map[6] != globs::INPUT.Key_Map[6])) || ((globs::INPUT.Key_Map[7] != false && (globs::INPUT.prevKey_Map[7] != globs::INPUT.Key_Map[7])))) || ((globs::INPUT.Key_Map[8] != false && (globs::INPUT.prevKey_Map[8] != globs::INPUT.Key_Map[8])))) || ((globs::INPUT.Key_Map[9] != false && (globs::INPUT.prevKey_Map[9] != globs::INPUT.Key_Map[9])))) && (selectedUnits = game::Message_GetSelectedUnits2((uint *)&local_10), local_10.x != 0.0)))) { firstObj = *selectedUnits; if (firstObj->type == LegoObject_Building) { BVar2 = FALSE; LVar5 = LegoObject_UpgradeType_Drill; upgrades = &firstObj->building->upgrades; primaryObj = game::Message_GetPrimarySelectedUnit(); canUpgDrill = gfx::Building_CanUpgradeType(primaryObj->building,LVar5,BVar2); BVar2 = FALSE; LVar5 = LegoObject_UpgradeType_Speed; primaryObj = game::Message_GetPrimarySelectedUnit(); canUpgSpeed = gfx::Building_CanUpgradeType(primaryObj->building,LVar5,BVar2); BVar2 = FALSE; LVar5 = LegoObject_UpgradeType_Scan; primaryObj = game::Message_GetPrimarySelectedUnit(); canUpgScan = gfx::Building_CanUpgradeType(primaryObj->building,LVar5,BVar2); BVar2 = FALSE; LVar5 = LegoObject_UpgradeType_Carry; primaryObj = game::Message_GetPrimarySelectedUnit(); canUpgCarry = gfx::Building_CanUpgradeType(primaryObj->building,LVar5,BVar2); } else { if (firstObj->type == LegoObject_Vehicle) { BVar2 = 0; LVar5 = LegoObject_UpgradeType_Drill; upgrades = &firstObj->vehicle->upgrades; primaryObj = game::Message_GetPrimarySelectedUnit(); canUpgDrill = gfx::Vehicle_CanUpgradeType(primaryObj->vehicle,LVar5,BVar2); BVar2 = 0; LVar5 = LegoObject_UpgradeType_Speed; primaryObj = game::Message_GetPrimarySelectedUnit(); canUpgSpeed = gfx::Vehicle_CanUpgradeType(primaryObj->vehicle,LVar5,BVar2); BVar2 = 0; LVar5 = LegoObject_UpgradeType_Scan; primaryObj = game::Message_GetPrimarySelectedUnit(); canUpgScan = gfx::Vehicle_CanUpgradeType(primaryObj->vehicle,LVar5,BVar2); BVar2 = 0; LVar5 = LegoObject_UpgradeType_Carry; primaryObj = game::Message_GetPrimarySelectedUnit(); canUpgCarry = gfx::Vehicle_CanUpgradeType(primaryObj->vehicle,LVar5,BVar2); } else { upgrades = NULL; canUpgCarry = bx; canUpgSpeed = bx; canUpgScan = bx; canUpgDrill = bx; } } if (upgrades != NULL) { local_18 = upgrades->currentLevel; upgradeLvl = local_18; // IsKeyPressed(KEY_FIVE) (6) // "Change selected unit visual upgrade parts (Carry level bit)" if (((globs::INPUT.Key_Map[6] != false) && (globs::INPUT.prevKey_Map[6] != globs::INPUT.Key_Map[6])) && (canUpgDrill != 0)) { upgradeLvl = local_18 ^ UPGRADE_FLAG_CARRY; } // IsKeyPressed(KEY_SIX) (7) // "Change selected unit visual upgrade parts (Scan level bit)" if (((globs::INPUT.Key_Map[7] != false) && (globs::INPUT.prevKey_Map[7] != globs::INPUT.Key_Map[7])) && (canUpgSpeed != 0)) { upgradeLvl ^= UPGRADE_FLAG_SCAN; } // IsKeyPressed(KEY_SEVEN) (8) // "Change selected unit visual upgrade parts (Speed level bit)" if (((globs::INPUT.Key_Map[8] != false) && (globs::INPUT.prevKey_Map[8] != globs::INPUT.Key_Map[8])) && (canUpgScan != 0)) { upgradeLvl ^= UPGRADE_FLAG_SPEED; } // IsKeyPressed(KEY_EIGHT) (9) // "Change selected unit visual upgrade parts (Drill level bit)" if (((globs::INPUT.Key_Map[9] != false) && (globs::INPUT.prevKey_Map[9] != globs::INPUT.Key_Map[9])) && (canUpgCarry != 0)) { upgradeLvl ^= UPGRADE_FLAG_DRILL; } if (upgradeLvl != local_18) { if ((*selectedUnits)->type == LegoObject_Building) { primaryObj = game::Message_GetPrimarySelectedUnit(); gfx::Building_SetUpgradeLevel(primaryObj->building,upgradeLvl); } else { if ((*selectedUnits)->type == LegoObject_Vehicle) { primaryObj = game::Message_GetPrimarySelectedUnit(); gfx::Vehicle_SetUpgradeLevel(primaryObj->vehicle,upgradeLvl); } } } } } // IsKeyPressed(KEY_BACKSPACE) (14) if ((globs::INPUT.Key_Map[14] != false) && (globs::INPUT.prevKey_Map[14] != globs::INPUT.Key_Map[14])) { ai::AITask_DoGather_Count(5); } // IsKeyPressed(KEYPAD_DELETE) (83) // "Destroys any walls at mousepoint, except border rock" if ((globs::INPUT.Key_Map[83] != false) && (globs::INPUT.prevKey_Map[83] != globs::INPUT.Key_Map[83])) { game::Level_DestroyWall(globs::legoGlobs.currLevel,bx,by,FALSE); } // IsKeyDown(KEYPAD_3) (81) // "Destroys connections between any walls at mousepoint, except border rock." if (globs::INPUT.Key_Map[81] != false) { game::Level_DestroyWallConnection(globs::legoGlobs.currLevel,bx,by); } // IsKeyPressed(KEY_W) (17) // "Tell selected monster to immediately carry a created boulder." if ((((globs::INPUT.Key_Map[17] != false) && (globs::INPUT.prevKey_Map[17] != globs::INPUT.Key_Map[17])) && (BVar2 = game::Message_AnyUnitSelected(), BVar2 != 0)) && (primaryObj = game::Message_GetPrimarySelectedUnit(), pLVar1 = globs::legoGlobs.currLevel, primaryObj->type == LegoObject_RockMonster)) { game::LegoObject_FindNearestWall(primaryObj,(int *)&local_18,(int *)&selectedUnits,1,0,0); liveObj_00 = game::LegoObject_Create((int **)globs::legoGlobs.contBoulder,LegoObject_Boulder,0); game::LegoObject_Hide(liveObj_00,TRUE); game::LegoObject_RoutingNoCarry_FUN_00447470(primaryObj,local_18,(uint)selectedUnits,liveObj_00) ; contTexture = lego::map::Detail_GetTexture (pLVar1->textureSet, pLVar1->blocks[pLVar1->width * (int)selectedUnits + local_18].texture); game::LegoObject_InitBoulderMesh_FUN_00440eb0(liveObj_00,contTexture); } // IsKeyPressed(KEY_N) (49) // "Stops routing for the primary selected unit." if (((globs::INPUT.Key_Map[49] != false) && (globs::INPUT.prevKey_Map[49] != globs::INPUT.Key_Map[49])) && (BVar2 = game::Message_AnyUnitSelected(), BVar2 != 0)) { BVar2 = FALSE; primaryObj = game::Message_GetPrimarySelectedUnit(); game::LegoObject_Route_End(primaryObj,BVar2); } // IsKeyDown(KEY_LEFTSHIFT) (42) && IsKeyPressed(KEY_A) (30) // "Tells a Rock Raider to get a Sonic Blaster from Tool Store and place at // mousepoint." if (((globs::INPUT.Key_Map[42] != false) && (globs::INPUT.Key_Map[30] != false)) && (globs::INPUT.prevKey_Map[30] != globs::INPUT.Key_Map[30])) { ai::AITask_DoBirdScarer_AtPosition(&mouseBlockPos); } // IsKeyPressed(KEY_B) (48) // "Pushes any Rock Raider or Monster at mousepoint east-northeast." if ((globs::INPUT.Key_Map[48] != false) && (globs::INPUT.prevKey_Map[48] != globs::INPUT.Key_Map[48])) { local_10.x = 2.0; local_10.y = 1.0; if (liveObj != NULL) { game::LegoObject_Push(liveObj,&local_10,40.0); } } // IsKeyPressed(KEY_H) (35) // "Creates a spider web at mousepoint." if ((globs::INPUT.Key_Map[35] != false) && (globs::INPUT.prevKey_Map[35] != globs::INPUT.Key_Map[35])) { game::SpiderWeb_SpawnAt(bx,by); } // IsKeyPressed(KEY_F) (33) // "Take 40 health points off all units selected." if ((((globs::INPUT.Key_Map[33] != false) && (globs::INPUT.prevKey_Map[33] != globs::INPUT.Key_Map[33])) && (BVar2 = game::Message_AnyUnitSelected(), BVar2 != 0)) && (uVar3 = game::Message_GetNumSelectedUnits(), uVar3 != 0)) { ppLVar4 = game::Message_GetSelectedUnits(); for (; uVar3 != 0; uVar3 -= 1) { game::LegoObject_AddDamage2(*ppLVar4,40.0,TRUE,noMouseButtonsElapsed); ppLVar4 = ppLVar4 + 1; } } // IsKeyPressed(KEY_H) (35) if (((globs::INPUT.Key_Map[35] != false) && (globs::INPUT.prevKey_Map[35] != globs::INPUT.Key_Map[35])) && ((BVar2 = game::Message_AnyUnitSelected(), BVar2 != 0 && (primaryObj = game::Message_GetPrimarySelectedUnit(), primaryObj->type == LegoObject_Building) ))) { game::ElectricFence_FUN_0040d420(primaryObj,0,0); } // IsKeyPressed(KEY_J) (36) // "Place an electric fence at mousepoint." if ((globs::INPUT.Key_Map[36] != false) && (globs::INPUT.prevKey_Map[36] != globs::INPUT.Key_Map[36])) { BVar2 = game::ElectricFence_Block_IsFence(bx,by); if (BVar2 == 0) { game::ElectricFence_Debug_PlaceFence(bx,by); } else { game::ElectricFence_Debug_RemoveFence(bx,by); } } // IsKeyPressed(KEY_Y) (21) // "Triggers the CrystalFound InfoMessage." if ((globs::INPUT.Key_Map[21] != false) && (globs::INPUT.prevKey_Map[21] != globs::INPUT.Key_Map[21])) { // Point2I blockPos = { 1, 1 }; local_10.x = 1.401298e-45; local_10.y = 1.401298e-45; front::Info_Send(Info_CrystalFound,NULL,NULL,(Point2I *)&local_10); } // IsKeyUp(KEY_LEFTSHIFT) (42) if (globs::INPUT.Key_Map[42] == false) { // IsKeyPressed(KEY_U) (22) // "Ends Advisor_Anim_Point_N." if ((globs::INPUT.Key_Map[22] != false) && (globs::INPUT.prevKey_Map[22] != globs::INPUT.Key_Map[22])) { front::Advisor_End(); } } else { // IsKeyPressed(KEY_U) (22) // "Begins Advisor_Anim_Point_N." if ((globs::INPUT.Key_Map[22] != false) && (globs::INPUT.prevKey_Map[22] != globs::INPUT.Key_Map[22])) { front::Panel_SetCurrentAdvisorFromButton(Panel_Radar,0,1); } } // IsKeyPressed(KEY_K) (37) // "Pt.1 Registers a selected vehicle as a get-in target.""Pt.2 Tells a selected // minifigure to get in a registered vehicle." if (((globs::INPUT.Key_Map[37] != false) && (globs::INPUT.prevKey_Map[37] != globs::INPUT.Key_Map[37])) && (BVar2 = game::Message_AnyUnitSelected(), BVar2 != 0)) { primaryObj = game::Message_GetPrimarySelectedUnit(); if (primaryObj->type == LegoObject_Vehicle) { globs::gamectrlGlobs.dbgGetInVehicle = game::Message_GetPrimarySelectedUnit(); return; } primaryObj = game::Message_GetPrimarySelectedUnit(); if ((primaryObj->type == LegoObject_MiniFigure) && (globs::gamectrlGlobs.dbgGetInVehicle != NULL)) { registeredVehicle = globs::gamectrlGlobs.dbgGetInVehicle; primaryObj = game::Message_GetPrimarySelectedUnit(); game::LegoObject_TryFindDriver_FUN_00440690(primaryObj,registeredVehicle); } } return; } void __cdecl lego::lrr::Lego_XYCallback_AddVisibleSmoke(int bx,int by) { if (((globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx].flags1 & BLOCK1_SMOKE) != BLOCK1_NONE) { effect::Smoke_Hide((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * by + bx].smoke,FALSE); } return; } Container_Texture * __cdecl lego::lrr::Lego_GetBlockDetail_ContainerTexture(Point2I *blockPos) { Container_Texture *meshTexture; meshTexture = lego::map::Detail_GetTexture ((globs::legoGlobs.currLevel)->textureSet, (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].texture ); return meshTexture; } void __cdecl lego::lrr::Lego_UnkUpdateMapsWorldUnk_FUN_004290d0(float elapsedAbs,BOOL pass2) { Map3D *map; float highPolyBlocksMult; float10 fVar1; longlong lVar2; Vector3F local_18; Vector3F local_c; if (pass2 == 0) { if (globs::legoGlobs.viewMode == ViewMode_Top) { gfx::Container_GetPosition((globs::legoGlobs.cameraMain)->cont2,NULL,&local_18); lego::map::Map3D_WorldToBlockPos_NoZ ((globs::legoGlobs.currLevel)->map,local_18.x,local_18.y,&pass2,(int *)&elapsedAbs); gfx::Container_GetOrientation((globs::legoGlobs.cameraMain)->contCam,NULL,&local_c,NULL); map = Lego_GetMap(); fVar1 = lego::map::Map3D_BlockSize(map); fVar1 = fVar1 * (float10)3.0; local_c.x = (float)(fVar1 * (float10)local_c.x); local_c.y = (float)(fVar1 * (float10)local_c.y); local_c.z = (float)(fVar1 * (float10)local_c.z); local_18.x = local_c.x + local_18.x; local_18.y = local_c.y + local_18.y; local_18.z = local_c.z + local_18.z; lego::map::Map3D_WorldToBlockPos_NoZ ((globs::legoGlobs.currLevel)->map,local_18.x,local_18.y,&pass2,(int *)&elapsedAbs); lego::map::Map3D_AddVisibleBlocksInRadius_AndDoCallbacks ((globs::legoGlobs.currLevel)->map,pass2,(int)elapsedAbs,8, Lego_XYCallback_AddVisibleSmoke); return; } if (globs::legoGlobs.viewMode == ViewMode_FP) { pass2 = (BOOL)((globs::legoGlobs.currLevel)->map->blockSize * globs::legoGlobs.FPClipBlocks); highPolyBlocksMult = (float)globs::legoGlobs.HPBlocks; if (((globs::legoGlobs.flags1 & GAME1_DYNAMICPM) != GAME1_NONE) && (elapsedAbs != 0.0)) { local_18.x = (float)globs::legoGlobs.HPBlocks; local_18.y = 0.0; lVar2 = __ftol((float10)(ulonglong)(uint)globs::legoGlobs.HPBlocks / (float10)elapsedAbs); highPolyBlocksMult = (float)lVar2; } unk::Lego_FPHighPolyBlocks_FUN_00433db0 ((globs::legoGlobs.cameraFP)->contCam,globs::legoGlobs.viewMain,(float)pass2, highPolyBlocksMult); return; } } else { if (((globs::legoGlobs.flags1 & GAME1_RADARON) != GAME1_NONE) && ((globs::legoGlobs.flags1 & GAME1_RADAR_TRACKOBJECTVIEW) != GAME1_NONE)) { gfx::Container_GetPosition((globs::legoGlobs.cameraTrack)->cont2,NULL,&local_c); lego::map::Map3D_WorldToBlockPos_NoZ ((globs::legoGlobs.currLevel)->map,local_c.x,local_c.y,&pass2,(int *)&elapsedAbs); lego::map::Map3D_AddVisibleBlocksInRadius_AndDoCallbacks ((globs::legoGlobs.currLevel)->map,pass2,(int)elapsedAbs,2,NULL); } } return; } void __cdecl lego::lrr::Lego_DrawDragSelectionBox(Lego_Level *level) { Point2F local_38; Point2F mousePos; Point2F lineList [5]; if ((globs::legoGlobs.flags1 & GAME1_MULTISELECTING) != GAME1_NONE) { mousePos.y = (float)globs::INPUT.msy; mousePos.x = (float)globs::INPUT.msx; lego::view::Viewport_WorldToScreen (globs::legoGlobs.viewMain,&local_38,&globs::legoGlobs.vectorDragStartUnk_a4); lineList[0].x = local_38.x; lineList[0].y = local_38.y; lineList[1].x = mousePos.x; lineList[1].y = local_38.y; lineList[2].x = mousePos.x; lineList[2].y = mousePos.y; lineList[3].x = local_38.x; lineList[3].y = mousePos.y; lineList[4].x = local_38.x; lineList[4].y = local_38.y; draw::Draw_LineListEx (lineList,lineList + 1,4,globs::legoGlobs.DragBoxRGB.red, globs::legoGlobs.DragBoxRGB.green,globs::legoGlobs.DragBoxRGB.blue, DrawEffect_HalfTrans); } return; } void __cdecl lego::lrr::Lego_MainView_MouseTransform(uint mouseX,uint mouseY,float *out_xPos,float *out_yPos) { BOOL BVar1; Vector3F local_4c; Vector3F local_40; Vector3F local_34; Vector3F local_28; Vector3F local_1c; Vector4F local_10; local_28.x = 0.0; local_4c.x = (float)mouseY; local_4c.y = 0.0; local_28.y = 0.0; local_28.z = 0.0; local_34.x = 0.0; local_34.y = 0.0; local_34.z = -1.0; local_10.z = 0.0; local_10.w = 1.0; local_10.x = (float)(ulonglong)mouseX; local_10.y = (float)(ulonglong)mouseY; lego::view::Viewport_InverseTransform(globs::legoGlobs.viewMain,&local_40,&local_10); local_10.z = 1.0; local_10.w = 1.0; local_10.x = (float)(ulonglong)mouseX; local_10.y = (float)(ulonglong)mouseY; lego::view::Viewport_InverseTransform(globs::legoGlobs.viewMain,&local_4c,&local_10); local_4c.x = local_4c.x - local_40.x; local_4c.y = local_4c.y - local_40.y; local_4c.z = local_4c.z - local_40.z; BVar1 = math::Maths_RayPlaneIntersection(&local_1c,&local_40,&local_4c,&local_28,&local_34); if (BVar1 != 0) { *out_xPos = local_1c.x; *out_yPos = local_1c.y; } return; } Container * __cdecl lego::lrr::Lego_GetCurrentViewLight(void) { Container *light; light = globs::legoGlobs.pointLightFP; if (globs::legoGlobs.viewMode != ViewMode_FP) { light = globs::legoGlobs.rootSpotlight; } return light; } // Returns TRUE if liveObj (or its drivenObj) is the first-person unit. // BUG: When in topdown view, returns TRUE if the objectFP is not NULL and matches the unit's // drivenObj. BOOL __cdecl lego::lrr::Lego_IsFPObject(LegoObject *liveObj) { if (((globs::legoGlobs.viewMode != ViewMode_FP) || (liveObj != globs::legoGlobs.objectFP)) && ((liveObj->driveObject == NULL || (liveObj->driveObject != globs::legoGlobs.objectFP)))) { return FALSE; } return TRUE; } void __cdecl lego::lrr::Lego_SetViewMode(ViewMode viewMode,LegoObject *liveObj,uint cameraFrame) { ViewMode VVar1; VVar1 = viewMode; if (viewMode == ViewMode_FP) { viewMode = 1063675494; if (cameraFrame != 0) { viewMode = 1058642330; } lego::view::Camera_SetFPObject(globs::legoGlobs.cameraFP,liveObj,cameraFrame); debug::Water_ChangeViewMode_removed(TRUE); lego::map::Map3D_SetEmissive((globs::legoGlobs.currLevel)->map,TRUE); globs::legoGlobs.objectFP = liveObj; if (liveObj->type == LegoObject_MiniFigure) { game::LegoObject_DropCarriedObject(liveObj,FALSE); } lego::view::Viewport_SetCamera(globs::legoGlobs.viewMain,(globs::legoGlobs.cameraFP)->contCam); snd::Sound3D_MakeListener((globs::legoGlobs.cameraFP)->contCam->masterFrame); snd::Sound3D_SetMinDistForAtten(50.0); lego::view::Viewport_SmoothSetField(globs::legoGlobs.viewMain,(float)viewMode); lego::view::Viewport_SetBackClip (globs::legoGlobs.viewMain, (globs::legoGlobs.currLevel)->BlockSize * globs::legoGlobs.FPClipBlocks); globs::legoGlobs.viewMode = VVar1; return; } if (viewMode == ViewMode_Top) { if (globs::legoGlobs.objectFP != NULL) { Lego_Goto(globs::legoGlobs.objectFP,NULL,FALSE); } (globs::legoGlobs.cameraFP)->trackObj = NULL; globs::legoGlobs.objectFP = NULL; debug::Water_ChangeViewMode_removed(FALSE); lego::map::Map3D_SetEmissive((globs::legoGlobs.currLevel)->map,FALSE); lego::view::Viewport_SetCamera(globs::legoGlobs.viewMain,(globs::legoGlobs.cameraMain)->contCam) ; snd::Sound3D_MakeListener((globs::legoGlobs.cameraMain)->contListener->masterFrame); snd::Sound3D_SetMinDistForAtten(globs::legoGlobs.MinDistFor3DSoundsOnTopView); lego::view::Viewport_SetField(globs::legoGlobs.viewMain,0.5); lego::view::Viewport_SetBackClip(globs::legoGlobs.viewMain,globs::legoGlobs.TVClipDist); } globs::legoGlobs.viewMode = viewMode; return; } void __cdecl lego::lrr::Lego_CDTrackPlayNextCallback(void) { snd::Sound_StopCD(); Lego_SetMusicPlaying(TRUE); return; } void __cdecl lego::lrr::Lego_SetMusicPlaying(BOOL isPlaying) { short rng; if (isPlaying != 0) { rng = math::Maths_Rand(); globs::legoGlobs.flags1 |= GAME1_MUSICPLAYING; snd::Sound_PlayCDTrack (((uint)(int)rng % globs::legoGlobs.CDTracks - 1) + globs::legoGlobs.CDStartTrack, SoundMode_Once,Lego_CDTrackPlayNextCallback); return; } globs::legoGlobs.flags1 &= ~GAME1_MUSICPLAYING; snd::Sound_StopCD(); snd::Sound_Update(FALSE); return; } void __cdecl lego::lrr::Lego_SetSoundOn(BOOL isSoundOn) { if (isSoundOn != 0) { globs::legoGlobs.flags1 |= GAME1_USESFX; snd::SFX_SetSoundOn_AndStopAll(isSoundOn); return; } globs::legoGlobs.flags1 &= ~GAME1_USESFX; snd::SFX_SetSoundOn_AndStopAll(FALSE); return; } LegoObject_ID __cdecl lego::lrr::Lego_GetEmergeCreatureID(void) { return (globs::legoGlobs.currLevel)->EmergeCreature; } float10 __cdecl lego::lrr::Lego_GetObjectUpgradeTime(LegoObject_Type objType) { return (float10)(globs::legoGlobs.currLevel)->UpgradeTimes[objType]; } float10 __cdecl lego::lrr::Lego_GetTrainTime(void) { return (float10)(globs::legoGlobs.currLevel)->TrainTime; } // WARNING: Could not reconcile some variable overlaps BOOL __cdecl lego::lrr::Lego_LoadLevel(char *levelName) { float fVar1; Config *config; char cVar2; SaveData *pSVar3; SaveStruct_18 *opt_saveStruct18; BOOL BVar4; int iVar5; Lego_Level *level; char *pcVar6; uint uVar7; BoolTri BVar8; float fVar9; LegoObject *pLVar10; LegoObject **ppLVar11; Lego_Level *pLVar12; float *pfVar13; uint uVar14; float10 fVar15; ColourRGBF *pCVar16; float *pfVar17; float local_1c0; float local_1bc; float local_1b8; char *nameEmergeCreature; LegoObject_Type local_1b0; char *local_1ac; char *local_1a8; char *local_1a4; char *local_1a0; char *local_19c; char *local_198; char *local_194; char *local_190; char *local_18c; char *local_188; char *local_184; Point2F filenameObjectList; char *local_178; char *filenameIntroAVI; char *filenameNERPMessage; char *filenameNERP; char *filenamePTL; uint local_164; char *local_160; char *local_15c; SearchAddCryOre_c searchAddCryOre; LegoObject *local_12c [10]; char local_104 [260]; config = globs::legoGlobs.config; game::Front_PlayLevelMovie(levelName,TRUE); unk::Teleporter_Restart(); front::Front_UpdateOptionsSliders(); front::HelpWindow_IfFlag4_AndParam_Clear1_Set2_Else_Clear3(FALSE); game::Construction_DisableCryOreDrop(FALSE); game::LegoObject_SetLevelEnding(FALSE); pSVar3 = save::Front_Save_GetCurrentSaveData(); if (pSVar3 == NULL) { opt_saveStruct18 = NULL; } else { opt_saveStruct18 = &pSVar3->saveStruct18_1c; } save::Object_Save_OverwriteStruct18(opt_saveStruct18); BVar4 = save::ObjectRecall_IsLoaded(); if ((BVar4 == 0) && (iVar5 = save::Front_Save_GetSaveNumber(), iVar5 != -1)) { std::sprintf(local_104,"%s\\%i.osf","Saves",iVar5); save::ObjectRecall_LoadRROSFile(local_104); } level = (Lego_Level *)io::Mem_Alloc(0x284); if (level == NULL) goto LAB_0042b198; pLVar12 = level; for (iVar5 = 0xa1; iVar5 != 0; iVar5 += -1) { pLVar12->name = NULL; pLVar12 = (Lego_Level *)&pLVar12->map; } globs::legoGlobs.flags1 |= GAME1_LEVELSTART; globs::legoGlobs.currLevel = level; front::Loader_display_loading_bar(levelName); ai::Priorities_LoadLevel(config,globs::legoGlobs.gameName,levelName); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"Seed",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"Seed",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } uVar7 = std::atoi(pcVar6); if (uVar7 != 0) { std::srand(uVar7); } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"BoulderAnimation",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if ((pcVar6 == NULL) || (iVar5 = std::_stricmp(pcVar6,"Rock"), iVar5 == 0)) { LAB_00429989: level->BoulderAnimation = TEXTURES_ROCK; } else { iVar5 = std::_stricmp(pcVar6,"Lava"); if (iVar5 == 0) { level->BoulderAnimation = TEXTURES_LAVA; } else { iVar5 = std::_stricmp(pcVar6,"Ice"); if (iVar5 != 0) goto LAB_00429989; level->BoulderAnimation = TEXTURES_ICE; } } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"FallinMultiplier",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"FallinMultiplier",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } globs::legoGlobs.FallinMultiplier = std::atoi(pcVar6); if (globs::legoGlobs.FallinMultiplier == 0) { globs::legoGlobs.FallinMultiplier = 1; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"blocksize",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"blocksize",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->BlockSize = (float)fVar15; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"digdepth",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"digdepth",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->DigDepth = (float)fVar15; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"useroof",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); level->UseRoof = BVar8; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"roofheight",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"roofheight",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->RoofHeight = (float)fVar15; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"roughlevel",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"roughlevel",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->RoughLevel = (float)fVar15; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"surfacemap",0); local_1a0 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"predugmap",0); local_1a8 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"terrainmap",0); local_194 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"blockPointersMap",0); local_198 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"CryOreMap",0); local_1ac = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"ErodeMap",0); local_18c = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"EmergeMap",0); local_184 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"AIMap",0); local_188 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"PathMap",0); local_1a4 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"FallinMap",0); local_190 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"textureset",0); local_178 = cfg::Config_GetTempStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"EmergeTimeOut",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"EmergeTimeOut",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->EmergeTimeOut = (float)fVar15; if (fVar15 == (float10)0.0) { level->EmergeTimeOut = 1500.0; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"olistfile",0); filenameObjectList.x = (float)cfg::Config_GetTempStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"elistfile",0); cfg::Config_GetTempStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"selboxheight",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"selboxheight",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->SelBoxHeight = (float)fVar15; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"PTLFile",0); filenamePTL = cfg::Config_GetTempStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"NERPFile",0); filenameNERP = cfg::Config_GetTempStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"NERPMessageFile",0); filenameNERPMessage = cfg::Config_GetTempStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"EmergeCreature",0); nameEmergeCreature = cfg::Config_GetTempStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"SafeCaverns",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); level->SafeCaverns = BVar8; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"IntroAVI",0); filenameIntroAVI = cfg::Config_GetTempStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"StartFP",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); level->StartFP = (uint)(BVar8 == BOOL3_TRUE); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"NoDrain",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); level->NoDrain = (uint)(BVar8 == BOOL3_TRUE); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"OxygenRate",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"OxygenRate",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->OxygenRate = (float)(fVar15 * (float10)0.001); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"UpgradeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"UpgradeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); fVar9 = (float)(fVar15 * (float10)25.0); pfVar13 = level->UpgradeTimes; for (iVar5 = 0x14; iVar5 != 0; iVar5 += -1) { *pfVar13 = fVar9; pfVar13 = pfVar13 + 1; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"MinifigureUpgradeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,levelName,"MinifigureUpgradeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); fVar1 = (float)fVar15; level->UpgradeTimes[2] = fVar1; if (fVar1 == 0.0) { level->UpgradeTimes[2] = fVar9; } else { level->UpgradeTimes[2] = fVar1 * 25.0; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"VehicleUpgradeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"VehicleUpgradeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); fVar1 = (float)fVar15; level->UpgradeTimes[1] = fVar1; if (fVar1 == 0.0) { level->UpgradeTimes[1] = fVar9; } else { level->UpgradeTimes[1] = fVar1 * 25.0; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"BuildingUpgradeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"BuildingUpgradeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); fVar1 = (float)fVar15; level->UpgradeTimes[4] = fVar1; if (fVar1 == 0.0) { level->UpgradeTimes[4] = fVar9; } else { level->UpgradeTimes[4] = fVar1 * 25.0; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"TrainTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"TrainTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->TrainTime = (float)(fVar15 * (float10)25.0); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"NoMultiSelect",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags2 |= GAME2_NOMULTISELECT; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"NoAutoEat",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags2 |= GAME2_NOAUTOEAT; } else { globs::legoGlobs.flags2 &= ~GAME2_NOAUTOEAT; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"EndGameAVI1",0); globs::legoGlobs.EndGameAVI1 = cfg::Config_GetStringValue(config,pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"EndGameAVI2",0); globs::legoGlobs.EndGameAVI2 = cfg::Config_GetStringValue(config,pcVar6); if (globs::legoGlobs.RenameReplace != NULL) { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"AllowRename",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags2 |= GAME2_ALLOWRENAME; } else { globs::legoGlobs.flags2 &= ~GAME2_ALLOWRENAME; } } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"RecallOLObjects",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags2 |= GAME2_RECALLOLOBJECTS; } else { globs::legoGlobs.flags2 &= ~GAME2_RECALLOLOBJECTS; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"GenerateSpiders",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags2 |= GAME2_GENERATESPIDERS; } else { globs::legoGlobs.flags2 &= ~GAME2_GENERATESPIDERS; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"DisableToolTipSound",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); if (BVar8 == BOOL3_TRUE) { globs::legoGlobs.flags2 |= GAME2_DISABLETOOLTIPSOUND; } else { globs::legoGlobs.flags2 &= ~GAME2_DISABLETOOLTIPSOUND; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"DisableEndTeleport",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); game::Objective_SetEndTeleportEnabled((uint)(BVar8 != BOOL3_TRUE)); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"DragBoxRGB",0); pcVar6 = cfg::Config_GetStringValue(config,pcVar6); local_19c = pcVar6; if (pcVar6 != NULL) { iVar5 = util::Util_Tokenise(pcVar6,(char **)local_12c,":"); if (iVar5 == 3) { uVar7 = 0; do { local_1b0 = std::atoi(*(char **)((int)local_12c + uVar7)); uVar14 = uVar7 + 4; *(float *)((int)globs::legoGlobs.langUpgradeLevel_name + (uVar7 - 0x2c)) = (float)local_1b0 * 0.003921569; pcVar6 = local_19c; uVar7 = uVar14; } while (uVar14 < 0xc); } io::Mem_Free(pcVar6); } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"BuildingTolerance",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"BuildingTolerance",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->BuildingTolerance = (float)fVar15; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"BuildingMaxVariation",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"BuildingMaxVariation",0) ; pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->BuildingMaxVariation = (float)fVar15; if (level->BuildingTolerance == 0.0) { level->BuildingTolerance = 4.0; } if ((float10)0.0 == fVar15) { level->BuildingMaxVariation = 6.0; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"MaxStolen",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"MaxStolen",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar9 = (float)std::atoi(pcVar6); level->MaxStolen = fVar9; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"Slug",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { level->Slug = 0x14; } else { BVar4 = Lego_GetObjectByName(pcVar6,&local_1b0,(LegoObject_ID *)&level->Slug,NULL); if (BVar4 != 0) { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"SlugTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"SlugTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); level->SlugTime = (float)fVar15; if ((float)fVar15 == 0.0) { level->SlugTime = 60.0; } level->SlugTime = level->SlugTime * 25.0; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"InitialSlugTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"InitialSlugTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); if ((float10)0.0 == fVar15) { fVar15 = (float10)60.0; } globs::legoGlobs.InitialSlugTime = (float)(fVar15 * (float10)25.0); } } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"RockFallStyle",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); effect::Effect_GetRockFallStyle(pcVar6,&local_164); effect::Effect_SetRockFallStyle(local_164); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"noFallins",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); globs::legoGlobs.IsFallinsEnabled = ZEXT14(BVar8 != BOOL3_TRUE); front::Panel_Crystals_LoadRewardQuota(config,globs::legoGlobs.gameName,levelName); Lego_GetObjectByName (nameEmergeCreature,(LegoObject_Type *)&nameEmergeCreature, (LegoObject_ID *)&level->EmergeCreature,NULL); pfVar17 = &globs::legoGlobs.FogColourRGB.blue; pfVar13 = &globs::legoGlobs.FogColourRGB.green; pCVar16 = &globs::legoGlobs.FogColourRGB; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"FogColourRGB",0); BVar4 = cfg::Config_GetRGBValue(globs::legoGlobs.config,pcVar6,&pCVar16->red,pfVar13,pfVar17); if (BVar4 == 0) { globs::legoGlobs.flags1 &= ~GAME1_FOGCOLOURRGB; } else { pfVar17 = &globs::legoGlobs.HighFogColourRGB.blue; pfVar13 = &globs::legoGlobs.HighFogColourRGB.green; pCVar16 = &globs::legoGlobs.HighFogColourRGB; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"HighFogColourRGB",0); BVar4 = cfg::Config_GetRGBValue(globs::legoGlobs.config,pcVar6,&pCVar16->red,pfVar13,pfVar17); if (BVar4 == 0) { globs::legoGlobs.flags1 &= ~GAME1_HIGHFOGCOLOURRGB; } else { globs::legoGlobs.flags1 |= GAME1_HIGHFOGCOLOURRGB; globs::legoGlobs.float_364 = 1.0; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"FogRate",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"FogRate",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); if ((float10)0.0 == fVar15) { globs::legoGlobs.FogRate = 1500.0; } else { globs::legoGlobs.FogRate = (float)fVar15 * 25.0; } } gfx::Container_SetFogColour (globs::legoGlobs.FogColourRGB.red,globs::legoGlobs.FogColourRGB.green, globs::legoGlobs.FogColourRGB.blue); gfx::Container_SetFogMode(D3DRMFOGMETHOD_TABLE); gfx::Container_SetFogParams (0.0,(globs::legoGlobs.currLevel)->BlockSize * globs::legoGlobs.FPClipBlocks,0.0032); globs::legoGlobs.flags1 |= GAME1_FOGCOLOURRGB; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"nextlevel",0); pcVar6 = cfg::Config_GetStringValue(config,pcVar6); level->nextLevelID = pcVar6; pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"FullName",0); nameEmergeCreature = cfg::Config_GetStringValue(config,pcVar6); level->FullName = nameEmergeCreature; if (nameEmergeCreature == NULL) { level->FullName = NULL; } else { iVar5 = -1; uVar7 = 0; pcVar6 = nameEmergeCreature; do { if (iVar5 == 0) break; iVar5 += -1; cVar2 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar2 != '\0'); if (iVar5 != -2) { do { cVar2 = nameEmergeCreature[uVar7]; if (cVar2 == '_') { cVar2 = ' '; } nameEmergeCreature[uVar7] = cVar2; nameEmergeCreature = level->FullName; uVar14 = 0xffffffff; uVar7 += 1; pcVar6 = nameEmergeCreature; do { if (uVar14 == 0) break; uVar14 -= 1; cVar2 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar2 != '\0'); } while (uVar7 < ~uVar14 - 1); } } game::Objective_LoadLevel (config,globs::legoGlobs.gameName,levelName,level,globs::mainGlobs.appWidth, globs::mainGlobs.appHeight); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"ErodeTriggerTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"ErodeTriggerTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); local_1bc = (float)fVar15; if ((float10)0.0 == fVar15) { local_1bc = 10.0; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"ErodeErodeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"ErodeErodeTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); local_1b8 = (float)fVar15; if ((float10)0.0 == fVar15) { local_1b8 = 5.0; } pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"ErodeLockTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"ErodeLockTime",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } fVar15 = std::atof(pcVar6); local_1c0 = (float)fVar15; if ((float10)0.0 == fVar15) { local_1c0 = 60.0; } game::Erode_Initialise(local_1bc,local_1b8,local_1c0); pcVar6 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,levelName,"NumberOfLandSlidesTillCaveIn",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,levelName,"NumberOfLandSlidesTillCaveIn",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } iVar5 = std::atoi(pcVar6); if (iVar5 == 0) { iVar5 = 3; } game::Fallin_Initialise(iVar5); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"DisableStartTeleport",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); level->name = levelName; level->IsStartTeleportEnabled = (uint)(BVar8 != BOOL3_TRUE); level->oxygenLevelMessage = (float)&DAT_42c80000; level->oxygenLevel = (float)&DAT_42c80000; level->crystals = 0; level->ore = 0; level->unused_crystals_90 = 0; level->unused_ore_a4 = 0; level->crystalsPickedUp = 0; level->orePickedUp = 0; level->status = LEVELSTATUS_INCOMPLETE; globs::legoGlobs.placeDestSmallTeleporter = NULL; globs::legoGlobs.placeDestBigTeleporter = NULL; nerps::NERPsFile_LoadScriptFile(filenameNERP); nerps::NERPsFile_LoadMessageFile(filenameNERPMessage); BVar4 = game::PTL_Initialise(filenamePTL,globs::legoGlobs.gameName); if (BVar4 != 0) { local_1bc = 0.0; local_1c0._0_1_ = '\0'; local_1b8 = 0.0; local_19c = NULL; local_1b0 = LegoObject_None; if ((local_1a0 != NULL) && (iVar5 = util::Util_Tokenise(local_1a0,&local_160,":"), iVar5 == 2)) { std::atoi(local_15c); } if ((local_1a8 != NULL) && (iVar5 = util::Util_Tokenise(local_1a8,&local_160,":"), iVar5 == 2)) { local_1b0 = std::atoi(local_15c); } if ((local_194 != NULL) && (iVar5 = util::Util_Tokenise(local_194,&local_160,":"), iVar5 == 2)) { local_19c = (char *)std::atoi(local_15c); } if ((local_198 != NULL) && (iVar5 = util::Util_Tokenise(local_198,&local_160,":"), iVar5 == 2)) { local_1b8 = (float)std::atoi(local_15c); } if ((local_1ac != NULL) && (iVar5 = util::Util_Tokenise(local_1ac,&local_160,":"), iVar5 == 2)) { iVar5 = std::atoi(local_15c); local_1c0._0_1_ = (char)iVar5; } if ((local_1a4 != NULL) && (iVar5 = util::Util_Tokenise(local_1a4,&local_160,":"), iVar5 == 2)) { local_1bc = (float)std::atoi(local_15c); } if ((local_190 != NULL) && (iVar5 = util::Util_Tokenise(local_190,&local_160,":"), iVar5 == 2)) { std::atoi(local_15c); } pcVar6 = local_184; if ((local_184 != NULL) && (iVar5 = util::Util_Tokenise(local_184,&local_160,":"), iVar5 == 2)) { local_1bc = (float)std::atoi(local_15c); } BVar4 = Lego_LoadMapSet(level,local_1a0,local_1a8,local_1b0,local_194,(int)local_19c,local_198, (int)local_1b8,local_1ac,local_1c0._0_1_,local_18c,local_1a4, (int)local_1bc,local_178,pcVar6,local_188,local_190); if (BVar4 != 0) { io::Mem_Free(local_1a0); io::Mem_Free(local_1a8); io::Mem_Free(local_194); io::Mem_Free(local_198); io::Mem_Free(local_1ac); io::Mem_Free(local_18c); io::Mem_Free(pcVar6); io::Mem_Free(local_188); io::Mem_Free(local_190); if (local_1a4 != NULL) { io::Mem_Free(local_1a4); } game::ElectricFence_Restart(level); game::SpiderWeb_Restart(level); game::Objective_SetStatus(LEVELSTATUS_INCOMPLETE); game::Objective_Update(globs::legoGlobs.textOnlyWindow,globs::legoGlobs.currLevel,1.0,1.0); BVar4 = Lego_LoadOLObjectList(level,(char *)filenameObjectList.x); if (BVar4 != 0) { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"InitialCrystals",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,levelName,"InitialCrystals",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } searchAddCryOre.crystalCount = std::atoi(pcVar6); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"InitialOre",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); if (pcVar6 == NULL) { pcVar6 = ____EMPTYSTR__; } else { pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"InitialOre",0); pcVar6 = cfg::Config_GetTempStringValue(config,pcVar6); } searchAddCryOre.oreCount = std::atoi(pcVar6); game::LegoObject_RunThroughListsSkipUpgradeParts (game::Level_AddCryOreToToolStore,&searchAddCryOre); front::Loader_display_loading_bar(NULL); filenameObjectList.x = 350.0; filenameObjectList.y = 70.0; Lego_PlayMovie_old(filenameIntroAVI,&filenameObjectList); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"NoGather",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); ai::AITask_Game_SetNoGather((uint)(BVar8 == BOOL3_TRUE)); front::Info_SetFlag4(TRUE); if ((level->StartFP == 0) || (globs::objectGlobs.minifigureObj_9cb8 == NULL)) { Lego_SetViewMode(ViewMode_Top,NULL,0); } else { Lego_SetViewMode(ViewMode_FP,globs::objectGlobs.minifigureObj_9cb8,1); game::Message_PostEvent(Message_Select,globs::objectGlobs.minifigureObj_9cb8,0,NULL); front::Interface_OpenMenu(Interface_Menu_FP,NULL); } nerps::NERPs_InitBlockPointersTable(level); pcVar6 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,levelName,"Precreate",0); BVar8 = cfg::Config_GetBoolValue(config,pcVar6); if (BVar8 == BOOL3_TRUE) { ppLVar11 = local_12c; iVar5 = 10; do { pLVar10 = game::LegoObject_Create ((int **)globs::legoGlobs.miniFigureData,LegoObject_MiniFigure,0); *ppLVar11 = pLVar10; ppLVar11 = ppLVar11 + 1; iVar5 += -1; } while (iVar5 != 0); ppLVar11 = local_12c; iVar5 = 10; do { game::LegoObject_Remove(*ppLVar11); ppLVar11 = ppLVar11 + 1; iVar5 += -1; } while (iVar5 != 0); } return TRUE; } } } io::Mem_Free(level); LAB_0042b198: io::Mem_Free(local_1a0); io::Mem_Free(local_1a8); io::Mem_Free(local_194); io::Mem_Free(local_198); io::Mem_Free(local_1ac); io::Mem_Free(local_18c); io::Mem_Free(local_184); front::Loader_display_loading_bar(NULL); globs::legoGlobs.currLevel = NULL; return FALSE; } // ANOMALY: This callback adds the cryOre count to EVERY ToolStore. Multiplying the initial number // of resources by number of ToolStores. BOOL __cdecl lego::game::Level_AddCryOreToToolStore(LegoObject *liveObj,SearchAddCryOre_c *search) { StatsFlags1 sflags1; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_STOREOBJECTS) != STATS1_NONE) { LegoObject_AddCrystalsStored(liveObj,search->crystalCount); LegoObject_AddOreStored(liveObj,search->oreCount); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadDetailMeshes(Lego_Level *level,char *meshBaseName) { Detail_Mesh **ppDVar1; Detail_Mesh *pDVar2; int iVar3; uint uVar4; uint uVar5; int local_20c; char meshName_a [256]; char meshName_b [256]; uint width; uint height; height = (level->textureSetSize).height; width = (level->textureSetSize).width; ppDVar1 = (Detail_Mesh **)io::Mem_Alloc(height * width * 4); level->promeshGrid = ppDVar1; if (ppDVar1 == NULL) { return 0; } if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEPROMESHES) == MAIN_FLAG_NONE) { uVar5 = 0; if (height != 0) { local_20c = 0; do { uVar4 = 0; iVar3 = local_20c; if (width != 0) { do { std::sprintf(meshName_a,"%s%0.1x%0.1xa",meshBaseName,uVar4,uVar5); std::sprintf(meshName_b,"%s%0.1x%0.1xb",meshBaseName,uVar4,uVar5); pDVar2 = lego::map::Detail_LoadMeshes (globs::legoGlobs.rootCont,meshName_a,meshName_b,level->BlockSize, level->textureSet); uVar4 += 1; *(Detail_Mesh **)((int)level->promeshGrid + iVar3) = pDVar2; iVar3 = iVar3 + 4; } while (uVar4 < width); } uVar5 += 1; local_20c += width * 4; } while (uVar5 < height); return TRUE; } } else { for (uVar5 = height * width & 0x3fffffff; uVar5 != 0; uVar5 -= 1) { *ppDVar1 = NULL; ppDVar1 = ppDVar1 + 1; } for (iVar3 = 0; iVar3 != 0; iVar3 += -1) { *(undefined *)ppDVar1 = 0; ppDVar1 = (Detail_Mesh **)((int)ppDVar1 + 1); } } return TRUE; } void __cdecl lego::lrr::Lego_FreeDetailMeshes(Lego_Level *level) { Lego_Level *pLVar1; int iVar2; int iVar3; int iVar4; Lego_Level *level_00; int width; level_00 = level; pLVar1 = (Lego_Level *)(level->textureSetSize).height; width = (level->textureSetSize).width; if (pLVar1 != NULL) { iVar3 = 0; iVar2 = width; level = pLVar1; iVar4 = iVar3; do { for (; iVar2 != 0; iVar2 = iVar2 + -1) { lego::map::Detail_FreeMesh(*(Detail_Mesh **)((int)level_00->promeshGrid + iVar3)); iVar3 += 4; } iVar3 = iVar4 + width * 4; level = (Lego_Level *)((int)&level[-1].IsStartTeleportEnabled + 3); iVar2 = width; iVar4 = iVar3; } while (level != NULL); } io::Mem_Free(level_00->promeshGrid); level_00->promeshGrid = NULL; return; } RadarMap * __cdecl lego::lrr::Lego_GetRadarMap(void) { return (globs::legoGlobs.currLevel)->radarMap; } BOOL __cdecl lego::lrr::Lego_LoadMapSet (Lego_Level *level,char *surfaceMap,char *predugMap,int predugParam,char *terrainMap, int terrainParam,char *blockPointersMap,int blockPointersParam,char *cryOreMap, char cryOreParam,char *erodeMap,char *pathMap,int pathParam,char *textureSet, char *emergeMap,char *aiMap,char *fallinMap) { short rng; Map3D *map; RadarMap *radarMap; BOOL BVar1; uint uVar2; int iVar3; uint uVar4; uint uVar5; map = lego::map::Map3D_Create (globs::legoGlobs.rootCont,surfaceMap,level->BlockSize,level->RoughLevel); level->map = map; if (map != NULL) { radarMap = game::RadarMap_Create (map,&globs::legoGlobs.radarScreenRect,globs::legoGlobs.radarZoom); level->radarMap = radarMap; lego::map::Map3D_SetPerspectiveCorrectionAll(level->map,TRUE); // It seems this entire chain of calls is redundant, as they all cause the exact same // effect. // // Original code likely was assigning roof textures for each surface type. // (But all surface types use the same texture, so we get this.) lego::map::Map3D_SetTextureNoFade(level->map,TEXTURE_ROOF_STD); lego::map::Map3D_SetTextureNoFade(level->map,TEXTURE_ROOF_STD); lego::map::Map3D_SetTextureNoFade(level->map,TEXTURE_ROOF_STD); lego::map::Map3D_SetTextureNoFade(level->map,TEXTURE_ROOF_STD); lego::map::Map3D_SetTextureNoFade(level->map,TEXTURE_ROOF_STD); lego::map::Map3D_SetTextureNoFade(level->map,TEXTURE_ROOF_STD); level->width = level->map->gridWidth; level->height = level->map->gridHeight; game::ElectricFence_Restart(level); game::SpiderWeb_Restart(level); if (level->UseRoof != BOOL3_FALSE) { game::Roof_Initialise(globs::legoGlobs.rootCont,level->width,level->height); // Roof is only visible in FirstPerson view, make sure we start with it hidden game::Roof_Hide(TRUE); } map = (Map3D *)Lego_LoadTextureSet(level,textureSet); if (map != NULL) { map = (Map3D *)io::Mem_Alloc(level->height * level->width * 0x48); level->blocks = (Lego_Block *)map; if (map != NULL) { uVar4 = 0; for (uVar2 = level->height * level->width * 0x48 >> 2; uVar2 != 0; uVar2 -= 1) { map->blockWidth = 0; map = (Map3D *)&map->blockHeight; } for (iVar3 = 0; iVar3 != 0; iVar3 += -1) { *(undefined *)&map->blockWidth = 0; map = (Map3D *)((int)&map->blockWidth + 1); } if (level->height != 0) { do { uVar2 = level->width; uVar5 = 0; if (uVar2 != 0) { do { level->blocks[uVar4 * uVar2 + uVar5].predug = Lego_PredugType_Wall; level->blocks[uVar4 * level->width + uVar5].texture = TEXTURE_FLOOR_STD; level->blocks[uVar4 * level->width + uVar5].terrain = Lego_SurfaceType8_Tunnel; level->blocks[uVar4 * level->width + uVar5].flags1 = BLOCK1_NONE; level->blocks[uVar4 * level->width + uVar5].direction = 0; level->blocks[uVar4 * level->width + uVar5].activity = NULL; level->blocks[uVar4 * level->width + uVar5].damage = 0.0; rng = math::Maths_Rand(); iVar3 = uVar4 * level->width + uVar5; uVar5 += 1; level->blocks[iVar3].randomness = rng; uVar2 = level->width; } while (uVar5 < uVar2); } uVar4 += 1; } while (uVar4 < level->height); } map = (Map3D *)Lego_LoadPreDugMap(level,predugMap,predugParam); if (map != NULL) { map = (Map3D *)Lego_LoadTerrainMap(level,terrainMap,terrainParam); if (map != NULL) { Lego_LoadCryOreMap(level,cryOreMap,cryOreParam); Lego_LoadErodeMap(level,erodeMap); Lego_LoadPathMap(level,pathMap,pathParam); Lego_LoadEmergeMap(level,emergeMap); Lego_LoadAIMap(level,aiMap); Lego_LoadFallinMap(level,fallinMap); BVar1 = Lego_LoadBlockPointersMap(level,blockPointersMap,blockPointersParam); if (BVar1 != 0) { level->hasBlockPointers = TRUE; } uVar2 = 0; if (level->height != 0) { do { uVar4 = 0; if (level->width != 0) { do { game::Level_BlockUpdateSurface(level,uVar4,uVar2,1); uVar4 += 1; } while (uVar4 < level->width); } uVar2 += 1; } while (uVar2 < level->height); } lego::map::Map3D_UpdateAllBlockNormals(level->map); game::Water_Initialise(globs::legoGlobs.rootCont,level); map = (Map3D *)TRUE; } } } } } // return FALSE; return (BOOL)map; } void __cdecl lego::lrr::Lego_InitTextureMappings(Map3D *map) { uint i; uint j; SurfaceTexture reinWalls [5]; SurfaceTexture inCorners [5]; SurfaceTexture reinInCorners [5]; SurfaceTexture outCorners [5]; SurfaceTexture reinOutCorner [5]; SurfaceTexture diagonalWalls [5]; SurfaceTexture roofTypes [6]; SurfaceTexture forwardWalls [16]; SurfaceTexture floorTypes [31]; SurfaceTexture roofTex; SurfaceTexture floorTex; roofTypes[0] = TEXTURE_ROOF_STD; roofTypes[1] = TEXTURE_ROOF_STD; roofTypes[2] = TEXTURE_ROOF_STD; roofTypes[3] = TEXTURE_ROOF_STD; roofTypes[4] = TEXTURE_ROOF_STD; roofTypes[5] = TEXTURE_ROOF_STD; forwardWalls[4] = TEXTURE_WALL_SOIL; forwardWalls[5] = TEXTURE_WALL_ORESEAM; forwardWalls[6] = TEXTURE_WALL_CRYSTALSEAM; forwardWalls[7] = TEXTURE_WALL_RECHARGESEAM; forwardWalls[12] = TEXTURE_WALL_SOIL; forwardWalls[13] = TEXTURE_WALL_ORESEAM; forwardWalls[14] = TEXTURE_WALL_CRYSTALSEAM; forwardWalls[15] = TEXTURE_WALL_RECHARGESEAM; floorTypes[0] = TEXTURE_FLOOR_STD; floorTypes[1] = TEXTURE_FLOOR_STD; floorTypes[2] = TEXTURE_FLOOR_STD; floorTypes[3] = TEXTURE_FLOOR_STD; floorTypes[4] = TEXTURE_FLOOR_LAVA; floorTypes[5] = TEXTURE_FLOOR_LAVA_NOTHOT; floorTypes[6] = TEXTURE_FLOOR_WATER; floorTypes[7] = TEXTURE_FLOOR_STD; floorTypes[8] = TEXTURE_FLOOR_PATH_FOUNDATION; floorTypes[9] = TEXTURE_FLOOR_POWERED_FOUNDATION; floorTypes[10] = TEXTURE_FLOOR_RUBBLE_MAX; floorTypes[11] = TEXTURE_FLOOR_RUBBLE_HIGH; floorTypes[12] = TEXTURE_FLOOR_RUBBLE_MED; floorTypes[13] = TEXTURE_FLOOR_RUBBLE_LOW; floorTypes[14] = TEXTURE_FLOOR_ERODE_LOW; floorTypes[15] = TEXTURE_FLOOR_ERODE_MED; floorTypes[16] = TEXTURE_FLOOR_ERODE_HIGH; floorTypes[17] = TEXTURE_FLOOR_ERODE_MAX; floorTypes[18] = TEXTURE_FLOOR_07; floorTypes[19] = TEXTURE_FLOOR_PATH_LAYED; floorTypes[20] = TEXTURE_FLOOR_PATH_4SIDES; floorTypes[21] = TEXTURE_FLOOR_PATH_2SIDES; floorTypes[22] = TEXTURE_FLOOR_PATH_CORNER; floorTypes[23] = TEXTURE_FLOOR_PATH_3SIDES; floorTypes[24] = TEXTURE_FLOOR_PATH_1SIDES; floorTypes[25] = TEXTURE_FLOOR_POWERED_4SIDES; floorTypes[26] = TEXTURE_FLOOR_POWERED_2SIDES; floorTypes[27] = TEXTURE_FLOOR_POWERED_CORNER; floorTypes[28] = TEXTURE_FLOOR_POWERED_3SIDES; floorTypes[29] = TEXTURE_FLOOR_POWERED_1SIDES; floorTypes[30] = TEXTURE_FLOOR_SLUGHOLE; forwardWalls[0] = TEXTURE_WALL_IMM; forwardWalls[1] = TEXTURE_WALL_HARD; forwardWalls[2] = TEXTURE_WALL_MED; forwardWalls[3] = TEXTURE_WALL_LOOSE; forwardWalls[8] = TEXTURE_WALL_IMM; forwardWalls[9] = TEXTURE_WALL_HARD; forwardWalls[10] = TEXTURE_WALL_MED; forwardWalls[11] = TEXTURE_WALL_LOOSE; reinWalls[0] = TEXTURE_REINWALL_IMM; reinWalls[1] = TEXTURE_REINWALL_HARD; reinWalls[2] = TEXTURE_REINWALL_MED; reinWalls[3] = TEXTURE_REINWALL_LOOSE; reinWalls[4] = TEXTURE_REINWALL_SOIL; inCorners[0] = TEXTURE_INCORNER_IMM; inCorners[1] = TEXTURE_INCORNER_HARD; inCorners[2] = TEXTURE_INCORNER_MED; inCorners[3] = TEXTURE_INCORNER_LOOSE; inCorners[4] = TEXTURE_INCORNER_SOIL; reinInCorners[0] = TEXTURE_INCORNER_IMM; reinInCorners[1] = TEXTURE_INCORNER_HARD; reinInCorners[2] = TEXTURE_INCORNER_MED; reinInCorners[3] = TEXTURE_INCORNER_LOOSE; reinInCorners[4] = TEXTURE_INCORNER_SOIL; outCorners[4] = TEXTURE_OUTCORNER_SOIL; reinOutCorner[4] = TEXTURE_OUTCORNER_SOIL; outCorners[0] = TEXTURE_OUTCORNER_IMM; outCorners[1] = TEXTURE_OUTCORNER_HARD; outCorners[2] = TEXTURE_OUTCORNER_MED; outCorners[3] = TEXTURE_OUTCORNER_LOOSE; reinOutCorner[0] = TEXTURE_OUTCORNER_IMM; reinOutCorner[1] = TEXTURE_OUTCORNER_HARD; reinOutCorner[2] = TEXTURE_OUTCORNER_MED; reinOutCorner[3] = TEXTURE_OUTCORNER_LOOSE; diagonalWalls[0] = TEXTURE_DIAGONAL_STD; diagonalWalls[1] = TEXTURE_DIAGONAL_STD; diagonalWalls[2] = TEXTURE_DIAGONAL_STD; diagonalWalls[3] = TEXTURE_DIAGONAL_STD; diagonalWalls[4] = TEXTURE_DIAGONAL_STD; i = 0; do { floorTex = floorTypes[i]; j = 0; do { lego::map::Map3D_AddTextureMapping(map,floorTex,forwardWalls[j]); j += 1; } while (j < 0x10); j = 0; do { lego::map::Map3D_AddTextureMapping(map,floorTex,reinWalls[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,floorTex,inCorners[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,floorTex,reinInCorners[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,floorTex,outCorners[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,floorTex,reinOutCorner[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,floorTex,diagonalWalls[j]); j += 1; } while (j < 5); i += 1; } while (i < 0x1f); i = 0; do { roofTex = roofTypes[i]; j = 0; do { lego::map::Map3D_AddTextureMapping(map,roofTex,forwardWalls[j]); j += 1; } while (j < 0x10); j = 0; do { lego::map::Map3D_AddTextureMapping(map,roofTex,reinWalls[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,roofTex,inCorners[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,roofTex,reinInCorners[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,roofTex,outCorners[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,roofTex,reinOutCorner[j]); j += 1; } while (j < 5); j = 0; do { lego::map::Map3D_AddTextureMapping(map,roofTex,diagonalWalls[j]); j += 1; } while (j < 5); i += 1; } while (i < 6); return; } BOOL __cdecl lego::lrr::Lego_LoadTextureSet(Lego_Level *level,char *keyTexturePath) { Map3D *map; Config *prop; char *pcVar1; int iVar2; int iVar3; char *pcVar4; Detail_TextureSet *tset; BOOL BVar5; BOOL result; prop = globs::legoGlobs.config; result = 0; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,keyTexturePath,"surftextwidth",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,keyTexturePath,"surftextwidth",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); } iVar2 = std::atoi(pcVar1); if (iVar2 != 0) { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,keyTexturePath,"surftextheight",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,keyTexturePath,"surftextheight",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); } iVar3 = std::atoi(pcVar1); if (iVar3 != 0) { map = level->map; (level->textureSetSize).width = iVar2; (level->textureSetSize).height = iVar3; Lego_InitTextureMappings(map); lego::map::Map3D_UpdateAllBlockNormals(level->map); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,keyTexturePath,"meshbasename",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); if (pcVar1 != NULL) { pcVar4 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,keyTexturePath,"texturebasename",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); if (pcVar4 != NULL) { tset = lego::map::Detail_LoadTextureSet (pcVar4,(level->textureSetSize).width,(level->textureSetSize).height); level->textureSet = tset; if (tset != NULL) { lego::map::Map3D_SetTextureSet(level->map,tset); BVar5 = Lego_LoadDetailMeshes(level,pcVar1); if (BVar5 != 0) { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,keyTexturePath,"rooftexture",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); if (pcVar1 != NULL) { BVar5 = game::Roof_SetTexture(pcVar1); if (BVar5 != 0) { result = TRUE; } } } } } } } } return result; } BOOL __cdecl lego::lrr::Lego_LoadPreDugMap(Lego_Level *level,char *filename,int modifier) { int *piVar1; BlockFlags1 *pBVar2; int iVar3; uint uVar4; char *pcVar5; int *piVar6; uint uVar7; int iVar8; uint by; int iVar9; char *bx; uint local_58; uint local_54; Point2I local_50; int local_48 [5]; undefined4 local_34; undefined4 local_30; undefined4 local_2c; undefined4 local_28; undefined4 local_24; undefined4 local_20; undefined4 local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; if ((filename != NULL) && (uVar4 = io::File_LoadBinaryHandle(filename,NULL), uVar4 != 0xffffffff)) { local_54 = uVar4; game::MapShared_GetDimensions(uVar4,(uint *)&filename,&local_58); if ((filename == (char *)level->width) && (local_58 == level->height)) { by = 1; pcVar5 = filename; uVar7 = local_58; if (local_58 != 1 && local_58 != 2) { do { bx = (char *)0x1; if (pcVar5 != (char *)0x1 && pcVar5 != (char *)0x2) { do { uVar4 = game::MapShared_GetBlock(local_54,(int)bx,by); iVar9 = uVar4 - modifier; if ((iVar9 == 1) || (iVar9 == 3)) { game::Level_DestroyWall(level,(uint)bx,by,1); local_48[0] = -1; local_48[1] = 0xffffffff; local_48[3] = 0xffffffff; local_34 = 0xffffffff; local_18 = 0xffffffff; local_10 = 0xffffffff; local_8 = 0; local_48[2] = 0; local_48[4] = 1; local_30 = 1; local_2c = 0; local_28 = 1; local_24 = 1; local_20 = 0; local_1c = 1; local_14 = 1; local_c = 0; local_4 = 0; piVar6 = local_48; iVar8 = 9; do { piVar1 = piVar6 + 1; iVar3 = *piVar6; piVar6 = piVar6 + 2; pBVar2 = &level->blocks[(int)(bx + iVar3 + (*piVar1 + by) * level->width)].flags1; iVar8 += -1; *pBVar2 = *pBVar2 | BLOCK1_EXPOSED; } while (iVar8 != 0); } else { if ((iVar9 == 2) || (iVar9 == 4)) { level->blocks[(int)(bx + by * level->width)].flags1 = level->blocks[(int)(bx + by * level->width)].flags1 | BLOCK1_HIDDEN; } } if (iVar9 == 3) { level->blocks[(int)(bx + by * level->width)].flags2 = level->blocks[(int)(bx + by * level->width)].flags2 | BLOCK2_SLUGHOLE_EXPOSED; local_50.x = (int)bx; local_50.y = by; game::LegoObject_RegisterSlimySlugHole(&local_50); } if (iVar9 == 4) { level->blocks[(int)(bx + by * level->width)].flags2 = level->blocks[(int)(bx + by * level->width)].flags2 | BLOCK2_SLUGHOLE_HIDDEN; } bx = bx + 1; pcVar5 = filename; uVar7 = local_58; } while (bx < filename + -1); } by += 1; uVar4 = local_54; } while (by < uVar7 - 1); } io::Mem_FreeHandle(uVar4); return 1; } io::Mem_FreeHandle(uVar4); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadErodeMap(Lego_Level *level,char *filename) { bool bVar1; short sVar2; uint uVar3; char *pcVar4; uint uVar5; char *bx; uint by; uint local_10; uint local_c; Point2I blockPos; if ((filename != NULL) && (uVar3 = io::File_LoadBinaryHandle(filename,NULL), uVar3 != 0xffffffff)) { local_c = uVar3; game::MapShared_GetDimensions(uVar3,(uint *)&filename,&local_10); if ((filename == (char *)level->width) && (local_10 == level->height)) { by = 0; pcVar4 = filename; uVar5 = local_10; if (local_10 != 0) { do { bx = NULL; if (pcVar4 != NULL) { do { blockPos.x = (int)bx; blockPos.y = by; uVar3 = game::MapShared_GetBlock(local_c,(int)bx,by); bVar1 = false; if ((uVar3 == 0) || ((uVar3 & 1) != 0)) { uVar3 += 1; } else { bVar1 = true; } level->blocks[(int)(bx + by * level->width)].erodeSpeed = (Lego_ErodeType)(uVar3 >> 1) ; if (bVar1) { sVar2 = math::Maths_Rand(); uVar3 = (int)sVar2 >> 0x1f; game::Erode_AddActiveBlock (&blockPos,(((int)sVar2 ^ uVar3) - uVar3 & 3 ^ uVar3) - uVar3); } bx = bx + 1; pcVar4 = filename; uVar5 = local_10; } while (bx < filename); } by += 1; uVar3 = local_c; } while (by < uVar5); } io::Mem_FreeHandle(uVar3); return 1; } io::Mem_FreeHandle(uVar3); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadAIMap(Lego_Level *level,char *filename) { uint memHandle; uint uVar1; char *pcVar2; char *bx; uint by; uint local_4; if ((filename != NULL) && (memHandle = io::File_LoadBinaryHandle(filename,NULL), memHandle != 0xffffffff)) { game::MapShared_GetDimensions(memHandle,(uint *)&filename,&local_4); if ((filename == (char *)level->width) && (local_4 == level->height)) { by = 0; pcVar2 = filename; uVar1 = local_4; if (local_4 != 0) { do { bx = NULL; if (pcVar2 != NULL) { do { uVar1 = game::MapShared_GetBlock(memHandle,(int)bx,by); pcVar2 = bx + by * level->width; bx = bx + 1; level->blocks[(int)pcVar2].aiNode = (byte)uVar1; pcVar2 = filename; uVar1 = local_4; } while (bx < filename); } by += 1; } while (by < uVar1); } io::Mem_FreeHandle(memHandle); return 1; } io::Mem_FreeHandle(memHandle); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadEmergeMap(Lego_Level *level,char *filename) { BlockFlags2 *pBVar1; uint memHandle; uint blockVal; EmergeTrigger *pEVar2; uint uVar3; int iVar4; char *pcVar5; uint emrgType; uint emrgID; uint bx; uint width; char *height; uint mapHandle; if (filename != NULL) { memHandle = io::File_LoadBinaryHandle(filename,NULL); mapHandle = memHandle; if (((memHandle != 0xffffffff) && (game::MapShared_GetDimensions(memHandle,&width,(uint *)&height), width == level->width)) && (height == (char *)level->height)) { filename = NULL; uVar3 = width; pcVar5 = height; if (height != NULL) { do { bx = 0; if (uVar3 != 0) { do { blockVal = game::MapShared_GetBlock(mapHandle,bx,(int)filename); if (blockVal != 0) { emrgType = (blockVal - 1) % 6; emrgID = (blockVal - 1) / 6; uVar3 = emrgID + 1; if (level->emergeCount < uVar3) { if (level->emergeTriggers == NULL) { pEVar2 = (EmergeTrigger *)io::Mem_Alloc(uVar3 * 0x4c); } else { pEVar2 = (EmergeTrigger *)io::Mem_ReAlloc(level->emergeTriggers,uVar3 * 0x4c); } level->emergeTriggers = pEVar2; pEVar2 = level->emergeTriggers + level->emergeCount; for (uVar3 = ((emrgID - level->emergeCount) + 1) * 0x13 & 0x3fffffff; uVar3 != 0; uVar3 -= 1) { pEVar2->field_0 = 0; pEVar2 = (EmergeTrigger *)&pEVar2->blockPos; } for (iVar4 = 0; iVar4 != 0; iVar4 += -1) { *(undefined *)&pEVar2->field_0 = 0; pEVar2 = (EmergeTrigger *)((int)&pEVar2->field_0 + 1); } level->emergeCount = emrgID + 1; } if (emrgType == 0) { iVar4 = (int)filename * level->width + bx; level->blocks[iVar4].flags2 = level->blocks[iVar4].flags2 | BLOCK2_EMERGE_TRIGGER; level->emergeTriggers[emrgID].blockPos.x = bx; level->emergeTriggers[emrgID].blockPos.y = (int)filename; } else { pBVar1 = &level->blocks[(int)filename * level->width + bx].flags2; *pBVar1 = *pBVar1 | BLOCK2_EMERGE_POINT; level->emergeTriggers[emrgID].emergePoints[emrgType - 1].blockPos.x = bx; level->emergeTriggers[emrgID].emergePoints[emrgType - 1].blockPos.y = (int)filename; level->emergeTriggers[emrgID].emergePoints[emrgType - 1].used = 1; } } bx += 1; uVar3 = width; pcVar5 = height; } while (bx < width); } filename = filename + 1; memHandle = mapHandle; } while (filename < pcVar5); } io::Mem_FreeHandle(memHandle); return TRUE; } io::Mem_FreeHandle(memHandle); } return 0; } BOOL __cdecl lego::game::Level_HandleEmergeTriggers (Lego_Level *level,Point2I *blockPos,Point2I *out_emergeBlockPos) { LegoObject *pLVar1; int iVar2; int iVar3; int iVar4; uint uVar5; uint local_4; iVar3 = 0; local_4 = 0; if (level->emergeCount == 0) { return 0; } do { iVar4 = (int)level->emergeTriggers->emergePoints + iVar3 + -0x10; if (((blockPos->x == *(int *)(iVar4 + 4)) && (blockPos->y == *(int *)(iVar4 + 8))) && ((ushort)((ushort)(*(float *)(iVar4 + 0xc) < 0.0) << 8 | (ushort)(*(float *)(iVar4 + 0xc) == 0.0) << 0xe) != 0)) { iVar4 = 0; uVar5 = 0; do { if (*(int *)((int)&level->emergeTriggers->emergePoints[0].used + iVar3 + uVar5) != 0) { iVar2 = (int)level->emergeTriggers->emergePoints + iVar3 + uVar5 + -0x10; pLVar1 = LegoObject_TryGenerateRMonster (globs::legoGlobs.rockMonsterData + level->EmergeCreature, LegoObject_RockMonster,level->EmergeCreature,*(uint *)(iVar2 + 0x10), *(uint *)(iVar2 + 0x14)); if (pLVar1 != NULL) { level->emergeTriggers[local_4].timeout = level->EmergeTimeOut; if (out_emergeBlockPos != NULL) { out_emergeBlockPos->x = level->emergeTriggers[local_4].emergePoints[iVar4].blockPos.x; out_emergeBlockPos->y = level->emergeTriggers[local_4].emergePoints[iVar4].blockPos.y; } return TRUE; } } uVar5 += 0xc; iVar4 += 1; } while (uVar5 < 0x3c); } local_4 += 1; iVar3 += 0x4c; } while (local_4 < level->emergeCount); return 0; } void __cdecl lego::game::Level_Emerge_FUN_0042c370(Lego_Level *level,float elapsedAbs) { float *pfVar1; float fVar2; int ptrOff; uint i; i = 0; if (level->emergeCount != 0) { ptrOff = 0; do { fVar2 = *(float *)((int)level->emergeTriggers->emergePoints + ptrOff + -4); pfVar1 = (float *)((int)level->emergeTriggers->emergePoints + ptrOff + -4); if ((ushort)((ushort)(fVar2 < 0.0) << 8 | (ushort)(fVar2 == 0.0) << 0xe) == 0) { *pfVar1 = *pfVar1 - elapsedAbs; } i += 1; ptrOff += 0x4c; } while (i < level->emergeCount); } return; } BOOL __cdecl lego::lrr::Lego_LoadTerrainMap(Lego_Level *level,char *filename,int modifier) { Lego_SurfaceType8 LVar1; uint memHandle; uint uVar2; int iVar3; char *pcVar4; uint by; char *bx; uint local_c; Point2I local_8; memHandle = io::File_LoadBinaryHandle(filename,NULL); if (memHandle != 0xffffffff) { game::MapShared_GetDimensions(memHandle,(uint *)&filename,&local_c); if ((filename == (char *)level->width) && (local_c == level->height)) { by = 0; pcVar4 = filename; uVar2 = local_c; if (local_c != 0) { do { bx = NULL; if (pcVar4 != NULL) { do { uVar2 = game::MapShared_GetBlock(memHandle,(int)bx,by); iVar3 = uVar2 - modifier; // Soil SurfaceType was removed, change to Dirt if (iVar3 == 5) { iVar3 = 4; } level->blocks[(int)(bx + by * level->width)].terrain = (Lego_SurfaceType8)iVar3; LVar1 = level->blocks[(int)(bx + by * level->width)].terrain; if (LVar1 == Lego_SurfaceType8_Lava) { level->blocks[(int)(bx + by * level->width)].erodeLevel = 4; } else { if (LVar1 == Lego_SurfaceType8_RechargeSeam) { local_8.x = (int)bx; local_8.y = by; game::LegoObject_RegisterRechargeSeam(&local_8); game::Level_BlockActivity_Create(level,&local_8,TRUE); } } bx = bx + 1; pcVar4 = filename; uVar2 = local_c; } while (bx < filename); } by += 1; } while (by < uVar2); } io::Mem_FreeHandle(memHandle); return 1; } io::Mem_FreeHandle(memHandle); } return 0; } BOOL __cdecl lego::lrr::Lego_GetBlockCryOre (Point2I *blockPos,uint *out_crystalLv0,uint *out_crystalLv1,uint *out_oreLv0, uint *out_oreLv1) { uint uVar1; uint uVar2; int CRYORE_COUNTS [5]; uVar2 = (uint)(globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].cryOre; CRYORE_COUNTS[0] = 1; uVar1 = uVar2 - 1; *out_oreLv1 = 0; *out_oreLv0 = 0; *out_crystalLv1 = 0; CRYORE_COUNTS[1] = 3; CRYORE_COUNTS[2] = 5; CRYORE_COUNTS[3] = 10; CRYORE_COUNTS[4] = 0x19; *out_crystalLv0 = 0; if (uVar2 != 0) { uVar2 = *(uint *)((int)CRYORE_COUNTS + (uVar1 & 0xfffffffc)); switch(uVar1 & 3) { case 0: *out_crystalLv0 = uVar2; return 1; case 1: *out_oreLv0 = uVar2; return 1; case 2: *out_crystalLv1 = uVar2; return 1; case 3: *out_oreLv1 = uVar2; } return 1; } return 0; } BOOL __cdecl lego::lrr::Lego_LoadCryOreMap(Lego_Level *level,char *filename,char modifier) { uint memHandle; uint uVar1; char *pcVar2; char *bx; uint by; uint local_4; memHandle = io::File_LoadBinaryHandle(filename,NULL); if (memHandle != 0xffffffff) { game::MapShared_GetDimensions(memHandle,(uint *)&filename,&local_4); if ((filename == (char *)level->width) && (local_4 == level->height)) { by = 0; pcVar2 = filename; uVar1 = local_4; if (local_4 != 0) { do { bx = NULL; if (pcVar2 != NULL) { do { uVar1 = game::MapShared_GetBlock(memHandle,(int)bx,by); pcVar2 = bx + by * level->width; bx = bx + 1; level->blocks[(int)pcVar2].cryOre = (char)uVar1 - modifier; pcVar2 = filename; uVar1 = local_4; } while (bx < filename); } by += 1; } while (by < uVar1); } io::Mem_FreeHandle(memHandle); return 1; } io::Mem_FreeHandle(memHandle); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadPathMap(Lego_Level *level,char *filename,int modifier) { BlockFlags1 *pBVar1; BlockFlags1 BVar2; uint uVar3; BOOL BVar4; char *pcVar5; uint uVar6; uint by; int iVar7; char *bx; uint local_10; uint local_c; Point2I local_8; if ((filename != NULL) && (uVar3 = io::File_LoadBinaryHandle(filename,NULL), uVar3 != 0xffffffff)) { local_c = uVar3; game::MapShared_GetDimensions(uVar3,(uint *)&filename,&local_10); if ((filename == (char *)level->width) && (local_10 == level->height)) { by = 0; pcVar5 = filename; uVar6 = local_10; if (local_10 != 0) { do { bx = NULL; if (pcVar5 != NULL) { do { local_8.x = (int)bx; local_8.y = by; uVar3 = game::MapShared_GetBlock(local_c,(int)bx,by); pBVar1 = &level->blocks[(int)(bx + by * level->width)].flags1; BVar2 = *pBVar1; if ((BVar2 & BLOCK1_FLOOR) != BLOCK1_NONE) { if (uVar3 - modifier == 2) { *pBVar1 = BVar2 | BLOCK1_PATH; } else { if ((((uVar3 - modifier == 1) && (((globs::legoGlobs.currLevel)->blocks [(int)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)].flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE)) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks [(int)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y )].flags2 & 4) == 0)) && ((((globs::legoGlobs.currLevel)->blocks [(int)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)].flags1 & BLOCK1_BUILDINGPATH) == BLOCK1_NONE && (BVar4 = game::Construction_Zone_ExistsAtBlock(&local_8), BVar4 == 0)))) { (globs::legoGlobs.currLevel)->blocks [(int)(char *)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)]. flags1 = (globs::legoGlobs.currLevel)->blocks [(int)(char *)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)].flags1 & ~BLOCK1_CLEARED; (globs::legoGlobs.currLevel)->blocks [(int)(char *)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)]. flags1 = (globs::legoGlobs.currLevel)->blocks [(int)(char *)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)].flags1 & ~BLOCK1_PATH; (globs::legoGlobs.currLevel)->blocks [(int)(char *)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)]. flags1 = (globs::legoGlobs.currLevel)->blocks [(int)(char *)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)].flags1 & ~BLOCK1_LAYEDPATH; game::LegoObject_RequestPowerGridUpdate(); ai::AITask_RemoveAttackPathReferences(&local_8); util::logf_removed((char *)&local_8); iVar7 = 4; do { ai::AITask_DoClear_AtPosition(&local_8,Message_ClearInitialComplete); iVar7 += -1; } while (iVar7 != 0); (globs::legoGlobs.currLevel)->blocks [(int)(char *)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)]. flags1 = (globs::legoGlobs.currLevel)->blocks [(int)(char *)(local_8.x + (globs::legoGlobs.currLevel)->width * local_8.y)].flags1 | BLOCK1_RUBBLE_FULL; } } } bx = bx + 1; pcVar5 = filename; uVar6 = local_10; } while (bx < filename); } by += 1; uVar3 = local_c; } while (by < uVar6); } io::Mem_FreeHandle(uVar3); return 1; } io::Mem_FreeHandle(uVar3); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadFallinMap(Lego_Level *level,char *filename) { uint uVar1; char *pcVar2; uint uVar3; uint by; char *bx; uint local_10; uint sharedIndex; uint local_8; undefined4 uStack4; globs::legoGlobs.hasFallins = 0; if ((filename != NULL) && (uVar1 = io::File_LoadBinaryHandle(filename,NULL), uVar1 != 0xffffffff)) { sharedIndex = uVar1; game::MapShared_GetDimensions(uVar1,(uint *)&filename,&local_10); if ((filename == (char *)level->width) && (local_10 == level->height)) { by = 0; pcVar2 = filename; uVar3 = local_10; if (local_10 != 0) { do { bx = NULL; if (pcVar2 != NULL) { do { uVar1 = game::MapShared_GetBlock(sharedIndex,(int)bx,by); level->blocks[(int)(bx + by * level->width)].fallinIntensity = 0; if (uVar1 != 0) { level->blocks[(int)(bx + by * level->width)].fallinIntensity = uVar1; // * 25 (0x19) local_8 = (uint)(int)level->blocks[(int)(bx + by * level->width)].randomness % (uVar1 * globs::legoGlobs.FallinMultiplier * 0x19); uStack4 = 0; level->blocks[(int)(bx + by * level->width)].fallinTimer = (float)(ulonglong)local_8 ; level->blocks[(int)(bx + by * level->width)].fallinUpper = 0; if (4 < uVar1) { level->blocks[(int)(bx + by * level->width)].fallinIntensity = uVar1 - 4; level->blocks[(int)(bx + by * level->width)].fallinUpper = TRUE; } } bx = bx + 1; pcVar2 = filename; uVar3 = local_10; } while (bx < filename); } by += 1; uVar1 = sharedIndex; } while (by < uVar3); } globs::legoGlobs.hasFallins = TRUE; io::Mem_FreeHandle(uVar1); return TRUE; } io::Mem_FreeHandle(uVar1); } return 0; } void __cdecl lego::lrr::Lego_UpdateFallins(float elapsedGame) { uint uVar1; uint uVar2; Lego_Level *level; int iVar3; BOOL BVar4; uint uVar5; uint uVar6; Point2I position; Lego_Block *block; level = Lego_GetLevel(); if ((((globs::legoGlobs.hasFallins != 0) && (uVar1 = level->width, uVar1 != 0)) && (uVar2 = level->height, uVar2 != 0)) && (uVar5 = 0, uVar2 != 0)) { do { uVar6 = 0; if (uVar1 != 0) { do { block = level->blocks + uVar5 * level->width + uVar6; if (block->fallinIntensity != 0) { block->fallinTimer = elapsedGame + block->fallinTimer; iVar3 = uVar5 * level->width + uVar6; block = level->blocks + iVar3; if ((float)(ulonglong) (level->blocks[iVar3].fallinIntensity * globs::legoGlobs.FallinMultiplier * 0x19) < block->fallinTimer) { block->fallinTimer = 0.0; position.x = uVar6; position.y = uVar5; BVar4 = game::Fallin_Block_FUN_0040f0c0 (&position,level->blocks[uVar5 * level->width + uVar6].fallinUpper); if (BVar4 != 0) { front::Info_Send(Info_Landslide,NULL,NULL,&position); } } } uVar6 += 1; } while (uVar6 < uVar1); } uVar5 += 1; } while (uVar5 < uVar2); } return; } BOOL __cdecl lego::lrr::Lego_LoadBlockPointersMap(Lego_Level *level,char *filename,int modifier) { uint memHandle; uint uVar1; char *pcVar2; char *bx; uint by; uint local_4; if ((filename != NULL) && (memHandle = io::File_LoadBinaryHandle(filename,NULL), memHandle != 0xffffffff)) { game::MapShared_GetDimensions(memHandle,(uint *)&filename,&local_4); if ((filename == (char *)level->width) && (local_4 == level->height)) { by = 0; pcVar2 = filename; uVar1 = local_4; if (local_4 != 0) { do { bx = NULL; if (pcVar2 != NULL) { do { uVar1 = game::MapShared_GetBlock(memHandle,(int)bx,by); pcVar2 = bx + by * level->width; bx = bx + 1; level->blocks[(int)pcVar2].blockpointer = (char)uVar1 - (char)modifier; pcVar2 = filename; uVar1 = local_4; } while (bx < filename); } by += 1; } while (by < uVar1); } io::Mem_FreeHandle(memHandle); return 1; } io::Mem_FreeHandle(memHandle); } return 0; } Upgrade_PartModel * __cdecl lego::lrr::Lego_GetUpgradePartModel(char *upgradeName) { int cmp; uint i; i = 0; if (globs::legoGlobs.upgradeCount == 0) { return NULL; } do { cmp = std::_stricmp(upgradeName,globs::legoGlobs.upgradeName[i]); if (cmp == 0) { return globs::legoGlobs.upgradeData + i; } i += 1; } while (i < globs::legoGlobs.upgradeCount); return NULL; } BOOL __cdecl lego::lrr::Lego_LoadVehicleTypes(void) { char cVar1; char *pcVar2; Config *pCVar3; BOOL BVar4; uint uVar5; uint uVar6; int iVar7; undefined4 *puVar8; undefined4 *puVar9; int local_4; iVar7 = 0; globs::legoGlobs.vehicleCount = 0; local_4 = 0; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"VehicleTypes",0); for (pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); pCVar3 != NULL; pCVar3 = cfg::Config_GetNextItem(pCVar3)) { globs::legoGlobs.vehicleCount += 1; } if ((globs::legoGlobs.vehicleCount != 0) && (globs::legoGlobs.vehicleData = (VehicleModel *)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 0x1ec), globs::legoGlobs.vehicleData != NULL)) { globs::legoGlobs.vehicleName = (char **)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4); if (globs::legoGlobs.vehicleName != NULL) { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"VehicleTypes",0); pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); while ((pCVar3 != NULL && (BVar4 = gfx::Vehicle_Load((VehicleModel *) ((int)(globs::legoGlobs.vehicleData)->contWheels + iVar7 + -0x10),local_4,globs::legoGlobs.rootCont, pCVar3->value,globs::legoGlobs.gameName), BVar4 != 0))) { gfx::Vehicle_Hide((VehicleModel *) ((int)(globs::legoGlobs.vehicleData)->contWheels + iVar7 + -0x10),TRUE); uVar5 = 0xffffffff; pcVar2 = pCVar3->key; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); pcVar2 = (char *)io::Mem_Alloc(~uVar5); iVar7 += 0x1ec; globs::legoGlobs.vehicleName[local_4] = pcVar2; uVar5 = 0xffffffff; puVar8 = (undefined4 *)pCVar3->key; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *(char *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); } while (cVar1 != '\0'); puVar8 = (undefined4 *)pCVar3->key; puVar9 = (undefined4 *)globs::legoGlobs.vehicleName[local_4]; for (uVar6 = ~uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar9 = *puVar8; puVar8 = puVar8 + 1; puVar9 = puVar9 + 1; } local_4 += 1; for (uVar5 = ~uVar5 & 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } pCVar3 = cfg::Config_GetNextItem(pCVar3); } if (pCVar3 == NULL) { return TRUE; } io::Mem_Free(globs::legoGlobs.vehicleName); } io::Mem_Free(globs::legoGlobs.vehicleData); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadMiniFigureTypes(void) { char cVar1; char *pcVar2; Config *pCVar3; BOOL BVar4; uint uVar5; uint uVar6; int iVar7; undefined4 *puVar8; undefined4 *puVar9; LegoObject_ID local_4; iVar7 = 0; globs::legoGlobs.miniFigureCount = 0; local_4 = 0; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiniFigureTypes",0); for (pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); pCVar3 != NULL; pCVar3 = cfg::Config_GetNextItem(pCVar3)) { globs::legoGlobs.miniFigureCount += 1; } if ((globs::legoGlobs.miniFigureCount != 0) && (globs::legoGlobs.miniFigureData = (CreatureModel *)io::Mem_Alloc(globs::legoGlobs.miniFigureCount * 0x74), globs::legoGlobs.miniFigureData != NULL)) { globs::legoGlobs.miniFigureName = (char **)io::Mem_Alloc(globs::legoGlobs.miniFigureCount * 4); if (globs::legoGlobs.miniFigureName != NULL) { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"MiniFigureTypes",0); pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); while ((pCVar3 != NULL && (BVar4 = gfx::Creature_Load((CreatureModel *) ((globs::legoGlobs.miniFigureData)->reserved1 + iVar7 + -8) ,local_4,globs::legoGlobs.rootCont,pCVar3->value, globs::legoGlobs.gameName), BVar4 != 0))) { gfx::Object_Hide((BasicObjectModel *) ((globs::legoGlobs.miniFigureData)->reserved1 + iVar7 + -8),TRUE); uVar5 = 0xffffffff; pcVar2 = pCVar3->key; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); pcVar2 = (char *)io::Mem_Alloc(~uVar5); iVar7 += 0x74; globs::legoGlobs.miniFigureName[local_4] = pcVar2; uVar5 = 0xffffffff; puVar8 = (undefined4 *)pCVar3->key; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *(char *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); } while (cVar1 != '\0'); puVar8 = (undefined4 *)pCVar3->key; puVar9 = (undefined4 *)globs::legoGlobs.miniFigureName[local_4]; for (uVar6 = ~uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar9 = *puVar8; puVar8 = puVar8 + 1; puVar9 = puVar9 + 1; } local_4 += 1; for (uVar5 = ~uVar5 & 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } pCVar3 = cfg::Config_GetNextItem(pCVar3); } if (pCVar3 == NULL) { return TRUE; } io::Mem_Free(globs::legoGlobs.miniFigureName); } io::Mem_Free(globs::legoGlobs.miniFigureData); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadRockMonsterTypes(void) { char cVar1; char *pcVar2; Config *pCVar3; BOOL BVar4; uint uVar5; uint uVar6; int iVar7; undefined4 *puVar8; undefined4 *puVar9; LegoObject_ID local_4; iVar7 = 0; globs::legoGlobs.rockMonsterCount = 0; local_4 = 0; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"RockMonsterTypes",0); for (pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); pCVar3 != NULL; pCVar3 = cfg::Config_GetNextItem(pCVar3)) { globs::legoGlobs.rockMonsterCount += 1; } if ((globs::legoGlobs.rockMonsterCount != 0) && (globs::legoGlobs.rockMonsterData = (CreatureModel *)io::Mem_Alloc(globs::legoGlobs.rockMonsterCount * 0x74), globs::legoGlobs.rockMonsterData != NULL)) { globs::legoGlobs.rockMonsterName = (char **)io::Mem_Alloc(globs::legoGlobs.rockMonsterCount * 4) ; if (globs::legoGlobs.rockMonsterName != NULL) { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"RockMonsterTypes",0); pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); while ((pCVar3 != NULL && (BVar4 = gfx::Creature_Load((CreatureModel *) ((globs::legoGlobs.rockMonsterData)->reserved1 + iVar7 + -8 ),local_4,globs::legoGlobs.rootCont,pCVar3->value, globs::legoGlobs.gameName), BVar4 != 0))) { gfx::Object_Hide((BasicObjectModel *) ((globs::legoGlobs.rockMonsterData)->reserved1 + iVar7 + -8),TRUE); uVar5 = 0xffffffff; pcVar2 = pCVar3->key; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); pcVar2 = (char *)io::Mem_Alloc(~uVar5); iVar7 += 0x74; globs::legoGlobs.rockMonsterName[local_4] = pcVar2; uVar5 = 0xffffffff; puVar8 = (undefined4 *)pCVar3->key; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *(char *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); } while (cVar1 != '\0'); puVar8 = (undefined4 *)pCVar3->key; puVar9 = (undefined4 *)globs::legoGlobs.rockMonsterName[local_4]; for (uVar6 = ~uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar9 = *puVar8; puVar8 = puVar8 + 1; puVar9 = puVar9 + 1; } local_4 += 1; for (uVar5 = ~uVar5 & 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } pCVar3 = cfg::Config_GetNextItem(pCVar3); } if (pCVar3 == NULL) { return TRUE; } io::Mem_Free(globs::legoGlobs.rockMonsterName); } io::Mem_Free(globs::legoGlobs.rockMonsterData); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadBuildingTypes(void) { char cVar1; char *pcVar2; Config *pCVar3; BOOL BVar4; uint uVar5; uint uVar6; int iVar7; undefined4 *puVar8; undefined4 *puVar9; LegoObject_ID local_4; iVar7 = 0; globs::legoGlobs.buildingCount = 0; local_4 = 0; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"BuildingTypes",0); for (pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); pCVar3 != NULL; pCVar3 = cfg::Config_GetNextItem(pCVar3)) { globs::legoGlobs.buildingCount += 1; } if ((globs::legoGlobs.buildingCount != 0) && (globs::legoGlobs.buildingData = (BuildingModel *)io::Mem_Alloc(globs::legoGlobs.buildingCount * 0x14c), globs::legoGlobs.buildingData != NULL)) { globs::legoGlobs.buildingName = (char **)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4); if (globs::legoGlobs.buildingName != NULL) { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"BuildingTypes",0); pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); while ((pCVar3 != NULL && (BVar4 = gfx::Building_Load((BuildingModel *) ((int)(globs::legoGlobs.buildingData)->carryNulls + iVar7 + -0x28),local_4,globs::legoGlobs.rootCont, pCVar3->value,globs::legoGlobs.gameName), BVar4 != 0))) { gfx::Building_Hide((BuildingModel *) ((int)(globs::legoGlobs.buildingData)->carryNulls + iVar7 + -0x28),TRUE); uVar5 = 0xffffffff; pcVar2 = pCVar3->key; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); pcVar2 = (char *)io::Mem_Alloc(~uVar5); iVar7 += 0x14c; globs::legoGlobs.buildingName[local_4] = pcVar2; uVar5 = 0xffffffff; puVar8 = (undefined4 *)pCVar3->key; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *(char *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); } while (cVar1 != '\0'); puVar8 = (undefined4 *)pCVar3->key; puVar9 = (undefined4 *)globs::legoGlobs.buildingName[local_4]; for (uVar6 = ~uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar9 = *puVar8; puVar8 = puVar8 + 1; puVar9 = puVar9 + 1; } local_4 += 1; for (uVar5 = ~uVar5 & 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } pCVar3 = cfg::Config_GetNextItem(pCVar3); } if (pCVar3 == NULL) { return TRUE; } io::Mem_Free(globs::legoGlobs.buildingName); } io::Mem_Free(globs::legoGlobs.buildingData); } return 0; } BOOL __cdecl lego::lrr::Lego_LoadUpgradeTypes(void) { char cVar1; char *pcVar2; Config *pCVar3; uint uVar4; uint uVar5; int iVar6; undefined4 *puVar7; undefined4 *puVar8; int local_4; iVar6 = 0; globs::legoGlobs.upgradeCount = 0; local_4 = 0; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"UpgradeTypes",0); for (pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); pCVar3 != NULL; pCVar3 = cfg::Config_GetNextItem(pCVar3)) { globs::legoGlobs.upgradeCount += 1; } if ((globs::legoGlobs.upgradeCount != 0) && (globs::legoGlobs.upgradeData = (Upgrade_PartModel *)io::Mem_Alloc(globs::legoGlobs.upgradeCount << 4), globs::legoGlobs.upgradeData != NULL)) { globs::legoGlobs.upgradeName = (char **)io::Mem_Alloc(globs::legoGlobs.upgradeCount * 4); if (globs::legoGlobs.upgradeName != NULL) { pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"UpgradeTypes",0); for (pCVar3 = cfg::Config_FindArray(globs::legoGlobs.config,pcVar2); pCVar3 != NULL; pCVar3 = cfg::Config_GetNextItem(pCVar3)) { gfx::Upgrade_Part_Load ((Upgrade_PartModel *)((int)&(globs::legoGlobs.upgradeData)->objID + iVar6), local_4,globs::legoGlobs.rootCont,pCVar3->value); gfx::Object_Hide((BasicObjectModel *)((int)&(globs::legoGlobs.upgradeData)->objID + iVar6), TRUE); uVar4 = 0xffffffff; pcVar2 = pCVar3->key; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); pcVar2 = (char *)io::Mem_Alloc(~uVar4); iVar6 += 0x10; globs::legoGlobs.upgradeName[local_4] = pcVar2; uVar4 = 0xffffffff; puVar7 = (undefined4 *)pCVar3->key; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *(char *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); } while (cVar1 != '\0'); puVar7 = (undefined4 *)pCVar3->key; puVar8 = (undefined4 *)globs::legoGlobs.upgradeName[local_4]; for (uVar5 = ~uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar7; puVar7 = puVar7 + 1; puVar8 = puVar8 + 1; } local_4 += 1; for (uVar4 = ~uVar4 & 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } if (true) { return TRUE; } io::Mem_Free(globs::legoGlobs.upgradeName); } io::Mem_Free(globs::legoGlobs.upgradeData); } return 0; } void __cdecl lego::lrr::Lego_LoadObjectNames(Config *config) { char *pcVar1; uint id; uint uVar2; globs::legoGlobs.langVehicle_name = (char **)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4); id = 0; if (globs::legoGlobs.vehicleCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectNames",globs::legoGlobs.vehicleName[id],0 ); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langVehicle_name[id] = pcVar1; id += 1; } while (id < globs::legoGlobs.vehicleCount); } globs::legoGlobs.langMiniFigure_name = (char **)io::Mem_Alloc(globs::legoGlobs.miniFigureCount * 4); id = 0; if (globs::legoGlobs.miniFigureCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectNames", globs::legoGlobs.miniFigureName[id],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langMiniFigure_name[id] = pcVar1; id += 1; } while (id < globs::legoGlobs.miniFigureCount); } globs::legoGlobs.langRockMonster_name = (char **)io::Mem_Alloc(globs::legoGlobs.rockMonsterCount * 4); id = 0; if (globs::legoGlobs.rockMonsterCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectNames", globs::legoGlobs.rockMonsterName[id],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langRockMonster_name[id] = pcVar1; id += 1; } while (id < globs::legoGlobs.rockMonsterCount); } globs::legoGlobs.langBuilding_name = (char **)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4); id = 0; if (globs::legoGlobs.buildingCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectNames",globs::legoGlobs.buildingName[id], 0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langBuilding_name[id] = pcVar1; id += 1; } while (id < globs::legoGlobs.buildingCount); } globs::legoGlobs.langUpgrade_name = (char **)io::Mem_Alloc(globs::legoGlobs.upgradeCount * 4); id = 0; if (globs::legoGlobs.upgradeCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectNames",globs::legoGlobs.upgradeName[id],0 ); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langUpgrade_name[id] = pcVar1; } uVar2 = id + 1; globs::legoGlobs.langUpgrade_name[id] = NULL; id = uVar2; } while (uVar2 < globs::legoGlobs.upgradeCount); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","PowerCrystal",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langPowerCrystal_name = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","Ore",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langOre_name = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","ProcessedOre",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langProcessedOre_name = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","Dynamite",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langDynamite_name = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","Barrier",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langBarrier_name = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","ElectricFence",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langElectricFence_name = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","SpiderWeb",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langSpiderWeb_name = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","OohScary",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langOohScary_name = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectNames","Path",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langPath_name = util::Util_RemoveUnderscores(pcVar1); } return; } void __cdecl lego::lrr::Lego_LoadObjectTheNames(Config *config) { char *pcVar1; uint id; uint uVar2; globs::legoGlobs.langVehicle_theName = (char **)io::Mem_Alloc(globs::legoGlobs.vehicleCount * 4); id = 0; if (globs::legoGlobs.vehicleCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectTheNames", globs::legoGlobs.vehicleName[id],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langVehicle_theName[id] = pcVar1; id += 1; } while (id < globs::legoGlobs.vehicleCount); } globs::legoGlobs.langMiniFigure_theName = (char **)io::Mem_Alloc(globs::legoGlobs.miniFigureCount * 4); id = 0; if (globs::legoGlobs.miniFigureCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectTheNames", globs::legoGlobs.miniFigureName[id],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langMiniFigure_theName[id] = pcVar1; id += 1; } while (id < globs::legoGlobs.miniFigureCount); } globs::legoGlobs.langRockMonster_theName = (char **)io::Mem_Alloc(globs::legoGlobs.rockMonsterCount * 4); id = 0; if (globs::legoGlobs.rockMonsterCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectTheNames", globs::legoGlobs.rockMonsterName[id],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langRockMonster_theName[id] = pcVar1; id += 1; } while (id < globs::legoGlobs.rockMonsterCount); } globs::legoGlobs.langBuilding_theName = (char **)io::Mem_Alloc(globs::legoGlobs.buildingCount * 4) ; id = 0; if (globs::legoGlobs.buildingCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectTheNames", globs::legoGlobs.buildingName[id],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langBuilding_theName[id] = pcVar1; id += 1; } while (id < globs::legoGlobs.buildingCount); } globs::legoGlobs.langUpgrade_theName = (char **)io::Mem_Alloc(globs::legoGlobs.upgradeCount * 4); id = 0; if (globs::legoGlobs.upgradeCount != 0) { do { pcVar1 = cfg::Config_BuildStringID (globs::legoGlobs.gameName,"ObjectTheNames", globs::legoGlobs.upgradeName[id],0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { pcVar1 = util::Util_RemoveUnderscores(pcVar1); globs::legoGlobs.langUpgrade_theName[id] = pcVar1; } uVar2 = id + 1; globs::legoGlobs.langUpgrade_theName[id] = NULL; id = uVar2; } while (uVar2 < globs::legoGlobs.upgradeCount); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","PowerCrystal",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langPowerCrystal_theName = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","Ore",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langOre_theName = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","ProcessedOre",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langProcessedOre_theName = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","Dynamite",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langDynamite_theName = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","Barrier",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langBarrier_theName = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","ElectricFence",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langElectricFence_theName = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","SpiderWeb",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langSpiderWeb_theName = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","OohScary",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langOohScary_theName = util::Util_RemoveUnderscores(pcVar1); } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ObjectTheNames","Path",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.langPath_theName = util::Util_RemoveUnderscores(pcVar1); } return; } void __cdecl lego::lrr::Lego_Goto(LegoObject *liveObj,Point2I *blockPos,BOOL smooth) { Point2F *pPVar1; int iVar2; uint scrollBlockX; uint scrollBlockY; uint bx; uint by; Point2F *pPVar3; Point2I blockPos2; Lego_Level *level; Map3D *map; level = globs::legoGlobs.currLevel; globs::legoGlobs.gotoSmooth = smooth; if (liveObj == NULL) { if (smooth == 0) { map = (globs::legoGlobs.currLevel)->map; pPVar1 = &globs::legoGlobs.gotoNewPos; pPVar3 = &globs::legoGlobs.gotoNewPos; by = blockPos->y; bx = blockPos->x; } else { pPVar1 = &globs::legoGlobs.gotoTargetPos; pPVar3 = &globs::legoGlobs.gotoTargetPos; by = blockPos->y; bx = blockPos->x; map = (globs::legoGlobs.currLevel)->map; } lego::map::Map3D_BlockToWorldPos(map,bx,by,&pPVar3->x,&pPVar1->y); blockPos2.x = blockPos->x; blockPos2.y = blockPos->y; } else { if (smooth == 0) { pPVar1 = &globs::legoGlobs.gotoNewPos; pPVar3 = &globs::legoGlobs.gotoNewPos; } else { pPVar1 = &globs::legoGlobs.gotoTargetPos; pPVar3 = &globs::legoGlobs.gotoTargetPos; } game::LegoObject_GetPosition(liveObj,&pPVar3->x,&pPVar1->y); game::LegoObject_GetBlockPos(liveObj,&blockPos2.x,&blockPos2.y); } scrollBlockY = blockPos2.y; scrollBlockX = blockPos2.x; iVar2 = lego::view::Camera_GetMouseScrollIndent(); if (blockPos2.x < iVar2) { scrollBlockX = lego::view::Camera_GetMouseScrollIndent(); } iVar2 = lego::view::Camera_GetMouseScrollIndent(); if ((int)(level->map->blockWidth - iVar2) <= blockPos2.x) { iVar2 = lego::view::Camera_GetMouseScrollIndent(); scrollBlockX = (level->map->blockWidth - iVar2) - 1; } iVar2 = lego::view::Camera_GetMouseScrollIndent(); if (blockPos2.y < iVar2) { scrollBlockY = lego::view::Camera_GetMouseScrollIndent(); } iVar2 = lego::view::Camera_GetMouseScrollIndent(); if ((int)(level->map->blockHeight - iVar2) <= blockPos2.y) { iVar2 = lego::view::Camera_GetMouseScrollIndent(); scrollBlockY = (level->map->blockHeight - iVar2) - 1; } if ((blockPos2.x != scrollBlockX) || (blockPos2.y != scrollBlockY)) { if (smooth == 0) { pPVar1 = &globs::legoGlobs.gotoNewPos; pPVar3 = &globs::legoGlobs.gotoNewPos; map = (globs::legoGlobs.currLevel)->map; } else { pPVar1 = &globs::legoGlobs.gotoTargetPos; pPVar3 = &globs::legoGlobs.gotoTargetPos; map = (globs::legoGlobs.currLevel)->map; } lego::map::Map3D_BlockToWorldPos(map,scrollBlockX,scrollBlockY,&pPVar3->x,&pPVar1->y); } globs::legoGlobs.flags1 = globs::legoGlobs.flags1 | GAME1_CAMERAGOTO; return; } void __cdecl lego::lrr::Lego_RemoveRecordObject(LegoObject *liveObj) { LegoObject **pRecordObj; uint i; i = 0; if (globs::legoGlobs.recordObjsCount != 0) { pRecordObj = globs::legoGlobs.recordObjs; do { if (liveObj == *pRecordObj) { *pRecordObj = NULL; } i += 1; pRecordObj = pRecordObj + 1; } while (i < globs::legoGlobs.recordObjsCount); } return; } BOOL __cdecl lego::lrr::Lego_GetRecordObject(uint recordObjPtr,LegoObject **out_liveObj) { LegoObject *liveObj; if ((recordObjPtr < globs::legoGlobs.recordObjsCount) && (liveObj = globs::legoGlobs.recordObjs[recordObjPtr], *out_liveObj = liveObj, liveObj != NULL)) { return TRUE; } return FALSE; } BOOL __cdecl lego::lrr::Lego_LoadOLObjectList(Lego_Level *level,char *filename) { LegoObject *liveObj; float heading; Config *prop; char *pcVar1; Config *prop_00; Config *pCVar2; uint by; BOOL BVar3; BlockFlags1 BVar4; Point2I *shapeBlocks; StatsFlags3 SVar5; StatsFlags1 SVar6; int iVar7; char **ppcVar8; LegoObject *pLVar9; Direction rotation; uint uVar10; LegoObject **ppLVar11; bool bVar12; float10 fVar13; float10 fVar14; float10 fVar15; float10 fVar16; ulonglong uVar17; ulonglong uVar18; longlong lVar19; float trackTilt; float trackRotationSpeed; LegoObject_AbilityFlags trainFlags; uint local_9c8; LegoObject_Type objType; Point2F worldPos; float objYpos; float objHeading; uint local_9b0; float objXpos; int objIndex; float objHealth; LegoObject **local_9a0; char *objDrivenByName; int local_998; Config *local_994; Container *objSrcData; char *objTypeName; uint shapeCount; Point2I shapeTranslation; char *objDrivingName; Point2F hiddenWorldPos; LegoObject *local_960 [200]; char *local_640 [200]; char *apcStack800 [200]; bVar12 = false; local_998 = 1; local_9c8 = 0; prop = cfg::Config_Load(filename); local_994 = prop; if (prop != NULL) { ppLVar11 = globs::legoGlobs.recordObjs; for (iVar7 = 10; iVar7 != 0; iVar7 += -1) { *ppLVar11 = NULL; ppLVar11 = ppLVar11 + 1; } globs::legoGlobs.recordObjsCount = 0; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,0); prop_00 = cfg::Config_FindArray(prop,pcVar1); if (prop_00 != NULL) { local_9a0 = local_960; do { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"type",0); objTypeName = cfg::Config_GetStringValue(prop,pcVar1); if (objTypeName == NULL) break; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"xpos",0); pCVar2 = cfg::Config_FindItem(prop,pcVar1); if (pCVar2 == NULL) break; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"ypos",0); pCVar2 = cfg::Config_FindItem(prop,pcVar1); if (pCVar2 == NULL) break; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"heading",0); pCVar2 = cfg::Config_FindItem(prop,pcVar1); if (pCVar2 == NULL) break; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"xpos",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"xpos",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); } fVar13 = std::atof(pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"ypos",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"ypos",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); } fVar14 = std::atof(pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"heading",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"heading",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); } fVar15 = std::atof(pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"health",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"health",0); pcVar1 = cfg::Config_GetTempStringValue(prop,pcVar1); } fVar16 = std::atof(pcVar1); objHealth = (float)fVar16; if ((float10)0.0 == fVar16) { objHealth = (float)&DAT_42c80000; } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,prop_00->key,"driving",0); pcVar1 = cfg::Config_GetStringValue(prop,pcVar1); apcStack800[local_9c8] = pcVar1; objDrivenByName = util::Util_StrCpy(prop_00->key); local_640[local_9c8] = objDrivenByName; uVar17 = __ftol((float10)((float)fVar13 - 1.0)); uVar10 = (uint)uVar17; uVar18 = __ftol((float10)((float)fVar14 - 1.0)); by = (uint)uVar18; lego::map::Map3D_BlockToWorldPos(level->map,uVar10,by,&worldPos.x,&worldPos.y); worldPos.x = worldPos.x + (((float)fVar13 - 1.0) - ((float)(uVar17 & 0xffffffff) - -0.5)) * level->BlockSize; worldPos.y = worldPos.y - (((float)fVar14 - 1.0) - ((float)(uVar18 & 0xffffffff) - -0.5)) * level->BlockSize; heading = (float)fVar15 * 0.005555556 * 3.141593; BVar3 = Lego_GetObjectByName(objTypeName,&objType,(LegoObject_ID *)&objIndex,&objSrcData); if (BVar3 == 0) break; pLVar9 = NULL; if (objType == LegoObject_TVCamera) { lego::view::Camera_SetTopdownPosition(globs::legoGlobs.cameraMain,worldPos.x,worldPos.y); lego::view::Camera_SetRotation(globs::legoGlobs.cameraMain,heading); lego::view::Camera_SetTilt(globs::legoGlobs.cameraMain,0.8); globs::legoGlobs.radarCenter.x = worldPos.x; globs::legoGlobs.radarCenter.y = worldPos.y; globs::legoGlobs.radarZoom = 15.0; } else { if ((uVar10 < (globs::legoGlobs.currLevel)->width - 1) && (by < (globs::legoGlobs.currLevel)->height - 1)) { BVar4 = (globs::legoGlobs.currLevel)->blocks [by * (globs::legoGlobs.currLevel)->width + uVar10].flags1 & BLOCK1_FLOOR; } else { BVar4 = BLOCK1_NONE; } if (BVar4 == BLOCK1_NONE) { hiddenWorldPos.x = worldPos.x; hiddenWorldPos.y = worldPos.y; game::HiddenObject_Add (objSrcData,objType,objIndex,&hiddenWorldPos,heading,objHealth,objDrivenByName ,pcVar1); } else { if (objType == LegoObject_Building) { shapeTranslation.x = uVar10; shapeTranslation.y = by; objDrivenByName = (char *)gfx::Building_GetShapePoints (globs::legoGlobs.buildingData + objIndex,&shapeCount); lVar19 = __ftol((float10)heading * (float10)0.1591549 * (float10)8.0); rotation = ((uint)lVar19 & 1) + (uint)lVar19 >> 1; shapeBlocks = gfx::SelectPlace_TransformShapePoints (&shapeTranslation,(Point2I *)objDrivenByName,shapeCount, rotation); pLVar9 = game::Construction_SpawnBuilding (objIndex,&shapeTranslation,rotation,shapeBlocks,shapeCount, level->IsStartTeleportEnabled); if (pLVar9 != NULL) { game::LegoObject_FUN_00438720(pLVar9); } } else { pLVar9 = game::LegoObject_Create((int **)objSrcData,objType,objIndex); } } } *local_9a0 = pLVar9; if (pLVar9 != NULL) { if (local_998 != 0) { trackRotationSpeed = 0.01; trackTilt = 0.7; fVar13 = stats::StatsObject_GetTrackDist(pLVar9); lego::view::Camera_TrackObject (globs::legoGlobs.cameraTrack,pLVar9,2.0,(float)fVar13,trackTilt, trackRotationSpeed); } local_998 = 0; if (objType != LegoObject_Building) { game::LegoObject_SetPositionAndHeading(pLVar9,worldPos.x,worldPos.y,heading,TRUE); } if ((((objType == LegoObject_PowerCrystal) || (objType == LegoObject_Ore)) || (objType == LegoObject_Dynamite)) || (objType == LegoObject_Barrier)) { ai::AITask_DoCollect(pLVar9,0.0); } if ((globs::objectGlobs.minifigureObj_9cb8 == NULL) && (pLVar9->type == LegoObject_MiniFigure)) { globs::objectGlobs.minifigureObj_9cb8 = pLVar9; } if (globs::legoGlobs.recordObjsCount < 10) { globs::legoGlobs.recordObjs[globs::legoGlobs.recordObjsCount] = pLVar9; globs::legoGlobs.recordObjsCount += 1; } pLVar9->flags4 = pLVar9->flags4 | LIVEOBJ4_DONTSHOWHELPWINDOW; pLVar9->health = objHealth; front::HelpWindow_RecallDependencies(pLVar9->type,pLVar9->id,0,TRUE); if ((globs::legoGlobs.flags2 & GAME2_RECALLOLOBJECTS) != GAME2_NONE) { game::ObjectRecall_RecallMiniFigure(pLVar9); } game::LegoObject_RegisterVehicle__callsForWater(pLVar9); if (objType == LegoObject_SpiderWeb) { pLVar9->flags3 = pLVar9->flags3 | LIVEOBJ3_UNK_10000; gfx::Container_SetActivity(pLVar9->other,"FlapInWind"); gfx::Container_SetAnimationTime(pLVar9->other,0.0); game::SpiderWeb_Add(uVar10,by,pLVar9); } else { if (objType == LegoObject_ElectricFence) { game::ElectricFence_CreateFence(pLVar9); } } } io::Mem_Free(objTypeName); local_9c8 += 1; local_9a0 = local_9a0 + 1; prop_00 = cfg::Config_GetNextItem(prop_00); prop = local_994; } while (prop_00 != NULL); bVar12 = prop_00 == NULL; } cfg::Config_Free(prop); } if (!bVar12) { return 0; } local_9b0 = 0; if (local_9c8 != 0) { do { pLVar9 = local_960[local_9b0]; if ((pLVar9 != NULL) && (pcVar1 = apcStack800[local_9b0], pcVar1 != NULL)) { uVar10 = 0; ppcVar8 = local_640; do { iVar7 = std::_stricmp(pcVar1,*ppcVar8); if (iVar7 == 0) { liveObj = local_960[uVar10]; if (liveObj != NULL) { pLVar9->routeToObject = liveObj; pLVar9->flags2 = pLVar9->flags2 | LIVEOBJ2_UNK_4; SVar5 = stats::StatsObject_GetStatsFlags3(liveObj); if ((SVar5 & STATS3_NEEDSPILOT) == STATS3_NONE) { SVar6 = stats::StatsObject_GetStatsFlags1(liveObj); if ((SVar6 & STATS1_CROSSWATER) == STATS1_NONE) { trainFlags = ABILITY_FLAG_DRIVER; } else { SVar6 = stats::StatsObject_GetStatsFlags1(liveObj); if ((SVar6 & STATS1_CROSSLAND) == STATS1_NONE) { trainFlags = ABILITY_FLAG_SAILOR; } else { trainFlags = ABILITY_FLAG_PILOT; } } } else { trainFlags = ABILITY_FLAG_PILOT; } game::LegoObject_TrainMiniFigure_instantunk(pLVar9,trainFlags); game::LegoObject_ClearDockOccupiedFlag(pLVar9,liveObj); } break; } uVar10 += 1; ppcVar8 = ppcVar8 + 1; } while (uVar10 < local_9c8); } local_9b0 += 1; } while (local_9b0 < local_9c8); } uVar10 = 0; if (local_9c8 != 0) { do { if (local_640[uVar10] != NULL) { io::Mem_Free(local_640[uVar10]); } if (apcStack800[uVar10] != NULL) { io::Mem_Free(apcStack800[uVar10]); } uVar10 += 1; } while (uVar10 < local_9c8); } return 1; } BOOL __cdecl lego::lrr::Lego_GetObjectByName (char *objName,LegoObject_Type *out_objType,LegoObject_ID *out_objID, Container **optout_model) { int iVar1; uint index; index = 0; *out_objID = 0; if (globs::legoGlobs.rockMonsterCount != 0) { do { iVar1 = std::_stricmp(globs::legoGlobs.rockMonsterName[index],objName); if (iVar1 == 0) { *out_objType = LegoObject_RockMonster; *out_objID = index; if (optout_model == NULL) { return 1; } *optout_model = (Container *)(globs::legoGlobs.rockMonsterData + index); return 1; } index += 1; } while (index < globs::legoGlobs.rockMonsterCount); } iVar1 = std::_stricmp("tvcamera",objName); if (iVar1 == 0) { *out_objType = LegoObject_TVCamera; if (optout_model != NULL) { *optout_model = NULL; return 1; } } else { iVar1 = std::_stricmp("PowerCrystal",objName); if (iVar1 == 0) { *out_objType = LegoObject_PowerCrystal; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contCrystal; return 1; } } else { iVar1 = std::_stricmp("Ore",objName); if (iVar1 == 0) { *out_objType = LegoObject_Ore; *out_objID = 0; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contOresTable[0]; return 1; } } else { iVar1 = std::_stricmp("ProcessedOre",objName); if (iVar1 == 0) { *out_objType = LegoObject_Ore; *out_objID = 1; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contOresTable[1]; return 1; } } else { iVar1 = std::_stricmp("Boulder",objName); if (iVar1 == 0) { *out_objType = LegoObject_Boulder; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contBoulder; return 1; } } else { iVar1 = std::_stricmp("Pusher",objName); if (iVar1 == 0) { *out_objType = LegoObject_Pusher; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contPusher; return 1; } } else { iVar1 = std::_stricmp("LaserShot",objName); if (iVar1 == 0) { *out_objType = LegoObject_LaserShot; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contLaserShot; return 1; } } else { iVar1 = std::_stricmp("Freezer",objName); if (iVar1 == 0) { *out_objType = LegoObject_Freezer; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contFreezer; return 1; } } else { iVar1 = std::_stricmp("Dynamite",objName); if (iVar1 == 0) { *out_objType = LegoObject_Dynamite; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contDynamite; return 1; } } else { iVar1 = std::_stricmp("ElectricFence",objName); if (iVar1 == 0) { *out_objType = LegoObject_ElectricFence; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contElectricFence; return 1; } } else { iVar1 = std::_stricmp("SpiderWeb",objName); if (iVar1 == 0) { *out_objType = LegoObject_SpiderWeb; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contSpiderWeb; return 1; } } else { iVar1 = std::_stricmp("Barrier",objName); if (iVar1 == 0) { *out_objType = LegoObject_Barrier; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contBarrier; return 1; } } else { iVar1 = std::_stricmp("OohScary",objName); if (iVar1 == 0) { *out_objType = LegoObject_OohScary; if (optout_model != NULL) { *optout_model = globs::legoGlobs.contOohScary; return 1; } } else { iVar1 = std::_stricmp("Path",objName); if (iVar1 == 0) { *out_objType = LegoObject_Path; if (optout_model != NULL) { *optout_model = NULL; return 1; } } else { index = 0; if (globs::legoGlobs.vehicleCount != 0) { do { iVar1 = std::_stricmp(globs::legoGlobs.vehicleName[index],objName) ; if (iVar1 == 0) { *out_objType = LegoObject_Vehicle; *out_objID = index; if (optout_model == NULL) { return 1; } *optout_model = (Container *)(globs::legoGlobs.vehicleData + index); return 1; } index += 1; } while (index < globs::legoGlobs.vehicleCount); } index = 0; if (globs::legoGlobs.miniFigureCount != 0) { do { iVar1 = std::_stricmp(globs::legoGlobs.miniFigureName[index], objName); if (iVar1 == 0) { *out_objType = LegoObject_MiniFigure; *out_objID = index; if (optout_model == NULL) { return 1; } *optout_model = (Container *)(globs::legoGlobs.miniFigureData + index); return 1; } index += 1; } while (index < globs::legoGlobs.miniFigureCount); } index = 0; if (globs::legoGlobs.buildingCount == 0) { return 0; } while (iVar1 = std::_stricmp(globs::legoGlobs.buildingName[index], objName), iVar1 != 0) { index += 1; if (globs::legoGlobs.buildingCount <= index) { return 0; } } *out_objType = LegoObject_Building; *out_objID = index; if (optout_model != NULL) { *optout_model = (Container *)(globs::legoGlobs.buildingData + index) ; } } } } } } } } } } } } } } } return 1; } BOOL __cdecl lego::lrr::Lego_GetObjectTypeModel (LegoObject_Type objType,LegoObject_ID objID,Container **out_model) { if (objType == LegoObject_TVCamera) { *out_model = NULL; return 1; } if (objType == LegoObject_PowerCrystal) { *out_model = globs::legoGlobs.contCrystal; return 1; } if (objType == LegoObject_Ore) { *out_model = globs::legoGlobs.contOresTable[objID]; return 1; } if (objType == LegoObject_Dynamite) { *out_model = globs::legoGlobs.contDynamite; return 1; } if (objType == LegoObject_Barrier) { *out_model = globs::legoGlobs.contBarrier; return 1; } if (objType == LegoObject_ElectricFence) { *out_model = globs::legoGlobs.contElectricFence; return 1; } if (objType == LegoObject_SpiderWeb) { *out_model = globs::legoGlobs.contSpiderWeb; return 1; } if (objType == LegoObject_OohScary) { *out_model = globs::legoGlobs.contOohScary; return 1; } if (objType == LegoObject_Path) { *out_model = NULL; return 1; } if (objType == LegoObject_Boulder) { *out_model = globs::legoGlobs.contBoulder; return 1; } if (objType == LegoObject_Vehicle) { *out_model = (Container *)(globs::legoGlobs.vehicleData + objID); return 1; } if (objType == LegoObject_MiniFigure) { *out_model = (Container *)(globs::legoGlobs.miniFigureData + objID); return 1; } if (objType == LegoObject_RockMonster) { *out_model = (Container *)(globs::legoGlobs.rockMonsterData + objID); return 1; } if (objType == LegoObject_Building) { *out_model = (Container *)(globs::legoGlobs.buildingData + objID); return 1; } if (objType == LegoObject_Pusher) { *out_model = globs::legoGlobs.contPusher; return 1; } if (objType == LegoObject_LaserShot) { *out_model = globs::legoGlobs.contLaserShot; return 1; } if (objType == LegoObject_Freezer) { *out_model = globs::legoGlobs.contFreezer; return 1; } return 0; } int __cdecl lego::lrr::Lego_GetObjectTypeIDCount(LegoObject_Type objType) { uint uVar1; uVar1 = objType + LegoObject_TVCamera; switch(objType) { case LegoObject_Vehicle: return globs::legoGlobs.vehicleCount; case LegoObject_MiniFigure: return globs::legoGlobs.miniFigureCount; case LegoObject_RockMonster: return globs::legoGlobs.rockMonsterCount; case LegoObject_Building: return globs::legoGlobs.buildingCount; case LegoObject_Boulder: case LegoObject_PowerCrystal: case LegoObject_Dynamite: case LegoObject_Barrier: case LegoObject_ElectricFence: case LegoObject_SpiderWeb: case LegoObject_OohScary: case LegoObject_ElectricFenceStud: case LegoObject_Path: case LegoObject_Pusher: case LegoObject_Freezer: case LegoObject_IceCube: case LegoObject_LaserShot: uVar1 = 1; break; case LegoObject_Ore: return 2; case LegoObject_UpgradePart: return globs::legoGlobs.upgradeCount; } return uVar1; } // This is an old method for playing movies. // It supports playing a movie that isn't just in the center of the screen // (which can be seen by setting certain Level CFG AVI properties). // All movie playback seen in LegoRR is done by Front_PlayMovie (which supports // skipping, and scales to screen, but not playing at a specified position). void __cdecl lego::lrr::Lego_PlayMovie_old(char *fName,Point2F *opt_screenPt) { Movie_t *mov; int iVar1; BOOL doFillSurface; RECT *lpRect; longlong lVar2; RECT rect; Point2F *opt_screenPt_00; if (fName == NULL) { return; } mov = video::Movie_Load(fName); opt_screenPt_00 = opt_screenPt; if (mov == NULL) { return; } if (opt_screenPt == NULL) { doFillSurface = TRUE; if (true) goto LAB_0042ef98; } else { video::Movie_GetSize(mov,(uint *)&fName,(uint *)&opt_screenPt); lVar2 = __ftol((float10)opt_screenPt_00->x); rect.left = (LONG)lVar2; lVar2 = __ftol((float10)opt_screenPt_00->y); rect.top = (LONG)lVar2; lVar2 = __ftol((float10)ZEXT48(fName) + (float10)opt_screenPt_00->x); rect.right = (LONG)lVar2; lVar2 = __ftol((float10)ZEXT48(opt_screenPt) + (float10)opt_screenPt_00->y); rect.bottom = (LONG)lVar2; doFillSurface = 0; } ddraw::DirectDraw_ReturnFrontBuffer(); LAB_0042ef98: lpRect = (RECT *)(~-(uint)(doFillSurface != 0) & (uint)&rect); iVar1 = video::Movie_Update(mov,1.0,lpRect); while (iVar1 != 0) { main::Main_LoopUpdate(doFillSurface); iVar1 = video::Movie_Update(mov,1.0,lpRect); } video::Movie_Free(mov); return; } // Returns string containing name of nextLevel. char * __cdecl lego::game::Level_Free(void) { char *nextLevelID; Lego_Level *level; level = globs::legoGlobs.currLevel; nextLevelID = NULL; if (globs::legoGlobs.currLevel != NULL) { io::Mem_Free((globs::legoGlobs.currLevel)->emergeTriggers); if (globs::legoGlobs.EndGameAVI1 != NULL) { io::Mem_Free(globs::legoGlobs.EndGameAVI1); } if (globs::legoGlobs.EndGameAVI2 != NULL) { io::Mem_Free(globs::legoGlobs.EndGameAVI2); } io::Mem_Free(level->FullName); globs::legoGlobs.flags1 &= ~(GAME1_CAMERAGOTO|GAME1_LEVELENDING); globs::objectGlobs.flags &= ~OBJECT_GLOB_FLAG_CYCLEUNITS; globs::legoGlobs.flags2 &= ~(GAME2_LEVELEXITING|GAME2_NOMULTISELECT); globs::legoGlobs.gotoSmooth = 0; globs::legoGlobs.objTeleportQueue_COUNT = 0; globs::objectGlobs.minifigureObj_9cb8 = NULL; globs::objectGlobs.cycleUnitCount = 0; globs::objectGlobs.cycleBuildingCount = 0; lrr::Lego_SetCallToArmsOn(0); globs::legoGlobs.flags1 &= ~GAME1_LASERTRACKER; globs::legoGlobs.flags2 &= ~(GAME2_ATTACKDEFER|GAME2_MESSAGE_HASNEXT|GAME2_MESSAGE_HASREPEAT|GAME2_MENU_HASNEXT); globs::legoGlobs.poweredBlockCount = 0; globs::legoGlobs.unpoweredBlockCount = 0; lego::view::Camera_Shake(globs::legoGlobs.cameraMain,0.0,0.0); lego::view::Camera_SetZoom(globs::legoGlobs.cameraMain,200.0); effect::Smoke_RemoveAll(); lrr::Lego_StopUserAction(); nextLevelID = level->nextLevelID; front::Text_Clear(); front::HelpWindow_ClearFlag1(); Dependencies_Reset_ClearAllLevelFlags_10c(); nerps::NERPs_FreeBlockPointers(); ai::AITask_CleanupLevel(FALSE); LegoObject_CleanupLevel(); Construction_RemoveAll(); effect::Effect_StopAll(); ai::AITask_CleanupLevel(TRUE); front::Info_SetFlag4(FALSE); Roof_Shutdown(); lego::view::Camera_TrackObject(globs::legoGlobs.cameraTrack,NULL,0.0,0.0,0.0,0.0); lego::view::Camera_SetFPObject(globs::legoGlobs.cameraFP,NULL,0); Message_CleanupSelectedUnitsCount(); nerps::NERPsFile_Free(); RadarMap_Free_UnwindMultiUse(level->radarMap); lego::map::Map3D_Remove(level->map); lrr::Lego_FreeDetailMeshes(level); lego::map::Detail_FreeTextureSet(level->textureSet); Level_BlockActivity_RemoveAll(level); effect::Effect_RemoveAll_BoulderExplode(); io::Mem_Free(level->blocks); io::Mem_Free(level); front::Info_ClearAllMessages(); front::Interface_ClearStates(); lrr::Lego_SetGameSpeed(1.0); front::Panel_ResetAll(); front::Advisor_Stop(); snd::Sound3D_StopAllSounds(); effect::DamageFont_Cleanup(); } globs::legoGlobs.currLevel = NULL; return nextLevelID; } void __cdecl lego::game::Level_Block_SetNotHot(Lego_Level *level,uint bx,uint by,BOOL notHot) { BlockFlags1 *pFlags1; if (notHot != 0) { pFlags1 = &level->blocks[level->width * by + bx].flags1; *pFlags1 = *pFlags1 | BLOCK1_NOTHOT; Level_BlockUpdateSurface(level,bx,by,0); return; } pFlags1 = &level->blocks[level->width * by + bx].flags1; *pFlags1 = *pFlags1 & ~BLOCK1_NOTHOT; Level_BlockUpdateSurface(level,bx,by,0); return; } SurfaceTexture __cdecl lego::game::Level_Block_ChoosePathTexture(int bx,int by,byte *ref_direction,BOOL powered) { BlockFlags1 BVar1; uint i; int bxOff; int *pDirY; int byOff; DirectionFlags connectionBits; Point2I DIRECTIONS [4]; DIRECTIONS[1].x = 1; DIRECTIONS[2].y = 1; DIRECTIONS[0].x = 0; DIRECTIONS[0].y = -1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].x = -1; DIRECTIONS[3].y = 0; connectionBits = DIRECTION_FLAG_NONE; i = 0; pDirY = &DIRECTIONS[0].y; do { bxOff = pDirY[-1] + bx; byOff = by + *pDirY; if ((((bxOff < 0) || (byOff < 0)) || ((int)(globs::legoGlobs.currLevel)->width <= bxOff)) || ((int)(globs::legoGlobs.currLevel)->height <= byOff)) { BVar1 = BLOCK1_NONE; } else { BVar1 = (globs::legoGlobs.currLevel)->blocks [byOff * (globs::legoGlobs.currLevel)->width + bxOff].flags1 & BLOCK1_PATH; } if ((BVar1 != BLOCK1_NONE) || (((globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * byOff + bxOff]. flags1 & BLOCK1_BUILDINGSOLID) != BLOCK1_NONE)) { connectionBits |= 1 << ((byte)i & 0x1f); } i += 1; pDirY = pDirY + 2; } while (i < 4); if (powered == 0) { switch(connectionBits) { case DIRECTION_FLAG_NONE: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_PATH_1SIDES; case DIRECTION_FLAG_N: *ref_direction = DIRECTION_DOWN; return TEXTURE_FLOOR_PATH_1SIDES; case DIRECTION_FLAG_E: *ref_direction = DIRECTION_LEFT; return TEXTURE_FLOOR_PATH_1SIDES; case DIRECTION_FLAG_NE: *ref_direction = DIRECTION_LEFT; return TEXTURE_FLOOR_PATH_CORNER; case DIRECTION_FLAG_S: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_PATH_1SIDES; case DIRECTION_FLAG_NS: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_PATH_2SIDES; case DIRECTION_FLAG_SE: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_PATH_CORNER; case DIRECTION_FLAG_NSE: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_PATH_3SIDES; case DIRECTION_FLAG_W: *ref_direction = DIRECTION_RIGHT; return TEXTURE_FLOOR_PATH_1SIDES; case DIRECTION_FLAG_NW: *ref_direction = DIRECTION_DOWN; return TEXTURE_FLOOR_PATH_CORNER; case DIRECTION_FLAG_EW: *ref_direction = DIRECTION_RIGHT; return TEXTURE_FLOOR_PATH_2SIDES; case DIRECTION_FLAG_NEW: *ref_direction = DIRECTION_LEFT; return TEXTURE_FLOOR_PATH_3SIDES; case DIRECTION_FLAG_SW: *ref_direction = DIRECTION_RIGHT; return TEXTURE_FLOOR_PATH_CORNER; case DIRECTION_FLAG_NSW: *ref_direction = DIRECTION_DOWN; return TEXTURE_FLOOR_PATH_3SIDES; case DIRECTION_FLAG_SEW: *ref_direction = DIRECTION_RIGHT; return TEXTURE_FLOOR_PATH_3SIDES; case DIRECTION_FLAG_NSEW: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_PATH_4SIDES; } } else { switch(connectionBits) { case DIRECTION_FLAG_NONE: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_POWERED_1SIDES; case DIRECTION_FLAG_N: *ref_direction = DIRECTION_DOWN; return TEXTURE_FLOOR_POWERED_1SIDES; case DIRECTION_FLAG_E: *ref_direction = DIRECTION_LEFT; return TEXTURE_FLOOR_POWERED_1SIDES; case DIRECTION_FLAG_NE: *ref_direction = DIRECTION_LEFT; return TEXTURE_FLOOR_POWERED_CORNER; case DIRECTION_FLAG_S: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_POWERED_1SIDES; case DIRECTION_FLAG_NS: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_POWERED_2SIDES; case DIRECTION_FLAG_SE: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_POWERED_CORNER; case DIRECTION_FLAG_NSE: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_POWERED_3SIDES; case DIRECTION_FLAG_W: *ref_direction = DIRECTION_RIGHT; return TEXTURE_FLOOR_POWERED_1SIDES; case DIRECTION_FLAG_NW: *ref_direction = DIRECTION_DOWN; return TEXTURE_FLOOR_POWERED_CORNER; case DIRECTION_FLAG_EW: *ref_direction = DIRECTION_RIGHT; return TEXTURE_FLOOR_POWERED_2SIDES; case DIRECTION_FLAG_NEW: *ref_direction = DIRECTION_LEFT; return TEXTURE_FLOOR_POWERED_3SIDES; case DIRECTION_FLAG_SW: *ref_direction = DIRECTION_RIGHT; return TEXTURE_FLOOR_POWERED_CORNER; case DIRECTION_FLAG_NSW: *ref_direction = DIRECTION_DOWN; return TEXTURE_FLOOR_POWERED_3SIDES; case DIRECTION_FLAG_SEW: *ref_direction = DIRECTION_RIGHT; return TEXTURE_FLOOR_POWERED_3SIDES; case DIRECTION_FLAG_NSEW: *ref_direction = DIRECTION_UP; return TEXTURE_FLOOR_POWERED_4SIDES; } } // Unreachable code return (SurfaceTexture)ref_direction; } // WARNING: Switch with 1 destination removed at 0x0042fd79 : 5 cases all go to same destination // WARNING: Switch with 1 destination removed at 0x0042fdd8 : 5 cases all go to same destination void __cdecl lego::game::Level_BlockUpdateSurface(Lego_Level *level,int bx,int by,BOOL reserved) { BlockFlags1 BVar1; Map3D *map; SurfaceTexture SVar2; int iVar3; BOOL isPath; BlockFlags2 BVar4; BlockFlags1 BVar5; BOOL BVar6; Smoke *smoke; uint uVar7; MainCLFlags clFlags; Point2I *pDir; uint *puVar8; uint uVar9; float local_60; int local_5c; float local_58; float local_54; Point2I *local_50; Map3D *local_4c; Vector3F local_48; BOOL YES_BLOCKFADE; Point2I local_38; Point2I DIRECTIONS [6]; Lego_Block *block; Lego_Block *blocks; if (level->width - 1 <= (uint)bx) { return; } if (level->height - 1 <= (uint)by) { return; } local_4c = level->map; iVar3 = by * level->width + bx; local_5c = 0; // // FIRST USAGE ONLY! // const Point2I DIRECTIONS[4] = { // { 0, 0 }, // { 1, 0 }, // { 1, 1 }, // { 0, 1 }, // }; DIRECTIONS[0].x = 0; isPath = level->blocks[iVar3].flags1 & BLOCK1_PATH; DIRECTIONS[0].y = 0; block = level->blocks + iVar3; DIRECTIONS[1].x = 1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 1; DIRECTIONS[2].y = 1; DIRECTIONS[3].x = 0; DIRECTIONS[3].y = 1; YES_BLOCKFADE = 1; if ((isPath == 0) || ((block->flags2 & BLOCK2_PATHSBUILTCOUNTED) != BLOCK2_NONE)) { if ((isPath == 0) && ((block->flags2 & BLOCK2_PATHSBUILTCOUNTED) != BLOCK2_NONE)) { LegoObject_IncLevelPathsBuilt(0); BVar4 = block->flags2 & ~BLOCK2_PATHSBUILTCOUNTED; goto LAB_0042f6d5; } } else { LegoObject_IncLevelPathsBuilt(1); BVar4 = block->flags2 | BLOCK2_PATHSBUILTCOUNTED; LAB_0042f6d5: block->flags2 = BVar4; } uVar7 = level->width; blocks = level->blocks; local_50 = &local_38; uVar9 = 0; // Get surrounding blocks for orientation? pDir = DIRECTIONS; do { if (blocks[(pDir->y + by) * uVar7 + bx + pDir->x].predug == Lego_PredugType_Cavern_Exposed) { local_48.x = (float)((uint)local_48.x & 0xffffff00 | uVar9 & 0xff); local_5c += 1; } else { *(char *)&local_50->x = (char)uVar9; local_50 = (Point2I *)((int)&local_50->x + 1); } uVar9 += 1; pDir = pDir + 1; } while (uVar9 < 4); BVar1 = block->flags1; BVar5 = BVar1 & ~(BLOCK1_FLOOR|BLOCK1_WALL|BLOCK1_INCORNER|BLOCK1_OUTCORNER|BLOCK1_DIAGONAL); block->flags1 = BVar5; if (local_5c == 4) { local_38.x = bx; local_38.y = by; block->flags1 = BVar1 & ~(BLOCK1_FLOOR|BLOCK1_WALL|BLOCK1_REINFORCED|BLOCK1_INCORNER|BLOCK1_OUTCORNER| BLOCK1_DIAGONAL) | (BLOCK1_SURVEYED|BLOCK1_FLOOR); block->direction = 0; if ((BVar1 & BLOCK1_FLOOR) == BLOCK1_NONE) { local_48.x = (float)bx; local_48.y = (float)by; ai::AITask_RemoveDigReferences(&local_38,FALSE); Level_BlockActivity_Destroy(level,(Point2I *)&local_48,TRUE); if ((globs::legoGlobs.flags1 & GAME1_ALWAYSROCKFALL) != GAME1_NONE) { Message_PostEvent(Message_DigComplete,0, (uint)(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * by + bx].direction, (Point2I *)&local_48); } } if ((block->flags1 & BLOCK1_EXPOSEDFLOORCHECKS) == BLOCK1_NONE) { if ((((((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * local_38.y + local_38.x].flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * local_38.y + local_38.x].flags2 & 4) == 0)) && ((*(byte *)((int)&(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * local_38.y + local_38.x].flags1 + 1) & 0x80) == 0)) && (BVar6 = Construction_Zone_ExistsAtBlock(&local_38), BVar6 == 0)) { iVar3 = (globs::legoGlobs.currLevel)->width * local_38.y + local_38.x; (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 & ~BLOCK1_CLEARED; iVar3 = (globs::legoGlobs.currLevel)->width * local_38.y + local_38.x; (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 & ~BLOCK1_PATH; iVar3 = (globs::legoGlobs.currLevel)->width * local_38.y + local_38.x; (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 & ~BLOCK1_LAYEDPATH; LegoObject_RequestPowerGridUpdate(); ai::AITask_RemoveAttackPathReferences(&local_38); util::logf_removed((char *)&local_38); iVar3 = 4; do { ai::AITask_DoClear_AtPosition(&local_38,Message_ClearComplete); iVar3 += -1; } while (iVar3 != 0); iVar3 = (globs::legoGlobs.currLevel)->width * local_38.y + local_38.x; (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 | BLOCK1_RUBBLE_FULL; } iVar3 = (globs::legoGlobs.currLevel)->width * local_38.y + local_38.x; (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar3].flags1 | BLOCK1_EXPOSEDFLOORCHECKS; front::Interface_BackToMain_IfSelectedWall_IsBlockPos(&local_38); } BVar6 = ElectricFence_Block_FUN_0040e110(level,bx,by); ElectricFence_Block_ElecFenceStud_FUN_0040e280(level,bx,by,(uint)(BVar6 != 0)); if ((block->terrain == Lego_SurfaceType8_Lava) || (BVar1 = block->flags1, (BVar1 & BLOCK1_ERODEACTIVE) != BLOCK1_NONE)) { Erode_Block_FUN_0040ed80(&local_38,TRUE); if ((block->flags1 & BLOCK1_NOTHOT) == BLOCK1_NONE) { if (block->erodeLevel == 4) { block->texture = TEXTURE_FLOOR_LAVA; lego::map::Map3D_SetBlockUVWobbles(level->map,bx,by,TRUE); if ((block->flags1 & BLOCK1_SMOKE) == BLOCK1_NONE) { if ((int)block->randomness % 3 == 0) { local_48.x = 0.1; local_48.y = 0.1; local_48.z = -1.0; // randomness is sign-extended from signed short to unsigned int. smoke = effect::Smoke_CreateSmokeArea (NULL,bx,by,&local_48,0.6,0.4,0.0,1.0,0.3,Smoke_Type_Looping, (int)block->randomness,SFX_Lava); block->smoke = smoke; block->flags1 = block->flags1 | BLOCK1_SMOKE; } } else { effect::Smoke_Hide(block->smoke,FALSE); } } else { lego::map::Map3D_SetBlockUVWobbles(level->map,bx,by,FALSE); switch(block->erodeLevel) { case 0: block->texture = TEXTURE_FLOOR_ERODE_LOW; break; case 1: block->texture = TEXTURE_FLOOR_ERODE_MED; break; case 2: block->texture = TEXTURE_FLOOR_ERODE_HIGH; break; case 3: block->texture = TEXTURE_FLOOR_ERODE_MAX; } } } else { lego::map::Map3D_SetBlockUVWobbles(level->map,bx,by,FALSE); block->texture = TEXTURE_FLOOR_LAVA_NOTHOT; if ((block->flags1 & BLOCK1_SMOKE) != BLOCK1_NONE) { effect::Smoke_Hide(block->smoke,TRUE); } } } else { if (block->terrain == Lego_SurfaceType8_Lake) { block->texture = TEXTURE_FLOOR_WATER; lego::map::Map3D_SetBlockUVWobbles(level->map,bx,by,TRUE); } else { if ((BVar1 & BLOCK1_FOUNDATION) == BLOCK1_NONE) { if ((BVar1 & BLOCK1_PATH) == BLOCK1_NONE) { if ((*(byte *)&block->flags2 & BLOCK2_SLUGHOLE_EXPOSED) == 0) { if ((BVar1 & BLOCK1_CLEARED) == BLOCK1_NONE) { switch(BVar1 & BLOCK1_RUBBLE_FULL) { case BLOCK1_NONE: block->texture = TEXTURE_FLOOR_RUBBLE_LOW; break; case BLOCK1_RUBBLE_LOW: block->texture = TEXTURE_FLOOR_RUBBLE_MED; break; case BLOCK1_RUBBLE_MEDIUM: block->texture = TEXTURE_FLOOR_RUBBLE_HIGH; break; case BLOCK1_RUBBLE_FULL: block->texture = TEXTURE_FLOOR_RUBBLE_MAX; } } else { if ((BVar1 & BLOCK1_LAYEDPATH) == BLOCK1_NONE) { block->texture = TEXTURE_FLOOR_STD; } else { block->texture = TEXTURE_FLOOR_PATH_LAYED; } } } else { block->texture = TEXTURE_FLOOR_SLUGHOLE; } } else { SVar2 = Level_Block_ChoosePathTexture (bx,by,&block->direction,block->flags2 & BLOCK2_POWERED); block->texture = SVar2; } } else { if ((block->flags2 & BLOCK2_POWERED) == BLOCK2_NONE) { block->texture = TEXTURE_FLOOR_PATH_FOUNDATION; } else { block->texture = TEXTURE_FLOOR_POWERED_FOUNDATION; } } } } goto switchD_0042fb8d_caseD_4; } if (local_5c != 2) { if ((local_5c != 1) && (local_5c != 3)) { if (((BVar1 & BLOCK1_SURVEYED) == BLOCK1_NONE) || (block->terrain - 1 < 5)) { block->texture = TEXTURE_ROOF_STD; } block->direction = 0; goto switchD_0042fb8d_caseD_4; } block->flags1 = BVar1 & ~(BLOCK1_FLOOR|BLOCK1_WALL|BLOCK1_REINFORCED|BLOCK1_INCORNER|BLOCK1_OUTCORNER| BLOCK1_DIAGONAL) | (BLOCK1_SURVEYED|BLOCK1_WALL); if (local_5c == 1) { if (true) { if (true) { switch(block->terrain) { case Lego_SurfaceType8_Immovable: case Lego_SurfaceType8_Water: goto switchD_0042fe25_caseD_1; case Lego_SurfaceType8_Hard: goto switchD_0042fe25_caseD_2; case Lego_SurfaceType8_Medium: goto switchD_0042fe25_caseD_3; case Lego_SurfaceType8_Loose: goto switchD_0042fe25_caseD_4; case Lego_SurfaceType8_Soil: goto switchD_0042fe25_caseD_5; } } } else { if (true) { switch(block->terrain) { case Lego_SurfaceType8_Immovable: case Lego_SurfaceType8_Water: switchD_0042fe25_caseD_1: block->texture = TEXTURE_INCORNER_IMM; break; case Lego_SurfaceType8_Hard: switchD_0042fe25_caseD_2: block->texture = TEXTURE_INCORNER_HARD; break; case Lego_SurfaceType8_Medium: switchD_0042fe25_caseD_3: block->texture = TEXTURE_INCORNER_MED; break; case Lego_SurfaceType8_Loose: switchD_0042fe25_caseD_4: block->texture = TEXTURE_INCORNER_LOOSE; break; case Lego_SurfaceType8_Soil: switchD_0042fe25_caseD_5: block->texture = TEXTURE_INCORNER_SOIL; } } } block->flags1 = BVar1 & ~(BLOCK1_FLOOR|BLOCK1_WALL|BLOCK1_REINFORCED|BLOCK1_INCORNER|BLOCK1_OUTCORNER| BLOCK1_DIAGONAL) | (BLOCK1_SURVEYED|BLOCK1_WALL|BLOCK1_INCORNER); local_38.y = by; block->direction = SUB41(local_48.x,0) + 2U & 3; local_38.x = bx; Level_BlockActivity_Destroy(level,&local_38,TRUE); } else { if (local_5c == 3) { if (true) { if (true) { switch(block->terrain) { case Lego_SurfaceType8_Immovable: case Lego_SurfaceType8_Water: goto switchD_0042febf_caseD_1; case Lego_SurfaceType8_Hard: goto switchD_0042febf_caseD_2; case Lego_SurfaceType8_Medium: goto switchD_0042febf_caseD_3; case Lego_SurfaceType8_Loose: goto switchD_0042febf_caseD_4; case Lego_SurfaceType8_Soil: goto switchD_0042febf_caseD_5; } } } else { // Duplicate code. Unreachable, but contains effects of above switch if (true) { switch(block->terrain) { case Lego_SurfaceType8_Immovable: case Lego_SurfaceType8_Water: switchD_0042febf_caseD_1: block->texture = TEXTURE_OUTCORNER_IMM; break; case Lego_SurfaceType8_Hard: switchD_0042febf_caseD_2: block->texture = TEXTURE_OUTCORNER_HARD; break; case Lego_SurfaceType8_Medium: switchD_0042febf_caseD_3: block->texture = TEXTURE_OUTCORNER_MED; break; case Lego_SurfaceType8_Loose: switchD_0042febf_caseD_4: block->texture = TEXTURE_OUTCORNER_LOOSE; break; case Lego_SurfaceType8_Soil: switchD_0042febf_caseD_5: block->texture = TEXTURE_OUTCORNER_SOIL; } } } local_48.x = (float)bx; local_48.y = (float)by; Level_BlockActivity_Destroy(level,(Point2I *)&local_48,TRUE); ai::AITask_RemoveReinforceReferences((Point2I *)&local_48); block->direction = (byte)local_38.x; block->flags1 = block->flags1 | BLOCK1_OUTCORNER; } } map = local_4c; lego::map::Map3D_BlockVertexToWorldPos(local_4c,bx,by,&local_60,&local_60,&local_58); lego::map::Map3D_BlockVertexToWorldPos(map,bx + 1U,by + 1U,&local_60,&local_60,&local_54); local_48.x = local_58 - local_54; lego::map::Map3D_BlockVertexToWorldPos(map,bx + 1U,by,&local_60,&local_60,&local_58); lego::map::Map3D_BlockVertexToWorldPos(map,bx,by + 1U,&local_60,&local_60,&local_54); lego::map::Map3D_SetBlockRotated (map,bx,by, (uint)((ushort)((ushort)(ABS(local_48.x) < ABS(local_58 - local_54)) << 8 | (ushort)(ABS(local_48.x) == ABS(local_58 - local_54)) << 0xe) == 0)); local_38.x = bx; local_38.y = by; Level_BlockActivity_Destroy(level,&local_38,TRUE); goto switchD_0042fb8d_caseD_4; } DIRECTIONS[0].y = 1; DIRECTIONS[1].x = 1; DIRECTIONS[5].x = 1; DIRECTIONS[0].x = 0; DIRECTIONS[3].x = 0; DIRECTIONS[4].x = 0; DIRECTIONS[2].y = 3; DIRECTIONS[3].y = 3; DIRECTIONS[5].y = 3; uVar7 = 0; DIRECTIONS[1].y = 2; DIRECTIONS[2].x = 2; DIRECTIONS[4].y = 2; block->flags1 = BVar5 | (BLOCK1_SURVEYED|BLOCK1_WALL); puVar8 = (uint *)&DIRECTIONS[0].y; do { if ((puVar8[-1] == (local_38.x & 0xffU)) && (*puVar8 == ((uint)local_38.x >> 8 & 0xff))) { bx._0_1_ = (byte)uVar7; goto LAB_0042fc43; } uVar7 += 1; puVar8 = puVar8 + 2; } while (uVar7 < 6); LAB_0042fc43: if (3 < (byte)bx) { if (block->terrain - 1 < 5) { block->texture = TEXTURE_DIAGONAL_STD; } // block->flags1 &= // ~(BLOCK1_FLOOR|BLOCK1_WALL|BLOCK1_CORNEROBTUSE|BLOCK1_CORNERINNER|BLOCK1_DIAGONAL); // // // Shorthand // block->flags1 &= ~(BLOCK1_FLOOR|BLOCK1_CORNEROBTUSE|BLOCK1_CORNERINNER); // block->flags1 |= (BLOCK1_SURVEYED|BLOCK1_WALL|BLOCK1_DIAGONAL); block->flags1 = BVar1 & ~(BLOCK1_RUBBLE_FULL|BLOCK1_SURVEYED|BLOCK1_FLOOR|BLOCK1_WALL|BLOCK1_REINFORCED| BLOCK1_INCORNER|BLOCK1_OUTCORNER|BLOCK1_HIGHPOLY|BLOCK1_NOTHOT| BLOCK1_BUILDINGSOLID|BLOCK1_ROCKFALLFX|BLOCK1_LANDSLIDING|BLOCK1_DIAGONAL| BLOCK1_SMOKE|BLOCK1_BUILDINGPATH) | (uint)CONCAT11((char)(BVar5 >> 8),(char)(BVar5 | (BLOCK1_SURVEYED|BLOCK1_WALL))) | BLOCK1_DIAGONAL; block->direction = (byte)bx - 4; // `((_ - 4) & 1)` -> `IsOdd(_ - 4)` lego::map::Map3D_SetBlockRotated(local_4c,bx,by,(byte)((byte)bx - 4) & 1); goto switchD_0042fb8d_caseD_4; } if ((BVar1 & BLOCK1_REINFORCED) == BLOCK1_NONE) { // Probably randomness to choose an alternative texture style (which doesn't exist). if ((int)block->randomness % 10 == 0) { if (true) { switch(block->terrain) { case Lego_SurfaceType8_Immovable: case Lego_SurfaceType8_Water: goto switchD_0042fce8_caseD_1; case Lego_SurfaceType8_Hard: goto switchD_0042fce8_caseD_2; case Lego_SurfaceType8_Medium: goto switchD_0042fce8_caseD_3; case Lego_SurfaceType8_Loose: goto switchD_0042fce8_caseD_4; case Lego_SurfaceType8_Soil: goto switchD_0042fce8_caseD_5; case Lego_SurfaceType8_OreSeam: goto switchD_0042fce8_caseD_8; case Lego_SurfaceType8_CrystalSeam: goto switchD_0042fce8_caseD_a; case Lego_SurfaceType8_RechargeSeam: goto switchD_0042fce8_caseD_b; } } } else { if (true) { switch(block->terrain) { case Lego_SurfaceType8_Immovable: case Lego_SurfaceType8_Water: switchD_0042fce8_caseD_1: block->texture = TEXTURE_WALL_IMM; block->direction = (byte)bx; goto switchD_0042fb8d_caseD_4; case Lego_SurfaceType8_Hard: switchD_0042fce8_caseD_2: block->texture = TEXTURE_WALL_HARD; block->direction = (byte)bx; goto switchD_0042fb8d_caseD_4; case Lego_SurfaceType8_Medium: switchD_0042fce8_caseD_3: block->texture = TEXTURE_WALL_MED; block->direction = (byte)bx; goto switchD_0042fb8d_caseD_4; case Lego_SurfaceType8_Loose: switchD_0042fce8_caseD_4: block->texture = TEXTURE_WALL_LOOSE; block->direction = (byte)bx; goto switchD_0042fb8d_caseD_4; case Lego_SurfaceType8_Soil: switchD_0042fce8_caseD_5: block->texture = TEXTURE_WALL_SOIL; block->direction = (byte)bx; goto switchD_0042fb8d_caseD_4; case Lego_SurfaceType8_OreSeam: switchD_0042fce8_caseD_8: block->texture = TEXTURE_WALL_ORESEAM; block->direction = (byte)bx; goto switchD_0042fb8d_caseD_4; case Lego_SurfaceType8_CrystalSeam: switchD_0042fce8_caseD_a: block->texture = TEXTURE_WALL_CRYSTALSEAM; block->direction = (byte)bx; goto switchD_0042fb8d_caseD_4; case Lego_SurfaceType8_RechargeSeam: switchD_0042fce8_caseD_b: block->texture = TEXTURE_WALL_RECHARGESEAM; } } } } else { if (true) { switch(block->terrain) { case Lego_SurfaceType8_Immovable: case Lego_SurfaceType8_Water: block->texture = TEXTURE_REINWALL_IMM; block->direction = (byte)bx; break; case Lego_SurfaceType8_Hard: block->texture = TEXTURE_REINWALL_HARD; block->direction = (byte)bx; break; case Lego_SurfaceType8_Medium: block->texture = TEXTURE_REINWALL_MED; block->direction = (byte)bx; break; case Lego_SurfaceType8_Loose: block->texture = TEXTURE_REINWALL_LOOSE; block->direction = (byte)bx; break; case Lego_SurfaceType8_Soil: block->texture = TEXTURE_REINWALL_SOIL; block->direction = (byte)bx; break; default: goto switchD_0042fce8_caseD_6; } goto switchD_0042fb8d_caseD_4; } } switchD_0042fce8_caseD_6: block->direction = (byte)bx; switchD_0042fb8d_caseD_4: BVar1 = block->flags1; if ((((BVar1 & BLOCK1_SURVEYED) != BLOCK1_NONE) && ((BVar1 & BLOCK1_DIGREQUEST) != BLOCK1_NONE)) && ((block->terrain == Lego_SurfaceType8_Immovable || ((block->terrain == Lego_SurfaceType8_Water || ((BVar1 & BLOCK1_FLOOR) != BLOCK1_NONE)))))) { block->flags1 = BVar1 & ~BLOCK1_DIGREQUEST; lego::map::Map3D_ClearBlockHighlight(level->map,bx,by); } clFlags = main::Main_GetCLFlags(); iVar3 = YES_BLOCKFADE; if ((clFlags & CL_FLAG_BLOCKFADE) == CL_FLAG_NONE) { iVar3 = 0; } if (iVar3 == 0) { lego::map::Map3D_SetBlockTexture(level->map,bx,by,block->texture,block->direction); } else { lego::map::Map3D_SetBlockFadeInTexture(level->map,bx,by,block->texture,block->direction); } if (level->UseRoof != BOOL3_FALSE) { Level_Block_LowerRoofVertices(level,bx,by); } return; } void __cdecl lego::game::Level_Block_Proc_FUN_004301e0(Point2I *blockPos) { BlockFlags1 *pBVar1; int idx; pBVar1 = &(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1; *pBVar1 = *pBVar1 & ~BLOCK1_PATH; idx = (globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x; (globs::legoGlobs.currLevel)->blocks[idx].flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1 & ~BLOCK1_LAYEDPATH; LegoObject_RequestPowerGridUpdate(); ai::AITask_RemoveAttackPathReferences(blockPos); util::logf_removed((char *)blockPos); return; } void __cdecl lego::ai::AITask_DoClearTypeAction(Point2I *blockPos,Message_Type completeAction) { BOOL BVar1; int iVar2; if (((((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags2 & 4) == 0 )) && (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1 & BLOCK1_BUILDINGPATH) == BLOCK1_NONE)) { BVar1 = game::Construction_Zone_ExistsAtBlock(blockPos); if (BVar1 == 0) { iVar2 = (globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x; (globs::legoGlobs.currLevel)->blocks[iVar2].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar2].flags1 & ~BLOCK1_CLEARED; iVar2 = (globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x; (globs::legoGlobs.currLevel)->blocks[iVar2].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar2].flags1 & ~BLOCK1_PATH; iVar2 = (globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x; (globs::legoGlobs.currLevel)->blocks[iVar2].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar2].flags1 & ~BLOCK1_LAYEDPATH; game::LegoObject_RequestPowerGridUpdate(); AITask_RemoveAttackPathReferences(blockPos); util::logf_removed((char *)blockPos); iVar2 = 4; do { AITask_DoClear_AtPosition(blockPos,completeAction); iVar2 += -1; } while (iVar2 != 0); iVar2 = (globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x; (globs::legoGlobs.currLevel)->blocks[iVar2].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar2].flags1 | BLOCK1_RUBBLE_FULL; } } return; } void __cdecl lego::debug::Level_Debug_WKey_NeedsBlockFlags1_8_FUN_004303a0 (Lego_Level *level,BOOL unused,uint bx,uint by) { Water_Pool *water; int idx; int width; if ((bx != 0) && (by != 0)) { width = level->width; // BLOCK1_UNK_8 // setting equate causes Ghidra to hang :( if ((bx < width - 2U) && ((by < level->height - 2 && ((*(byte *)&level->blocks[by * width + bx].flags1 & 8) != 0)))) { water = game::Water_FindPoolDrain(bx,by,NULL); if (water != NULL) { idx = by * level->width + bx; level->blocks[idx].flags1 = level->blocks[idx].flags1 & ~BLOCK1_FLOOR; idx = by * level->width + bx; level->blocks[idx].flags1 = level->blocks[idx].flags1 | BLOCK1_WALL; game::Level_BlockUpdateSurface(level,bx,by,0); game::Water_DamBlock(bx,by); } } } return; } BOOL __cdecl lego::game::Level_DestroyWall(Lego_Level *level,uint bx,uint by,BOOL isHiddenCavern) { int *piVar1; Lego_Block *pLVar2; ushort *puVar3; Map3D *map; int *piVar4; Point2I *pPVar5; TutorialFlags tutorialFlags; BOOL BVar6; uint uVar7; int iVar8; int iVar9; uint uVar10; Info_Type infoType; Point2I local_50; Point2I local_48; Point2I ANGLES [8]; uint bx_00; BlockFlags1 flags1; BlockFlags2 flags2; BlockFlags1 *pFlags1; BlockFlags2 *pFlags2; Lego_PredugType predug; Lego_SurfaceType8 terrain; bx_00 = bx; map = level->map; ANGLES[0].x = 0; ANGLES[0].y = 0; ANGLES[1].x = 1; ANGLES[1].y = 0; ANGLES[2].x = 1; ANGLES[2].y = 1; ANGLES[3].x = 0; ANGLES[3].y = 1; if ((((bx == 0) || (by == 0)) || (level->width - 2 <= bx)) || ((level->height - 2 <= by || (pLVar2 = level->blocks + by * level->width + bx, (*(byte *)&pLVar2->flags1 & 8) != 0)))) { return 0; } if ((pLVar2->terrain == Lego_SurfaceType8_OreSeam) || (pLVar2->terrain == Lego_SurfaceType8_CrystalSeam)) { local_48.x = bx; local_48.y = by; pLVar2->damage = 0.0; pPVar5 = ANGLES; bx = 4; do { uVar7 = pPVar5->y + by; iVar9 = pPVar5->x; iVar8 = uVar7 * level->width + bx_00 + iVar9; if (level->blocks[iVar8].predug == Lego_PredugType_Wall) { local_50.x = bx_00; local_50.y = by; level->blocks[iVar8].predug = Lego_PredugType_Cavern_Exposed|Lego_PredugType_SlugHole_Hidden ; terrain = level->blocks[by * level->width + bx_00].terrain; if ((terrain == Lego_SurfaceType8_OreSeam) || (terrain == Lego_SurfaceType8_CrystalSeam)) { front::Info_Send(Info_GenericSeamFound,NULL,NULL,&local_50); } terrain = level->blocks[by * level->width + bx_00].terrain; if (terrain == Lego_SurfaceType8_OreSeam) { infoType = Info_OreSeamFound; } else { if (terrain != Lego_SurfaceType8_CrystalSeam) goto LAB_00430c0d; infoType = Info_CrystalSeamFound; } front::Info_Send(infoType,NULL,NULL,&local_50); } LAB_00430c0d: predug = level->blocks[uVar7 * level->width + bx_00 + iVar9].predug; if (predug != Lego_PredugType_Cavern_Exposed) { level->blocks[uVar7 * level->width + bx_00 + iVar9].predug = predug + ~Lego_PredugType_Wall; lego::map::Map3D_MoveBlockVertices(map,iVar9 + bx_00,uVar7,level->DigDepth * 0.25); } pPVar5 = pPVar5 + 1; bx -= 1; } while (bx != 0); Level_Block_FUN_00430d20(&local_48); puVar3 = &level->blocks[by * level->width + bx_00].seamDigCount; *puVar3 = *puVar3 + 1; iVar9 = 4; if (level->blocks[by * level->width + bx_00].seamDigCount != 4) { Level_Block_LowerRoofVertices(globs::legoGlobs.currLevel,bx_00,by); Construction_FlattenGround(&local_48); return 0; } level->blocks[by * level->width + bx_00].terrain = Lego_SurfaceType8_Soil; pPVar5 = ANGLES; do { piVar1 = &pPVar5->y; piVar4 = &pPVar5->x; pPVar5 = pPVar5 + 1; iVar9 += -1; level->blocks[(*piVar1 + by) * level->width + bx_00 + *piVar4].predug = Lego_PredugType_Cavern_Exposed; } while (iVar9 != 0); Level_DestroyWall(level,bx_00,by,isHiddenCavern); } else { if (pLVar2->predug == Lego_PredugType_Wall) { lego::map::Map3D_MoveBlockVertices(map,bx,by,level->DigDepth); level->blocks[by * level->width + bx].predug = Lego_PredugType_Cavern_Exposed; } if (level->blocks[by * level->width + 1 + bx].predug == Lego_PredugType_Wall) { lego::map::Map3D_MoveBlockVertices(map,bx + 1,by,level->DigDepth); level->blocks[by * level->width + 1 + bx].predug = Lego_PredugType_Cavern_Exposed; } uVar7 = by + 1; if (level->blocks[uVar7 * level->width + 1 + bx].predug == Lego_PredugType_Wall) { lego::map::Map3D_MoveBlockVertices(map,bx + 1,uVar7,level->DigDepth); level->blocks[uVar7 * level->width + 1 + bx].predug = Lego_PredugType_Cavern_Exposed; } if (level->blocks[uVar7 * level->width + bx].predug == Lego_PredugType_Wall) { lego::map::Map3D_MoveBlockVertices(map,bx,uVar7,level->DigDepth); level->blocks[uVar7 * level->width + bx].predug = Lego_PredugType_Cavern_Exposed; } ANGLES[0].x = -1; ANGLES[0].y = -1; ANGLES[1].y = -1; ANGLES[2].y = -1; ANGLES[3].x = -1; ANGLES[5].x = -1; pPVar5 = ANGLES; ANGLES[1].x = 0; ANGLES[2].x = 1; ANGLES[3].y = 0; ANGLES[4].x = 1; ANGLES[4].y = 0; ANGLES[5].y = 1; ANGLES[6].x = 0; ANGLES[6].y = 1; ANGLES[7].x = 1; ANGLES[7].y = 1; bx = 8; do { iVar9 = pPVar5->x; iVar8 = pPVar5->y + by; pFlags1 = &level->blocks[iVar8 * level->width + bx_00 + iVar9].flags1; flags1 = *pFlags1; if ((flags1 & BLOCK1_FLOOR) == BLOCK1_NONE) { *pFlags1 = flags1 | BLOCK1_WALL; iVar9 = iVar8 * level->width + bx_00 + iVar9; level->blocks[iVar9].flags1 = level->blocks[iVar9].flags1 & ~BLOCK1_DESTROYEDCONNECTION; } pPVar5 = pPVar5 + 1; bx -= 1; } while (bx != 0); local_48.x = bx_00; local_48.y = by; pFlags1 = &level->blocks[by * level->width + bx_00].flags1; *pFlags1 = *pFlags1 | BLOCK1_FLOOR; Level_BlockActivity_Destroy(level,&local_48,TRUE); iVar9 = by * level->width + bx_00; level->blocks[iVar9].flags1 = level->blocks[iVar9].flags1 & ~BLOCK1_REINFORCED; iVar9 = by * level->width + bx_00; level->blocks[iVar9].flags1 = level->blocks[iVar9].flags1 | BLOCK1_EXPOSEDFLOORCHECKS; flags1 = level->blocks[by * level->width + bx_00].flags1; if ((((flags1 & BLOCK1_EXPOSED) == BLOCK1_NONE) || ((flags1 & BLOCK1_HIDDEN) != BLOCK1_NONE)) && ((flags1 & BLOCK1_DIGREQUEST) != BLOCK1_NONE)) { reward::RewardQuota_WallDestroyed(); } if (isHiddenCavern == 0) { uVar7 = by - 1; local_48.x = bx_00; local_48.y = by; if (uVar7 <= by + 1) { do { uVar10 = bx_00 - 1; if (uVar10 <= bx_00 + 1) { do { // if ((block->flags1 & BLOCK1_HIDDEN) != BLOCK1_NONE) if ((*(byte *)((int)&level->blocks[uVar7 * level->width + uVar10].flags1 + 2) & 2) != 0) { Level_UncoverHiddenCavern(uVar10,uVar7); tutorialFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (tutorialFlags == TUTORIAL_NONE) { front::Info_Send(Info_CavernLocated,NULL,NULL,&local_48); front::Text_DisplayMessage(Text_CavernDiscovered,TRUE,FALSE); reward::RewardQuota_CavernDiscovered(); } } uVar10 += 1; } while (uVar10 <= bx_00 + 1); } uVar7 += 1; } while (uVar7 <= by + 1); } iVar9 = (globs::legoGlobs.currLevel)->width * by + bx_00; (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 | BLOCK1_ROCKFALLFX; Message_PostEvent(Message_DigComplete,0, (uint)(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * by + bx_00].direction,&local_48 ); Water_DestroyWallComplete(level,bx_00,by); local_50.x = bx_00; local_50.y = by; if (((((globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx_00]. flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * by + bx_00].flags2 & 4) == 0)) && ((((globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx_00]. flags1 & BLOCK1_BUILDINGPATH) == BLOCK1_NONE && (BVar6 = Construction_Zone_ExistsAtBlock(&local_50), BVar6 == 0)))) { iVar9 = (globs::legoGlobs.currLevel)->width * local_50.y + local_50.x; (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 & ~BLOCK1_CLEARED; iVar9 = (globs::legoGlobs.currLevel)->width * local_50.y + local_50.x; (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 & ~BLOCK1_PATH; iVar9 = (globs::legoGlobs.currLevel)->width * local_50.y + local_50.x; (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 & ~BLOCK1_LAYEDPATH; LegoObject_RequestPowerGridUpdate(); ai::AITask_RemoveAttackPathReferences(&local_50); util::logf_removed((char *)&local_50); iVar9 = 4; do { ai::AITask_DoClear_AtPosition(&local_50,Message_ClearComplete); iVar9 += -1; } while (iVar9 != 0); iVar9 = (globs::legoGlobs.currLevel)->width * local_50.y + local_50.x; (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar9].flags1 | BLOCK1_RUBBLE_FULL; } front::Interface_BackToMain_IfSelectedWall_IsBlockPos(&local_50); } else { pFlags1 = &level->blocks[by * level->width + bx_00].flags1; *pFlags1 = *pFlags1 | BLOCK1_CLEARED; } local_48.x = bx_00; local_48.y = by; ai::AITask_RemoveDigReferences(&local_48,FALSE); uVar7 = by - 1; if (uVar7 < by + 2) { do { uVar10 = bx_00 - 1; if (uVar10 < bx_00 + 2) { do { Level_BlockUpdateSurface(level,uVar10,uVar7,isHiddenCavern); uVar10 += 1; } while (uVar10 < bx_00 + 2); } uVar7 += 1; } while (uVar7 < by + 2); } iVar9 = by * level->width + bx_00; level->blocks[iVar9].flags1 = level->blocks[iVar9].flags1 & ~BLOCK1_DIGREQUEST; uVar7 = by - 1; if (uVar7 <= by + 2) { do { uVar10 = bx_00 - 1; if (uVar10 <= bx_00 + 2) { do { lego::map::Map3D_SetBlockVertexModified(map,uVar10,uVar7); uVar10 += 1; } while (uVar10 <= bx_00 + 2); } uVar7 += 1; } while (uVar7 <= by + 2); } if ((isHiddenCavern == 0) && ((globs::legoGlobs.flags2 & GAME2_GENERATESPIDERS) != GAME2_NONE)) { uVar7 = SEXT24(level->blocks[by * level->width + bx_00].randomness); uVar10 = (int)uVar7 >> 0x1f; // if (positive modulus (block->randomness % 4) == 0) if (((uVar7 ^ uVar10) - uVar10 & 3 ^ uVar10) == uVar10) { LegoObject_GenerateSmallSpiders(bx_00,by,(int)uVar7 % 0x549); } } local_50.x = bx_00; local_50.y = by; HiddenObject_ExposeBlock(&local_50); pFlags2 = &level->blocks[by * level->width + bx_00].flags2; flags2 = *pFlags2; if ((flags2 & BLOCK2_SLUGHOLE_HIDDEN) != BLOCK2_NONE) { *pFlags2 = flags2 & ~BLOCK2_SLUGHOLE_HIDDEN; iVar9 = by * level->width + bx_00; level->blocks[iVar9].flags2 = level->blocks[iVar9].flags2 | BLOCK2_SLUGHOLE_EXPOSED; LegoObject_RegisterSlimySlugHole(&local_50); Level_BlockUpdateSurface(level,bx_00,by,0); } if (isHiddenCavern == 0) { front::Info_Send(Info_WallDug,NULL,NULL,&local_50); return TRUE; } } return TRUE; } void __cdecl lego::game::Level_Block_FUN_00430d20(Point2I *blockPos) { int idx; Point2I *pDir; uint i; Point2I genBlockPos; Point2I DIRECTIONS [4]; int bx; int by; Lego_SurfaceType8 terrain; i = 0; DIRECTIONS[0].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[1].x = 1; DIRECTIONS[2].y = 1; by = blockPos->y; bx = blockPos->x; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].y = 0; pDir = DIRECTIONS; do { idx = (pDir->y + by) * (globs::legoGlobs.currLevel)->width + bx + pDir->x; // BLOCK1_FLOOR (0x8) if ((((*(byte *)&(globs::legoGlobs.currLevel)->blocks[idx].flags1 & 8) != 0) && (terrain = (globs::legoGlobs.currLevel)->blocks[idx].terrain, terrain != Lego_SurfaceType8_Lake)) && (terrain != Lego_SurfaceType8_Lava)) break; i += 1; pDir = pDir + 1; } while (i < 4); if (i != 4) { genBlockPos.y = DIRECTIONS[i].y + by; genBlockPos.x = DIRECTIONS[i].x + bx; terrain = (globs::legoGlobs.currLevel)->blocks[by * (globs::legoGlobs.currLevel)->width + bx]. terrain; if (terrain == Lego_SurfaceType8_OreSeam) { Level_GenerateOre(&genBlockPos,0,NULL,TRUE); return; } if (terrain == Lego_SurfaceType8_CrystalSeam) { Level_GenerateCrystal(&genBlockPos,0,NULL,TRUE); } } return; } BOOL __cdecl lego::game::Level_DestroyWallConnection(Lego_Level *level,uint bx,uint by) { int *piVar1; uint *puVar2; BlockFlags1 *pBVar3; int iVar4; uint uVar5; Point2I *pDir; int *piVar6; uint i; int iVar7; uint uVar8; Point2I local_28; Point2I DIRECTIONS [4]; Lego_Block **pBlocks; uVar5 = bx; local_28.x = (int)level->map; DIRECTIONS[0].x = -1; DIRECTIONS[0].y = -1; DIRECTIONS[1].x = 0; DIRECTIONS[1].y = -1; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = 0; DIRECTIONS[3].x = -1; DIRECTIONS[3].y = 0; if ((((bx != 0) && (by != 0)) && (bx < level->width - 2)) && (by < level->height - 2)) { if (level->blocks[by * level->width + bx].predug == Lego_PredugType_Wall) { lego::map::Map3D_MoveBlockVertices((Map3D *)local_28.x,bx,by,level->DigDepth); iVar7 = 4; level->blocks[by * level->width + bx].predug = Lego_PredugType_Cavern_Exposed; piVar6 = &DIRECTIONS[0].y; do { piVar1 = piVar6 + -1; iVar4 = *piVar6; piVar6 = piVar6 + 2; pBVar3 = &level->blocks[(by + iVar4) * level->width + *piVar1 + bx].flags1; iVar7 += -1; *pBVar3 = *pBVar3 | BLOCK1_DESTROYEDCONNECTION; } while (iVar7 != 0); for (i = by - 1; i <= by; i += 1) { for (uVar8 = bx - 1; uVar8 <= bx; uVar8 += 1) { Level_BlockUpdateSurface(level,uVar8,i,0); } } i = by - 1; if (i <= by + 1) { do { uVar8 = bx - 1; if (uVar8 <= bx + 1) { do { lego::map::Map3D_SetBlockVertexModified((Map3D *)local_28.x,uVar8,i); uVar8 += 1; } while (uVar8 <= bx + 1); } i += 1; } while (i <= by + 1); } puVar2 = &level->width; pBlocks = &level->blocks; i = 0; DIRECTIONS[1].x = 1; DIRECTIONS[2].y = 1; local_28.x = bx; local_28.y = by; level = NULL; DIRECTIONS[0].x = 0; DIRECTIONS[0].y = -1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].x = -1; DIRECTIONS[3].y = 0; pDir = DIRECTIONS; do { if ((*pBlocks)[(pDir->y + by) * *puVar2 + uVar5 + pDir->x].predug == Lego_PredugType_Cavern_Exposed) { level = (Lego_Level *)((int)&level->name + 1); bx = i; } i += 1; pDir = pDir + 1; } while (i < 4); if (level == (Lego_Level *)0x1) { Message_PostEvent(Message_DigComplete,0,bx - 2 & 3 | 0x10000,&local_28); } ai::AITask_RemoveDigReferences(&local_28,TRUE); } return TRUE; } return FALSE; } void __cdecl lego::game::Level_Block_RemoveReinforcement(Point2I *blockPos) { Lego_Level *level; int idx; level = globs::legoGlobs.currLevel; Level_BlockActivity_Destroy(globs::legoGlobs.currLevel,blockPos,FALSE); idx = level->width * blockPos->y + blockPos->x; level->blocks[idx].flags1 = level->blocks[idx].flags1 & ~BLOCK1_REINFORCED; Level_BlockUpdateSurface(level,blockPos->x,blockPos->y,0); return; } void __cdecl lego::game::Level_Block_Reinforce(int bx,int by) { Lego_Level *level; Point2I blockPos; BlockFlags1 flags1; BlockFlags1 *pFlags1; level = globs::legoGlobs.currLevel; pFlags1 = &(globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx]. flags1; flags1 = *pFlags1; if (((flags1 & BLOCK1_WALL) != BLOCK1_NONE) && ((flags1 & (BLOCK1_REINFORCED|BLOCK1_INCORNER|BLOCK1_OUTCORNER)) == BLOCK1_NONE)) { *pFlags1 = flags1 | BLOCK1_REINFORCED; Level_BlockUpdateSurface(level,bx,by,0); blockPos.x = bx; blockPos.y = by; Level_BlockActivity_Create(level,&blockPos,FALSE); ai::AITask_RemoveReinforceReferences(&blockPos); front::Info_Send(Info_WallReinforced,NULL,NULL,&blockPos); } return; } // staticEffect states that the block does not perform specific activities, but simply exists with // the block. When false, the block will use Build/Stand/Destroy activities. void __cdecl lego::game::Level_BlockActivity_Create(Lego_Level *level,Point2I *blockPos,BOOL staticEffect) { int idx; Lego_BlockActivity *blockAct; Container *cont; int iVar1; uint dir; Lego_BlockActivity *pLVar2; float10 wZ; Vector3F wPos; Vector3F DIRECTIONS [4]; Lego_BlockActivity *blockActLast; cont = globs::legoGlobs.contRechargeSparkle; idx = blockPos->y * level->width + blockPos->x; DIRECTIONS[0].x = 0.0; DIRECTIONS[0].y = 1.0; DIRECTIONS[0].z = 0.0; dir = (uint)level->blocks[idx].direction; DIRECTIONS[1].x = 1.0; DIRECTIONS[1].y = 0.0; DIRECTIONS[1].z = 0.0; DIRECTIONS[2].x = 0.0; DIRECTIONS[2].y = -1.0; DIRECTIONS[2].z = 0.0; DIRECTIONS[3].x = -1.0; DIRECTIONS[3].y = 0.0; DIRECTIONS[3].z = 0.0; // Support for reinforcement block activities was either ditched, or never finished. if (staticEffect != 0) { blockAct = level->blocks[idx].activity; if (blockAct == NULL) { blockAct = (Lego_BlockActivity *)io::Mem_Alloc(0x1c); // std::memset(blockAct, 0, sizeof(Lego_BlockActivity)); pLVar2 = blockAct; for (iVar1 = 7; iVar1 != 0; iVar1 += -1) { pLVar2->cont = NULL; pLVar2 = (Lego_BlockActivity *)&pLVar2->blockPos; } blockAct->staticEffect = staticEffect; cont = gfx::Container_Clone(cont); blockAct->cont = cont; if (blockAct->staticEffect == 0) { // Reinforcements would start with a build animation. gfx::Container_SetActivity(cont,"Activity_Build"); } gfx::Container_SetAnimationTime(blockAct->cont,0.0); (blockAct->blockPos).x = blockPos->x; // (blockAct->blockPos).y = blockPos->y; WTF Ghidra *(int *)&blockAct->blockPos = blockPos->y; // Hook up to linked list. blockAct->next = NULL; blockActLast = level->blockActLast; blockAct->previous = blockActLast; if (blockActLast != NULL) { blockActLast->next = blockAct; } level->blockActLast = blockAct; level->blocks[blockPos->y * level->width + blockPos->x].activity = blockAct; } lego::map::Map3D_BlockToWorldPos(level->map,blockPos->x,blockPos->y,&wPos.x,&wPos.y); wZ = lego::map::Map3D_GetWorldZ(level->map,wPos.x,wPos.y); wPos.z = (float)wZ; gfx::Container_SetPosition(blockAct->cont,NULL,wPos.x,wPos.y,wPos.z); gfx::Container_SetOrientation (blockAct->cont,NULL,DIRECTIONS[dir].x,DIRECTIONS[dir].y,DIRECTIONS[dir].z,0.0,0.0, -1.0); } return; } void __cdecl lego::game::Level_BlockActivity_UpdateAll(Lego_Level *level,float elapsedGame) { Lego_BlockActivity *blockAct; float10 time; BlockActivityFlags baflags; Lego_BlockActivity *previous; previous = level->blockActLast; while (blockAct = previous, blockAct != NULL) { previous = blockAct->previous; time = gfx::Container_MoveAnimation(blockAct->cont,elapsedGame); // FIXME: staticEffect check prevents recharge sparkles from being removed when the wall // is destroyed. if (blockAct->staticEffect == 0) { baflags = blockAct->flags; if (((baflags & BLOCKACT_FLAG_STANDING) == BLOCKACT_FLAG_NONE) && ((float)time != 0.0)) { blockAct->flags = baflags | BLOCKACT_FLAG_STANDING; gfx::Container_SetActivity(blockAct->cont,"Activity_Stand"); } else { if ((baflags & BLOCKACT_FLAG_REMOVING) == BLOCKACT_FLAG_NONE) { if (((baflags & BLOCKACT_FLAG_DESTROYING) != BLOCKACT_FLAG_NONE) && ((float)time != 0.0)) { blockAct->flags = baflags | BLOCKACT_FLAG_REMOVING; } } else { Level_BlockActivity_Remove(blockAct); } } } } return; } // NOTE: This does not DIRECTLY remove the block activity. But it will subsequently mark it for // removal in the next UpdateAll loop. void __cdecl lego::game::Level_BlockActivity_Destroy(Lego_Level *level,Point2I *blockPos,BOOL wallDestroyed) { Lego_BlockActivity *blockAct; blockAct = level->blocks[level->width * blockPos->y + blockPos->x].activity; if (blockAct != NULL) { if ((wallDestroyed == 0) && (blockAct->staticEffect == 0)) { gfx::Container_SetActivity(blockAct->cont,"Activity_Destroy"); gfx::Container_SetAnimationTime(blockAct->cont,0.0); blockAct->flags = blockAct->flags | BLOCKACT_FLAG_DESTROYING; return; } blockAct->flags = blockAct->flags | BLOCKACT_FLAG_REMOVING; } return; } void __cdecl lego::game::Level_BlockActivity_Remove(Lego_BlockActivity *blockAct) { Lego_Level *level; level = globs::legoGlobs.currLevel; gfx::Container_Remove(blockAct->cont); level->blocks[(blockAct->blockPos).y * level->width + (blockAct->blockPos).x].activity = NULL; if (blockAct->next == NULL) { level->blockActLast = blockAct->previous; } else { blockAct->next->previous = blockAct->previous; } if (blockAct->previous != NULL) { blockAct->previous->next = blockAct->next; } io::Mem_Free(blockAct); return; } void __cdecl lego::game::Level_BlockActivity_RemoveAll(Lego_Level *level) { Lego_BlockActivity *blockAct; Lego_BlockActivity *previous; blockAct = level->blockActLast; while (blockAct != NULL) { previous = blockAct->previous; Level_BlockActivity_Remove(blockAct); blockAct = previous; } return; } Lego_Level * __cdecl lego::lrr::Lego_GetLevel(void) { return globs::legoGlobs.currLevel; } Map3D * __cdecl lego::lrr::Lego_GetMap(void) { Lego_Level *level; level = Lego_GetLevel(); return level->map; } void __cdecl lego::game::Level_UncoverHiddenCavern(uint bx,uint by) { uint uVar1; float fVar2; float fVar3; Lego_Level *level; float *pfVar4; int iVar5; uint uVar6; uint by_00; uint uVar7; int iVar8; float *pfVar9; longlong lVar10; uint local_2c; int local_10 [2]; float *local_8 [2]; uint bx_00; level = globs::legoGlobs.currLevel; iVar8 = (globs::legoGlobs.currLevel)->height + (globs::legoGlobs.currLevel)->width; local_10[0] = 0; local_10[1] = 0; uVar7 = 0; pfVar4 = (float *)io::Mem_Alloc(iVar8 * 0x20); local_8[0] = pfVar4; if (pfVar4 != NULL) { local_8[1] = pfVar4 + iVar8 * 4; *pfVar4 = (float)(ulonglong)bx; bx = (uint)local_10; local_10[0] = 1; iVar8 = 0; pfVar4[1] = (float)(ulonglong)by; do { local_2c = 0; if (*(int *)bx != 0) { pfVar9 = *(float **)((int)local_8 + iVar8); do { fVar2 = pfVar9[1]; fVar3 = *pfVar9; lVar10 = __ftol((float10)fVar2); by_00 = (int)lVar10 - 1; iVar8 = (int)lVar10 + 1; if ((int)by_00 <= iVar8) { lVar10 = __ftol((float10)fVar3); uVar1 = (int)lVar10 - 1; bx_00 = uVar1; do { for (; (int)bx_00 <= (int)lVar10 + 1; bx_00 = bx_00 + 1) { if ((level->blocks[by_00 * level->width + bx_00].flags1 & BLOCK1_HIDDEN) != BLOCK1_NONE) { Level_DestroyWall(level,bx_00,by_00,TRUE); iVar5 = by_00 * level->width + bx_00; level->blocks[iVar5].flags1 = level->blocks[iVar5].flags1 & ~BLOCK1_HIDDEN; if ((fVar3 != (float)bx_00) || ((float)by_00 != fVar2)) { uVar6 = (uint)(uVar7 == 0); iVar5 = local_10[uVar6]; pfVar4 = local_8[uVar6]; pfVar4[iVar5 * 2] = (float)bx_00; local_10[uVar6] = iVar5 + 1; pfVar4[iVar5 * 2 + 1] = (float)by_00; } } } by_00 += 1; bx_00 = uVar1; } while ((int)by_00 <= iVar8); } local_2c += 1; pfVar9 = pfVar9 + 2; pfVar4 = local_8[0]; } while (local_2c < *(uint *)bx); } uVar7 = (uint)(uVar7 == 0); *(undefined4 *)bx = 0; iVar8 = uVar7 * 4; bx = (uint)(local_10 + uVar7); } while (local_10[uVar7] != 0); io::Mem_Free(pfVar4); } return; } void __cdecl lego::game::Lego_PTL_RockFall(uint bx,uint by,int param_3,BOOL isBlockVertexPos) { BlockFlags1 *pBVar1; Lego_Block *pLVar2; uint uVar3; BOOL BVar4; float *pfVar5; bool bVar6; float10 fVar7; float10 extraout_ST0; longlong lVar8; longlong lVar9; float dirX; float fVar10; float local_40; undefined4 uStack60; uint local_38; float local_34; undefined4 uStack48; Vector3F local_2c; float local_20 [5]; undefined4 local_c; undefined4 local_8; undefined4 local_4; uStack60 = 0; fVar7 = (float10)(ulonglong)by; uStack48 = 0; local_38 = 0; local_34 = (float)(ulonglong)bx; pLVar2 = (globs::legoGlobs.currLevel)->blocks; uVar3 = (globs::legoGlobs.currLevel)->width; local_20[0] = 1.0; local_20[1] = 0.0; local_20[2] = 0.0; local_20[3] = 1.0; local_20[4] = -1.0; local_c = 0; local_8 = 0; local_4 = 0xbf800000; pfVar5 = local_20; // local_40 = 4; local_40 = 5.605194e-45; do { *pfVar5 = local_34 + *pfVar5; fVar10 = pfVar5[1]; pfVar5[1] = (float)(fVar7 + (float10)fVar10); lVar8 = __ftol(fVar7 + (float10)fVar10); lVar9 = __ftol((float10)*pfVar5); if ((*(byte *)&pLVar2[uVar3 * (int)lVar8 + (int)lVar9].flags1 & 8) != 0) { local_38 += 1; } pfVar5 = pfVar5 + 2; local_40 = (float)((int)local_40 + -1); fVar7 = extraout_ST0; } while (local_40 != 0.0); if ((float)isBlockVertexPos == 0.0) { lego::map::Map3D_BlockToWorldPos ((globs::legoGlobs.currLevel)->map,bx,by,&local_40,(float *)&isBlockVertexPos); } else { lego::map::Map3D_BlockVertexToWorldPos ((globs::legoGlobs.currLevel)->map,bx,by,&local_40,(float *)&isBlockVertexPos, &local_34); } local_2c.y = (float)isBlockVertexPos; local_2c.x = local_40; fVar7 = lego::map::Map3D_GetWorldZ ((globs::legoGlobs.currLevel)->map,local_40,(float)isBlockVertexPos); local_2c.z = (float)fVar7; snd::SFX_Random_PlaySound3DOnContainer(NULL,SFX_RockBreak,FALSE,FALSE,&local_2c); bVar6 = 1 < local_38; local_20[0] = 0.0; local_20[1] = 1.0; local_20[2] = 1.0; local_20[3] = 0.0; local_20[4] = 0.0; local_c = 0xbf800000; local_8 = 0xbf800000; local_4 = 0; fVar10 = local_20[param_3 * 2 + 1]; dirX = local_20[param_3 * 2]; fVar7 = lego::map::Map3D_GetWorldZ ((globs::legoGlobs.currLevel)->map,local_40,(float)isBlockVertexPos); BVar4 = effect::Effect_Spawn_RockFall ((uint)bVar6,bx,by,local_40,isBlockVertexPos,(float)fVar7,dirX,fVar10); if (BVar4 != 0) { pBVar1 = &(globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx]. flags1; *pBVar1 = *pBVar1 | BLOCK1_ROCKFALLFX; } return; } Lego_SurfaceType __cdecl lego::lrr::Lego_GetBlockTerrain(int bx,int by) { return (uint)(globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx]. terrain; } uint __cdecl lego::game::MapShared_GetBlock(uint memHandle,int bx,int by) { MapFileInfo *mapFile; uint local_4; uint sharedIndex_00; sharedIndex_00 = memHandle; mapFile = (MapFileInfo *)io::Mem_AddressHandle(memHandle); MapShared_GetDimensions(sharedIndex_00,&memHandle,&local_4); return (uint)mapFile->blocks[memHandle * by + bx]; } BOOL __cdecl lego::game::Level_FindSelectedUnit_BlockCheck_FUN_00431960(uint bx,uint by,BOOL param_3) { LegoObject **pLiveObj; BOOL BVar1; uint local_8; uint numSelected; pLiveObj = Message_GetSelectedUnits2(&numSelected); if ((pLiveObj != NULL) && (local_8 = 0, numSelected != 0)) { do { BVar1 = LiveObject_BlockCheck_FUN_004326a0(*pLiveObj,bx,by,param_3,TRUE); if (BVar1 != 0) { return TRUE; } local_8 += 1; pLiveObj = pLiveObj + 1; } while (local_8 < numSelected); return 0; } return 0; } BOOL __cdecl lego::game::Level_FindSelectedLiveObject_BlockReinforce_FUN_004319e0(uint bx,uint by) { LegoObject **ppLVar1; BOOL BVar2; uint uVar3; uint local_4; ppLVar1 = Message_GetSelectedUnits2(&local_4); if ((ppLVar1 != NULL) && (uVar3 = 0, local_4 != 0)) { do { BVar2 = LiveObject_CanReinforceBlock(*ppLVar1,bx,by); if (BVar2 != 0) { return TRUE; } uVar3 += 1; ppLVar1 = ppLVar1 + 1; } while (uVar3 < local_4); return 0; } return 0; } BOOL __cdecl lego::game::Level_CanBuildOnBlock(int bx,int by,BOOL isPath,BOOL isWaterEntrance) { int idx; BOOL BVar1; Point2I *pDir; uint i; Point2I blockPos; Point2I DIRECTIONS [4]; BlockFlags1 bflags1; Lego_Block *block; blockPos.y = by; idx = (globs::legoGlobs.currLevel)->width * by + bx; blockPos.x = bx; block = (globs::legoGlobs.currLevel)->blocks + idx; if ((*(byte *)&(globs::legoGlobs.currLevel)->blocks[idx].flags2 & BLOCK2_SLUGHOLE_EXPOSED) == 0) { BVar1 = Construction_Zone_ExistsAtBlock(&blockPos); if ((BVar1 == 0) && (bflags1 = block->flags1, (bflags1 & BLOCK1_PATH) == BLOCK1_NONE)) { i = 0; if (((isPath == 0) || ((isWaterEntrance == 0 || (block->terrain == Lego_SurfaceType8_Lake)))) && (((isPath == 0 || ((bflags1 & BLOCK1_BUILDINGPATH) == BLOCK1_NONE)) && ((((isWaterEntrance != 0 || (block->terrain != Lego_SurfaceType8_Lake)) && (block->terrain != Lego_SurfaceType8_Lava)) && ((((bflags1 & BLOCK1_FLOOR) != BLOCK1_NONE && ((bflags1 & BLOCK1_CLEARED) != BLOCK1_NONE)) && ((bflags1 & (BLOCK1_BUILDINGSOLID|BLOCK1_BUILDINGPATH|BLOCK1_FOUNDATION)) == BLOCK1_NONE)))))))) { BVar1 = ElectricFence_Block_IsFence(bx,by); if (BVar1 == 0) { DIRECTIONS[0].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[0].x = 0; DIRECTIONS[1].x = 1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = 1; DIRECTIONS[3].y = 0; pDir = DIRECTIONS; while ((globs::legoGlobs.currLevel)->blocks [(pDir->y + by) * (globs::legoGlobs.currLevel)->width + bx + pDir->x].terrain != Lego_SurfaceType8_RechargeSeam) { i += 1; pDir = pDir + 1; if (3 < i) { return TRUE; } } } } } } return 0; } BOOL __cdecl lego::game::LiveObject_FUN_00431ba0 (LegoObject *liveObj,Point2I *blockPos,Point2I *out_blockOffPos,BOOL param_4) { bool bVar1; uint uVar2; int crossType; uint uVar3; int bx1; Lego_Level *level; uint dir; uint i; Point2I DIRECTIONS [4]; BlockFlags1 bflags1; int by1; DIRECTIONS[0].y = -1; DIRECTIONS[3].x = -1; // static variable used only in this function globs::gamectrlGlobs.direction_178 += DIRECTION_RIGHT; DIRECTIONS[0].x = 0; DIRECTIONS[1].x = 1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = 1; DIRECTIONS[3].y = 0; i = 0; level = globs::legoGlobs.currLevel; do { dir = globs::gamectrlGlobs.direction_178 + i & 3; if (param_4 == 0) { LAB_00431c58: by1 = DIRECTIONS[dir].y + blockPos->y; bx1 = DIRECTIONS[dir].x + blockPos->x; crossType = Lego_GetCrossTerrainType(liveObj,bx1,by1,bx1,by1,FALSE); level = globs::legoGlobs.currLevel; if (crossType != 0) { by1 = DIRECTIONS[dir].y; out_blockOffPos->x = DIRECTIONS[dir].x + blockPos->x; out_blockOffPos->y = by1 + blockPos->y; return TRUE; } } else { uVar3 = DIRECTIONS[dir].x + blockPos->x; uVar2 = DIRECTIONS[dir].y + blockPos->y; if ((((uVar3 < level->width - 1) && (uVar2 < level->height - 1)) && (bflags1 = level->blocks[uVar2 * level->width + uVar3].flags1, (bflags1 & BLOCK1_WALL) != BLOCK1_NONE)) && ((bflags1 & BLOCK1_FLOOR) == BLOCK1_NONE)) { bVar1 = true; } else { bVar1 = false; } if (!bVar1) goto LAB_00431c58; } i += 1; if (3 < i) { return 0; } } while( true ); } // 0 = Can't Cross, 1 = Can Cross (floor), 2 = diagonal, 3 = wall int __cdecl lego::game::Lego_GetCrossTerrainType (LegoObject *liveObj,int bx1,int by1,int bx2,int by2,BOOL param_6) { uint uVar1; LegoObject *liveObj_00; StatsFlags1 sflags1; int *pDirY; StatsFlags3 sflags3; StatsFlags2 sflags2; BOOL BVar2; int iVar3; BOOL checkWater; BOOL isWall; BOOL checkLava; BOOL checkLand; BOOL checkEnterToolStore; BOOL checkSingleWidthDig; Point2I blockPos; Point2I DIRECTIONS [4]; BlockFlags1 bflags1; Lego_Block *block1; Lego_Block *blocksGrid; int by1_00; Lego_Level *level; uint width; by1_00 = by1; liveObj_00 = liveObj; level = globs::legoGlobs.currLevel; width = (globs::legoGlobs.currLevel)->width; blocksGrid = (globs::legoGlobs.currLevel)->blocks; checkWater = 0; checkLand = TRUE; checkLava = 0; checkEnterToolStore = 0; block1 = blocksGrid + by1 * width + bx1; // const Point2I DIRECTIONS[4] = { // { 0, -1 }, // { 1, 0 }, // { 0, 1 }, // { -1, 0 }, // }; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; by1 = 1; DIRECTIONS[0].y = -1; DIRECTIONS[1].x = 1; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = 1; DIRECTIONS[3].x = -1; DIRECTIONS[3].y = 0; if (((liveObj != NULL) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_CANBEDRIVEN) != STATS1_NONE)) && (liveObj->driveObject == NULL)) { return 0; } liveObj = NULL; pDirY = &DIRECTIONS[0].y; do { if ((pDirY[-1] + bx2 == bx1) && (by2 + *pDirY == by1_00)) break; pDirY = pDirY + 2; liveObj = (LegoObject *)((int)&liveObj->type + 1); } while (liveObj < (LegoObject *)&DAT_00000004); if (liveObj_00 == NULL) { checkSingleWidthDig = 0; } else { if (liveObj_00->type == LegoObject_ElectricFence) { return 0; } sflags3 = stats::StatsObject_GetStatsFlags3(liveObj_00); checkEnterToolStore = sflags3 & STATS3_ENTERTOOLSTORE; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); checkSingleWidthDig = sflags1 & STATS1_SINGLEWIDTHDIG; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); checkWater = sflags1 & STATS1_CROSSWATER; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); checkLand = sflags1 & STATS1_CROSSLAND; sflags2 = stats::StatsObject_GetStatsFlags2(liveObj_00); checkLava = sflags2 & STATS2_CROSSLAVA; if (((param_6 == 0) && (BVar2 = LegoObject_GetBlockPos(liveObj_00,&blockPos.x,&blockPos.y), BVar2 != 0)) && ((bx1 == blockPos.x && (by1_00 == blockPos.y)))) { return 1; } } if (block1->terrain == Lego_SurfaceType8_Lake) { if (checkWater == STATS1_NONE) { return 0; } if (true) goto LAB_00431ea3; } if (checkLand == 0) { return 0; } LAB_00431ea3: if (((block1->terrain == Lego_SurfaceType8_Lava) && (checkLava == STATS2_NONE)) && ((block1->flags1 & BLOCK1_NOTHOT) == BLOCK1_NONE)) { return 0; } bflags1 = block1->flags1; if ((bflags1 & BLOCK1_BUILDINGSOLID) != BLOCK1_NONE) { return 0; } if ((param_6 != 0) && ((bflags1 & BLOCK1_INCORNER) != BLOCK1_NONE)) { return 0; } // BLOCK2_TOOLSTORE_UNK (0x4) if ((checkEnterToolStore == 0) && ((*(byte *)&block1->flags2 & 4) != 0)) { return 0; } if (checkSingleWidthDig == 0) { if ((bflags1 & BLOCK1_FLOOR) == BLOCK1_NONE) { return 0; } } else { if ((bflags1 & BLOCK1_WALL) != BLOCK1_NONE) { by1 = 3; } if (block1->predug == Lego_PredugType_Wall) { return 0; } uVar1 = level->width; block1 = level->blocks; iVar3 = by1_00 * uVar1 + bx1; isWall = block1[iVar3].flags1 & BLOCK1_WALL; if (isWall != 0) { if ((block1 + iVar3)[-1].terrain == Lego_SurfaceType8_Lava) { return 0; } if (block1[(by1_00 + -1) * uVar1 + bx1].terrain == Lego_SurfaceType8_Lava) { return 0; } } if (isWall != 0) { if ((block1 + iVar3)[-1].terrain == Lego_SurfaceType8_Water) { return 0; } if (block1[(by1_00 + -1) * uVar1 + bx1].terrain == Lego_SurfaceType8_Water) { return 0; } } if (liveObj == NULL) { if ((bflags1 & BLOCK1_DIAGONAL) != BLOCK1_NONE) { by1 = 2; } if ((blocksGrid[by2 * width + bx2].flags1 & BLOCK1_DIAGONAL) != BLOCK1_NONE) { by1 = 2; } } } if ((bx2 != bx1) && (by2 != by1_00)) { // BLOCK1_FLOOR (0x8) if (((*(byte *)&level->blocks[by2 * level->width + bx1].flags1 & 8) != 0) && ((*(byte *)&level->blocks[by1_00 * level->width + bx2].flags1 & 8) != 0)) { return 2; } } return by1; } // Marks a block as powered, adds it to the first PowerGrid list, then updates its surface. void __cdecl lego::game::Level_PowerGrid_AddPoweredBlock(Point2I *blockPos) { Lego_Level *level; BlockFlags2 *pBFlags2; level = globs::legoGlobs.currLevel; pBFlags2 = &(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags2; *pBFlags2 = *pBFlags2 | BLOCK2_POWERED; globs::legoGlobs.poweredBlocks[globs::legoGlobs.poweredBlockCount].x = blockPos->x; globs::legoGlobs.poweredBlocks[globs::legoGlobs.poweredBlockCount].y = blockPos->y; globs::legoGlobs.poweredBlockCount += 1; Level_BlockUpdateSurface(level,blockPos->x,blockPos->y,0); return; } BOOL __cdecl lego::game::Level_Block_IsPowered(Point2I *blockPos) { return (globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].flags2 & BLOCK2_POWERED; } // Updates the block surfaces for unpowered blocks in the second PowerGrid list. Then clears the // list. void __cdecl lego::game::Level_PowerGrid_UpdateUnpoweredBlockSurfaces(void) { Lego_Level *level; uint i; Point2I *blockPos; level = globs::legoGlobs.currLevel; i = 0; if (globs::legoGlobs.unpoweredBlockCount != 0) { blockPos = globs::legoGlobs.unpoweredBlocks; do { // if (!(level->blocks[level->width * by + bx].flags2 & BLOCK2_POWERED)) if ((*(byte *)((int)&level->blocks[level->width * blockPos->y + blockPos->x].flags2 + 1) & 1) == 0) { Level_BlockUpdateSurface(level,blockPos->x,blockPos->y,0); } i += 1; blockPos = blockPos + 1; } while (i < globs::legoGlobs.unpoweredBlockCount); } globs::legoGlobs.unpoweredBlockCount = 0; return; } // Marks blocks in the first PowerGrid list as unpowered and moves them to the second list. Then // clears the first list. void __cdecl lego::game::Level_PowerGrid_UnpowerPoweredBlocks(void) { int *piVar1; int *piVar2; Point2I *blockPos; uint i; Lego_Level *level; BlockFlags2 *pBFlags2; level = globs::legoGlobs.currLevel; i = 0; globs::legoGlobs.unpoweredBlockCount = globs::legoGlobs.poweredBlockCount; if (globs::legoGlobs.poweredBlockCount != 0) { blockPos = globs::legoGlobs.poweredBlocks; do { // legoGlobs.unpoweredBlocks[i] = legoGlobs.poweredBlocks[i]; blockPos[100].x = blockPos->x; blockPos[100].y = blockPos->y; piVar1 = &blockPos->y; piVar2 = &blockPos->x; blockPos = blockPos + 1; pBFlags2 = &level->blocks[*piVar1 * level->width + *piVar2].flags2; i += 1; *pBFlags2 = *pBFlags2 & ~BLOCK2_POWERED; globs::legoGlobs.unpoweredBlockCount = globs::legoGlobs.poweredBlockCount; } while (i < globs::legoGlobs.poweredBlockCount); } globs::legoGlobs.poweredBlockCount = 0; return; } void __cdecl lego::game::Level_PowerGrid_AddDrainPowerBlock(Point2I *blockPos) { BlockFlags2 *pBFlags2; pBFlags2 = &(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags2; *pBFlags2 = *pBFlags2 | BLOCK2_DRAINPOWER_TEMP; globs::legoGlobs.powerDrainBlocks[globs::legoGlobs.powerDrainCount].x = blockPos->x; globs::legoGlobs.powerDrainBlocks[globs::legoGlobs.powerDrainCount].y = blockPos->y; globs::legoGlobs.powerDrainCount = globs::legoGlobs.powerDrainCount + 1; return; } BOOL __cdecl lego::game::Level_PowerGrid_IsDrainPowerBlock(Point2I *blockPos) { return (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags2 & BLOCK2_DRAINPOWER_TEMP; } void __cdecl lego::game::Level_PowerGrid_ClearDrainPowerBlocks(void) { int *piVar1; int *piVar2; Point2I *pBlockPos; uint i; Lego_Level *level; BlockFlags2 *pFlags2; level = globs::legoGlobs.currLevel; i = 0; if (globs::legoGlobs.powerDrainCount != 0) { pBlockPos = globs::legoGlobs.powerDrainBlocks; do { piVar1 = &pBlockPos->y; piVar2 = &pBlockPos->x; pBlockPos = pBlockPos + 1; pFlags2 = &level->blocks[*piVar1 * level->width + *piVar2].flags2; i += 1; *pFlags2 = *pFlags2 & ~BLOCK2_DRAINPOWER_TEMP; } while (i < globs::legoGlobs.powerDrainCount); } globs::legoGlobs.powerDrainCount = 0; return; } void __cdecl lego::game::Level_Block_UnsetBuildingTile(Point2I *blockPos) { Lego_Level *level; BlockFlags2 *pFlags2; BlockFlags1 *pFlags1; level = globs::legoGlobs.currLevel; pFlags1 = &(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1; *pFlags1 = *pFlags1 & ~(BLOCK1_BUILDINGSOLID|BLOCK1_BUILDINGPATH|BLOCK1_FOUNDATION|BLOCK1_PATH); pFlags2 = &level->blocks[level->width * blockPos->y + blockPos->x].flags2; *pFlags2 = *pFlags2 & ~BLOCK2_TOOLSTORE; Level_BlockUpdateSurface(level,blockPos->x,blockPos->y,0); return; } void __cdecl lego::game::Level_Block_UnsetGeneratePower(Point2I *blockPos) { BlockFlags2 *pFlags2; pFlags2 = &(globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].flags2; *pFlags2 = *pFlags2 & ~BLOCK2_GENERATEPOWER; return; } void __cdecl lego::game::Level_Block_SetToolStoreBuilding(Point2I *blockPos) { Lego_Level *level; BlockFlags1 *pFlags1; BlockFlags2 *pFlags2; level = globs::legoGlobs.currLevel; pFlags1 = &(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1; *pFlags1 = *pFlags1 | (BLOCK1_BUILDINGPATH|BLOCK1_FOUNDATION); pFlags2 = &level->blocks[level->width * blockPos->y + blockPos->x].flags2; *pFlags2 = *pFlags2 | BLOCK2_TOOLSTORE; Level_BlockUpdateSurface(level,blockPos->x,blockPos->y,0); return; } void __cdecl lego::game::Level_Block_SetSolidBuilding(int bx,int by) { Lego_Level *level; BlockFlags1 *pFlags1; level = globs::legoGlobs.currLevel; pFlags1 = &(globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx]. flags1; *pFlags1 = *pFlags1 | (BLOCK1_BUILDINGSOLID|BLOCK1_FOUNDATION); Level_BlockUpdateSurface(level,bx,by,0); return; } void __cdecl lego::game::Level_Block_SetPathBuilding(int bx,int by) { Lego_Level *level; BlockFlags1 *pFlags1; level = globs::legoGlobs.currLevel; pFlags1 = &(globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx]. flags1; *pFlags1 = *pFlags1 | (BLOCK1_BUILDINGPATH|BLOCK1_FOUNDATION|BLOCK1_PATH); Level_BlockUpdateSurface(level,bx,by,0); return; } void __cdecl lego::game::Level_Block_SetFenceRequest(int bx,int by,BOOL state) { int idx; int width; BlockFlags2 *pFlags2; width = (globs::legoGlobs.currLevel)->width; if (state != 0) { pFlags2 = &(globs::legoGlobs.currLevel)->blocks[width * by + bx].flags2; *pFlags2 = *pFlags2 | BLOCK2_FENCEREQUEST; return; } idx = width * by + bx; (globs::legoGlobs.currLevel)->blocks[idx].flags2 = (globs::legoGlobs.currLevel)->blocks[idx].flags2 & ~BLOCK2_FENCEREQUEST; return; } BOOL __cdecl lego::game::Level_Block_IsFenceRequest(int bx,int by) { return (globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx].flags2 & BLOCK2_FENCEREQUEST; } // Some originally optional functionality, always returns TRUE. BOOL __cdecl lego::game::Level_IsBuildPathBoolUnk_true(Point2I *blockPos) { return TRUE; } void __cdecl lego::game::Level_Block_SetLayedPath(Point2I *blockPos,BOOL state) { Lego_Level *level; BlockFlags1 *pFlags1; BlockFlags1 flags1; level = globs::legoGlobs.currLevel; if (state == 0) { pFlags1 = &(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1; flags1 = *pFlags1 & ~BLOCK1_LAYEDPATH; } else { pFlags1 = &(globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1; flags1 = *pFlags1 | BLOCK1_LAYEDPATH; } *pFlags1 = flags1; Level_BlockUpdateSurface(level,blockPos->x,blockPos->y,0); return; } void __cdecl lego::game::Level_Block_SetGeneratePower(Point2I *blockPos) { BlockFlags2 *pFlags2; pFlags2 = &(globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].flags2; *pFlags2 = *pFlags2 | BLOCK2_GENERATEPOWER; return; } // Also updates path connections... I think. BOOL __cdecl lego::game::Level_Block_SetPath(Point2I *blockPos) { Lego_Level *level; int idx; int dir; Point2I *pDir; Point2I DIRECTIONS_I5 [5]; Lego_Block *block; BlockFlags1 flags1; level = globs::legoGlobs.currLevel; idx = (globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x; block = (globs::legoGlobs.currLevel)->blocks + idx; flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1; if (((flags1 & BLOCK1_CLEARED) != BLOCK1_NONE) && (block->terrain != Lego_SurfaceType8_Lava)) { DIRECTIONS_I5[0].x = 0; DIRECTIONS_I5[0].y = 0; DIRECTIONS_I5[1].x = 0; DIRECTIONS_I5[1].y = -1; DIRECTIONS_I5[2].x = 1; DIRECTIONS_I5[2].y = 0; DIRECTIONS_I5[3].x = 0; DIRECTIONS_I5[3].y = 1; DIRECTIONS_I5[4].x = -1; DIRECTIONS_I5[4].y = 0; if ((flags1 & BLOCK1_ERODEACTIVE) == BLOCK1_NONE) { block->flags1 = flags1 | BLOCK1_PATH; } else { Erode_Block_FUN_0040ed80(blockPos,0); level->blocks[level->width * blockPos->y + blockPos->x].erodeLevel = 0; } idx = level->width * blockPos->y + blockPos->x; pDir = DIRECTIONS_I5; dir = 5; level->blocks[idx].flags1 = level->blocks[idx].flags1 & ~BLOCK1_LAYEDPATH; do { Level_BlockUpdateSurface(level,blockPos->x + pDir->x,pDir->y + blockPos->y,0); pDir = pDir + 1; dir += -1; } while (dir != 0); LegoObject_RequestPowerGridUpdate(); return TRUE; } return 0; } void __cdecl lego::game::Level_Block_SetBusyFloor(Point2I *blockPos,BOOL busyFloor) { int idx; int width; BlockFlags1 *pBFlags1; width = (globs::legoGlobs.currLevel)->width; if (busyFloor != 0) { pBFlags1 = &(globs::legoGlobs.currLevel)->blocks[width * blockPos->y + blockPos->x].flags1; *pBFlags1 = *pBFlags1 | BLOCK1_BUSY_FLOOR; return; } idx = width * blockPos->y + blockPos->x; (globs::legoGlobs.currLevel)->blocks[idx].flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1 & ~BLOCK1_BUSY_FLOOR; return; } BOOL __cdecl lego::game::LiveObject_BlockCheck_FUN_004326a0 (LegoObject *liveObj,uint bx,uint by,BOOL param_4,BOOL param_5) { StatsFlags1 sflags1; uint i; float10 fVar1; Point2I DIRECTIONS_1 [4]; Point2I DIRECTIONS_2 [4]; Lego_Block *block; Lego_Level *level; Point2I *pDir; Lego_SurfaceType8 terrain; uint width; level = globs::legoGlobs.currLevel; block = (globs::legoGlobs.currLevel)->blocks + by * (globs::legoGlobs.currLevel)->width + bx; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) || (liveObj->driveObject != NULL)) { if ((param_4 != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_SINGLEWIDTHDIG) == STATS1_NONE)) { return 0; } if (((((param_5 == 0) || ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE)) && ((*(byte *)&liveObj->flags3 & LIVEOBJ3_CANDIG) != 0)) && ((fVar1 = stats::StatsObject_GetDrillTimeType(liveObj,(uint)block->terrain), fVar1 != (float10)0.0 && (width = level->width, bx < width - 2)))) && (by < level->height - 2)) { i = 0; if (param_4 == 0) { if ((((block->flags1 & BLOCK1_WALL) != BLOCK1_NONE) && ((block->flags1 & BLOCK1_INCORNER) == BLOCK1_NONE)) && ((terrain = block->terrain, terrain != Lego_SurfaceType8_Immovable && ((terrain != Lego_SurfaceType8_Water && (terrain != Lego_SurfaceType8_RechargeSeam)))))) { return TRUE; } } else { if (block->predug == Lego_PredugType_Wall) { DIRECTIONS_1[1].x = 1; DIRECTIONS_1[2].y = 1; DIRECTIONS_2[0].x = -1; DIRECTIONS_2[0].y = -1; DIRECTIONS_2[1].x = 0; DIRECTIONS_2[1].y = -1; DIRECTIONS_2[2].x = 0; DIRECTIONS_2[2].y = 0; DIRECTIONS_2[3].x = -1; DIRECTIONS_2[3].y = 0; DIRECTIONS_1[0].x = 0; DIRECTIONS_1[0].y = -1; DIRECTIONS_1[1].y = 0; DIRECTIONS_1[2].x = 0; DIRECTIONS_1[3].x = -1; DIRECTIONS_1[3].y = 0; pDir = DIRECTIONS_1; do { if (level->blocks[(pDir->y + by) * width + bx + pDir->x].predug != Lego_PredugType_Wall) break; i += 1; pDir = pDir + 1; } while (i < 4); if (i < 4) { i = 0; pDir = DIRECTIONS_2; do { terrain = level->blocks[(pDir->y + by) * width + bx + pDir->x].terrain; if ((terrain != Lego_SurfaceType8_Immovable) && (terrain != Lego_SurfaceType8_Water)) break; i += 1; pDir = pDir + 1; } while (i < 4); if (i < 4) { return TRUE; } } } } } } return FALSE; } BOOL __cdecl lego::game::LiveObject_CanDynamiteBlockPos(LegoObject *liveObj,uint bx,uint by) { int idx; BlockFlags1 flags1; int width; Lego_SurfaceType8 terrain; if (((((liveObj->flags3 & LIVEOBJ3_CANDYNAMITE) != LIVEOBJ3_NONE) && (bx != 0)) && (by != 0)) && ((width = (globs::legoGlobs.currLevel)->width, bx < width - 2U && (by < (globs::legoGlobs.currLevel)->height - 2)))) { idx = by * width + bx; flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1; if (((((flags1 & BLOCK1_WALL) != BLOCK1_NONE) && (((flags1 & BLOCK1_INCORNER) == BLOCK1_NONE && (terrain = (globs::legoGlobs.currLevel)->blocks[idx].terrain, terrain != Lego_SurfaceType8_Immovable)))) && (terrain != Lego_SurfaceType8_RechargeSeam)) && (terrain != Lego_SurfaceType8_Water)) { return TRUE; } } return 0; } // "Nearly" identical to Level_Block_IsGround... // only used for BirdScarer placement... BOOL __cdecl lego::game::Level_Block_IsGround_alt(LegoObject *liveObj,uint bx,uint by) { BOOL BVar1; Lego_Level *level; level = globs::legoGlobs.currLevel; BVar1 = lego::map::Map3D_IsInsideDimensions((globs::legoGlobs.currLevel)->map,bx,by); // GHIDRA WARNING: DO NOT TRY TO EQUATE THIS FLAG 0x8!! // It causes Ghidra to fail decompilation... -_- if ((BVar1 != 0) && ((*(byte *)&level->blocks[level->width * by + bx].flags1 & 8) != 0)) { return TRUE; } return 0; } BOOL __cdecl lego::game::LiveObject_CanReinforceBlock(LegoObject *liveObj,uint bx,uint by) { int width; BlockFlags1 flags1; Lego_SurfaceType8 terrain; if (((((liveObj == NULL) || ((*(byte *)&liveObj->flags3 & LIVEOBJ3_CANREINFORCE) != 0)) && (bx != 0)) && ((by != 0 && (width = (globs::legoGlobs.currLevel)->width, bx < width - 2U)))) && (by < (globs::legoGlobs.currLevel)->height - 2)) { flags1 = (globs::legoGlobs.currLevel)->blocks[by * width + bx].flags1; if ((((flags1 & BLOCK1_WALL) != BLOCK1_NONE) && ((flags1 & BLOCK1_REINFORCED) == BLOCK1_NONE)) && ((terrain = (globs::legoGlobs.currLevel)->blocks[by * width + bx].terrain, terrain != Lego_SurfaceType8_RechargeSeam && ((terrain != Lego_SurfaceType8_OreSeam && (terrain != Lego_SurfaceType8_CrystalSeam)))))) { return TRUE; } } return 0; } // When includeToolStore is true, blocks marked with the toolstore flag will return true, regardless // of the solid flag. BOOL __cdecl lego::game::Level_Block_IsSolidBuilding(uint bx,uint by,BOOL includeToolStore) { int width; width = (globs::legoGlobs.currLevel)->width; if (includeToolStore == 0) { return (globs::legoGlobs.currLevel)->blocks[width * by + bx].flags1 & BLOCK1_BUILDINGSOLID; } if ((((globs::legoGlobs.currLevel)->blocks[width * by + bx].flags1 & BLOCK1_BUILDINGSOLID) == BLOCK1_NONE) && ((*(byte *)&(globs::legoGlobs.currLevel)->blocks[width * by + bx].flags2 & BLOCK2_TOOLSTORE) == 0)) { // return FALSE; return BLOCK1_NONE; } // return TRUE; return BLOCK1_RUBBLE_LOW; } BOOL __cdecl lego::game::Level_Block_IsRockFallFX(uint bx,uint by) { int width; width = (globs::legoGlobs.currLevel)->width; if ((bx < width - 1U) && (by < (globs::legoGlobs.currLevel)->height - 1)) { return (globs::legoGlobs.currLevel)->blocks[by * width + bx].flags1 & BLOCK1_ROCKFALLFX; } return BLOCK1_NONE; } BOOL __cdecl lego::game::Level_Block_IsGround(uint bx,uint by) { int width; width = (globs::legoGlobs.currLevel)->width; if ((bx < width - 1U) && (by < (globs::legoGlobs.currLevel)->height - 1)) { return (globs::legoGlobs.currLevel)->blocks[by * width + bx].flags1 & BLOCK1_FLOOR; } return BLOCK1_NONE; } BOOL __cdecl lego::game::Level_Block_IsSeamWall(uint bx,uint by) { Lego_SurfaceType8 terrain; terrain = (globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx]. terrain; if (((terrain != Lego_SurfaceType8_OreSeam) && (terrain != Lego_SurfaceType8_CrystalSeam)) && (terrain != Lego_SurfaceType8_RechargeSeam)) { return 0; } return TRUE; } BOOL __cdecl lego::game::Level_Block_IsWall(uint bx,uint by) { int width; BlockFlags1 flags1; width = (globs::legoGlobs.currLevel)->width; if ((((bx < width - 1U) && (by < (globs::legoGlobs.currLevel)->height - 1)) && (flags1 = (globs::legoGlobs.currLevel)->blocks[by * width + bx].flags1, (flags1 & BLOCK1_WALL) != BLOCK1_NONE)) && ((flags1 & BLOCK1_FLOOR) == BLOCK1_NONE)) { return TRUE; } return 0; } // This flag is not fully understood, but is related to an unimplemented feature // involving !SingleWidthDig, where a walls connections are destroyed, rather // than the entire block. BOOL __cdecl lego::game::Level_Block_IsDestroyedConnection(uint bx,uint by) { return (globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx].flags1 & BLOCK1_DESTROYEDCONNECTION; } uint __cdecl lego::game::Level_Block_GetRubbleLayers(Point2I *blockPos) { BlockFlags1 flags1; flags1 = (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1; if ((flags1 & BLOCK1_CLEARED) != BLOCK1_NONE) { return 0; } return (flags1 & BLOCK1_RUBBLE_FULL) + BLOCK1_RUBBLE_LOW; } // Returns true if the block surface is fully cleared of all rubble. BOOL __cdecl lego::game::Level_Block_ClearRubbleLayer(Point2I *blockPos) { Lego_Level *level; int idx; BlockFlags1 rubble; BOOL result; float10 fVar1; Vector3F worldPos; Vector3F vecRandom; BlockFlags1 flags1; Lego_Block *pBlock; level = globs::legoGlobs.currLevel; result = TRUE; idx = (globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x; pBlock = (globs::legoGlobs.currLevel)->blocks + idx; flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1; // BLOCK1_RUBBLE_FULL is also a mask for rubble level rubble = flags1 & BLOCK1_RUBBLE_FULL; if ((flags1 & BLOCK1_CLEARED) == BLOCK1_NONE) { if (rubble != BLOCK1_NONE) { // Positive modulus ((rubble - 1) % 4) pBlock->flags1 = (rubble + ~BLOCK1_NONE ^ flags1) & BLOCK1_RUBBLE_FULL ^ flags1; } else { pBlock->flags1 = flags1 | BLOCK1_CLEARED; front::Info_RemoveAllAtBlockPos(blockPos); front::Interface_BackToMain_IfSelectedRubble_IsBlockPos(blockPos); ai::AITask_DelayOrRemoveClearReferences(blockPos,FALSE); lego::map::Map3D_BlockToWorldPos(level->map,blockPos->x,blockPos->y,&worldPos.x,&worldPos.y); fVar1 = lego::map::Map3D_GetWorldZ(level->map,worldPos.x,worldPos.y); worldPos.z = (float)fVar1; math::Maths_Vector3DRandom(&vecRandom); vecRandom.z = 0.0; effect::Effect_Spawn_Particle(MISCOBJECT_PATHDUST,&worldPos,&vecRandom); } result = ZEXT14(rubble == BLOCK1_NONE); Level_BlockUpdateSurface(level,blockPos->x,blockPos->y,0); } return result; } BOOL __cdecl lego::game::Level_Block_IsReinforced(uint bx,uint by) { int width; width = (globs::legoGlobs.currLevel)->width; if ((bx < width - 1U) && (by < (globs::legoGlobs.currLevel)->height - 1)) { return (globs::legoGlobs.currLevel)->blocks[by * width + bx].flags1 & BLOCK1_REINFORCED; } return BLOCK1_NONE; } BOOL __cdecl lego::game::Level_Block_IsBusy(Point2I *blockPos) { return (globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].flags1 & BLOCK1_BUSY_WALL ; } void __cdecl lego::game::Level_Block_SetBusy(Point2I *blockPos,BOOL state) { int idx; int width; BlockFlags1 *pFlags1; width = (globs::legoGlobs.currLevel)->width; if (state != 0) { pFlags1 = &(globs::legoGlobs.currLevel)->blocks[width * blockPos->y + blockPos->x].flags1; *pFlags1 = *pFlags1 | BLOCK1_BUSY_WALL; return; } idx = width * blockPos->y + blockPos->x; (globs::legoGlobs.currLevel)->blocks[idx].flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1 & ~BLOCK1_BUSY_WALL; return; } BOOL __cdecl lego::game::Level_Block_IsCorner(uint bx,uint by) { // (BLOCK1_CORNEROBTUSE|BLOCK1_CORNERINNER) (0x40|0x80) if ((*(byte *)&(globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx] .flags1 & 0xc0) == 0) { return 0; } return TRUE; } BOOL __cdecl lego::game::Level_Block_IsExposed(Point2I *blockPos) { return (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1 & BLOCK1_EXPOSED; } BOOL __cdecl lego::game::Level_Block_IsImmovable(Point2I *blockPos) { return (uint)((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].terrain == Lego_SurfaceType8_Immovable); } BOOL __cdecl lego::game::Level_Block_IsLava(Point2I *blockPos) { return (uint)((globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].terrain == Lego_SurfaceType8_Lava); } BOOL __cdecl lego::game::Level_Block_IsNotWallOrGround(uint bx,uint by) { int width; width = (globs::legoGlobs.currLevel)->width; if ((bx < width - 1U) && (by < (globs::legoGlobs.currLevel)->height - 1)) { return (uint)(((globs::legoGlobs.currLevel)->blocks[by * width + bx].flags1 & (BLOCK1_FLOOR|BLOCK1_WALL)) == BLOCK1_NONE); } return TRUE; } BOOL __cdecl lego::game::Level_Block_IsSurveyed(uint bx,uint by) { if ((bx < (globs::legoGlobs.currLevel)->width - 1) && (by < (globs::legoGlobs.currLevel)->height - 1)) { return (globs::legoGlobs.currLevel)->blocks[by * (globs::legoGlobs.currLevel)->width + bx]. flags1 & BLOCK1_SURVEYED; } return BLOCK1_NONE; } // Returns if a wall has diagonal connection between two wall tiles and two ground tiles. BOOL __cdecl lego::game::Level_Block_IsGap(uint bx,uint by) { return (globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx].flags1 & BLOCK1_DIAGONAL; } BOOL __cdecl lego::game::Level_Block_IsCornerInner(uint bx,uint by) { return (globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx].flags1 & BLOCK1_OUTCORNER; } BOOL __cdecl lego::game::Level_Block_IsPathBuilding(Point2I *blockPos) { return (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags1 & BLOCK1_BUILDINGPATH; } BOOL __cdecl lego::game::Level_Block_IsGeneratePower(Point2I *blockPos) { return (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos->y + blockPos->x].flags2 & BLOCK2_GENERATEPOWER; } BOOL __cdecl lego::game::Level_Block_IsPath(Point2I *blockPos) { int x; int y; x = blockPos->x; if ((((-1 < x) && (y = blockPos->y, -1 < y)) && (x < (int)(globs::legoGlobs.currLevel)->width)) && (y < (int)(globs::legoGlobs.currLevel)->height)) { return (globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * y + x].flags1 & BLOCK1_PATH; } return BLOCK1_NONE; } // Generally used to tell Rock Monsters where they can't go. BOOL __cdecl lego::game::Level_Block_IsFoundationOrBusyFloor(Point2I *blockPos) { if (((globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].flags1 & (BLOCK1_BUSY_FLOOR|BLOCK1_FOUNDATION)) == BLOCK1_NONE) { return FALSE; } return TRUE; } void __cdecl lego::game::Level_Block_SetDozerClearing(Point2I *blockPos,BOOL state) { int idx; BlockFlags1 *pFlags1; if (state != 0) { pFlags1 = &(globs::legoGlobs.currLevel)->blocks [blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x].flags1; *pFlags1 = *pFlags1 | BLOCK1_DOZERCLEARING; return; } idx = blockPos->y * (globs::legoGlobs.currLevel)->width + blockPos->x; (globs::legoGlobs.currLevel)->blocks[idx].flags1 = (globs::legoGlobs.currLevel)->blocks[idx].flags1 & ~BLOCK1_DOZERCLEARING; return; } BOOL __cdecl lego::game::Level_GetObjectDamageFromSurface (LegoObject *liveObj,int bx,int by,float elapsedGame,float *optout_damage) { StatsFlags1 sflags1; StatsFlags2 sflags2; uint weaponID; float10 damage; Lego_Level *level; LegoObject_Type objType; // Returns true if the object can be damaged by the surface type at bx,by. // And optionally returns the elapsed damage value if optout_damage is non-null. level = globs::legoGlobs.currLevel; objType = liveObj->type; // Ignore objects that are not affected by fallin damage, or even track damage(?) // // CHECKS: Vehicle, MiniFigure, RockMonster, Building, Barrier, UpgradePart, SpiderWeb if ((((((objType != LegoObject_PowerCrystal) && (objType != LegoObject_Ore)) && (objType != LegoObject_Boulder)) && ((objType != LegoObject_Dynamite && (objType != LegoObject_ElectricFence)))) && (((objType != LegoObject_OohScary && ((objType != LegoObject_ElectricFenceStud && (objType != LegoObject_Path)))) && (objType != LegoObject_Pusher)))) && (((objType != LegoObject_Freezer && (objType != LegoObject_IceCube)) && (objType != LegoObject_LaserShot)))) { // Driver should not take damage when vehicle drives over lava. // (Does this cause damage for carried vehicles like with Cargo Carrier?) if ((liveObj->driveObject != NULL) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE)) { return 0; } if (((level->blocks[by * level->width + bx].terrain == Lego_SurfaceType8_Lava) && ((level->blocks[by * level->width + bx].flags1 & BLOCK1_NOTHOT) == BLOCK1_NONE)) && (sflags2 = stats::StatsObject_GetStatsFlags2(liveObj), (sflags2 & STATS2_CROSSLAVA) == STATS2_NONE)) { if (optout_damage == NULL) { return 1; } // 1 pt of lava damage per tick *optout_damage = elapsedGame; return TRUE; } // Is this a currently-falling-in flag? if ((level->blocks[by * level->width + bx].flags1 & BLOCK1_LANDSLIDING) != BLOCK1_NONE) { if (optout_damage != NULL) { weaponID = tools::Weapon_GetWeaponIDByName("RockFallIn"); damage = tools::Weapon_GetDamageForObject(weaponID,liveObj); *optout_damage = (float)(damage * (float10)elapsedGame); } return TRUE; } } return 0; } uint __cdecl lego::game::Level_Block_GetDirection(uint bx,uint by) { return (uint)(globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx]. direction; } void __cdecl lego::game::Level_Block_SetSurveyed(uint bx,uint by) { int iVar1; if ((bx < (globs::legoGlobs.currLevel)->width - 1) && (by < (globs::legoGlobs.currLevel)->height - 1)) { iVar1 = by * (globs::legoGlobs.currLevel)->width + bx; (globs::legoGlobs.currLevel)->blocks[iVar1].flags1 = (globs::legoGlobs.currLevel)->blocks[iVar1].flags1 | BLOCK1_SURVEYED; } return; } BOOL __cdecl lego::game::Level_Block_GetSurfaceType(uint bx,uint by,Lego_SurfaceType *out_surfaceType) { if ((bx < (globs::legoGlobs.currLevel)->width - 1) && (by < (globs::legoGlobs.currLevel)->height - 1)) { *out_surfaceType = (uint)(globs::legoGlobs.currLevel)->blocks[by * (globs::legoGlobs.currLevel)->width + bx]. terrain; return TRUE; } return 0; } void __cdecl lego::game::Level_Block_LowerRoofVertices(Lego_Level *level,uint bx,uint by) { float fVar1; int idx; Vector3F vertPoses [4]; int width; BlockFlags1 block; Lego_Block *blocksGrid; if ((bx < level->width - 1) && (by < level->height - 1)) { lego::map::Map3D_GetBlockVertexPositions(level->map,bx,by,vertPoses); width = level->width; blocksGrid = level->blocks; idx = by * width + bx; block = blocksGrid[idx].flags1; if ((block & BLOCK1_FLOOR) == BLOCK1_NONE) { if ((block & BLOCK1_WALL) == BLOCK1_NONE) { return; } if (blocksGrid[idx].predug == Lego_PredugType_Cavern_Exposed) { vertPoses[0].z = vertPoses[0].z - (level->DigDepth + level->RoofHeight); } if (blocksGrid[idx + 1].predug == Lego_PredugType_Cavern_Exposed) { vertPoses[1].z = vertPoses[1].z - (level->DigDepth + level->RoofHeight); } idx = (by + 1) * width + bx; if (blocksGrid[idx + 1].predug == Lego_PredugType_Cavern_Exposed) { vertPoses[2].z = vertPoses[2].z - (level->DigDepth + level->RoofHeight); } if (blocksGrid[idx].predug == Lego_PredugType_Cavern_Exposed) { vertPoses[3].z = vertPoses[3].z - (level->DigDepth + level->RoofHeight); } } else { fVar1 = level->DigDepth + level->RoofHeight; vertPoses[0].z = vertPoses[0].z - fVar1; vertPoses[1].z = vertPoses[1].z - fVar1; vertPoses[2].z = vertPoses[2].z - fVar1; vertPoses[3].z = vertPoses[3].z - fVar1; } Roof_SetBlockRoofVertices(bx,by,vertPoses,vertPoses + 1,vertPoses + 2,vertPoses + 3); } return; } void __cdecl lego::game::MapShared_GetDimensions(uint memHandle,uint *out_width,uint *out_height) { MapFileInfo *mapFile; mapFile = (MapFileInfo *)io::Mem_AddressHandle(memHandle); *out_width = (mapFile->dimensions).width; *out_height = (mapFile->dimensions).height; return; } BOOL __cdecl lego::lrr::Lego_LoadGraphicsSettings(void) { char *pcVar1; int cmp; BoolTri dither; BoolTri filter; BoolTri blend; BoolTri sort; BoolTri mipmap; BoolTri linearmipmap; Graphics_Quality renderQuality; float10 fVar2; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","fpclipblocks",0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","fpclipblocks",0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); } fVar2 = std::atof(pcVar1); globs::legoGlobs.FPClipBlocks = (float)fVar2; if ((float10)0.0 != fVar2) { pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","quality",0); pcVar1 = cfg::Config_GetTempStringValue(globs::legoGlobs.config,pcVar1); if (pcVar1 != NULL) { cmp = std::_stricmp("gouraud",pcVar1); if (cmp == 0) { renderQuality = Gouraud; } else { cmp = std::_stricmp("flat",pcVar1); if (cmp == 0) { renderQuality = Flat; } else { cmp = std::_stricmp("wireframe",pcVar1); if (cmp != 0) { return 0; } renderQuality = Wireframe; } } globs::legoGlobs.quality = renderQuality; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","dither",0); dither = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","filter",0); filter = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","blend",0); blend = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","sort",0); sort = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","mipmap",0); mipmap = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","linearmipmap",0); linearmipmap = cfg::Config_GetBoolValue(globs::legoGlobs.config,pcVar1); main::Main_Setup3D(renderQuality,(uint)(dither == BOOL3_TRUE),(uint)(filter == BOOL3_TRUE), (uint)(mipmap == BOOL3_TRUE),(uint)(linearmipmap == BOOL3_TRUE), (uint)(blend == BOOL3_TRUE),(uint)(sort == BOOL3_TRUE)); return TRUE; } } return 0; } BOOL __cdecl lego::lrr::Lego_LoadLighting(void) { char *pcVar1; BOOL BVar2; Container *opt_parent; float *pfVar3; float *pfVar4; float *pfVar5; float b; float g; float r; pfVar4 = &b; pfVar5 = &g; pfVar3 = &r; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","topspotrgb",0); BVar2 = cfg::Config_GetRGBValue(globs::legoGlobs.config,pcVar1,pfVar3,pfVar5,pfVar4); if (BVar2 == 0) { return 0; } globs::legoGlobs.spotlightTop = gfx::Container_MakeLight((globs::legoGlobs.cameraMain)->cont3,D3DRMLIGHT_SPOT,r,g,b); if (globs::legoGlobs.spotlightTop == NULL) { return 0; } gfx::Container_Light_SetSpotPenumbra(globs::legoGlobs.spotlightTop,0.85); gfx::Container_Light_SetSpotUmbra(globs::legoGlobs.spotlightTop,0.4); gfx::Container_SetPosition (globs::legoGlobs.spotlightTop,(globs::legoGlobs.cameraMain)->cont3,200.0,140.0,-130.0); gfx::Container_SetOrientation (globs::legoGlobs.spotlightTop,(globs::legoGlobs.cameraMain)->cont3,-1.0,-0.8,0.75,0.0, 1.0,0.0); pfVar4 = &b; pfVar5 = &g; pfVar3 = &r; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","trackspotrgb",0); BVar2 = cfg::Config_GetRGBValue(globs::legoGlobs.config,pcVar1,pfVar3,pfVar5,pfVar4); if (BVar2 == 0) { return 0; } globs::legoGlobs.spotlightTrack = gfx::Container_MakeLight((globs::legoGlobs.cameraTrack)->cont2,D3DRMLIGHT_SPOT,r,g,b); if (globs::legoGlobs.spotlightTrack == NULL) { return 0; } gfx::Container_SetPosition(globs::legoGlobs.spotlightTrack,NULL,0.0,0.0,-150.0); gfx::Container_SetOrientation(globs::legoGlobs.spotlightTrack,NULL,0.0,0.0,1.0,0.0,1.0,0.0); pfVar4 = &b; pfVar5 = &g; pfVar3 = &r; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","ambientrgb",0); BVar2 = cfg::Config_GetRGBValue(globs::legoGlobs.config,pcVar1,pfVar3,pfVar5,pfVar4); if (BVar2 == 0) { return 0; } globs::legoGlobs.ambientLight = gfx::Container_MakeLight(globs::legoGlobs.rootCont,D3DRMLIGHT_AMBIENT,r,g,b); pfVar5 = &b; if (globs::legoGlobs.ambientLight == NULL) { return 0; } pfVar3 = &g; pfVar4 = &r; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","fplightrgb",0); BVar2 = cfg::Config_GetRGBValue(globs::legoGlobs.config,pcVar1,pfVar4,pfVar3,pfVar5); if (BVar2 == 0) { return 0; } globs::legoGlobs.pointLightFP = gfx::Container_MakeLight((globs::legoGlobs.cameraFP)->contCam,D3DRMLIGHT_POINT,r,g,b); pfVar5 = &b; if (globs::legoGlobs.pointLightFP == NULL) { return 0; } pfVar3 = &g; pfVar4 = &r; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","fprotlightrgb",0); BVar2 = cfg::Config_GetRGBValue(globs::legoGlobs.config,pcVar1,pfVar4,pfVar3,pfVar5); if (BVar2 == 0) { globs::legoGlobs.dirLightFP = NULL; } else { globs::legoGlobs.dirLightFP = gfx::Container_MakeLight((globs::legoGlobs.cameraFP)->contCam,D3DRMLIGHT_DIRECTIONAL,r,g,b) ; } globs::legoGlobs.dirLightCallToArms = gfx::Container_MakeLight ((globs::legoGlobs.cameraFP)->contCam,D3DRMLIGHT_DIRECTIONAL,1.0,0.0,0.0); if (globs::legoGlobs.dirLightCallToArms == NULL) { return 0; } opt_parent = gfx::Container_GetRoot(); globs::legoGlobs.rootLight = gfx::Container_Create(opt_parent); globs::legoGlobs.rootSpotlight = gfx::Container_MakeLight(globs::legoGlobs.rootLight,D3DRMLIGHT_SPOT,1.0,1.0,1.0); if (globs::legoGlobs.rootSpotlight == NULL) { return 0; } light::LightEffects_Initialise (globs::legoGlobs.rootSpotlight,globs::legoGlobs.rootLight,0.8,0.8,0.8); gfx::Container_SetOrientation(globs::legoGlobs.rootSpotlight,NULL,0.0,0.0,1.0,0.0,1.0,0.0); gfx::Container_Light_SetSpotPenumbra(globs::legoGlobs.rootSpotlight,0.85); gfx::Container_Light_SetSpotUmbra(globs::legoGlobs.rootSpotlight,0.0); gfx::Container_Hide(globs::legoGlobs.pointLightFP,TRUE); if (globs::legoGlobs.dirLightFP != NULL) { gfx::Container_Hide(globs::legoGlobs.dirLightFP,TRUE); } gfx::Container_Hide(globs::legoGlobs.spotlightTop,TRUE); gfx::Container_Hide(globs::legoGlobs.spotlightTrack,TRUE); gfx::Container_Hide(globs::legoGlobs.ambientLight,TRUE); gfx::Container_Hide(globs::legoGlobs.rootSpotlight,TRUE); gfx::Container_Hide(globs::legoGlobs.dirLightCallToArms,TRUE); gfx::Container_Light_SetSpotRange(globs::legoGlobs.spotlightTop,2000.0); gfx::Container_Light_SetSpotRange(globs::legoGlobs.spotlightTrack,2000.0); gfx::Container_Light_SetSpotRange(globs::legoGlobs.rootSpotlight,2000.0); return TRUE; } BOOL __cdecl lego::game::Lego_WorldToBlockPos_NoZ(float xPos,float yPos,int *out_bx,int *out_by) { BOOL BVar1; BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ ((globs::legoGlobs.currLevel)->map,xPos,yPos,out_bx,out_by); return BVar1; } BOOL __cdecl lego::game::LiveObject_FUN_00433b40(LegoObject *liveObj,float param_2,BOOL param_3) { BlockFlags1 BVar1; float fVar2; bool bVar3; short rng; StatsFlags1 SVar4; BOOL BVar5; uint uVar6; uint uVar7; Point2I *pPVar8; uint uVar9; ulonglong uVar10; float local_2c; int local_28; int local_24; Point2I DIRECTIONS [4]; uVar9 = 0; DIRECTIONS[0].x = -1; DIRECTIONS[0].y = 0; DIRECTIONS[1].x = 1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = -1; DIRECTIONS[3].x = 0; DIRECTIONS[3].y = 1; SVar4 = stats::StatsObject_GetStatsFlags1(liveObj); if (((((SVar4 & STATS1_RANDOMENTERWALL) != STATS1_NONE) && ((*(byte *)&liveObj->flags1 & 1) == 0)) && (BVar5 = LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(liveObj), BVar5 == 0)) && (param_2 != 0.0)) { local_2c = param_2; // if (param_2 > 300.0f) if ((ushort)((ushort)(param_2 < 300.0) << 8 | (ushort)(param_2 == 300.0) << 0xe) == 0) { local_2c = 300.0; } rng = math::Maths_Rand(); uVar10 = __ftol((float10)300.0 / (float10)local_2c); if ((int)((ulonglong)(uint)(int)rng % (uVar10 & 0xffffffff)) == 0) { LegoObject_GetBlockPos(liveObj,&local_24,&local_28); pPVar8 = DIRECTIONS; do { uVar6 = pPVar8->y + local_28; uVar7 = local_24 + pPVar8->x; if (((uVar7 < (globs::legoGlobs.currLevel)->width - 1) && (uVar6 < (globs::legoGlobs.currLevel)->height - 1)) && ((BVar1 = (globs::legoGlobs.currLevel)->blocks [uVar6 * (globs::legoGlobs.currLevel)->width + uVar7].flags1, (BVar1 & BLOCK1_WALL) != BLOCK1_NONE && ((BVar1 & BLOCK1_FLOOR) == BLOCK1_NONE)))) { bVar3 = true; } else { bVar3 = false; } if (bVar3) { liveObj->health = -1.0; LegoObject_TryDepart_FUN_004499c0(liveObj); return TRUE; } uVar9 += 1; pPVar8 = pPVar8 + 1; } while (uVar9 < 4); } } if (((param_3 != 0) || (SVar4 = stats::StatsObject_GetStatsFlags1(liveObj), (SVar4 & STATS1_RANDOMMOVE) != STATS1_NONE)) && (((*(byte *)&liveObj->flags1 & 1) == 0 && ((BVar5 = LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(liveObj), BVar5 == 0 && (fVar2 = liveObj->stats->RandomMoveTime, param_2 != 0.0)))))) { local_2c = param_2; if ((ushort)((ushort)(param_2 < fVar2) << 8 | (ushort)(param_2 == fVar2) << 0xe) == 0) { local_2c = fVar2; } if (param_3 == 0) { rng = math::Maths_Rand(); uVar10 = __ftol((float10)fVar2 / (float10)local_2c); if ((int)((ulonglong)(uint)(int)rng % (uVar10 & 0xffffffff)) != 0) { return 0; } } LegoObject_FUN_00444520(liveObj); return TRUE; } return FALSE; } BOOL __cdecl lego::game::Level_Block_IsMeshHidden(uint bx,uint by) { Map3D *map; BOOL BVar1; if (((globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by + bx].flags1 & BLOCK1_HIGHPOLY) == BLOCK1_NONE) { map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_IsBlockMeshHidden(map,bx,by); if (BVar1 != 0) { return TRUE; } } return 0; } // WARNING: Function: _alloca4k replaced with injection: alloca_probe void __cdecl lego::unk::Lego_FPHighPolyBlocks_FUN_00433db0 (Container *contCamera,Viewport *view,float fpClipBlocksMult,float highPolyBlocksMult) { BlockFlags1 *pBVar1; bool bVar2; Lego_Level *level; float fVar3; BOOL BVar4; uint uVar5; uint *puVar6; float *pfVar7; Map3D *map; uint uVar8; int iVar9; float10 fVar10; longlong lVar11; float fStack7376; uint uStack7372; Map3D *pMStack7368; uint uStack7364; float fStack7360; float fStack7356; float fStack7352; undefined4 uStack7348; float fStack7344; int iStack7340; float fStack7336; float fStack7332; float fStack7328; float fStack7324; float fStack7320; float fStack7316; float fStack7312; float fStack7308; int iStack7304; Vector3F VStack7300; int iStack7288; uint uStack7284; undefined4 uStack7280; float fStack7276; undefined4 uStack7272; Point2F PStack7268; Vector3F VStack7260; Vector3F aVStack7248 [4]; uint auStack7200 [600]; float local_12c0 [1199]; undefined4 uStack4; level = globs::legoGlobs.currLevel; uStack4 = 0x433dba; map = (globs::legoGlobs.currLevel)->map; fStack7332 = 0.0; pMStack7368 = map; fVar10 = lego::map::Map3D_BlockSize(map); fStack7356 = (float)fVar10; lVar11 = __ftol((float10)fpClipBlocksMult / (float10)fStack7356); iVar9 = (int)lVar11; iStack7340 = 0; gfx::Container_GetPosition(contCamera,NULL,&VStack7300); lego::map::Map3D_WorldToBlockPos_NoZ(map,VStack7300.x,VStack7300.y,&iStack7304,&iStack7288); gfx::Container_GetOrientation(contCamera,NULL,&VStack7260,NULL); fVar10 = lego::view::Viewport_GetField(globs::legoGlobs.viewMain); fVar10 = (float10)fcos(fVar10 * (float10)1.4); fStack7344 = (float)fVar10; lego::view::Viewport_GetSize(globs::legoGlobs.viewMain,(uint *)&fStack7376,&uStack7372); PStack7268.x = (float)(ulonglong)(uint)fStack7376; uStack7348 = 0; PStack7268.y = (float)(ulonglong)uStack7372; fStack7352 = (float)(iStack7304 - iVar9); uVar5 = iStack7288 - iVar9; fStack7360 = (float)(iStack7304 + iVar9); uStack7364 = iVar9 + iStack7288; if ((int)fStack7352 < 0) { fStack7352 = 0.0; } if ((int)uVar5 < 0) { uVar5 = 0; } if ((int)fStack7360 < 0) { fStack7360 = 0.0; } if ((int)uStack7364 < 0) { uStack7364 = 0; } if ((int)level->width <= (int)fStack7360) { fStack7360 = (float)(level->width - 1); } if ((int)level->height <= (int)uStack7364) { uStack7364 = level->height - 1; } fVar3 = fStack7352; uVar8 = uStack7364; uStack7372 = uVar5; if (uVar5 < uStack7364) { do { fStack7376 = fVar3; fVar3 = fStack7376; if ((uint)fStack7376 < (uint)fStack7360) { puVar6 = auStack7200 + iStack7340 * 2 + 1; pfVar7 = local_12c0 + (int)fStack7332 * 4 + 1; uStack7372 = uVar5; do { map = pMStack7368; if ((*(byte *)&level->blocks[uVar5 * level->width + (int)fStack7376].flags1 & 0x18) != 0) { lego::map::Map3D_BlockToWorldPos (pMStack7368,(uint)fStack7376,uVar5,&fStack7316,&fStack7312); fVar10 = lego::map::Map3D_GetWorldZ(map,fStack7316,fStack7312); fStack7308 = (float)fVar10; fStack7328 = (float)((float10)fStack7316 - (float10)VStack7300.x); fStack7324 = (float)((float10)fStack7312 - (float10)VStack7300.y); fStack7320 = (float)(fVar10 - (float10)VStack7300.z); fVar10 = SQRT((fVar10 - (float10)VStack7300.z) * (float10)fStack7320 + ((float10)fStack7312 - (float10)VStack7300.y) * (float10)fStack7324 + ((float10)fStack7316 - (float10)VStack7300.x) * (float10)fStack7328); fStack7336 = (float)fVar10; uVar5 = uStack7372; if (fVar10 < (float10)fpClipBlocksMult) { fVar3 = 1.0 / fStack7336; fVar3 = fVar3 * fStack7320 * VStack7260.z + fVar3 * fStack7324 * VStack7260.y + fVar3 * fStack7328 * VStack7260.x; bVar2 = fStack7336 < (fVar3 - -2.0) * fStack7356; if (bVar2) { fVar3 = fStack7344 - -1.0; } if ((ushort)((ushort)(fVar3 < fStack7344) << 8 | (ushort)(fVar3 == fStack7344) << 0xe) == 0) { lego::map::Map3D_GetBlockVertexPositions (pMStack7368,(uint)fStack7376,uStack7372,aVStack7248); fStack7276 = fStack7376; uStack7272 = 0; uStack7284 = uStack7372; uStack7280 = 0; pfVar7[-1] = (float)(ulonglong)(uint)fStack7376; *pfVar7 = (float)(ulonglong)uStack7372; pfVar7[1] = fStack7336; fVar10 = lego::map::Detail_FUN_0040b3a0(aVStack7248,view,&PStack7268,(uint)bVar2); pfVar7[2] = (float)fVar10; uVar5 = uStack7372; if ((ushort)((ushort)(fVar10 < (float10)0.0) << 8 | (ushort)(fVar10 == (float10)0.0) << 0xe) == 0) { fStack7332 = (float)((int)fStack7332 + 1); pfVar7 = pfVar7 + 4; } else { puVar6[-1] = (uint)fStack7376; iStack7340 += 1; *puVar6 = uStack7372; puVar6 = puVar6 + 2; } } } } fStack7376 = (float)((int)fStack7376 + 1); fVar3 = fStack7352; map = pMStack7368; uVar8 = uStack7364; } while ((uint)fStack7376 < (uint)fStack7360); } uVar5 += 1; uStack7372 = uVar5; } while (uVar5 < uVar8); } fVar3 = fStack7332; std::qsort(local_12c0,(uint)fStack7332,0x10,Lego_QsortCompareUnk_FUN_00434380); pMStack7368 = NULL; if (fVar3 != 0.0) { pfVar7 = local_12c0 + 2; fStack7356 = fVar3; do { lVar11 = __ftol((float10)pfVar7[-2]); fVar3 = (float)lVar11; fStack7376 = fVar3; lVar11 = __ftol((float10)pfVar7[-1]); uStack7372 = (uint)lVar11; if (((uint)highPolyBlocksMult <= pMStack7368) || (fpClipBlocksMult * 0.6666667 <= *pfVar7)) { pBVar1 = &level->blocks[uStack7372 * level->width + (int)fVar3].flags1; *pBVar1 = *pBVar1 & ~BLOCK1_HIGHPOLY; lego::map::Map3D_AddVisibleBlock(map,(int)fStack7376,uStack7372); game::Roof_AddVisibleBlock((uint)fStack7376,uStack7372); if ((level->blocks[uStack7372 * level->width + (int)fStack7376].flags1 & BLOCK1_SMOKE) != BLOCK1_NONE) { effect::Smoke_Hide(level->blocks[uStack7372 * level->width + (int)fStack7376].smoke,FALSE) ; } } else { fStack7344 = 1.0 - *pfVar7 / (fpClipBlocksMult * 0.6666667); fStack7352 = fStack7344 * 0.7 - -0.3; if ((((byte)globs::legoGlobs.flags1 & GAME1_USEDETAIL) == 0) || (BVar4 = game::Level_Block_Detail_FUN_004343b0 (level,(uint)fVar3,uStack7372,fStack7344,fStack7352), fVar3 = fStack7376, BVar4 == 0)) { lego::map::Map3D_AddVisibleBlock(map,(int)fVar3,uStack7372); game::Roof_AddVisibleBlock((uint)fStack7376,uStack7372); if ((level->blocks[uStack7372 * level->width + (int)fStack7376].flags1 & BLOCK1_SMOKE) != BLOCK1_NONE) { effect::Smoke_Hide(level->blocks[uStack7372 * level->width + (int)fStack7376].smoke, FALSE); } iVar9 = uStack7372 * level->width + (int)fStack7376; level->blocks[iVar9].flags1 = level->blocks[iVar9].flags1 & ~BLOCK1_HIGHPOLY; } else { pBVar1 = &level->blocks[uStack7372 * level->width + (int)fStack7376].flags1; *pBVar1 = *pBVar1 | BLOCK1_HIGHPOLY; game::Roof_AddVisibleBlock((uint)fStack7376,uStack7372); pMStack7368 = (Map3D *)((int)pMStack7368 + 1); } } pfVar7 = pfVar7 + 4; fStack7356 = (float)((int)fStack7356 + -1); } while (fStack7356 != 0.0); } if (iStack7340 != 0) { puVar6 = auStack7200; iVar9 = iStack7340; do { game::Roof_AddVisibleBlock(*puVar6,puVar6[1]); puVar6 = puVar6 + 2; iVar9 += -1; } while (iVar9 != 0); } return; } int __cdecl lego::unk::Lego_QsortCompareUnk_FUN_00434380(int param_1,int param_2) { if (*(float *)(param_1 + 0xc) < *(float *)(param_2 + 0xc)) { return 1; } if ((ushort)((ushort)(*(float *)(param_1 + 0xc) < *(float *)(param_2 + 0xc)) << 8 | (ushort)(*(float *)(param_1 + 0xc) == *(float *)(param_2 + 0xc)) << 0xe) == 0) { return -1; } return 0; } BOOL __cdecl lego::game::Level_Block_Detail_FUN_004343b0 (Lego_Level *level,uint bx,uint by,float scaleZ,float brightness) { Detail_Mesh *detailMesh; int idx; Vector3F vertPoses [4]; SurfaceTexture texture; // if ((level->blocks[idx].flags1 & (BLOCK1_WALL|BLOCK1_FLOOR)) && // ... if (((*(byte *)&level->blocks[by * level->width + bx].flags1 & 0x18) != 0) && (texture = level->blocks[by * level->width + bx].texture, detailMesh = level->promeshGrid [(level->textureSetSize).width * (texture & 0xf) + (uint)(texture >> 4)], detailMesh != NULL)) { lego::map::Map3D_GetBlockVertexPositions(level->map,bx,by,vertPoses); idx = by * level->width + bx; lego::map::Detail_FUN_0040b7b0 (detailMesh,vertPoses,level->blocks[idx].texture,level->blocks[idx].direction,scaleZ, brightness); return TRUE; } return FALSE; } void __cdecl lego::game::Level_RemoveAll_ProMeshes(void) { uint i; Lego_Level *level; level = globs::legoGlobs.currLevel; i = 0; if (((globs::legoGlobs.currLevel)->textureSetSize).height * ((globs::legoGlobs.currLevel)->textureSetSize).width != 0) { do { if (level->promeshGrid[i] != NULL) { lego::map::Detail_RemoveMesh_FUN_0040b740(level->promeshGrid[i]); } i += 1; } while (i < (uint)((level->textureSetSize).height * (level->textureSetSize).width)); } return; } // destroyTime can also be drillTime. BOOL __cdecl lego::game::Level_Block_Damage(uint bx,uint by,float destroyTime,float elapsed) { int idx; float damage; Lego_Level *level; level = globs::legoGlobs.currLevel; // Divide-by-zero guard if ((destroyTime != 0.0) && (idx = by * (globs::legoGlobs.currLevel)->width + bx, (globs::legoGlobs.currLevel)->blocks[idx].damage = elapsed / destroyTime + (globs::legoGlobs.currLevel)->blocks[idx].damage, damage = level->blocks[by * level->width + bx].damage, (ushort)((ushort)(damage < 1.0) << 8 | (ushort)(damage == 1.0) << 0xe) == 0)) { return TRUE; } return 0; } void __cdecl lego::lrr::Lego_LoadPanels(Config *config,uint screenWidth,uint screenHeight) { char cVar1; char *pcVar2; Config *prop; BOOL BVar3; int yClosed; int xClosed; int yOpen; int xOpen; uint uVar4; uint uVar5; undefined4 *puVar6; char *pcVar7; undefined4 *puVar8; Panel_Type panelType; char *stringParts [10]; char buff [256]; std::sprintf(buff,"Panels%ix%i",screenWidth,screenHeight); pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,buff,0); prop = cfg::Config_FindArray(config,pcVar2); do { if (prop == NULL) { return; } BVar3 = front::Panel_GetPanelType(prop->key,&panelType); if (BVar3 != 0) { uVar4 = 0xffffffff; pcVar2 = prop->value; do { pcVar7 = pcVar2; if (uVar4 == 0) break; uVar4 -= 1; pcVar7 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar7; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar7 + -uVar4); puVar8 = (undefined4 *)buff; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } util::Util_Tokenise(buff,stringParts,","); front::Panel_LoadImage(stringParts[0],panelType,PANEL_FLAG_CLOSED); yClosed = std::atoi(stringParts[4]); xClosed = std::atoi(stringParts[3]); yOpen = std::atoi(stringParts[2]); xOpen = std::atoi(stringParts[1]); front::Panel_SetSlidingPositions(panelType,xOpen,yOpen,xClosed,yClosed); } prop = cfg::Config_GetNextItem(prop); } while( true ); } // WARNING: Function: _alloca4k replaced with injection: alloca_probe void __cdecl lego::lrr::Lego_LoadPanelButtons(Config *config,uint screenWidth,uint screenHeight) { char *pcVar1; Config *prop; BOOL BVar2; int iVar3; char **pButtonStr; uint uVar4; uint *puVar5; char **ppcVar6; Panel_Type panelType; int iStack11752; int totalButtonCount; PanelButtonType buttonType; ToolTip_Type toolTipType; uint buttonCounts [12]; char *parts [9]; char buff [128]; ToolTip_Type toolTips [12] [24]; PanelButtonType buttonTypes [12] [24]; char *imageStrs [3] [12] [24]; char *buttonStrs [288]; Area2F buttonAreas [12] [24]; buttonAreas[11][23].height = 6.178193e-39; puVar5 = buttonCounts; buttonCounts[0] = 0; for (iVar3 = 0xb; puVar5 = puVar5 + 1, iVar3 != 0; iVar3 += -1) { *puVar5 = 0; } totalButtonCount = 0; std::sprintf(buff,"Buttons%ix%i",screenWidth,screenHeight); pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,buff,0); prop = cfg::Config_FindArray(config,pcVar1); if (prop != NULL) { pButtonStr = buttonStrs; do { BVar2 = front::Panel_GetPanelType(prop->key,&panelType); if (BVar2 != 0) { pcVar1 = util::Util_StrCpy(prop->value); *pButtonStr = pcVar1; util::Util_Tokenise(pcVar1,parts,","); BVar2 = front::Panel_GetButtonType(panelType,parts[0],&buttonType); if (BVar2 != 0) { uVar4 = 0; ppcVar6 = parts; buttonTypes[panelType][buttonCounts[panelType]] = buttonType; do { ppcVar6 = ppcVar6 + 1; iVar3 = std::_stricmp("NULL",*ppcVar6); if (iVar3 == 0) { imageStrs[panelType + uVar4][buttonCounts[panelType]] = NULL; } else { imageStrs[panelType + uVar4][buttonCounts[panelType]] = *ppcVar6; } uVar4 += 0xc; } while (uVar4 < 0x24); iStack11752 = std::atoi(parts[4]); buttonAreas[panelType][buttonCounts[panelType]].x = (float)iStack11752; iStack11752 = std::atoi(parts[5]); buttonAreas[panelType][buttonCounts[panelType]].y = (float)iStack11752; iStack11752 = std::atoi(parts[6]); buttonAreas[panelType][buttonCounts[panelType]].width = (float)iStack11752; iStack11752 = std::atoi(parts[7]); buttonAreas[panelType][buttonCounts[panelType]].height = (float)iStack11752; BVar2 = front::ToolTip_GetType(parts[8],&toolTipType); uVar4 = buttonCounts[panelType]; if (BVar2 == 0) { toolTips[panelType][uVar4] = ToolTip_Null; } else { toolTips[panelType][uVar4] = toolTipType; } buttonCounts[panelType] = uVar4 + 1; totalButtonCount += 1; pButtonStr = pButtonStr + 1; } } prop = cfg::Config_GetNextItem(prop); } while (prop != NULL); do { panelType = (Panel_Type)prop; // i = 0; front::Panel_CreateButtons ((Panel_Type)prop,buttonCounts[(int)prop],(PanelButton_Type *)buttonTypes[(int)prop] ,(Area2F *)buttonAreas[(int)prop],(char **)imageStrs[(int)prop], (char **)imageStrs[1][(int)prop],(char **)imageStrs[2][(int)prop], (ToolTip_Type *)toolTips[(int)prop]); // i++ prop = (Config *)(panelType + Panel_RadarFill); } while (prop < (Config *)&DAT_0000000c); if (totalButtonCount != 0) { pButtonStr = buttonStrs; iVar3 = totalButtonCount; panelType = (Panel_Type)prop; do { io::Mem_Free(*pButtonStr); pButtonStr = pButtonStr + 1; iVar3 += -1; } while (iVar3 != 0); } } return; } void __cdecl lego::lrr::Lego_LoadTutorialIcon(Config *config) { char *pcVar1; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","TutorialIcon",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 != NULL) { globs::legoGlobs.TutorialIcon = lego::image::Image_LoadBMPScaled(pcVar1,0,0); if (globs::legoGlobs.TutorialIcon != NULL) { lego::image::Image_SetPenZeroTrans(globs::legoGlobs.TutorialIcon); } } return; } void __cdecl lego::lrr::Lego_LoadSamples(Config *config,BOOL noReduceSamples) { char *pcVar1; Config *prop; BOOL BVar2; SFX_ID sfxType; bool reduced; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Samples",0); prop = cfg::Config_FindArray(config,pcVar1); if (prop != NULL) { snd::SFX_SetSamplePopulateMode(TRUE); do { pcVar1 = prop->key; reduced = false; if ((*pcVar1 == '!') && (pcVar1 = pcVar1 + 1, noReduceSamples == 0)) { reduced = true; } if (!reduced) { // Audio_SetSamplePopulateMode(TRUE); was called, meaning this function will register // new SFX if they don't already exist BVar2 = snd::SFX_GetType(pcVar1,&sfxType); if (BVar2 != 0) { snd::SFX_LoadSampleProperty(prop->value,sfxType); } } prop = cfg::Config_GetNextItem(prop); } while (prop != NULL); snd::SFX_SetSamplePopulateMode(FALSE); } return; } void __cdecl lego::lrr::Lego_LoadTextMessages(Config *config) { char cVar1; char *pcVar2; Config *pCVar3; BOOL BVar4; uint uVar5; uint uVar6; undefined4 *puVar7; char *pcVar8; undefined4 *puVar9; Text_Type local_22c; char *stringParts [10]; char buffer [512]; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"TextMessages",0); for (pCVar3 = cfg::Config_FindArray(config,pcVar2); pCVar3 != NULL; pCVar3 = cfg::Config_GetNextItem(pCVar3)) { BVar4 = front::Text_GetTextType(pCVar3->key,&local_22c); if (BVar4 != 0) { front::Text_SetMessage(local_22c,pCVar3->value); } } pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"TextMessagesWithImages",0); pCVar3 = cfg::Config_FindArray(config,pcVar2); do { if (pCVar3 == NULL) { return; } BVar4 = front::Text_GetTextType(pCVar3->key,&local_22c); if (BVar4 != 0) { uVar5 = 0xffffffff; pcVar2 = pCVar3->value; do { pcVar8 = pcVar2; if (uVar5 == 0) break; uVar5 -= 1; pcVar8 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar8; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar8 + -uVar5); puVar9 = (undefined4 *)buffer; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar9 = *puVar7; puVar7 = puVar7 + 1; puVar9 = puVar9 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } util::Util_Tokenise(buffer,stringParts,":"); front::Text_SetMessageWithImage(local_22c,stringParts[0],stringParts[1],stringParts[2]); } pCVar3 = cfg::Config_GetNextItem(pCVar3); } while( true ); } void __cdecl lego::lrr::Lego_LoadInfoMessages(Config *config) { char cVar1; char *pcVar2; Config *prop; BOOL BVar3; int iVar4; uint uVar5; uint uVar6; undefined4 *puVar7; char *pcVar8; undefined4 *puVar9; Info_Type infoType; SFX_ID sfxType; char *stringParts [10]; char buffer [1024]; pcVar2 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"InfoMessages",0); prop = cfg::Config_FindArray(config,pcVar2); do { if (prop == NULL) { return; } BVar3 = front::Info_GetInfoType(prop->key,&infoType); if (BVar3 != 0) { uVar5 = 0xffffffff; pcVar2 = prop->value; do { pcVar8 = pcVar2; if (uVar5 == 0) break; uVar5 -= 1; pcVar8 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar8; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar8 + -uVar5); puVar9 = (undefined4 *)buffer; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar9 = *puVar7; puVar7 = puVar7 + 1; puVar9 = puVar9 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } uVar5 = util::Util_Tokenise(buffer,stringParts,":"); front::Info_SetTypeText(infoType,stringParts[0]); front::Info_SetTypeImageFile(infoType,stringParts[1]); BVar3 = snd::SFX_GetType(stringParts[2],&sfxType); if (BVar3 != 0) { front::Info_SetTypeSFX(infoType,sfxType); } if (uVar5 < 4) { front::Info_SetTypeChangeGameSpeed(infoType,1); BVar3 = 0; } else { iVar4 = std::_stricmp(stringParts[3],"SLOW"); front::Info_SetTypeChangeGameSpeed(infoType,(uint)(iVar4 == 0)); iVar4 = std::_stricmp(stringParts[3],"ALWAYSPLAYSFX"); if (iVar4 == 0) { BVar3 = 1; } else { if ((uVar5 < 5) || (iVar4 = std::_stricmp(stringParts[4],"ALWAYSPLAYSFX"), iVar4 != 0)) { BVar3 = 0; } else { BVar3 = 1; } } } front::Info_SetTypeFlag_20000(infoType,BVar3); } prop = cfg::Config_GetNextItem(prop); } while( true ); } void __cdecl lego::lrr::Lego_LoadToolTips(Config *config) { char *pcVar1; Config *pCVar2; BOOL BVar3; ToolTip_Type toolTipType; SFX_ID sfxType; pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTips",0); for (pCVar2 = cfg::Config_FindArray(config,pcVar1); pCVar2 != NULL; pCVar2 = cfg::Config_GetNextItem(pCVar2)) { BVar3 = front::ToolTip_GetType(pCVar2->key,&toolTipType); if (BVar3 != 0) { front::ToolTip_SetContent(toolTipType,pCVar2->value); } } pcVar1 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipsSFXs",0); for (pCVar2 = cfg::Config_FindArray(config,pcVar1); pCVar2 != NULL; pCVar2 = cfg::Config_GetNextItem(pCVar2)) { BVar3 = front::ToolTip_GetType(pCVar2->key,&toolTipType); if ((BVar3 != 0) && (BVar3 = snd::SFX_GetType(pCVar2->value,&sfxType), BVar3 != 0)) { front::ToolTip_SetSFX(toolTipType,sfxType); } } return; } BOOL __cdecl lego::game::Lego_TryTeleportObject(LegoObject_Type objType,LegoObject_ID objID) { StatsFlags2 SVar1; BOOL BVar2; Vector3F local_c; globs::legoGlobs.flags3 &= ~GAME3_PLACEBUILDING; front::HelpWindow_IfFlag4_AndParam_Clear1_Set2_Else_Clear3(TRUE); if ((objType == LegoObject_Building) || (objType == LegoObject_ElectricFence)) { globs::legoGlobs.flags3 |= GAME3_PLACEBUILDING; globs::legoGlobs.placeObjType = objType; globs::legoGlobs.placeObjID = objID; gfx::Container_GetOrientation((globs::legoGlobs.cameraMain)->contCam,NULL,&local_c,NULL); if (ABS(local_c.x) <= ABS(local_c.y)) { if ((ushort)((ushort)(local_c.y < 0.0) << 8 | (ushort)(local_c.y == 0.0) << 0xe) == 0) { globs::legoGlobs.placeObjDirection = DIRECTION_DOWN; return TRUE; } globs::legoGlobs.placeObjDirection = DIRECTION_UP; return TRUE; } if ((ushort)((ushort)(local_c.x < 0.0) << 8 | (ushort)(local_c.x == 0.0) << 0xe) == 0) { globs::legoGlobs.placeObjDirection = DIRECTION_LEFT; return TRUE; } globs::legoGlobs.placeObjDirection = DIRECTION_RIGHT; return TRUE; } SVar1 = stats::Stats_GetStatsFlags2(objType,objID); if ((SVar1 & STATS2_USESMALLTELEPORTER) != STATS2_NONE) { BVar2 = LegoObject_QueueTeleport(globs::legoGlobs.placeDestSmallTeleporter,objType,objID); return BVar2; } SVar1 = stats::Stats_GetStatsFlags2(objType,objID); if ((SVar1 & STATS2_USEBIGTELEPORTER) != STATS2_NONE) { BVar2 = LegoObject_QueueTeleport(globs::legoGlobs.placeDestBigTeleporter,objType,objID); return BVar2; } SVar1 = stats::Stats_GetStatsFlags2(objType,objID); if ((SVar1 & STATS2_USEWATERTELEPORTER) != STATS2_NONE) { BVar2 = LegoObject_QueueTeleport(globs::legoGlobs.placeDestWaterTeleporter,objType,objID); return BVar2; } SVar1 = stats::Stats_GetStatsFlags2(objType,objID); if ((SVar1 & STATS2_USELEGOMANTELEPORTER) != STATS2_NONE) { BVar2 = LegoObject_QueueTeleport(NULL,objType,objID); return BVar2; } return FALSE; } void __cdecl lego::game::Level_Block_UpdateSurveyRadius_FUN_00434f40(Point2I *blockPos,int surveyRadius) { uint bx; Lego_Level *pLVar1; uint by; int iVar2; int iVar3; int iVar4; pLVar1 = globs::legoGlobs.currLevel; iVar2 = -surveyRadius; iVar4 = iVar2; if (-surveyRadius == surveyRadius || SBORROW4(iVar2,surveyRadius) != surveyRadius * -2 < 0) { do { for (iVar3 = iVar2; iVar3 <= surveyRadius; iVar3 += 1) { if ((((iVar3 * iVar3 + iVar4 * iVar4 <= surveyRadius * surveyRadius) && (bx = iVar3 + blockPos->x, -1 < (int)bx)) && ((int)bx < (int)pLVar1->width)) && ((by = blockPos->y + iVar4, -1 < (int)by && ((int)by < (int)pLVar1->height)))) { Level_Block_SetSurveyed(bx,by); } } iVar4 += 1; } while (iVar4 <= surveyRadius); } return; } void __cdecl lego::lrr::Lego_LoadSurfaceTypeDescriptions_sound(Config *config,char *gameName) { char cVar1; char *pcVar2; BOOL BVar3; uint uVar4; uint uVar5; SFX_ID *pSVar6; undefined4 *puVar7; char *pcVar8; char *pcVar9; undefined4 *puVar10; SFX_ID sfxType; undefined4 *local_42c; char *local_428; char *local_424; char buff [1024]; pSVar6 = globs::legoGlobs.langSurface_sound; do { pcVar2 = cfg::Config_BuildStringID(gameName,"SurfaceTypeDescriptions",pSVar6[-0x24],0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 != NULL) { uVar4 = 0xffffffff; local_42c = (undefined4 *)buff; pcVar8 = pcVar2; do { pcVar9 = pcVar8; if (uVar4 == 0) break; uVar4 -= 1; pcVar9 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar9; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar7 = (undefined4 *)(pcVar9 + -uVar4); puVar10 = local_42c; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } util::Util_Tokenise(pcVar2,&local_428,","); pcVar2 = util::Util_RemoveUnderscores(local_428); pSVar6[-0x12] = (SFX_ID)pcVar2; BVar3 = snd::SFX_GetType(local_424,&sfxType); *pSVar6 = -(uint)(BVar3 != 0) & sfxType; } pSVar6 = pSVar6 + 1; if ((SFX_ID *)((int)globs::legoGlobs.langSurface_sound + 0x47) < pSVar6) { return; } } while( true ); } char * __cdecl lego::game::Lego_GetSurfaceTypeDescription(Lego_SurfaceType surfaceType) { char *pcVar1; pcVar1 = globs::legoGlobs.langSurface_name[surfaceType]; if (pcVar1 == NULL) { pcVar1 = "Need config for surface type."; } return pcVar1; } SFX_ID __cdecl lego::game::Lego_GetSurfaceTypeSFX(Lego_SurfaceType surfaceType) { return globs::legoGlobs.langSurface_sound[surfaceType]; } void __cdecl lego::game::Level_SetPointer_FromSurfaceType(Lego_SurfaceType surfaceType) { if (surfaceType == Lego_SurfaceType_Immovable) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_SurfaceType_Immovable); return; } if (surfaceType == Lego_SurfaceType_Hard) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_SurfaceType_Hard); return; } if (surfaceType == Lego_SurfaceType_Medium) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_SurfaceType_Medium); return; } if (surfaceType == Lego_SurfaceType_Loose) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_SurfaceType_Loose); return; } if (surfaceType == Lego_SurfaceType_Soil) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_SurfaceType_Soil); return; } if (surfaceType == Lego_SurfaceType_OreSeam) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_SurfaceType_OreSeam); return; } if (surfaceType == Lego_SurfaceType_CrystalSeam) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_SurfaceType_CrystalSeam); return; } if (surfaceType == Lego_SurfaceType_RechargeSeam) { front::Pointer_SetCurrent_IfTimerFinished(Pointer_SurfaceType_RechargeSeam); } return; } void __cdecl lego::game::Level_GenerateFallin_InRadius(Point2I *blockPos,int radius,BOOL param_3) { short rng1; short rng2; uint uVar1; BOOL BVar2; int iVar3; BOOL *pBVar4; uint i; Point2I blockOffPos; BOOL fallins [100]; uint diameter; // Fallins can be performed in a maximum of 10x10 diameter(?) pBVar4 = fallins; for (iVar3 = 100; iVar3 != 0; iVar3 += -1) { *pBVar4 = 0; pBVar4 = pBVar4 + 1; } diameter = radius * 2; i = 0; while( true ) { if (param_3 == 0) { uVar1 = diameter * diameter >> 2; } else { uVar1 = diameter * diameter; } if (uVar1 <= i) break; rng1 = math::Maths_Rand(); rng2 = math::Maths_Rand(); blockOffPos.x = ((uint)(int)rng1 % diameter + blockPos->x) - radius; blockOffPos.y = (blockPos->y + (uint)(int)rng2 % diameter) - radius; iVar3 = (uint)(int)rng2 % diameter + ((uint)(int)rng1 % diameter) * 10; if (fallins[iVar3] == 0) { BVar2 = Fallin_Block_FUN_0040f0c0(&blockOffPos,TRUE); if ((BVar2 != 0) && (param_3 != 0)) { return; } fallins[iVar3] = TRUE; } i += 1; } return; } void __cdecl lego::game::Level_UpdateTutorialBlockFlashing (Lego_Level *level,Viewport *viewMain,float elapsedGame,float elapsedAbs) { Lego_Block *pLVar1; TutorialFlags TVar2; Map3D *pMVar3; BOOL BVar4; WallHighlightType WVar5; uint by; uint bx; float10 fVar6; float10 fVar7; Point2F local_14; Vector3F local_c; fVar6 = (float10)fsin((float10)globs::gamectrlGlobs.timerTutorialBlockFlash); globs::gamectrlGlobs.timerTutorialBlockFlash = globs::gamectrlGlobs.timerTutorialBlockFlash - elapsedAbs * 25.0 * -0.01333333; TVar2 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (TVar2 != TUTORIAL_NONE) { by = 0; pMVar3 = level->map; if (pMVar3->blockHeight != 0) { do { bx = 0; if (pMVar3->blockWidth != 0) { do { BVar4 = Level_Block_IsMeshHidden(bx,by); if (BVar4 == 0) { pLVar1 = level->blocks + by * level->width + bx; if (pLVar1->blockpointer == 0) { if (pLVar1->tutoHighlightState == 1) { pLVar1->tutoHighlightState = 0; TVar2 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((((TVar2 & TUTORIAL_FLAG_NOBLOCKACTION) == TUTORIAL_NONE) && (level->blocks[by * level->width + bx].clickCount != 0)) && (globs::interfaceGlobs.currMenuType == Interface_Menu_Main)) { lego::map::Map3D_SetBlockHighlight ((globs::legoGlobs.currLevel)->map,bx,by,WALLHIGHLIGHT_SELECTED); } else { pMVar3 = (globs::legoGlobs.currLevel)->map; LAB_0043544b: lego::map::Map3D_ClearBlockHighlight(pMVar3,bx,by); } } else { if ((pLVar1->tutoHighlightState == 0) && (WVar5 = lego::map::Map3D_GetBlockHighlight ((globs::legoGlobs.currLevel)->map,bx,by), WVar5 == WALLHIGHLIGHT_TUTORIAL)) { pMVar3 = (globs::legoGlobs.currLevel)->map; goto LAB_0043544b; } } } else { lego::map::Map3D_BlockToWorldPos(level->map,bx,by,&local_c.x,&local_c.y); fVar7 = lego::map::Map3D_GetWorldZ(level->map,local_c.x,local_c.y); local_c.z = (float)fVar7; lego::view::Viewport_WorldToScreen(viewMain,&local_14,&local_c); local_14.x = local_14.x - (float)((int)(globs::legoGlobs.TutorialIcon)->width / 2); local_14.y = local_14.y - ((float)fVar6 * 20.0 + (float)((globs::legoGlobs.TutorialIcon)->height << 1)); lego::image::Image_DisplayScaled(globs::legoGlobs.TutorialIcon,NULL,&local_14,NULL); if (globs::interfaceGlobs.flashingState == 0) { lego::map::Map3D_ClearBlockHighlight((globs::legoGlobs.currLevel)->map,bx,by); level->blocks[by * level->width + bx].tutoHighlightState = 1; } else { lego::map::Map3D_SetBlockHighlight ((globs::legoGlobs.currLevel)->map,bx,by,WALLHIGHLIGHT_TUTORIAL); level->blocks[by * level->width + bx].tutoHighlightState = 1; } } } bx += 1; } while (bx < level->map->blockWidth); } pMVar3 = level->map; by += 1; } while (by < pMVar3->blockHeight); } } return; } BOOL __cdecl lego::lrr::Lego_UpdateGameCtrlLeftButtonLast(void) { if ((globs::INPUT.mslb == 0) && (globs::gamectrlGlobs.mslb_Last_1 != 0)) { globs::gamectrlGlobs.mslb_Last_1 = globs::INPUT.mslb; return TRUE; } globs::gamectrlGlobs.mslb_Last_1 = globs::INPUT.mslb; return FALSE; } BOOL __cdecl lego::lrr::Lego_DrawDialogContrastOverlay(void) { Point2F point; point.x = 0.0; point.y = 0.0; if (globs::legoGlobs.DialogContrastOverlay == NULL) { return FALSE; } lego::image::Image_DisplayScaled(globs::legoGlobs.DialogContrastOverlay,NULL,&point,NULL); return TRUE; } int __cdecl lego::lrr::Lego_SaveMenu_ConfirmMessage_FUN_004354f0 (char *titleText,char *message,char *okText,char *cancelText) { float fVar1; float fVar2; uint uVar3; uint uVar4; BOOL BVar5; int iVar6; Point2F local_18; float local_c; undefined4 local_8; float local_4; iVar6 = -1; if (((globs::legoGlobs.DialogImage != NULL) && (globs::legoGlobs.DialogTextWndTitle != NULL)) && (globs::legoGlobs.DialogTextWndMessage != NULL)) { Lego_DrawDialogContrastOverlay(); local_18.x = (float)((int)globs::mainGlobs.appWidth / 2) - (float)((globs::legoGlobs.DialogImage)->width >> 1); local_18.y = (float)((int)globs::mainGlobs.appHeight / 2) - (float)((globs::legoGlobs.DialogImage)->height >> 1); lego::image::Image_DisplayScaled(globs::legoGlobs.DialogImage,NULL,&local_18,NULL); front::TextWindow_Clear(globs::legoGlobs.DialogTextWndTitle); front::TextWindow_Clear(globs::legoGlobs.DialogTextWndMessage); front::TextWindow_Clear(globs::legoGlobs.DialogTextWndOK); front::TextWindow_Clear(globs::legoGlobs.DialogTextWndCancel); if (okText != NULL) { local_c = 0.0; local_8 = 0; local_4 = 0.0; uVar3 = lego::image::Font_GetStringWidth(globs::legoGlobs.fontBriefingLo,okText); uVar4 = lego::image::Font_GetHeight(globs::legoGlobs.fontBriefingLo); fVar1 = (((globs::legoGlobs.DialogTextWndOK)->windowSize).x - ((globs::legoGlobs.DialogTextWndOK)->windowSize).width * -0.5) - (float)(uVar3 >> 1); local_c = ((globs::legoGlobs.DialogTextWndOK)->windowSize).y; local_4 = (float)(ulonglong)uVar4; fVar2 = (float)globs::INPUT.msx; if ((((ushort)((ushort)(fVar2 < fVar1) << 8 | (ushort)(fVar2 == fVar1) << 0xe) != 0) || (fVar1 + (float)(ulonglong)uVar3 <= fVar2)) || ((fVar1 = (float)globs::INPUT.msy, (ushort)((ushort)(fVar1 < local_c) << 8 | (ushort)(fVar1 == local_c) << 0xe) != 0 || (local_c + local_4 <= fVar1)))) { (globs::legoGlobs.DialogTextWndOK)->font = globs::legoGlobs.fontBriefingLo; front::TextWindow_PrintF(globs::legoGlobs.DialogTextWndOK,okText); } else { (globs::legoGlobs.DialogTextWndOK)->font = globs::legoGlobs.fontBriefingHi; front::TextWindow_PrintF(globs::legoGlobs.DialogTextWndOK,okText); BVar5 = Lego_UpdateGameCtrlLeftButtonLast(); if (BVar5 != 0) { iVar6 = 1; } } } if (cancelText != NULL) { local_c = 0.0; local_8 = 0; local_4 = 0.0; uVar3 = lego::image::Font_GetStringWidth(globs::legoGlobs.fontBriefingLo,cancelText); uVar4 = lego::image::Font_GetHeight(globs::legoGlobs.fontBriefingLo); fVar1 = (((globs::legoGlobs.DialogTextWndCancel)->windowSize).x - ((globs::legoGlobs.DialogTextWndCancel)->windowSize).width * -0.5) - (float)(uVar3 >> 1); local_c = ((globs::legoGlobs.DialogTextWndCancel)->windowSize).y; local_4 = (float)(ulonglong)uVar4; fVar2 = (float)globs::INPUT.msx; if ((((ushort)((ushort)(fVar2 < fVar1) << 8 | (ushort)(fVar2 == fVar1) << 0xe) != 0) || (fVar1 + (float)(ulonglong)uVar3 <= fVar2)) || ((fVar1 = (float)globs::INPUT.msy, (ushort)((ushort)(fVar1 < local_c) << 8 | (ushort)(fVar1 == local_c) << 0xe) != 0 || (local_c + local_4 <= fVar1)))) { (globs::legoGlobs.DialogTextWndCancel)->font = globs::legoGlobs.fontBriefingLo; front::TextWindow_PrintF(globs::legoGlobs.DialogTextWndCancel,cancelText); } else { (globs::legoGlobs.DialogTextWndCancel)->font = globs::legoGlobs.fontBriefingHi; front::TextWindow_PrintF(globs::legoGlobs.DialogTextWndCancel,cancelText); BVar5 = Lego_UpdateGameCtrlLeftButtonLast(); if (BVar5 != 0) { iVar6 = 0; } } } front::TextWindow_PrintF(globs::legoGlobs.DialogTextWndTitle,titleText); front::TextWindow_PrintF(globs::legoGlobs.DialogTextWndMessage,message); front::TextWindow_Update(globs::legoGlobs.DialogTextWndTitle,0,1.0,NULL); front::TextWindow_Update(globs::legoGlobs.DialogTextWndMessage,0,1.0,NULL); front::TextWindow_Update(globs::legoGlobs.DialogTextWndOK,0,1.0,NULL); front::TextWindow_Update(globs::legoGlobs.DialogTextWndCancel,0,1.0,NULL); return iVar6; } return -1; } // This is a messy function that handles a ton of front end behavior on level end. // Including: show rewards, level cleanup, RUN MAIN MENU LEVEL SELECT IU LOOP!!!! BOOL __cdecl lego::lrr::Lego_EndLevel(void) { BOOL unkMission; BOOL unkTuto; BOOL BVar1; char *nextLevelID; Lego_GetLevel(); unkMission = front::Front_IsMissionSelected(); unkTuto = front::Front_IsTutorialSelected(); snd::Sound3D_StopAllSounds(); BVar1 = front::Front_IsFrontEndEnabled(); if (BVar1 != 0) { reward::Reward_CreateLevel(); reward::Reward_Prepare(); reward::Reward_Show(); reward::Reward_FreeLevel(); } Lego_SetViewMode(ViewMode_Top,NULL,0); front::TextWindow_Clear(globs::legoGlobs.textOnlyWindow); nextLevelID = game::Level_Free(); BVar1 = front::Front_IsFrontEndEnabled(); if (BVar1 != 0) { if (unkMission == 0) { if (unkTuto == 0) goto LAB_00435915; front::Front_RunScreenMenuType(Menu_Screen_Training); BVar1 = front::Front_IsTriggerAppQuit(); if (BVar1 != 0) { return FALSE; } } else { front::Front_RunScreenMenuType(Menu_Screen_Missions); BVar1 = front::Front_IsTriggerAppQuit(); if (BVar1 != 0) { return FALSE; } } nextLevelID = front::Front_GetSelectedLevel(); } LAB_00435915: front::Front_LoadOptionParameters(TRUE,FALSE); if (nextLevelID == NULL) { return FALSE; } BVar1 = Lego_LoadLevel(nextLevelID); if (BVar1 == 0) { return FALSE; } // Another memory leak? Only freed on LoadLevel failure... // I'm not even sure how this bit of memory is supposed to be managed. io::Mem_Free(nextLevelID); return TRUE; } void __cdecl lego::lrr::Lego_StopUserAction(void) { globs::legoGlobs.flags3 &= ~(GAME3_ENCYCLOPEDIA|GAME3_LEGOMANGOTO|GAME3_VEHICLEGOTO|GAME3_PICKUPOBJECT|GAME3_LOADVEHICLE |GAME3_LEGOMANDIG|GAME3_VEHICLEDIG|GAME3_PLACEBUILDING); gfx::SelectPlace_Hide(globs::legoGlobs.selectPlace,TRUE); return; } void __cdecl lego::lrr::Lego_UnkTeleporterInit_FUN_00435980(void) { BOOL BVar1; if ((globs::legoGlobs.flags1 & GAME1_LEVELENDING) != GAME1_NONE) { BVar1 = unk::Teleporter_ServiceAll (TELEPORT_SERVIVE_VEHICLE|TELEPORT_SERVIVE_MINIFIGURE| TELEPORT_SERVIVE_BUILDING|TELEPORT_SERVIVE_ELECTRICFENCE); if (BVar1 != 0) { globs::legoGlobs.flags2 |= GAME2_LEVELEXITING; } } return; } void __cdecl lego::lrr::Lego_SetAttackDefer(BOOL defer) { if (defer != 0) { globs::legoGlobs.flags2 = globs::legoGlobs.flags2 | GAME2_ATTACKDEFER; return; } globs::legoGlobs.flags2 = globs::legoGlobs.flags2 & ~GAME2_ATTACKDEFER; return; } void __cdecl lego::lrr::Lego_SetCallToArmsOn(BOOL callToArms) { if (callToArms != 0) { globs::legoGlobs.flags2 |= GAME2_CALLTOARMS; if ((ushort)((ushort)(globs::legoGlobs.timerGame_e3c < 0.0) << 8 | (ushort)(globs::legoGlobs.timerGame_e3c == 0.0) << 0xe) != 0) { snd::SFX_Random_PlaySoundNormal(SFX_Siren,FALSE); globs::legoGlobs.timerGame_e3c = 250.0; } front::Panel_Button_SetToggled(Panel_TopPanel,PanelButton_TopPanel_CallToArms,TRUE); return; } globs::legoGlobs.flags2 &= ~GAME2_CALLTOARMS; globs::legoGlobs.timerGame_e3c = 0.0; front::Panel_Button_SetToggled(Panel_TopPanel,PanelButton_TopPanel_CallToArms,FALSE); return; } LegoCamera * __cdecl lego::view::Camera_Create(Container *root,LegoCamera_Type camType) { LegoCamera *cam; Container *cont; cam = (LegoCamera *)io::Mem_Alloc(0xbc); if (cam != NULL) { cam->type = camType; cam->trackObj = NULL; cam->trackRadarZoom = 0.0; cam->trackRadarZoomSpeed = 0.0; *(undefined *)&cam->flags = CAMERA_FLAG_NONE; cam->rotation = 0.0; cam->tilt = 0.0; cam->zoom = 200.0; cam->trackFPCameraFrame = 0; (cam->moveVector).x = 0.0; (cam->moveVector).y = 0.0; (cam->moveVector).z = 0.0; cam->moveSpeed = 0.0; cam->shakeTimer = 0.0; cam->shakeDuration = 0.0; cam->shakeIntensity = 0.0; (cam->shakeVector).z = 0.0; (cam->shakeVector).y = 0.0; (cam->shakeVector).x = 0.0; cont = gfx::Container_Create(NULL); cam->contCam = cont; if (cam->contCam != NULL) { gfx::Container_SetPosition(cam->contCam,NULL,0.0,0.0,-cam->zoom); gfx::Container_SetOrientation(cam->contCam,NULL,0.0,0.0,1.0,0.0,1.0,0.0); if (camType == LegoCamera_FP) { gfx::Container_SetParent(cam->contCam,root); return cam; } cont = gfx::Container_Create(root); cam->cont2 = cont; if (cam->cont2 != NULL) { cont = gfx::Container_Create(root); cam->cont3 = cont; if (cam->cont3 != NULL) { cont = gfx::Container_Create(cam->cont2); cam->cont4 = cont; if (cam->cont4 != NULL) { if (camType == LegoCamera_Top) { cont = gfx::Container_Create(cam->cont4); cam->contListener = cont; if (cam->contListener != NULL) { gfx::Container_SetPosition(cam->contListener,NULL,0.0,0.0,-80.0); } } gfx::Container_SetParent(cam->contCam,cam->cont4); return cam; } gfx::Container_Remove(cam->cont3); } gfx::Container_Remove(cam->cont2); } gfx::Container_Remove(cam->contCam); } io::Mem_Free(cam); } return NULL; } // If true, allows orientation movement while ignoring // zoom, tilt, and yaw range restrictions. void __cdecl lego::view::Camera_EnableFreeMovement(LegoCamera *cam,BOOL on) { if (on == FALSE) { // ~CAMERA_FLAG_FREEMOVEMENT (~0x8) *(byte *)&cam->flags = *(byte *)&cam->flags & 0xf7; } else { *(byte *)&cam->flags = *(byte *)&cam->flags | CAMERA_FLAG_FREEMOVEMENT; } return; } void __cdecl lego::view::Camera_Free(LegoCamera *cam) { gfx::Container_Remove(cam->contCam); if (cam->type != LegoCamera_FP) { gfx::Container_Remove(cam->cont2); gfx::Container_Remove(cam->cont4); } io::Mem_Free(cam); return; } void __cdecl lego::view::Camera_InitCameraMovements (float cameraSpeed,float cameraDropOff,float cameraAcceleration,int mouseScrollIndent) { globs::cameraGlobs.maxSpeed = cameraSpeed; globs::cameraGlobs.deceleration = cameraDropOff; globs::cameraGlobs.acceleration = cameraAcceleration; globs::cameraGlobs.mouseScrollIndent = mouseScrollIndent; return; } void __cdecl lego::view::Camera_CopyFPPositionOrientation(LegoCamera *dstCamera,LegoCamera *srcCamera) { Vector3F vectorPos; Vector3F vectorD; Vector3F vectorU; if (dstCamera->type == LegoCamera_FP) { gfx::Container_GetPosition(srcCamera->contCam,NULL,&vectorPos); gfx::Container_GetOrientation(srcCamera->contCam,NULL,&vectorD,&vectorU); gfx::Container_SetPosition(dstCamera->contCam,NULL,vectorPos.x,vectorPos.y,vectorPos.z); gfx::Container_SetOrientation (dstCamera->contCam,NULL,vectorD.x,vectorD.y,vectorD.z,vectorU.x,vectorU.y,vectorU.z); } return; } // Set liveObj to NULL to disable. void __cdecl lego::view::Camera_TrackObject (LegoCamera *cam,LegoObject *liveObj,float trackFloat_8,float trackDist,float trackTilt, float trackRotationSpeed) { cam->trackObj = liveObj; cam->trackRadarZoomSpeed = trackFloat_8; cam->trackRadarZoom = trackDist; Camera_SetTilt(cam,trackTilt); cam->trackRadarRotationSpeed = trackRotationSpeed; return; } void __cdecl lego::view::Camera_SetFPObject(LegoCamera *cam,LegoObject *liveObj,int cameraFrame) { cam->trackObj = liveObj; cam->trackFPCameraFrame = cameraFrame; return; } int __cdecl lego::view::Camera_GetFPCameraFrame(LegoCamera *cam) { return cam->trackFPCameraFrame; } void __cdecl lego::view::Camera_StopMovement(LegoCamera *cam) { cam->moveSpeed = 0.0; return; } int __cdecl lego::view::Camera_GetMouseScrollIndent(void) { return globs::cameraGlobs.mouseScrollIndent; } void __cdecl lego::view::Camera_Shake(LegoCamera *cam,float intensity,float duration) { cam->shakeIntensity = intensity; cam->shakeDuration = duration; cam->shakeTimer = 0.0; return; } void __cdecl lego::view::Camera_Update(LegoCamera *cam,Lego_Level *level,float elapsedAbs,float elapsedGame) { float fVar1; float fVar2; float fVar3; float fVar4; float fVar5; float fVar6; float fVar7; float fVar8; float fVar9; BOOL bInside; Map3D *map; Container *radar_objCont; float10 fVar10; float10 fVar11; Vector3F radar_vecCont1Pos2; Vector3F local_d4; Vector3F local_c8; Vector3F radar_vecCont2Pos; Vector3F radar_vecObjDir; Vector3F radar_vecCont1Pos; Vector3F radar_vecObjPos; Vector3F fp_vecObjPos; Vector3F fp_vecObjDir; float fp_distOrient; Vector3F fp_vecCont1Pos; Vector3F fp_vecCont1Dir; float fp_distPos; Vector3F top_vecPos; Vector3F top_vecDir; Vector3F top_vecUp; uint blockY; uint blockX; gfx::Container_AddTranslation (cam->contCam,Container_Combine_Before,-(cam->shakeVector).x,-(cam->shakeVector).y, -(cam->shakeVector).z); fVar1 = globs::cameraGlobs.deceleration; if (cam->type == LegoCamera_Top) { // Decelerate camera movement. // Maths_Vector3DScale(cam->vector_18, cam->vector_18, cameraGlobs.CameraDropOff); (cam->moveVector).x = (cam->moveVector).x * globs::cameraGlobs.deceleration; (cam->moveVector).y = (cam->moveVector).y * fVar1; (cam->moveVector).z = (cam->moveVector).z * fVar1; gfx::Container_AddTranslation (cam->cont2,Container_Combine_After,(cam->moveVector).x,(cam->moveVector).y, (cam->moveVector).z); gfx::Container_GetPosition(cam->cont2,NULL,&top_vecPos); gfx::Container_GetOrientation(cam->cont2,NULL,&top_vecDir,&top_vecUp); bInside = lego::map::Map3D_WorldToBlockPos_NoZ (level->map,top_vecPos.x,top_vecPos.y,(int *)&blockX,(int *)&blockY); if (bInside == 0) { // Cancel out moveVector ?? gfx::Container_AddTranslation (cam->cont2,Container_Combine_After,-(cam->moveVector).x,-(cam->moveVector).y, -(cam->moveVector).z); } else { if ((blockX < (uint)globs::cameraGlobs.mouseScrollIndent) || (level->map->blockWidth - globs::cameraGlobs.mouseScrollIndent <= blockX)) { gfx::Container_AddTranslation (cam->cont2,Container_Combine_After,-(cam->moveVector).x,0.0,0.0); } if ((blockY < (uint)globs::cameraGlobs.mouseScrollIndent) || (level->map->blockHeight - globs::cameraGlobs.mouseScrollIndent <= blockY)) { gfx::Container_AddTranslation (cam->cont2,Container_Combine_After,0.0,-(cam->moveVector).y,0.0); } fVar10 = lego::map::Map3D_GetWorldZ(level->map,top_vecPos.x,top_vecPos.y); gfx::Container_SetPosition(cam->cont3,NULL,top_vecPos.x,top_vecPos.y,(float)fVar10); gfx::Container_SetOrientation(cam->cont3,NULL,top_vecUp.x,top_vecUp.y,0.0,0.0,0.0,-1.0); map = lrr::Lego_GetMap(); fVar10 = lego::map::Map3D_UnkCameraXYFunc_RetZunk(map,top_vecPos.x,top_vecPos.y); gfx::Container_SetPosition(cam->contCam,cam->cont4,0.0,0.0,-(cam->zoom + (float)-fVar10)); } goto LAB_004368f0; } if (cam->type != LegoCamera_FP) { if (cam->type == LegoCamera_Radar) { if (cam->trackObj == NULL) { game::Lego_SetRadarNoTrackObject(TRUE); } else { radar_objCont = game::LegoObject_GetActivityContainer(cam->trackObj); if (radar_objCont != NULL) { fVar2 = cam->trackRadarZoomSpeed * elapsedGame; game::Lego_SetRadarNoTrackObject(FALSE); gfx::Container_GetPosition(cam->contCam,NULL,&radar_vecCont1Pos); gfx::Container_GetPosition(radar_objCont,NULL,&radar_vecObjPos); radar_vecObjPos.z = radar_vecObjPos.z - cam->trackRadarZoom / 10.0; fVar1 = cam->zoom; cam->zoom = cam->trackRadarZoom; gfx::Container_SetPosition(cam->contCam,cam->cont4,0.0,0.0,-cam->zoom); gfx::Container_GetPosition(cam->cont2,NULL,&radar_vecCont2Pos); gfx::Container_SetPosition (cam->cont2,NULL,radar_vecObjPos.x,radar_vecObjPos.y,radar_vecObjPos.z); gfx::Container_GetPosition(cam->contCam,NULL,&radar_vecCont1Pos2); fVar10 = std::sqrt((double)((radar_vecCont1Pos2.z - radar_vecCont1Pos.z) * (radar_vecCont1Pos2.z - radar_vecCont1Pos.z) + (radar_vecCont1Pos2.y - radar_vecCont1Pos.y) * (radar_vecCont1Pos2.y - radar_vecCont1Pos.y) + (radar_vecCont1Pos2.x - radar_vecCont1Pos.x) * (radar_vecCont1Pos2.x - radar_vecCont1Pos.x))); if (((ushort)((ushort)(fVar10 < (float10)fVar2) << 8 | (ushort)(fVar10 == (float10)fVar2) << 0xe) == 0) && ((float)fVar10 < 120.0)) { fVar3 = (float)fVar10 / fVar2; gfx::Container_GetOrientation(radar_objCont,NULL,&radar_vecObjDir,NULL); radar_vecObjPos.x = radar_vecObjPos.x + radar_vecObjDir.x * fVar3; radar_vecObjPos.y = radar_vecObjPos.y + radar_vecObjDir.y * fVar3; radar_vecObjPos.z = radar_vecObjPos.z + radar_vecObjDir.z * fVar3; fVar4 = radar_vecObjPos.x - radar_vecCont2Pos.x; fVar5 = radar_vecObjPos.y - radar_vecCont2Pos.y; fVar6 = radar_vecObjPos.z - radar_vecCont2Pos.z; fVar10 = std::sqrt((double)(fVar6 * fVar6 + fVar5 * fVar5 + fVar4 * fVar4)); fVar11 = std::fabs((double)(cam->trackRadarZoom - fVar1)); fVar3 = (float)fVar11; fVar7 = (float)fVar10 + fVar3; fVar11 = std::sqrt((double)(fVar6 * fVar6 + fVar5 * fVar5 + fVar4 * fVar4)); fVar8 = 1.0 / (float)fVar11; fVar9 = ((float)fVar10 / fVar7) * fVar2; radar_vecCont2Pos.x = radar_vecCont2Pos.x + fVar4 * fVar8 * fVar9; radar_vecCont2Pos.y = radar_vecCont2Pos.y + fVar5 * fVar8 * fVar9; radar_vecCont2Pos.z = radar_vecCont2Pos.z + fVar6 * fVar8 * fVar9; gfx::Container_SetPosition (cam->cont2,NULL,radar_vecCont2Pos.x,radar_vecCont2Pos.y,radar_vecCont2Pos.z); if ((ushort)((ushort)(fVar1 < cam->trackRadarZoom) << 8 | (ushort)(fVar1 == cam->trackRadarZoom) << 0xe) == 0) { cam->zoom = fVar1 - (fVar3 / fVar7) * fVar2; } else { if (fVar1 != cam->trackRadarZoom) { cam->zoom = (fVar3 / fVar7) * fVar2 + fVar1; } } gfx::Container_SetPosition(cam->contCam,cam->cont4,0.0,0.0,-cam->zoom); } Camera_AddRotation(cam,cam->trackRadarRotationSpeed * elapsedAbs); } } } goto LAB_004368f0; } if ((cam->trackObj == NULL) || (elapsedAbs == 0.0)) goto LAB_004368f0; gfx::Container_GetPosition(cam->contCam,NULL,&fp_vecCont1Pos); gfx::Container_GetOrientation(cam->contCam,NULL,&fp_vecCont1Dir,&fp_vecObjDir); game::LegoObject_FP_GetPositionAndHeading (cam->trackObj,cam->trackFPCameraFrame,&fp_vecObjPos,&fp_vecObjDir); if ((*(byte *)&cam->flags & CAMERA_FLAG_FPSETUP) == 0) { LAB_0043621d: fp_vecCont1Pos.x = fp_vecObjPos.x; fp_vecCont1Pos.y = fp_vecObjPos.y; fp_vecCont1Pos.z = fp_vecObjPos.z; fp_vecCont1Dir.x = fp_vecObjDir.x; fp_vecCont1Dir.y = fp_vecObjDir.y; fp_vecCont1Dir.z = fp_vecObjDir.z; } else { fVar10 = std::sqrt((double)((fp_vecObjPos.z - fp_vecCont1Pos.z) * (fp_vecObjPos.z - fp_vecCont1Pos.z) + (fp_vecObjPos.y - fp_vecCont1Pos.y) * (fp_vecObjPos.y - fp_vecCont1Pos.y) + (fp_vecObjPos.x - fp_vecCont1Pos.x) * (fp_vecObjPos.x - fp_vecCont1Pos.x))); fp_distPos = (float)fVar10; if (((ushort)((ushort)(fVar10 < (float10)100.0) << 8 | (ushort)(fVar10 == (float10)100.0) << 0xe ) == 0) || (fp_distOrient = fp_vecObjDir.x * fp_vecCont1Dir.x + fp_vecObjDir.y * fp_vecCont1Dir.y + fp_vecObjDir.z * fp_vecCont1Dir.z, fp_distOrient < 0.0)) goto LAB_0043621d; } fVar1 = (1.0 / elapsedAbs) * 4.0; fVar10 = std::sqrt((double)(fp_vecCont1Dir.z * fp_vecCont1Dir.z + fp_vecCont1Dir.y * fp_vecCont1Dir.y + fp_vecCont1Dir.x * fp_vecCont1Dir.x)); fVar2 = 1.0 / (float)fVar10; fp_vecCont1Dir.x = fp_vecCont1Dir.x * fVar2; fp_vecCont1Dir.y = fp_vecCont1Dir.y * fVar2; fp_vecCont1Dir.z = fp_vecCont1Dir.z * fVar2; fVar10 = std::sqrt((double)(fp_vecObjDir.z * fp_vecObjDir.z + fp_vecObjDir.y * fp_vecObjDir.y + fp_vecObjDir.x * fp_vecObjDir.x)); fVar2 = 1.0 / (float)fVar10; fp_vecCont1Dir.x = fp_vecCont1Dir.x * fVar1; fp_vecCont1Dir.y = fp_vecCont1Dir.y * fVar1; fp_vecCont1Dir.z = fp_vecCont1Dir.z * fVar1; fp_vecObjDir.x = fp_vecObjDir.x * fVar2 + fp_vecCont1Dir.x; fp_vecObjDir.y = fp_vecObjDir.y * fVar2 + fp_vecCont1Dir.y; fp_vecObjDir.z = fp_vecObjDir.z * fVar2 + fp_vecCont1Dir.z; fp_vecCont1Pos.x = fp_vecCont1Pos.x * fVar1; fp_vecCont1Pos.y = fp_vecCont1Pos.y * fVar1; fp_vecCont1Pos.z = fp_vecCont1Pos.z * fVar1; fVar1 = 1.0 / (fVar1 + 1.0); fp_vecObjPos.x = (fp_vecObjPos.x + fp_vecCont1Pos.x) * fVar1; fp_vecObjPos.y = (fp_vecObjPos.y + fp_vecCont1Pos.y) * fVar1; fp_vecObjPos.z = (fp_vecObjPos.z + fp_vecCont1Pos.z) * fVar1; if ((ushort)((ushort)(fp_distPos < 0.01) << 8 | (ushort)(fp_distPos == 0.01) << 0xe) == 0) { gfx::Container_SetPosition(cam->contCam,NULL,fp_vecObjPos.x,fp_vecObjPos.y,fp_vecObjPos.z); } if (fp_distOrient < 0.99999) { gfx::Container_SetOrientation (cam->contCam,NULL,fp_vecObjDir.x,fp_vecObjDir.y,fp_vecObjDir.z,0.0,0.0,-1.0); } *(byte *)&cam->flags = *(byte *)&cam->flags | CAMERA_FLAG_FPSETUP; LAB_004368f0: if (cam->shakeDuration <= cam->shakeTimer) { (cam->shakeVector).z = 0.0; (cam->shakeVector).y = 0.0; (cam->shakeVector).x = 0.0; } else { fVar1 = cam->shakeDuration; fVar2 = cam->shakeTimer; fVar3 = cam->shakeDuration; fVar4 = cam->shakeIntensity; fVar10 = math::Maths_RandRange(0.0,1.0); math::Maths_Vector3DRandom(&cam->shakeVector); fVar1 = ((fVar1 - fVar2) / fVar3) * fVar4 * (float)fVar10; (cam->shakeVector).x = (cam->shakeVector).x * fVar1; (cam->shakeVector).y = (cam->shakeVector).y * fVar1; (cam->shakeVector).z = (cam->shakeVector).z * fVar1; cam->shakeTimer = cam->shakeTimer + elapsedGame; gfx::Container_AddTranslation (cam->contCam,Container_Combine_Before,-(cam->shakeVector).x,-(cam->shakeVector).y, -(cam->shakeVector).z); } return; } void __cdecl lego::view::Camera_SetTiltRange(LegoCamera *cam,float minTilt,float maxTilt) { *(byte *)&cam->flags = *(byte *)&cam->flags | CAMERA_FLAG_TILTRANGE; (cam->tiltRange).min = minTilt; (cam->tiltRange).max = maxTilt; return; } void __cdecl lego::view::Camera_SetTilt(LegoCamera *cam,float tilt) { float fVar1; if ((((*(byte *)&cam->flags & CAMERA_FLAG_TILTRANGE) == 0) || ((*(byte *)&cam->flags & CAMERA_FLAG_FREEMOVEMENT) != 0)) || (((cam->tiltRange).min <= tilt && (fVar1 = (cam->tiltRange).max, (ushort)((ushort)(tilt < fVar1) << 8 | (ushort)(tilt == fVar1) << 0xe) != 0)))) { cam->tilt = tilt; gfx::Container_SetOrientation(cam->cont4,cam->cont2,0.0,0.0,1.0,0.0,1.0,0.0); gfx::Container_AddRotation(cam->cont4,Container_Combine_Before,1.0,0.0,0.0,-tilt); } return; } void __cdecl lego::view::Camera_AddTilt(LegoCamera *cam,float tiltAmount) { Camera_SetTilt(cam,tiltAmount + cam->tilt); return; } void __cdecl lego::view::Camera_SetRotationRange(LegoCamera *cam,float minYaw,float maxYaw) { *(byte *)&cam->flags = *(byte *)&cam->flags | CAMERA_FLAG_ROTATIONRANGE; (cam->rotationRange).min = minYaw; (cam->rotationRange).max = maxYaw; return; } void __cdecl lego::view::Camera_SetRotation(LegoCamera *cam,float yaw) { float fVar1; if ((((*(byte *)&cam->flags & CAMERA_FLAG_ROTATIONRANGE) == 0) || ((*(byte *)&cam->flags & CAMERA_FLAG_FREEMOVEMENT) != 0)) || (((cam->rotationRange).min <= yaw && (fVar1 = (cam->rotationRange).max, (ushort)((ushort)(yaw < fVar1) << 8 | (ushort)(yaw == fVar1) << 0xe) != 0)))) { cam->rotation = yaw; gfx::Container_SetOrientation(cam->cont2,NULL,0.0,0.0,1.0,0.0,1.0,0.0); gfx::Container_AddRotation(cam->cont2,Container_Combine_Before,0.0,0.0,1.0,-yaw); } return; } void __cdecl lego::view::Camera_AddRotation(LegoCamera *cam,float yawAmount) { Camera_SetRotation(cam,yawAmount + cam->rotation); return; } void __cdecl lego::view::Camera_SetZoomRange(LegoCamera *cam,float minDist,float maxDist) { *(byte *)&cam->flags = *(byte *)&cam->flags | CAMERA_FLAG_ZOOMRANGE; (cam->zoomRange).min = minDist; (cam->zoomRange).max = maxDist; return; } void __cdecl lego::view::Camera_SetZoom(LegoCamera *cam,float dist) { float fVar1; if ((((*(byte *)&cam->flags & CAMERA_FLAG_ZOOMRANGE) == 0) || ((*(byte *)&cam->flags & CAMERA_FLAG_FREEMOVEMENT) != 0)) || (((cam->zoomRange).min <= dist && (fVar1 = (cam->zoomRange).max, (ushort)((ushort)(dist < fVar1) << 8 | (ushort)(dist == fVar1) << 0xe) != 0)))) { cam->zoom = dist; } return; } void __cdecl lego::view::Camera_AddZoom(LegoCamera *cam,float distAmount) { Camera_SetZoom(cam,distAmount + cam->zoom); return; } void __cdecl lego::view::Camera_AddTranslation2D(LegoCamera *cam,float translateX,float translateY) { gfx::Container_AddTranslation(cam->cont2,Container_Combine_Before,translateX,translateY,0.0); return; } void __cdecl lego::view::Camera_GetTopdownPosition(LegoCamera *cam,Vector3F *out_position) { if (cam->type == LegoCamera_Top) { gfx::Container_GetPosition(cam->cont2,NULL,out_position); } return; } void __cdecl lego::view::Camera_SetTopdownPosition(LegoCamera *cam,float x,float y) { if (cam->type == LegoCamera_Top) { gfx::Container_SetPosition(cam->cont2,NULL,x,y,0.0); } return; } // Same as Camera_GetTopdownPosition, but the returned Z value is the Map3D surface Z. BOOL __cdecl lego::view::Camera_GetTopdownWorldPos(LegoCamera *cam,Map3D *surfMap,Vector3F *out_worldPos) { float10 z; if (cam->type == LegoCamera_Top) { gfx::Container_GetPosition(cam->cont2,NULL,out_worldPos); z = lego::map::Map3D_GetWorldZ(surfMap,out_worldPos->x,out_worldPos->y); out_worldPos->z = (float)z; } return TRUE; } float10 __cdecl lego::view::Camera_GetRotation(LegoCamera *cam) { return (float10)cam->rotation; } void __cdecl lego::view::Camera_Move(LegoCamera *cam,Vector3F *ref_dir,float elapsedAbs) { float10 dir_dist; float dir_norm; float moveDist; // Maths_Vector3DNormalize(ref_dir); dir_dist = std::sqrt((double)(ref_dir->z * ref_dir->z + ref_dir->y * ref_dir->y + ref_dir->x * ref_dir->x)); dir_norm = 1.0 / (float)dir_dist; ref_dir->x = ref_dir->x * dir_norm; ref_dir->y = ref_dir->y * dir_norm; ref_dir->z = ref_dir->z * dir_norm; // Add (acceleration*timeDelta) to current speed. // (note that moveSpeed itself does not contain time info, // which is the best way to handle it) cam->moveSpeed = elapsedAbs * globs::cameraGlobs.acceleration + cam->moveSpeed; // cap acceleration at max (CameraSpeed) // // if (cam->movingSpeed > cameraGlobs.CameraSpeed) // cam->movingSpeed = cameraGlobs.CameraSpeed; if ((ushort)((ushort)(cam->moveSpeed < globs::cameraGlobs.maxSpeed) << 8 | (ushort)(cam->moveSpeed == globs::cameraGlobs.maxSpeed) << 0xe) == 0) { cam->moveSpeed = globs::cameraGlobs.maxSpeed; } moveDist = cam->moveSpeed * elapsedAbs; // Set length of direction vector to moveDist // Maths_Vector3DScale(ref_dir, ref_dir, moveDist); ref_dir->x = ref_dir->x * moveDist; ref_dir->y = ref_dir->y * moveDist; ref_dir->z = ref_dir->z * moveDist; // Add directional movement to cam->vector_18 // Maths_Vector3DAdd(cam->vector_18, cam->vector_18, ref_dir); (cam->moveVector).x = (cam->moveVector).x + ref_dir->x; (cam->moveVector).y = (cam->moveVector).y + ref_dir->y; (cam->moveVector).z = (cam->moveVector).z + ref_dir->z; return; } void __cdecl lego::game::LegoObject_Initialise(void) { int iVar1; LegoObject_Globs *pLVar2; pLVar2 = &globs::objectGlobs; for (iVar1 = 0x318f; iVar1 != 0; iVar1 += -1) { pLVar2->listSet[0] = NULL; pLVar2 = (LegoObject_Globs *)(pLVar2->listSet + 1); } globs::objectGlobs.activityName[0] = "Activity_Stand"; globs::objectGlobs.activityName[1] = "Activity_Route"; globs::objectGlobs.activityName[2] = "Activity_RouteRubble"; globs::objectGlobs.activityName[3] = "Activity_RunPanic"; globs::objectGlobs.activityName[4] = "Activity_Drill"; globs::objectGlobs.activityName[5] = "Activity_Teleport"; globs::objectGlobs.activityName[6] = "Activity_Walk"; globs::objectGlobs.activityName[7] = "Activity_Reinforce"; globs::objectGlobs.activityName[8] = "Activity_Reverse"; globs::objectGlobs.activityName[9] = "Activity_TurnLeft"; globs::objectGlobs.activityName[10] = "Activity_TurnRight"; globs::objectGlobs.activityName[11] = "Activity_CantDo"; globs::objectGlobs.activityName[12] = "Activity_Emerge"; globs::objectGlobs.activityName[13] = "Activity_Enter"; globs::objectGlobs.activityName[14] = "Activity_EnterRein"; globs::objectGlobs.activityName[15] = "Activity_Collect"; globs::objectGlobs.activityName[16] = "Activity_Gather"; globs::objectGlobs.activityName[17] = "Activity_Carry"; globs::objectGlobs.activityName[18] = "Activity_CarryRubble"; globs::objectGlobs.activityName[19] = "Activity_Throw"; globs::objectGlobs.activityName[20] = "Activity_CarryTurnLeft"; globs::objectGlobs.activityName[21] = "Activity_CarryTurnRight"; globs::objectGlobs.activityName[22] = "Activity_CarryStand"; globs::objectGlobs.activityName[23] = "Activity_HitLeft"; globs::objectGlobs.activityName[24] = "Activity_HitRight"; globs::objectGlobs.activityName[25] = "Activity_HitFront"; globs::objectGlobs.activityName[26] = "Activity_HitBack"; globs::objectGlobs.activityName[27] = "Activity_HitHard"; globs::objectGlobs.activityName[28] = "Activity_Dynamite"; globs::objectGlobs.activityName[29] = "Activity_Deposit"; globs::objectGlobs.activityName[30] = "Activity_Clear"; globs::objectGlobs.activityName[31] = "Activity_Place"; globs::objectGlobs.activityName[32] = "Activity_Repair"; globs::objectGlobs.activityName[33] = "Activity_Slip"; globs::objectGlobs.activityName[34] = "Activity_Rest"; globs::objectGlobs.activityName[35] = "Activity_Eat"; globs::objectGlobs.activityName[36] = "Activity_Stamp"; globs::objectGlobs.activityName[37] = "Activity_ThrowMan"; globs::objectGlobs.activityName[38] = "Activity_ThrownByRockMonster"; globs::objectGlobs.activityName[39] = "Activity_GetUp"; globs::objectGlobs.activityName[40] = "Activity_BuildPath"; globs::objectGlobs.activityName[41] = "Activity_Upgrade"; globs::objectGlobs.activityName[42] = "Activity_Explode"; globs::objectGlobs.activityName[43] = "Activity_Unpowered"; globs::objectGlobs.activityName[44] = "Activity_FireLaser"; globs::objectGlobs.activityName[45] = "Activity_Freezed"; globs::objectGlobs.activityName[46] = "Activity_FreezeStart"; globs::objectGlobs.activityName[47] = "Activity_FreezeMelt"; globs::objectGlobs.activityName[48] = "Activity_Recharge"; globs::objectGlobs.activityName[49] = "Activity_WakeUp"; globs::objectGlobs.activityName[50] = "Activity_Train"; globs::objectGlobs.activityName[51] = "Activity_FloatOn"; globs::objectGlobs.activityName[52] = "Activity_FloatOff"; globs::objectGlobs.activityName[53] = "Activity_Opening"; globs::objectGlobs.activityName[54] = "Activity_Closing"; globs::objectGlobs.activityName[55] = "Activity_Open"; globs::objectGlobs.activityName[56] = "Activity_Waiting1"; globs::objectGlobs.activityName[57] = "Activity_Waiting2"; globs::objectGlobs.activityName[58] = "Activity_Waiting3"; globs::objectGlobs.activityName[59] = "Activity_Waiting4"; globs::objectGlobs.activityName[60] = "Activity_Waiting5"; globs::objectGlobs.activityName[61] = "Activity_Waiting6"; globs::objectGlobs.activityName[62] = "Activity_Waiting7"; globs::objectGlobs.activityName[63] = "Activity_Waiting8"; globs::objectGlobs.activityName[64] = "Activity_Waiting9"; globs::objectGlobs.activityName[65] = "Activity_Waiting10"; globs::objectGlobs.activityName[66] = "Activity_Waiting11"; globs::objectGlobs.activityName[67] = "Activity_Waiting12"; globs::objectGlobs.activityName[68] = "Activity_Waiting13"; globs::objectGlobs.activityName[69] = "Activity_Waiting14"; globs::objectGlobs.activityName[70] = "Activity_Waiting15"; globs::objectGlobs.activityName[71] = "Activity_Waiting16"; globs::objectGlobs.activityName[72] = "Activity_Waiting17"; globs::objectGlobs.activityName[73] = "Activity_Waiting18"; globs::objectGlobs.activityName[74] = "Activity_Waiting19"; globs::objectGlobs.activityName[75] = "Activity_Waiting20"; globs::objectGlobs.activityName[76] = "Activity_Waiting21"; globs::objectGlobs.activityName[77] = "Activity_Crumble"; globs::objectGlobs.activityName[78] = "Activity_TeleportIn"; globs::objectGlobs.abilityName[0] = "LegoObject_AbilityType_Pilot"; globs::objectGlobs.abilityName[1] = "LegoObject_AbilityType_Sailor"; globs::objectGlobs.abilityName[2] = "LegoObject_AbilityType_Driver"; globs::objectGlobs.abilityName[3] = "LegoObject_AbilityType_Dynamite"; globs::objectGlobs.abilityName[4] = "LegoObject_AbilityType_Repair"; globs::objectGlobs.abilityName[5] = "LegoObject_AbilityType_Scanner"; pLVar2 = &globs::objectGlobs; for (iVar1 = 0x20; iVar1 != 0; iVar1 += -1) { pLVar2->listSet[0] = NULL; pLVar2 = (LegoObject_Globs *)(pLVar2->listSet + 1); } globs::objectGlobs.freeList = NULL; globs::objectGlobs.listCount = 0; globs::objectGlobs.flags = OBJECT_GLOB_FLAG_INITIALISED; globs::objectGlobs.toolNullIndex[0] = 0; globs::objectGlobs.toolNullIndex[1] = 0; globs::objectGlobs.toolNullIndex[2] = 1; globs::objectGlobs.toolNullIndex[3] = 1; globs::objectGlobs.toolNullIndex[4] = 4; globs::objectGlobs.toolNullIndex[5] = 4; globs::objectGlobs.toolNullIndex[6] = 4; globs::objectGlobs.toolNullIndex[7] = 4; globs::objectGlobs.toolNullIndex[8] = 3; globs::objectGlobs.toolNullIndex[9] = 2; globs::objectGlobs.toolNullIndex[10] = 4; globs::legoGlobs.toolName[0] = "LegoObject_ToolType_Drill"; globs::legoGlobs.toolName[1] = "LegoObject_ToolType_Spade"; globs::legoGlobs.toolName[2] = "LegoObject_ToolType_Hammer"; globs::legoGlobs.toolName[3] = "LegoObject_ToolType_Spanner"; globs::legoGlobs.toolName[4] = "LegoObject_ToolType_Laser"; globs::legoGlobs.toolName[5] = "LegoObject_ToolType_PusherGun"; globs::legoGlobs.toolName[6] = "LegoObject_ToolType_BirdScarer"; globs::legoGlobs.toolName[7] = "LegoObject_ToolType_FreezerGun"; return; } void __cdecl lego::game::LegoObject_Shutdown(void) { LegoObject_Globs *pLVar1; LegoObject_RemoveAll(); pLVar1 = &globs::objectGlobs; do { if (pLVar1->listSet[0] != NULL) { io::Mem_Free(pLVar1->listSet[0]); } pLVar1 = (LegoObject_Globs *)(pLVar1->listSet + 1); } while (pLVar1 < (LegoObject_Globs *)&globs::objectGlobs.freeList); globs::objectGlobs.freeList = NULL; globs::objectGlobs.flags = OBJECT_GLOB_FLAG_NONE; if (globs::objectGlobs.UnkSurfaceGrid_1_TABLE != NULL) { io::Mem_Free(globs::objectGlobs.UnkSurfaceGrid_1_TABLE); } globs::objectGlobs.flags = globs::objectGlobs.flags & ~OBJECT_GLOB_FLAG_INITIALISED; return; } void __cdecl lego::save::Object_Save_CopyStruct18(SaveStruct_18 *out_saveStruct18) { int iVar1; SaveStruct_18 *pSVar2; pSVar2 = &globs::objectGlobs.savestruct18_c01c; for (iVar1 = 6; iVar1 != 0; iVar1 += -1) { *(undefined4 *)out_saveStruct18 = *(undefined4 *)pSVar2; pSVar2 = (SaveStruct_18 *)&pSVar2->field_0x4; out_saveStruct18 = (SaveStruct_18 *)&out_saveStruct18->field_0x4; } return; } // NULL will simply memzero the entire structure at the address void __cdecl lego::save::Object_Save_OverwriteStruct18(SaveStruct_18 *opt_saveStruct18) { int iVar1; SaveStruct_18 *pSVar2; iVar1 = 6; if (opt_saveStruct18 != NULL) { pSVar2 = &globs::objectGlobs.savestruct18_c01c; for (; iVar1 != 0; iVar1 += -1) { *(undefined4 *)pSVar2 = *(undefined4 *)opt_saveStruct18; opt_saveStruct18 = (SaveStruct_18 *)&opt_saveStruct18->field_0x4; pSVar2 = (SaveStruct_18 *)&pSVar2->field_0x4; } return; } pSVar2 = &globs::objectGlobs.savestruct18_c01c; for (; iVar1 != 0; iVar1 += -1) { *(undefined4 *)pSVar2 = 0; pSVar2 = (SaveStruct_18 *)&pSVar2->field_0x4; } return; } uint __cdecl lego::game::LegoObject_GetObjectsBuilt(LegoObject_Type objType,BOOL excludeToolStore) { StatsFlags1 SVar1; uint uVar2; uint builtCount; LegoObject_ID objID; uint objLevel; builtCount = 0; // This function will have an access violation if excludeToolStore is true, and objType // has less than the max allowed object IDs. objID = 0; do { objLevel = 0; do { if (excludeToolStore == 0) { LAB_004373e4: uVar2 = LegoObject_GetLevelObjectsBuilt(objType,objID,objLevel,TRUE); builtCount += uVar2; } else { SVar1 = stats::Stats_GetStatsFlags1(objType,objID); if ((SVar1 & STATS1_STOREOBJECTS) == STATS1_NONE) goto LAB_004373e4; } objLevel += 1; } while (objLevel < 0x10); objID += 1; if (0xe < objID) { return builtCount; } } while( true ); } void __cdecl lego::game::Object_LoadToolTipIcons(Config *config) { char *keyPath; Config *prop; int iVar1; Image *pIVar2; int iVar3; char **ppcVar4; Image **ppIVar5; keyPath = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"ToolTipIcons",0); prop = cfg::Config_FindArray(config,keyPath); do { if (prop == NULL) { if (globs::objectGlobs.ToolTipIcon_Ore != NULL) { lego::image::Image_SetupTrans(globs::objectGlobs.ToolTipIcon_Ore,0.0,0.0,0.0,0.0,0.0,0.0); } return; } iVar3 = 0; ppcVar4 = globs::legoGlobs.toolName; do { if ((*ppcVar4 != NULL) && (iVar1 = std::_stricmp(prop->key,*ppcVar4), iVar1 == 0)) { pIVar2 = lego::image::Image_LoadBMPScaled(prop->value,0,0); globs::objectGlobs.ToolTipIcons_Tools[iVar3] = pIVar2; break; } ppcVar4 = ppcVar4 + 1; iVar3 += 1; } while (ppcVar4 < globs::legoGlobs.langTool_name); if (iVar3 == 0xb) { iVar3 = 0; ppIVar5 = (Image **)globs::objectGlobs.abilityName; do { if ((*ppIVar5 != NULL) && (iVar1 = std::_stricmp(prop->key,(char *)*ppIVar5), iVar1 == 0)) { pIVar2 = lego::image::Image_LoadBMPScaled(prop->value,0,0); globs::objectGlobs.ToolTipIcons_Abilities[iVar3] = pIVar2; break; } ppIVar5 = ppIVar5 + 1; iVar3 += 1; } while (ppIVar5 < globs::objectGlobs.ToolTipIcons_Abilities); } if (iVar3 == 6) { iVar3 = std::_stricmp(prop->key,"Blank"); if (iVar3 == 0) { globs::objectGlobs.ToolTipIcon_Blank = lego::image::Image_LoadBMPScaled(prop->value,0,0); } else { iVar3 = std::_stricmp(prop->key,"Ore"); if (iVar3 == 0) { globs::objectGlobs.ToolTipIcon_Ore = lego::image::Image_LoadBMPScaled(prop->value,0,0); } } } prop = cfg::Config_GetNextItem(prop); } while( true ); } void __cdecl lego::game::LegoObject_CleanupLevel(void) { int iVar1; Point2I *pPVar2; LegoObject **ppLVar3; LegoObject_RemoveAll(); LegoObject_CleanupObjectLevels(); HiddenObject_RemoveAll(); pPVar2 = globs::objectGlobs.slugHoleBlocks; for (iVar1 = 0x28; iVar1 != 0; iVar1 += -1) { pPVar2->x = 0; pPVar2 = (Point2I *)&pPVar2->y; } pPVar2 = globs::objectGlobs.rechargeSeamBlocks; for (iVar1 = 0x14; iVar1 != 0; iVar1 += -1) { pPVar2->x = 0; pPVar2 = (Point2I *)&pPVar2->y; } globs::objectGlobs.slugHoleCount = 0; globs::objectGlobs.rechargeSeamCount = 0; globs::objectGlobs.dischargeBuildup = 0.0; ppLVar3 = globs::objectGlobs.liveObjArray100_c43c; for (iVar1 = 100; iVar1 != 0; iVar1 += -1) { *ppLVar3 = NULL; ppLVar3 = ppLVar3 + 1; } globs::objectGlobs.uintCount_c5cc = 0; LegoObject_SetNumBuildingsTeleported(0); return; } // Used for consuming and producing unpowered crystals after weapon discharge. void __cdecl lego::game::LegoObject_Weapon_FUN_004375c0(LegoObject *liveObj,int weaponID,float coef) { LegoObject *crystalObj; float10 fVar1; Point2I blockPos; if (weaponID == -1) { fVar1 = (float10)coef; } else { fVar1 = tools::Weapon_GetDischargeRate(weaponID); fVar1 = fVar1 * (float10)coef; } globs::objectGlobs.dischargeBuildup = (float)(fVar1 + (float10)globs::objectGlobs.dischargeBuildup); LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); while (((1.0 <= globs::objectGlobs.dischargeBuildup && (crystalObj = LegoObject_FUN_00438d20(&blockPos,LegoObject_PowerCrystal,0,0), crystalObj != NULL)) && (crystalObj = LegoObject_SpawnCarryableObject(crystalObj,LegoObject_PowerCrystal,0,0), crystalObj != NULL))) { crystalObj->flags3 = crystalObj->flags3 | LIVEOBJ3_POWEROFF; LegoObject_SetCrystalPoweredColour(crystalObj,FALSE); globs::objectGlobs.dischargeBuildup = globs::objectGlobs.dischargeBuildup - 1.0; } return; } BOOL __cdecl lego::game::LegoObject_DoOpeningClosing(LegoObject *liveObj,BOOL open) { BOOL BVar1; if ((open == 0) && ((liveObj->flags4 & LIVEOBJ4_UNK_2000) != LIVEOBJ4_NONE)) { liveObj->flags4 = liveObj->flags4 & ~LIVEOBJ4_UNK_2000 | LIVEOBJ4_UNK_4000; LegoObject_SetActivity(liveObj,Activity_Closing,0); BVar1 = LegoObject_UpdateActivityChange(liveObj); return BVar1; } if ((open != 0) && ((liveObj->flags4 & LIVEOBJ4_UNK_2000) == LIVEOBJ4_NONE)) { liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_UNK_1000; LegoObject_SetActivity(liveObj,Activity_Opening,0); } BVar1 = LegoObject_UpdateActivityChange(liveObj); return BVar1; } void __cdecl lego::game::LegoObject_CleanupObjectLevels(void) { int iVar1; uint (*paauVar2) [15] [16]; paauVar2 = globs::objectGlobs.objectPrevLevels; for (iVar1 = 0x12c0; iVar1 != 0; iVar1 += -1) { (*paauVar2)[0] = 0; paauVar2 = (uint (*) [15] [16])(*paauVar2 + 1); } paauVar2 = globs::objectGlobs.objectTotalLevels; for (iVar1 = 0x12c0; iVar1 != 0; iVar1 += -1) { (*paauVar2)[0] = 0; paauVar2 = (uint (*) [15] [16])(*paauVar2 + 1); } return; } uint __cdecl lego::game::LegoObject_GetLevelObjectsBuilt (LegoObject_Type objType,LegoObject_ID objID,uint objLevel,BOOL currentCount) { uint levelsCount; levelsCount = globs::objectGlobs.objectTotalLevels[objType][objID][objLevel]; if (currentCount != 0) { levelsCount -= globs::objectGlobs.objectPrevLevels[objType][objID][objLevel]; } return levelsCount; } uint __cdecl lego::game::LegoObject_GetPreviousLevelObjectsBuilt (LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { return globs::objectGlobs.objectPrevLevels[objType][objID][objLevel]; } void __cdecl lego::game::LegoObject_IncLevelPathsBuilt(BOOL incCurrent) { if (incCurrent != 0) { globs::objectGlobs.objectTotalLevels[15][0][0] += 1; return; } globs::objectGlobs.objectPrevLevels[15][0][0] += 1; return; } // Removes all route-to references that match the specified object. // Does nothing if routeToObj is a Boulder type. void __cdecl lego::game::LegoObject_RemoveRouteToReferences(LegoObject *routeToObj) { if (routeToObj->type != LegoObject_Boulder) { LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_RemoveRouteToReference,routeToObj); } return; } // Removes the route-to reference if it matches the specified object. BOOL __cdecl lego::game::LegoObject_Callback_RemoveRouteToReference(LegoObject *liveObj,LegoObject *routeToObj) { if (liveObj->routeToObject == routeToObj) { LegoObject_Route_End(liveObj,FALSE); liveObj->routeToObject = NULL; } return 0; } BOOL __cdecl lego::game::LegoObject_Remove(LegoObject *liveObj) { StatsFlags1 sflags1; LegoObject_Type objType; LiveFlags4 *pLFlags4; LegoObject *routeToObj; VehicleModel *vehicle; globs::objectGlobs.objectPrevLevels[liveObj->type][liveObj->id][liveObj->objLevel] = globs::objectGlobs.objectPrevLevels[liveObj->type][liveObj->id][liveObj->objLevel] + 1; if ((liveObj->flags4 & LIVEOBJ4_DRILLSOUNDPLAYING) != LIVEOBJ4_NONE) { snd::SFX_Sound3D_StopSound(liveObj->drillSoundHandle); } if ((liveObj->flags4 & LIVEOBJ4_ENGINESOUNDPLAYING) != LIVEOBJ4_NONE) { snd::SFX_Sound3D_StopSound(liveObj->engineSoundHandle); } LegoObject_RunThroughListsSkipUpgradeParts (tools::Weapon_Callback_RemoveProjectileReference,liveObj); if (liveObj->type == LegoObject_RockMonster) { ai::AITask_RemoveAttackRockMonsterReferences(liveObj); } if (liveObj->contMiniTeleportUp != NULL) { gfx::Container_Remove(liveObj->contMiniTeleportUp); } if (liveObj->carryingThisObject != NULL) { LegoObject_DropCarriedObject(liveObj->carryingThisObject,FALSE); } if ((liveObj->flags4 & LIVEOBJ4_DOCKOCCUPIED) != LIVEOBJ4_NONE) { liveObj->flags4 = liveObj->flags4 & ~LIVEOBJ4_DOCKOCCUPIED; if (liveObj->routeToObject != NULL) { pLFlags4 = &liveObj->routeToObject->flags4; *pLFlags4 = *pLFlags4 & ~LIVEOBJ4_DOCKOCCUPIED; } } LegoObject_WaterVehicle_Unregister(liveObj); if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_LASERTRACKERMODE) != 0) { globs::legoGlobs.flags1 &= ~GAME1_LASERTRACKER; } if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_ENTRANCEOCCUPIED) != 0) { routeToObj = liveObj->routeToObject; if (routeToObj != NULL) { routeToObj->flags4 = routeToObj->flags4 & ~LIVEOBJ4_ENTRANCEOCCUPIED; } liveObj->routeToObject = NULL; } LegoObject_Route_End(liveObj,FALSE); LegoObject_DoBuildingsCallback_AttackByBoulder(liveObj); LegoObject_DropCarriedObject(liveObj,FALSE); ai::AITask_RemoveTargetObjectReferences(liveObj); LegoObject_RemoveTeleportDownReference(liveObj); front::Encyclopedia_RemoveCurrentReference(liveObj); sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_PROCESSCRYSTAL) != STATS1_NONE) || (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_PROCESSORE) != STATS1_NONE)) { ai::AITask_LiveObject_FUN_00403940(liveObj); } Message_RemoveObjectReference(liveObj); front::Info_RemoveObjectReferences(liveObj); front::Bubble_RemoveObjectReferences(liveObj); LegoObject_RemoveRouteToReferences(liveObj); lrr::Lego_RemoveRecordObject(liveObj); objType = liveObj->type; if (objType == LegoObject_Vehicle) { gfx::Vehicle_Remove(liveObj->vehicle); vehicle = liveObj->vehicle; } else { if (objType == LegoObject_MiniFigure) { gfx::Creature_Remove(liveObj->miniFigure); vehicle = (VehicleModel *)liveObj->miniFigure; } else { if (objType == LegoObject_RockMonster) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_FLOCKS) != STATS1_NONE) { LegoObject_FlocksDestroy(liveObj); } gfx::Creature_Remove(liveObj->rockMonster); vehicle = (VehicleModel *)liveObj->rockMonster; } else { if (objType == LegoObject_Building) { gfx::Building_Remove(liveObj->building); vehicle = (VehicleModel *)liveObj->building; } else { if ((liveObj->flags3 & LIVEOBJ3_SIMPLEOBJECT) != LIVEOBJ3_NONE) { gfx::Container_Remove(liveObj->other); goto LAB_00437a4d; } if (objType != LegoObject_UpgradePart) goto LAB_00437a4d; gfx::Upgrade_Part_Remove(liveObj->upgradePart); vehicle = (VehicleModel *)liveObj->upgradePart; } } } } io::Mem_Free(vehicle); LAB_00437a4d: liveObj->nextFree = globs::objectGlobs.freeList; globs::objectGlobs.freeList = liveObj; return 0; } BOOL __cdecl lego::game::LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_RunThroughListsCallback callback,void *search) { BOOL BVar1; BVar1 = LegoObject_RunThroughLists(callback,search,TRUE); return BVar1; } BOOL __cdecl lego::game::LegoObject_RunThroughLists (LegoObject_RunThroughListsCallback callback,void *search,BOOL skipUpgradeParts) { LegoObject *liveObj; BOOL BVar1; int iVar2; LegoObject_Globs *pLVar3; uint uVar4; uint uVar5; uint tblIndex; tblIndex = 0; if (globs::objectGlobs.listCount == 0) { return 0; } pLVar3 = &globs::objectGlobs; do { if (pLVar3->listSet[0] != NULL) { uVar5 = 0; uVar4 = 1 << ((byte)tblIndex & 0x1f); if (uVar4 != 0) { iVar2 = 0; do { liveObj = (LegoObject *)((int)(pLVar3->listSet[0]->routeCurve).points + iVar2 + -0x34); if ((((liveObj != NULL) && (liveObj->nextFree == liveObj)) && ((skipUpgradeParts == 0 || ((liveObj->flags3 & LIVEOBJ3_UPGRADEPART) == LIVEOBJ3_NONE) ))) && (BVar1 = (*callback)(liveObj,search), BVar1 != 0)) { return TRUE; } uVar5 += 1; iVar2 += 0x40c; } while (uVar5 < uVar4); } } tblIndex += 1; pLVar3 = (LegoObject_Globs *)(pLVar3->listSet + 1); if (globs::objectGlobs.listCount <= tblIndex) { return 0; } } while( true ); } // Pass NULL or empty string to remove custom name void __cdecl lego::game::LegoObject_SetCustomName(LegoObject *liveObj,char *opt_customName) { char *pcVar1; if ((opt_customName != NULL) && (*opt_customName != '\0')) { // There is no regard for memory bounds here, // allocates 11 bytes, assigns bytes[11]... // why...... if (liveObj->customName == NULL) { pcVar1 = (char *)io::Mem_Alloc(0xb); liveObj->customName = pcVar1; } std::strncpy(liveObj->customName,opt_customName,0xb); liveObj->customName[0xb] = '\0'; return; } if (liveObj->customName != NULL) { io::Mem_Free(liveObj->customName); } liveObj->customName = NULL; return; } void __cdecl lego::game::HiddenObject_RemoveAll(void) { int iVar1; char **ppcVar2; uint uVar3; HiddenObject *pHVar4; uVar3 = 0; if (globs::objectGlobs.hiddenObjectCount != 0) { ppcVar2 = &globs::objectGlobs.hiddenObjects[0].olistID; do { if (ppcVar2[1] != NULL) { io::Mem_Free(ppcVar2[1]); } if (*ppcVar2 != NULL) { io::Mem_Free(*ppcVar2); } uVar3 += 1; ppcVar2 = ppcVar2 + 0xb; } while (uVar3 < globs::objectGlobs.hiddenObjectCount); } globs::objectGlobs.hiddenObjectCount = 0; pHVar4 = globs::objectGlobs.hiddenObjects; for (iVar1 = 200; iVar1 != 0; iVar1 += -1) { (pHVar4->blockPos).x = 0; pHVar4 = (HiddenObject *)&(pHVar4->blockPos).y; } nerps::NERPsRuntime_ClearHiddenObjectsFound(); return; } void __cdecl lego::game::HiddenObject_ExposeBlock(Point2I *blockPos) { char *pcVar1; char *pcVar2; LegoObject *liveObj; Point2I *pPVar3; LegoObject *pLVar4; StatsFlags3 sflags3; StatsFlags1 sflags1; int iVar5; HiddenObject *translation; HiddenObject *pHVar6; uint i; Direction rotation; int *piVar7; uint uVar8; longlong lVar9; LegoObject_AbilityFlags trainFlags; char **local_96c; uint local_968; uint local_964; LegoObject *apLStack2400 [200]; char *local_640 [200]; char *apcStack800 [200]; LegoObject_Type objType; uVar8 = 0; i = 0; local_968 = 0; if (globs::objectGlobs.hiddenObjectCount != 0) { local_96c = local_640; translation = globs::objectGlobs.hiddenObjects; do { // GHIDRA FAIL: this is comparing hiddenstruct->blockPos.x and blockPos.y // (whatever this *(int *)&hiddenstruct->blockPos nonsense is, is LIES. pHVar6 = translation; if (((translation->blockPos).x == blockPos->x) && (*(int *)&translation->blockPos == blockPos->y)) { if (translation->type == LegoObject_Building) { pPVar3 = gfx::Building_GetShapePoints (globs::legoGlobs.buildingData + translation->id,&local_964); lVar9 = __ftol((float10)translation->heading * (float10)0.1591549 * (float10)8.0); rotation = ((uint)lVar9 & 1) + (uint)lVar9 >> 1; pPVar3 = gfx::SelectPlace_TransformShapePoints (&translation->blockPos,pPVar3,local_964,rotation); pLVar4 = Construction_SpawnBuilding (translation->id,&translation->blockPos,rotation,pPVar3,local_964,0); uVar8 = local_968; } else { pLVar4 = LegoObject_Create((int **)translation->model,translation->type,translation->id); } if (pLVar4 != NULL) { if (translation->type != LegoObject_Building) { LegoObject_SetPositionAndHeading (pLVar4,(translation->worldPos).x,(translation->worldPos).y, translation->heading,1); } objType = translation->type; if ((((objType == LegoObject_PowerCrystal) || (objType == LegoObject_Ore)) || (objType == LegoObject_Dynamite)) || (objType == LegoObject_Barrier)) { ai::AITask_DoCollect(pLVar4,0.0); } pLVar4->health = translation->health; if (pLVar4->type == LegoObject_MiniFigure) { nerps::NERPsRuntime_IncHiddenObjectsFound(LegoObject_MiniFigure); front::Info_Send(Info_FoundMinifigure,NULL,pLVar4,NULL); } pLVar4->flags4 = pLVar4->flags4 | LIVEOBJ4_DONTSHOWHELPWINDOW; LegoObject_FUN_00438720(pLVar4); if (pLVar4->type == LegoObject_ElectricFence) { ElectricFence_CreateFence(pLVar4); } pcVar1 = translation->olistID; pcVar2 = translation->olistDrivingID; apLStack2400[uVar8] = pLVar4; apcStack800[uVar8] = pcVar1; *local_96c = pcVar2; local_968 = uVar8 + 1; local_96c = local_96c + 1; translation->olistID = NULL; } i -= 1; pHVar6 = translation + -1; piVar7 = (int *)((int)globs::objectGlobs.rechargeSeamBlocks + globs::objectGlobs.hiddenObjectCount * 0x2c + 0x2c); globs::objectGlobs.hiddenObjectCount = globs::objectGlobs.hiddenObjectCount - 1; for (iVar5 = 0xb; uVar8 = local_968, iVar5 != 0; iVar5 += -1) { (translation->blockPos).x = *piVar7; piVar7 = piVar7 + 1; translation = (HiddenObject *)&translation->blockPos; } } i += 1; translation = pHVar6 + 1; } while (i < globs::objectGlobs.hiddenObjectCount); } local_96c = NULL; if (uVar8 != 0) { do { pcVar1 = local_640[(int)local_96c]; if (pcVar1 != NULL) { i = 0; do { if ((local_96c != (char **)i) && (iVar5 = std::_stricmp(apcStack800[i],pcVar1), iVar5 == 0)) { pLVar4 = apLStack2400[(int)local_96c]; liveObj = apLStack2400[i]; pLVar4->routeToObject = liveObj; pLVar4->flags2 = pLVar4->flags2 | LIVEOBJ2_UNK_4; sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if ((sflags3 & STATS3_NEEDSPILOT) == STATS3_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CROSSWATER) == STATS1_NONE) { trainFlags = ABILITY_FLAG_DRIVER; } else { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) { trainFlags = ABILITY_FLAG_SAILOR; } else { trainFlags = ABILITY_FLAG_PILOT; } } } else { trainFlags = ABILITY_FLAG_PILOT; } LegoObject_TrainMiniFigure_instantunk(pLVar4,trainFlags); LegoObject_ClearDockOccupiedFlag(pLVar4,liveObj); uVar8 = local_968; } i += 1; } while (i < uVar8); } local_96c = (char **)((int)local_96c + 1); } while (local_96c < uVar8); } i = 0; if (uVar8 != 0) { do { if (local_640[i] != NULL) { io::Mem_Free(local_640[i]); } if (apcStack800[i] != NULL) { io::Mem_Free(apcStack800[i]); } i += 1; } while (i < uVar8); } return; } void __cdecl lego::game::HiddenObject_Add (void *objModel,LegoObject_Type objType,LegoObject_ID objID,Point2F *worldPos, float heading,float health,char *thisOLName,char *drivingOLName) { char *str; Map3D *map; HiddenObject *out_bx; int *out_by; HiddenObject *hidden; uint index; float xPos; float yPos; index = globs::objectGlobs.hiddenObjectCount; out_bx = globs::objectGlobs.hiddenObjects + globs::objectGlobs.hiddenObjectCount; hidden = globs::objectGlobs.hiddenObjects + globs::objectGlobs.hiddenObjectCount; globs::objectGlobs.hiddenObjectCount = globs::objectGlobs.hiddenObjectCount + 1; (hidden->worldPos).x = worldPos->x; yPos = worldPos->y; globs::objectGlobs.hiddenObjects[index].model = objModel; globs::objectGlobs.hiddenObjects[index].worldPos.y = yPos; globs::objectGlobs.hiddenObjects[index].health = health; globs::objectGlobs.hiddenObjects[index].heading = heading; globs::objectGlobs.hiddenObjects[index].type = objType; globs::objectGlobs.hiddenObjects[index].id = objID; if (thisOLName != NULL) { str = util::Util_StrCpy(thisOLName); globs::objectGlobs.hiddenObjects[index].olistID = str; } if (drivingOLName != NULL) { str = util::Util_StrCpy(drivingOLName); globs::objectGlobs.hiddenObjects[index].olistDrivingID = str; } yPos = worldPos->y; xPos = worldPos->x; out_by = &globs::objectGlobs.hiddenObjects[index].blockPos.y; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,xPos,yPos,(int *)out_bx,out_by); return; } BOOL __cdecl lego::game::LegoObject_CanShootObject(LegoObject *liveObj) { StatsFlags2 sflags2; float10 fVar1; sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_CANBESHOTAT) != STATS2_NONE) { fVar1 = stats::StatsObject_GetPainThreshold(liveObj); if (fVar1 < (float10)liveObj->health) { return TRUE; } } return FALSE; } LegoObject * __cdecl lego::game::LegoObject_Create(int **objModel,LegoObject_Type objType,LegoObject_ID objID) { LegoObject *liveObj; BOOL BVar1; VehicleModel *vehicleModel; uint carryNullFrames; StatsFlags1 sflags1; CreatureModel *creatureModel; BuildingModel *buildingModel; Upgrade_PartModel *upgradePartModel; Container *cont; LiveFlags3 lflags3; BOOL BVar2; StatsFlags2 sflags2; LegoObject_Type objType_; liveObj = LegoObject_Create_internal(); if (liveObj == NULL) { return NULL; } liveObj->type = objType; liveObj->id = objID; liveObj->flags3 = LIVEOBJ3_NONE; // 100.0f liveObj->health = (float)&DAT_42c80000; liveObj->energy = (float)&DAT_42c80000; gfx::Container_EnableSoundTriggers(0); BVar1 = snd::SFX_IsSoundOn(); snd::SFX_SetSoundOn(0,0); objType_ = liveObj->type; if (objType_ == LegoObject_Vehicle) { vehicleModel = (VehicleModel *)io::Mem_Alloc(0x1ec); liveObj->vehicle = vehicleModel; gfx::Vehicle_Clone((VehicleModel *)objModel,vehicleModel); gfx::Vehicle_SetOwnerObject(liveObj->vehicle,liveObj); carryNullFrames = gfx::Vehicle_GetCarryNullFrames(liveObj->vehicle); liveObj->carryNullFrames = carryNullFrames; gfx::Vehicle_SetUpgradeLevel(liveObj->vehicle,0); liveObj->abilityFlags = ABILITY_FLAG_SCANNER; liveObj->flags3 = liveObj->flags3 | (LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_CANDAMAGE|LIVEOBJ3_AITASK_UNK_400000); stats::StatsObject_SetObjectLevel(liveObj,0); // if (objModel->drillNullName != NULL) if (objModel[0x2d] != NULL) { liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_CANDIG; } // if (objModel->carryNullName != NULL) if (objModel[0x37] != NULL) { liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_CANCARRY; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CROSSLAND) != STATS1_NONE) { liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_CANPICKUP; } } goto LAB_00438452; } if (objType_ == LegoObject_MiniFigure) { creatureModel = (CreatureModel *)io::Mem_Alloc(0x74); liveObj->miniFigure = creatureModel; gfx::Creature_Clone((CreatureModel *)objModel,creatureModel); gfx::Object_SetOwnerObject((BasicObjectModel *)liveObj->miniFigure,liveObj); // Creature_GetCarryNullFrames(liveObj->miniFigure); carryNullFrames = nerps::funcs::NERPFunc__True((int *)liveObj->miniFigure); lflags3 = liveObj->flags3; liveObj->carryNullFrames = carryNullFrames; liveObj->flags3 = lflags3 | (LIVEOBJ3_UNK_1|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY| LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT|LIVEOBJ3_CANDAMAGE| LIVEOBJ3_AITASK_UNK_400000); // if (objModel->drillNullName != NULL) if (objModel[0xb] != NULL) { liveObj->flags3 = lflags3 | (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANFIRSTPERSON| LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT| LIVEOBJ3_CANDAMAGE|LIVEOBJ3_AITASK_UNK_400000); } stats::StatsObject_SetObjectLevel(liveObj,0); liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_CANDYNAMITE; LegoObject_MiniFigure_EquipTool(liveObj,LegoObject_ToolType_Drill); goto LAB_00438452; } if (objType_ == LegoObject_RockMonster) { creatureModel = (CreatureModel *)io::Mem_Alloc(0x74); liveObj->rockMonster = creatureModel; gfx::Creature_Clone((CreatureModel *)objModel,creatureModel); gfx::Object_SetOwnerObject((BasicObjectModel *)liveObj->rockMonster,liveObj); // Creature_GetCarryNullFrames(liveObj->rockMonster) carryNullFrames = nerps::funcs::NERPFunc__True((int *)liveObj->rockMonster); lflags3 = liveObj->flags3; liveObj->carryNullFrames = carryNullFrames; liveObj->flags3 = lflags3 | (LIVEOBJ3_UNK_200|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_MONSTER_UNK_8000000); // if (objModel->drillNullName != NULL) if (objModel[0xb] != NULL) { liveObj->flags3 = lflags3 | (LIVEOBJ3_CANDIG|LIVEOBJ3_UNK_200|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_AITASK_UNK_400000 |LIVEOBJ3_MONSTER_UNK_8000000); } stats::StatsObject_SetObjectLevel(liveObj,0); sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_FLOCKS) == STATS1_NONE) { liveObj->flocks = NULL; } else { LegoObject_Flocks_Initialise(liveObj); sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_FLOCKS_DEBUG) == STATS1_NONE) { LegoObject_Hide(liveObj,TRUE); liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); } } BVar2 = LegoObject_CanShootObject(liveObj); if (BVar2 != 0) { ai::AITask_DoAttackRockMonster_Target(liveObj); } liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_POWEROFF; goto LAB_00438452; } if (objType_ == LegoObject_Building) { buildingModel = (BuildingModel *)io::Mem_Alloc(0x14c); liveObj->building = buildingModel; gfx::Building_Clone((BuildingModel *)objModel,buildingModel); gfx::Object_SetOwnerObject((BasicObjectModel *)liveObj->building,liveObj); carryNullFrames = gfx::Building_GetCarryNullFrames(liveObj->building); liveObj->carryNullFrames = carryNullFrames; liveObj->flags3 = liveObj->flags3 | (LIVEOBJ3_CANSELECT|LIVEOBJ3_CANDAMAGE); gfx::Building_SetUpgradeLevel(liveObj->building,0); stats::StatsObject_SetObjectLevel(liveObj,0); sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_SMALLTELEPORTER) != STATS1_NONE) { globs::legoGlobs.placeDestSmallTeleporter = liveObj; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_BIGTELEPORTER) != STATS1_NONE) { globs::legoGlobs.placeDestBigTeleporter = liveObj; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_WATERTELEPORTER) != STATS1_NONE) { globs::legoGlobs.placeDestWaterTeleporter = liveObj; } stats::StatsObject_GetStatsFlags1(liveObj); sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_SNAXULIKE) != STATS1_NONE) { ai::AITask_DoGotoEat(liveObj); } ai::AITask_DoRepair(liveObj); liveObj->abilityFlags = ABILITY_FLAG_SCANNER; LegoObject_RequestPowerGridUpdate(); goto LAB_00438452; } if (objType_ == LegoObject_UpgradePart) { upgradePartModel = (Upgrade_PartModel *)io::Mem_Alloc(0x10); liveObj->upgradePart = upgradePartModel; gfx::Upgrade_Part_Clone((Upgrade_PartModel *)objModel,upgradePartModel); liveObj->stats = &globs::constant::c_ObjectStats_Upgrade; liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_UPGRADEPART; goto LAB_00438452; } cont = gfx::Container_Clone((Container *)objModel); liveObj->other = cont; gfx::Container_SetUserData(cont,liveObj); lflags3 = liveObj->flags3; objType_ = liveObj->type; liveObj->flags3 = lflags3 | LIVEOBJ3_SIMPLEOBJECT; if (objType_ == LegoObject_ElectricFence) { liveObj->flags3 = lflags3 | (LIVEOBJ3_CANSELECT|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE); } if ((objType_ == LegoObject_Ore) || (objType_ == LegoObject_PowerCrystal)) { lflags3 = liveObj->flags3 | (LIVEOBJ3_CANSELECT|LIVEOBJ3_ALLOWCULLING_UNK); LAB_004383f9: liveObj->flags3 = lflags3; } else { if ((objType_ == LegoObject_Dynamite) || (objType_ == LegoObject_OohScary)) { lflags3 = liveObj->flags3 | LIVEOBJ3_CANDAMAGE; goto LAB_004383f9; } } LegoObject_SetCrystalPoweredColour(liveObj,TRUE); if (true) { switch(liveObj->type) { case LegoObject_Dynamite: liveObj->stats = &globs::constant::c_ObjectStats_Dynamite; break; case LegoObject_Barrier: liveObj->stats = &globs::constant::c_ObjectStats_Barrier; break; default: goto switchD_0043841c_caseD_a; case LegoObject_SpiderWeb: case LegoObject_OohScary: case LegoObject_ElectricFenceStud: case LegoObject_Pusher: case LegoObject_Freezer: case LegoObject_IceCube: case LegoObject_LaserShot: liveObj->stats = &globs::constant::c_ObjectStats_Other; } } else { switchD_0043841c_caseD_a: stats::StatsObject_SetObjectLevel(liveObj,0); } LAB_00438452: liveObj->activityName2 = globs::objectGlobs.activityName[0]; liveObj->activityName1 = globs::objectGlobs.activityName[9]; BVar2 = LegoObject_UpdateActivityChange(liveObj); if (BVar2 != 0) { liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_CANTURN; } liveObj->activityName1 = globs::objectGlobs.activityName[16]; BVar2 = LegoObject_UpdateActivityChange(liveObj); if (BVar2 != 0) { liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_CANGATHER; } liveObj->activityName1 = globs::objectGlobs.activityName[2]; BVar2 = LegoObject_UpdateActivityChange(liveObj); if (BVar2 != 0) { liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_CANROUTERUBBLE; } liveObj->activityName1 = globs::objectGlobs.activityName[0]; LegoObject_UpdateActivityChange(liveObj); ai::AITask_LiveObject_Unk_UpdateAITask_AnimationWait(liveObj); gfx::Container_EnableSoundTriggers(TRUE); if (BVar1 != 0) { snd::SFX_SetSoundOn(TRUE,FALSE); } LegoObject_UpdatePowerConsumption(liveObj); globs::objectGlobs.objectTotalLevels[liveObj->type][liveObj->id][0] = globs::objectGlobs.objectTotalLevels[liveObj->type][liveObj->id][0] + 1; sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_UNSELECTABLE) != STATS2_NONE) { liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000| LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); } return liveObj; } LegoObject * __cdecl lego::game::LegoObject_Create_internal(void) { int iVar1; LegoObject *pLVar2; LegoObject *liveObj; if (globs::objectGlobs.freeList == NULL) { LegoObject_AddList(); } liveObj = globs::objectGlobs.freeList; pLVar2 = globs::objectGlobs.freeList; globs::objectGlobs.freeList = (globs::objectGlobs.freeList)->nextFree; for (iVar1 = 0x103; iVar1 != 0; iVar1 += -1) { pLVar2->type = LegoObject_None; pLVar2 = (LegoObject *)&pLVar2->id; } liveObj->nextFree = liveObj; (liveObj->targetBlockPos).y = -1.0; (liveObj->targetBlockPos).x = -1.0; return liveObj; } void __cdecl lego::game::LegoObject_AddList(void) { LegoObject *pLVar1; LegoObject *pLVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::objectGlobs.listCount & 0x1f); pLVar2 = (LegoObject *)io::Mem_Alloc(uVar4 * 0x40c); globs::objectGlobs.listSet[globs::objectGlobs.listCount] = pLVar2; pLVar2 = globs::objectGlobs.listSet[globs::objectGlobs.listCount]; if (pLVar2 != NULL) { globs::objectGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pLVar1 = pLVar2; do { pLVar1->nextFree = pLVar1 + 1; iVar3 += -1; pLVar1 = pLVar1 + 1; } while (iVar3 != 0); } pLVar2[uVar4 - 1].nextFree = globs::objectGlobs.freeList; globs::objectGlobs.freeList = pLVar2; } return; } int __cdecl lego::game::LegoObject_GetNumBuildingsTeleported(int *stack) { return globs::objectGlobs.BuildingsTeleported; } void __cdecl lego::game::LegoObject_SetNumBuildingsTeleported(uint numTeleported) { globs::objectGlobs.BuildingsTeleported = numTeleported; return; } void __cdecl lego::game::LegoObject_SetCrystalPoweredColour(LegoObject *liveObj,BOOL powered) { uint uVar1; D3DRMGroupIndex DVar2; float b; D3DRMGroupIndex groupID; float local_4; if (liveObj->type == LegoObject_PowerCrystal) { if (powered == 0) { powered = (BOOL)globs::legoGlobs.UnpoweredCrystalRGB.red; local_4 = globs::legoGlobs.UnpoweredCrystalRGB.green; b = globs::legoGlobs.UnpoweredCrystalRGB.blue; } else { powered = (BOOL)globs::legoGlobs.PowerCrystalRGB.red; local_4 = globs::legoGlobs.PowerCrystalRGB.green; b = globs::legoGlobs.PowerCrystalRGB.blue; } groupID = D3DRMGROUP_0; uVar1 = gfx::Container_Mesh_GetGroupCount(liveObj->other); if (uVar1 != 0) { do { gfx::Container_Mesh_SetColourAlpha(liveObj->other,groupID,(float)powered,local_4,b,1.0); gfx::Container_Mesh_SetEmissive(liveObj->other,groupID,(float)powered,local_4,b); groupID += 1; DVar2 = gfx::Container_Mesh_GetGroupCount(liveObj->other); } while (groupID < DVar2); } } return; } void __cdecl lego::game::LegoObject_FUN_00438720(LegoObject *liveObj) { StatsFlags1 sflags1; if (liveObj->type == LegoObject_Building) { LegoObject_UpdateActivityChange(liveObj); liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_CANCARRY; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_STOREOBJECTS) == STATS1_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_PROCESSORE) == STATS1_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_PROCESSCRYSTAL) == STATS1_NONE) { // liveObj->flags3 &= ~LIVEOBJ3_CANCARRY; liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT| LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); } else { ai::AITask_DoDeposit_ObjectType(liveObj,LegoObject_PowerCrystal,0,0); } } else { ai::AITask_DoDeposit_ObjectType(liveObj,LegoObject_Ore,0,0); } } else { ai::AITask_LiveObject_FUN_004038d0(liveObj); } LegoObject_RequestPowerGridUpdate(); liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_UNK_200000; } else { if (liveObj->type == LegoObject_Vehicle) { gfx::Vehicle_HideWheels(liveObj->vehicle,FALSE); } } if ((liveObj->type == LegoObject_MiniFigure) || (liveObj->type == LegoObject_Vehicle)) { LegoObject_RemoveTeleportDownReference(liveObj); } front::HelpWindow_RecallDependencies (liveObj->type,liveObj->id,0,liveObj->flags4 & LIVEOBJ4_DONTSHOWHELPWINDOW); if (liveObj->type == LegoObject_Building) { globs::objectGlobs.BuildingsTeleported += 1; } if ((liveObj->type == LegoObject_MiniFigure) || (liveObj->type == LegoObject_Vehicle)) { ai::AITask_DoAttackObject(liveObj); } if ((liveObj->type == LegoObject_Vehicle) || (liveObj->type == LegoObject_Building)) { liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_UNK_40000; } return; } void __cdecl lego::game::LegoObject_SetPowerOn(LegoObject *liveObj,BOOL on) { LiveFlags3 lflags3; if (on == 0) { lflags3 = liveObj->flags3 | LIVEOBJ3_POWEROFF; } else { lflags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000); } liveObj->flags3 = lflags3; LegoObject_RequestPowerGridUpdate(); return; } // This seems to be a catch-all type function to see if an object is "active". // // For buildings, it must be receiving power, and NOT be powered-off. // Aside from that, there are many other checks based on various flags states, and also health. // // When ignoreUnpowered is true, powered state will not be checked. // // Old name: LegoObject_CheckCondition_AndIsPowered BOOL __cdecl lego::game::LegoObject_IsActive(LegoObject *liveObj,BOOL ignoreUnpowered) { if ((((((liveObj->flags1 & (LIVEOBJ1_EXPANDING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE) && ((liveObj->flags2 & LIVEOBJ2_UNK_100000) == LIVEOBJ2_NONE)) && (0.0 <= liveObj->health)) && ((liveObj->flags1 & LIVEOBJ1_ENTERING_WALLHOLE) == LIVEOBJ1_NONE)) && ((ignoreUnpowered != 0 || (((liveObj->flags3 & LIVEOBJ3_HASPOWER) != LIVEOBJ3_NONE && ((liveObj->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE)))))) { return TRUE; } return FALSE; } LegoObject * __cdecl lego::game::LegoObject_CreateInWorld (void *objModel,LegoObject_Type objType,LegoObject_ID objID,uint objLevel,float xPos, float yPos,float heading) { LegoObject *liveObj; liveObj = LegoObject_Create((int **)objModel,objType,objID); if (liveObj != NULL) { LegoObject_SetPositionAndHeading(liveObj,xPos,yPos,heading,TRUE); if ((liveObj->type == LegoObject_PowerCrystal) || (liveObj->type == LegoObject_Ore)) { LegoObject_SetLevel(liveObj,objLevel); } return liveObj; } return NULL; } LegoObject * __cdecl lego::game::LegoObject_FindPoweredBuildingAtBlockPos(Point2I *blockPos) { SearchObjectBlockXY_c search; search.resultObj = NULL; search.bx = blockPos->x; search.by = blockPos->y; LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_FindPoweredBuildingAtBlockPos,&search); return search.resultObj; } BOOL __cdecl lego::game::LegoObject_Callback_FindPoweredBuildingAtBlockPos (LegoObject *liveObj,SearchObjectBlockXY_c *search) { StatsFlags2 sflags2; BOOL BVar1; int bx; int by; if (liveObj->type == LegoObject_Building) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_GENERATEPOWER) != STATS2_NONE) { BVar1 = LegoObject_IsActive(liveObj,FALSE); if (BVar1 != 0) { LegoObject_GetBlockPos(liveObj,&bx,&by); if ((bx == search->bx) && (by == search->by)) { search->resultObj = liveObj; return TRUE; } } } } return FALSE; } BOOL __cdecl lego::game::LegoObject_AddThisDrainedCrystals(LegoObject *liveObj,int crystalCount) { int count; if ((globs::legoGlobs.currLevel)->NoDrain != 0) { crystalCount = 0; } count = Level_GetCrystalCount(FALSE); if (count < crystalCount) { front::Info_Send(Info_NoPower,NULL,liveObj,NULL); return 0; } Level_AddCrystalsDrained(crystalCount); return TRUE; } BOOL __cdecl lego::game::LegoObject_GetBuildingUpgradeCost(LegoObject *liveObj,uint *optout_oreCost) { uint uVar1; uVar1 = stats::Stats_GetLevels(liveObj->type,liveObj->id); if (uVar1 <= liveObj->objLevel + 1) { return 0; } uVar1 = Level_GetOreCount(FALSE); if (uVar1 < (uint)globs::legoGlobs.BuildingUpgradeCostOre) { uVar1 = Level_GetOreCount(TRUE); if (uVar1 < (uint)globs::legoGlobs.BuildingUpgradeCostStuds) { return 0; } if (optout_oreCost != NULL) { *optout_oreCost = globs::legoGlobs.BuildingUpgradeCostStuds; } } else { if (optout_oreCost != NULL) { *optout_oreCost = 0; return TRUE; } } return TRUE; } void __cdecl lego::game::LegoObject_UpgradeBuilding(LegoObject *liveObj) { BOOL BVar1; Container *cont; LegoObject *oreAmount; Container *opt_ref; Vector3F *out_pos; Vector3F spawnEffectPos; LegoObject *liveObj_; liveObj_ = liveObj; if (liveObj->type == LegoObject_Building) { BVar1 = LegoObject_GetBuildingUpgradeCost(liveObj,(uint *)&liveObj); if (BVar1 != 0) { oreAmount = liveObj; if (liveObj == NULL) { oreAmount = (LegoObject *)globs::legoGlobs.BuildingUpgradeCostOre; } Level_SubtractOreStored((uint)(liveObj != NULL),(int)oreAmount); liveObj_->elapsedTime2 = 0.0; gfx::Building_SetUpgradeLevel(liveObj_->building,liveObj_->objLevel + 1); stats::StatsObject_SetObjectLevel(liveObj_,liveObj_->objLevel + 1); out_pos = &spawnEffectPos; opt_ref = NULL; cont = LegoObject_GetActivityContainer(liveObj_); gfx::Container_GetPosition(cont,opt_ref,out_pos); effect::Effect_Spawn_Particle(MISCOBJECT_UPGRADEEFFECT,&spawnEffectPos,NULL); front::HelpWindow_RecallDependencies(liveObj_->type,liveObj_->id,liveObj_->objLevel,FALSE); } } return; } BOOL __cdecl lego::game::LegoObject_HasEnoughOreToUpgrade(LegoObject *liveObj,int objLevel) { BOOL BVar1; uint uVar2; uint uVar3; uint uVar4; uint uVar5; if ((liveObj->type != LegoObject_Vehicle) || (BVar1 = gfx::Vehicle_CanUpgradeType(liveObj->vehicle,objLevel,TRUE), BVar1 == 0)) { return 0; } uVar2 = stats::Stats_GetUpgradeCostOre(liveObj->type,liveObj->id,objLevel); uVar3 = stats::Stats_GetUpgradeCostOre(liveObj->type,liveObj->id,objLevel); uVar4 = stats::Stats_GetUpgradeCostOre(liveObj->type,liveObj->id,objLevel); uVar5 = Level_GetOreCount(FALSE); if ((uVar5 < uVar4) && (uVar4 = Level_GetOreCount(TRUE), uVar4 < (uint)(uVar2 % 5 != 0) + uVar3 / 5)) { return 0; } return TRUE; } undefined4 __cdecl lego::game::LegoObject_Search_FUN_00438c20(LegoObject *opt_liveObj,BOOL param_2) { undefined4 local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = 0; local_20 = 0.0; local_1c = 0.0; local_18 = 0x461c4000; local_14 = 0x2000; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; if (param_2 != 0) { local_14 = 0x6000; } if (opt_liveObj != NULL) { LegoObject_GetPosition(opt_liveObj,&local_20,&local_1c); } LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } undefined4 __cdecl lego::game::LegoObject_Search_FUN_00438ca0(LegoObject *liveObj,BOOL param_2) { undefined4 local_24; float local_20; float local_1c; undefined4 local_18; uint local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = 0; local_20 = 0.0; local_1c = 0.0; local_18 = 0x461c4000; local_14 = 0x1000; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; LegoObject_GetPosition(liveObj,&local_20,&local_1c); if (param_2 != 0) { local_14 |= 0x400; } LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } LegoObject * __cdecl lego::game::LegoObject_FUN_00438d20 (Point2I *blockPos,LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { Map3D *map; uint bx; uint by; float *out_x; float *out_y; LegoObject *local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; LegoObject_Type local_10; LegoObject_ID local_c; uint local_8; undefined4 local_4; local_c = objID; local_24 = NULL; local_20 = 0.0; local_1c = 0.0; local_4 = 0; out_y = &local_1c; out_x = &local_20; local_10 = objType; local_8 = objLevel; local_18 = 0x461c4000; local_14 = 1; by = blockPos->y; bx = blockPos->x; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,by,out_x,out_y); LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } LegoObject * __cdecl lego::game::LegoObject_FindResourceProcessingBuilding (LegoObject *liveObj,Point2I *blockPos,LegoObject_Type objType,uint objLevel) { Map3D *map; uint bx; uint by; float *out_x; float *out_y; LegoObject *local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; LegoObject_Type local_10; undefined4 local_c; uint local_8; undefined4 local_4; local_10 = objType; local_18 = 0x461c4000; local_24 = NULL; local_20 = 0.0; local_1c = 0.0; // Flag 0x2 checks for buildings that can have the stat: processe ore/crystals. local_14 = 2; local_c = 0; local_8 = objLevel; local_4 = 0; if (liveObj == NULL) { out_y = &local_1c; out_x = &local_20; by = blockPos->y; bx = blockPos->x; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,by,out_x,out_y); } else { LegoObject_GetPosition(liveObj,&local_20,&local_1c); } LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } undefined4 __cdecl lego::game::LegoObject_Search_FUN_00438e40(LegoObject *liveObj,undefined4 param_2) { undefined4 local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = 0; local_20 = 0.0; local_1c = 0.0; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; local_14 = param_2; local_18 = 0x461c4000; LegoObject_GetPosition(liveObj,&local_20,&local_1c); LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } undefined4 __cdecl lego::game::LegoObject_Search_FUN_00438eb0(LegoObject *liveObj) { undefined4 local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = 0; local_20 = 0.0; local_1c = 0.0; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; local_18 = 0x461c4000; local_14 = 0x80; LegoObject_GetPosition(liveObj,&local_20,&local_1c); LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } LegoObject * __cdecl lego::game::LegoObject_FindSnackServingBuilding(LegoObject *liveObj) { LegoObject *local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = NULL; local_20 = 0.0; local_1c = 0.0; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; local_18 = 1176256512; local_14 = LegoObject_Building; LegoObject_GetPosition(liveObj,&local_20,&local_1c); LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } LegoObject * __cdecl lego::game::LegoObject_FindBigTeleporter(Point2F *worldPos) { LegoObject *local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = NULL; local_18 = 0x461c4000; local_20 = worldPos->x; local_1c = worldPos->y; local_14 = 0x20; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } LegoObject * __cdecl lego::game::LegoObject_FindSmallTeleporter(Point2F *worldPos) { LegoObject *local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = NULL; local_18 = 0x461c4000; local_20 = worldPos->x; local_1c = worldPos->y; local_14 = 0x10; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } LegoObject * __cdecl lego::game::LegoObject_FindWaterTeleporter(Point2F *worldPos) { LegoObject *local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = NULL; local_18 = 0x461c4000; local_20 = worldPos->x; local_1c = worldPos->y; local_14 = 0x200; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } LegoObject * __cdecl lego::game::Level_GetBuildingAtPosition(Point2F *worldPos) { LegoObject *local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_24 = NULL; local_18 = 0x461c4000; local_20 = worldPos->x; local_1c = worldPos->y; local_14 = 8; local_10 = 0; local_c = 0; local_8 = 0; local_4 = 0; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } undefined4 __cdecl lego::game::LegoObject_Search_FUN_00439110 (LegoObject *liveObj,Point2F *opt_worldPos,LegoObject_AbilityFlags trainedType) { undefined4 local_24; float local_20; float local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; LegoObject_AbilityFlags local_4; local_4 = trainedType; local_24 = 0; local_20 = 0.0; local_1c = 0.0; local_18 = 0x461c4000; local_14 = 0x100; local_10 = 0; local_c = 0; local_8 = 0; if (opt_worldPos != NULL) { local_20 = opt_worldPos->x; local_1c = opt_worldPos->y; } if (liveObj != NULL) { LegoObject_GetPosition(liveObj,&local_20,&local_1c); } LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackSearch_FUN_00439270,&local_24); return local_24; } BOOL __cdecl lego::game::LegoObject_HasTraining(LegoObject *liveObj,LegoObject_AbilityFlags training) { StatsFlags2 sflags2; sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if (((sflags2 & STATS2_TRAINPILOT) == STATS2_NONE) || (training != ABILITY_FLAG_PILOT)) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if (((sflags2 & STATS2_TRAINSAILOR) == STATS2_NONE) || (training != ABILITY_FLAG_SAILOR)) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if (((sflags2 & STATS2_TRAINDRIVER) == STATS2_NONE) || (training != ABILITY_FLAG_DRIVER)) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if (((sflags2 & STATS2_TRAINDYNAMITE) == STATS2_NONE) || (training != ABILITY_FLAG_DYNAMITE) ) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if (((sflags2 & STATS2_TRAINREPAIR) == STATS2_NONE) || (training != ABILITY_FLAG_REPAIR)) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if (((sflags2 & STATS2_TRAINSCANNER) == STATS2_NONE) || (training != ABILITY_FLAG_SCANNER)) { return 0; } } } } } } return 1; } BOOL __cdecl lego::game::LegoObject_IsDocksBuilding_Unk(LegoObject *liveObj) { BOOL BVar1; LegoObject_Type objType; LegoObject_ID objID; BVar1 = lrr::Lego_GetObjectByName("Docks",&objType,&objID,NULL); if (((BVar1 != 0) && (liveObj->type == objType)) && (liveObj->id == objID)) { return 1; } return 0; } BOOL __cdecl lego::game::LegoObject_CallbackSearch_FUN_00439270(LegoObject *liveObj,int **search) { int *piVar1; bool bVar2; BOOL BVar3; StatsFlags2 sflags2; StatsFlags1 sflags1; float local_8; float local_4; piVar1 = search[4]; bVar2 = false; BVar3 = LegoObject_IsActive(liveObj,(uint)piVar1 & 0x400); if (BVar3 == 0) { return 0; } if ((((uint)piVar1 & 0x4000) != 0) && ((*(byte *)&liveObj->flags4 & 0x10) != 0)) { return 0; } if (((uint)piVar1 & 0xfffffbff) == 0) { if (liveObj->type != LegoObject_Building) goto LAB_00439459; } else { if (((((uint)piVar1 & 1) != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_STOREOBJECTS) != STATS1_NONE)) && (BVar3 = LegoObject_CanSpawnCarryableObject (liveObj,(LegoObject_Type)search[5],(LegoObject_ID)search[6]), BVar3 != 0) ) { bVar2 = true; } if ((((uint)piVar1 & 0x1000) != 0) && (BVar3 = LegoObject_IsDocksBuilding_Unk(liveObj), BVar3 != 0)) { bVar2 = true; } if (((((uint)piVar1 & 0x2000) != 0) && (sflags2 = stats::StatsObject_GetStatsFlags2(liveObj), (sflags2 & STATS2_SELFPOWERED) == STATS2_NONE)) && ((sflags2 = stats::StatsObject_GetStatsFlags2(liveObj), (sflags2 & STATS2_GENERATEPOWER) == STATS2_NONE && (BVar3 = LegoObject_IsActive(liveObj,FALSE), BVar3 != 0)))) { bVar2 = true; } if ((((uint)piVar1 & 0x100) != 0) && (BVar3 = LegoObject_HasTraining(liveObj,(LegoObject_AbilityFlags)search[8]), BVar3 != 0)) { bVar2 = true; } if (((((uint)piVar1 & 0x40) != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_STOREOBJECTS) == STATS1_NONE)) && (liveObj->type == LegoObject_Building)) { bVar2 = true; } if (((((uint)piVar1 & 0x80) != 0) && (sflags2 = stats::StatsObject_GetStatsFlags2(liveObj), (sflags2 & STATS2_UPGRADEBUILDING) != STATS2_NONE)) && (liveObj->interactObject == NULL)) { bVar2 = true; } if ((((uint)piVar1 & 0x800) != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_MANTELEPORTER) != STATS1_NONE)) { bVar2 = true; } if ((((uint)piVar1 & 0x10) != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_SMALLTELEPORTER) != STATS1_NONE)) { bVar2 = true; } if ((((uint)piVar1 & 0x20) != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_BIGTELEPORTER) != STATS1_NONE)) { bVar2 = true; } if ((((uint)piVar1 & 0x200) != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_WATERTELEPORTER) != STATS1_NONE)) { bVar2 = true; } if ((((uint)piVar1 & 2) != 0) && (((sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_PROCESSORE) != STATS1_NONE && (search[5] == (int *)&DAT_00000007)) || ((sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_PROCESSCRYSTAL) != STATS1_NONE && (search[5] == (int *)0x6)))))) { bVar2 = true; } if ((((uint)piVar1 & 4) != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_SNAXULIKE) != STATS1_NONE)) { bVar2 = true; } if ((((uint)piVar1 & 8) == 0) || (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_TOOLSTORE) == STATS1_NONE)) goto LAB_00439459; } bVar2 = true; LAB_00439459: if (bVar2) { LegoObject_GetPosition(liveObj,&local_8,&local_4); piVar1 = (int *)SQRT(((float)search[2] - local_4) * ((float)search[2] - local_4) + ((float)search[1] - local_8) * ((float)search[1] - local_8)); if ((float)piVar1 < (float)search[3]) { search[3] = piVar1; *search = (int *)liveObj; return 0; } } return 0; } BOOL __cdecl lego::game::LegoObject_CanStoredObjectTypeBeSpawned(LegoObject_Type objType) { BOOL BVar1; if (((objType != LegoObject_Vehicle) && (objType != LegoObject_MiniFigure)) && (objType != LegoObject_Building)) { BVar1 = LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_CanSpawnStoredObjects,&objType); if (BVar1 != 0) { return TRUE; } } return FALSE; } BOOL __cdecl lego::game::LegoObject_Callback_CanSpawnStoredObjects(LegoObject *liveObj1,LegoObject *spawnObj) { StatsFlags1 sflags1; BOOL BVar1; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj1); if ((sflags1 & STATS1_STOREOBJECTS) != STATS1_NONE) { BVar1 = LegoObject_CanSpawnCarryableObject(liveObj1,spawnObj->type,0); if (BVar1 != 0) { return TRUE; } } return 0; } void __cdecl lego::game::LegoObject_PTL_GenerateFromCryOre(Point2I *blockPos) { Point2I *blockPos_00; BOOL BVar1; uint pPVar2; uint i; uint local_c; uint local_8; uint local_4; blockPos_00 = blockPos; BVar1 = lrr::Lego_GetBlockCryOre(blockPos,(uint *)&blockPos,&local_c,&local_8,&local_4); if (BVar1 != 0) { pPVar2 = 0; if (blockPos != NULL) { do { Level_GenerateCrystal(blockPos_00,0,NULL,TRUE); pPVar2 = (int)(int *)pPVar2 + 1; } while (pPVar2 < blockPos); } i = 0; if (local_c != 0) { do { Level_GenerateCrystal(blockPos_00,1,NULL,TRUE); i += 1; } while (i < local_c); } i = 0; if (local_8 != 0) { do { Level_GenerateOre(blockPos_00,0,NULL,TRUE); i += 1; } while (i < local_8); } i = 0; if (local_4 != 0) { do { Level_GenerateOre(blockPos_00,1,NULL,TRUE); i += 1; } while (i < local_4); } } return; } void __cdecl lego::game::LegoObject_PTL_GenerateCrystalsAndOre(Point2I *blockPos,uint objLevel) { Level_GenerateCrystal(blockPos,objLevel,NULL,TRUE); Level_GenerateOre(blockPos,objLevel,NULL,TRUE); return; } void __cdecl lego::game::Level_GenerateCrystal (Point2I *blockPos,uint objLevel,Point2F *opt_worldPos,BOOL showInfoMessage) { Map3D *surfMap; float fVar1; LegoObject *argument1Obj; Lego_Level *pLVar2; int iVar3; float xPos; float10 fVar4; float10 fVar5; uint bx; uint by; Vector3F *out_vertPoses; Vector3F local_30 [2]; float local_18; float local_14; surfMap = lrr::Lego_GetMap(); fVar4 = lego::map::Map3D_BlockSize(surfMap); surfMap = lrr::Lego_GetMap(); fVar5 = lego::map::Map3D_BlockSize(surfMap); fVar1 = (float)((float10)(float)(fVar4 * (float10)0.5) - fVar5 * (float10)0.25); if (opt_worldPos == NULL) { by = blockPos->y; bx = blockPos->x; out_vertPoses = local_30; surfMap = lrr::Lego_GetMap(); lego::map::Map3D_GetBlockVertexPositions(surfMap,bx,by,out_vertPoses); fVar4 = math::Maths_RandRange(local_30[0].x + fVar1,local_18 - fVar1); xPos = (float)fVar4; fVar4 = math::Maths_RandRange(local_30[0].y - fVar1,local_14 + fVar1); fVar1 = (float)fVar4; } else { xPos = opt_worldPos->x; fVar1 = opt_worldPos->y; } argument1Obj = LegoObject_CreateInWorld (globs::legoGlobs.contCrystal,LegoObject_PowerCrystal,0,objLevel,xPos, fVar1,0.0); Message_PostEvent(Message_GenerateCrystalComplete,argument1Obj,0,NULL); if (showInfoMessage != 0) { front::Info_Send(Info_CrystalFound,NULL,NULL,blockPos); front::Text_DisplayMessage(Text_CrystalFound,TRUE,FALSE); pLVar2 = lrr::Lego_GetLevel(); iVar3 = pLVar2->width * blockPos->y + blockPos->x; pLVar2 = lrr::Lego_GetLevel(); pLVar2->blocks[iVar3].generateCrystals = pLVar2->blocks[iVar3].generateCrystals + 1; } return; } void __cdecl lego::game::Level_GenerateOre (Point2I *blockPos,uint objLevel,Point2F *opt_worldPos,BOOL showInfoMessage) { Map3D *map; float fVar1; LegoObject *argument1Obj; Lego_Level *level; int iVar2; float xPos; float10 fVar3; float10 fVar4; uint bx; uint by; Vector3F *out_vertPoses; Vector3F local_30 [2]; float local_18; float local_14; map = lrr::Lego_GetMap(); fVar3 = lego::map::Map3D_BlockSize(map); map = lrr::Lego_GetMap(); fVar4 = lego::map::Map3D_BlockSize(map); fVar1 = (float)((float10)(float)(fVar3 * (float10)0.5) - fVar4 * (float10)0.25); if (opt_worldPos == NULL) { by = blockPos->y; bx = blockPos->x; out_vertPoses = local_30; map = lrr::Lego_GetMap(); lego::map::Map3D_GetBlockVertexPositions(map,bx,by,out_vertPoses); fVar3 = math::Maths_RandRange(local_30[0].x + fVar1,local_18 - fVar1); xPos = (float)fVar3; fVar3 = math::Maths_RandRange(local_30[0].y - fVar1,local_14 + fVar1); fVar1 = (float)fVar3; } else { xPos = opt_worldPos->x; fVar1 = opt_worldPos->y; } argument1Obj = LegoObject_CreateInWorld (globs::legoGlobs.contOresTable[0],LegoObject_Ore,0,objLevel,xPos,fVar1, 0.0); Message_PostEvent(Message_GenerateOreComplete,argument1Obj,0,NULL); front::Text_DisplayMessage(Text_OreFound,TRUE,FALSE); if (showInfoMessage != 0) { level = lrr::Lego_GetLevel(); iVar2 = level->width * blockPos->y + blockPos->x; level = lrr::Lego_GetLevel(); level->blocks[iVar2].generateOre = level->blocks[iVar2].generateOre + 1; } return; } char * __cdecl lego::game::LegoObject_GetLangName(LegoObject *liveObj) { if (true) { switch(liveObj->type) { case LegoObject_Vehicle: return globs::legoGlobs.langVehicle_name[liveObj->vehicle->objID]; case LegoObject_MiniFigure: return globs::legoGlobs.langMiniFigure_name[liveObj->miniFigure->objID]; case LegoObject_RockMonster: return globs::legoGlobs.langRockMonster_name[liveObj->rockMonster->objID]; case LegoObject_Building: return globs::legoGlobs.langBuilding_name[liveObj->building->objID]; case LegoObject_PowerCrystal: return globs::legoGlobs.langPowerCrystal_name; case LegoObject_Ore: return globs::legoGlobs.toolName[liveObj->id - 0x1b]; case LegoObject_Dynamite: return globs::legoGlobs.langDynamite_name; case LegoObject_Barrier: return globs::legoGlobs.langBarrier_name; case LegoObject_UpgradePart: return globs::legoGlobs.langUpgrade_name[liveObj->upgradePart->objID]; case LegoObject_ElectricFence: return globs::legoGlobs.langElectricFence_name; case LegoObject_SpiderWeb: return globs::legoGlobs.langSpiderWeb_name; case LegoObject_OohScary: return globs::legoGlobs.langOohScary_name; case LegoObject_Path: return globs::legoGlobs.langPath_name; } } return NULL; } char * __cdecl lego::game::Object_GetTypeName(LegoObject_Type objType,LegoObject_ID objID) { if (objType < LegoObject_Barrier) { if (objType == LegoObject_Dynamite) { return "Dynamite"; } if (true) { switch(objType) { case LegoObject_Vehicle: return globs::legoGlobs.vehicleName[objID]; case LegoObject_MiniFigure: return globs::legoGlobs.miniFigureName[objID]; case LegoObject_RockMonster: return globs::legoGlobs.rockMonsterName[objID]; case LegoObject_Building: return globs::legoGlobs.buildingName[objID]; case LegoObject_PowerCrystal: return "PowerCrystal"; case LegoObject_Ore: if (objID == 0) { return "Ore"; } return "ProcessedOre"; } } } else { if (objType < LegoObject_OohScary) { if (objType == LegoObject_SpiderWeb) { return "SpiderWeb"; } if (objType == LegoObject_Barrier) { return "Barrier"; } if (objType == LegoObject_ElectricFence) { return "ElectricFence"; } } else { if (objType == LegoObject_OohScary) { return "OohScary"; } if (objType == LegoObject_TVCamera) { return "tvcamera"; } } } return NULL; } char * __cdecl lego::game::Object_GetLangTheName(LegoObject_Type objType,LegoObject_ID objID) { if (true) { switch(objType) { case LegoObject_Vehicle: return globs::legoGlobs.langVehicle_theName[objID]; case LegoObject_MiniFigure: return globs::legoGlobs.langMiniFigure_theName[objID]; case LegoObject_RockMonster: return globs::legoGlobs.langRockMonster_theName[objID]; case LegoObject_Building: return globs::legoGlobs.langBuilding_theName[objID]; case LegoObject_PowerCrystal: return globs::legoGlobs.langPowerCrystal_theName; case LegoObject_Ore: return globs::legoGlobs.toolName[objID - 0x12]; case LegoObject_Dynamite: return globs::legoGlobs.langDynamite_theName; case LegoObject_Barrier: return globs::legoGlobs.langBarrier_theName; case LegoObject_UpgradePart: return globs::legoGlobs.langUpgrade_theName[objID]; case LegoObject_ElectricFence: return globs::legoGlobs.langElectricFence_theName; case LegoObject_SpiderWeb: return globs::legoGlobs.langSpiderWeb_theName; case LegoObject_OohScary: return globs::legoGlobs.langOohScary_theName; case LegoObject_Path: return globs::legoGlobs.langPath_theName; } } return NULL; } char * __cdecl lego::game::Object_GetLangName(LegoObject_Type objType,LegoObject_ID objID) { if (true) { switch(objType) { case LegoObject_Vehicle: return globs::legoGlobs.langVehicle_name[objID]; case LegoObject_MiniFigure: return globs::legoGlobs.langMiniFigure_name[objID]; case LegoObject_RockMonster: return globs::legoGlobs.langRockMonster_name[objID]; case LegoObject_Building: return globs::legoGlobs.langBuilding_name[objID]; case LegoObject_PowerCrystal: return globs::legoGlobs.langPowerCrystal_name; case LegoObject_Ore: return globs::legoGlobs.toolName[objID - 0x1b]; case LegoObject_Dynamite: return globs::legoGlobs.langDynamite_name; case LegoObject_Barrier: return globs::legoGlobs.langBarrier_name; case LegoObject_UpgradePart: return globs::legoGlobs.langUpgrade_name[objID]; case LegoObject_ElectricFence: return globs::legoGlobs.langElectricFence_name; case LegoObject_SpiderWeb: return globs::legoGlobs.langSpiderWeb_name; case LegoObject_OohScary: return globs::legoGlobs.langOohScary_name; case LegoObject_Path: return globs::legoGlobs.langPath_name; } } return NULL; } void __cdecl lego::game::LegoObject_GetTypeAndID (LegoObject *liveObj,LegoObject_Type *out_objType,LegoObject_ID *out_objID) { *out_objType = liveObj->type; *out_objID = liveObj->id; return; } void __cdecl lego::game::Object_LoadToolNames(Config *config,char *gameName) { char *keyPath; char **ppcVar1; char ***pppcVar2; pppcVar2 = (char ***)globs::legoGlobs.langTool_name; do { keyPath = cfg::Config_BuildStringID(gameName,"ToolNames",pppcVar2[-0xb],0); ppcVar1 = (char **)cfg::Config_GetStringValue(config,keyPath); *pppcVar2 = ppcVar1; pppcVar2 = pppcVar2 + 1; } while (pppcVar2 < &globs::legoGlobs.langVehicle_name); return; } // If we're currently in the update loop, then delay recalculations until the end of the update // loop/next tick(?). // // Otherwise, we can turn on power updating mode right now. void __cdecl lego::game::LegoObject_RequestPowerGridUpdate(void) { // We're in the update loop. Recalculating power now is dangerous when only some of the // objects have been update while others are awaiting an update. // Delay recalculation until the end of the update loop. if ((globs::objectGlobs.flags & OBJECT_GLOB_FLAG_UPDATING) != OBJECT_GLOB_FLAG_NONE) { globs::objectGlobs.flags = globs::objectGlobs.flags | OBJECT_GLOB_FLAG_POWERNEEDSUPDATE; return; } // Not in the update loop, go straight to power grid recalculation mode. globs::objectGlobs.flags |= OBJECT_GLOB_FLAG_POWERUPDATING; Level_ResetCrystalsDrained(); return; } BOOL __cdecl lego::game::LegoObject_VehicleMaxCarryChecksTime_FUN_00439c80(LegoObject *liveObj) { uint uVar1; uint uVar2; if ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { return 0; } if (liveObj->type == LegoObject_Vehicle) { uVar2 = liveObj->carryNullFrames; uVar1 = stats::StatsObject_GetMaxCarry(liveObj); if (uVar1 <= uVar2) { uVar2 = stats::StatsObject_GetMaxCarry(liveObj); } if ((liveObj->numCarriedObjects < uVar2) && (liveObj->elapsedTime1 < 75.0)) { return 0; } } return TRUE; } BOOL __cdecl lego::game::LegoObject_TryCollectObject(LegoObject *liveObj,LegoObject *targetObj) { LegoObject *liveObj_00; LegoObject *liveObj_01; BOOL BVar1; Map3D *pMVar2; LegoObject **ppLVar3; LegoObject **ppLVar4; int *local_24; int *local_20; LegoObject *local_1c; LegoObject *local_18; uint local_14; Point2F local_10; float local_8; float local_4; liveObj_00 = liveObj; BVar1 = LegoObject_VehicleMaxCarryChecksTime_FUN_00439c80(liveObj); liveObj_01 = targetObj; if ((BVar1 == 0) && (BVar1 = LegoObject_FUN_00439e90(liveObj_00,targetObj,TRUE), BVar1 != 0)) { LegoObject_GetPosition(liveObj_01,&local_10.x,&local_10.y); ppLVar4 = &liveObj; ppLVar3 = &targetObj; pMVar2 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(pMVar2,local_10.x,local_10.y,(int *)ppLVar3,(int *)ppLVar4) ; LegoObject_GetPosition(liveObj_00,&local_8,&local_4); ppLVar4 = &local_18; ppLVar3 = &local_1c; pMVar2 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(pMVar2,local_8,local_4,(int *)ppLVar3,(int *)ppLVar4); if ((local_1c == targetObj) && (local_18 == liveObj)) { LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,1,(int *)&targetObj,(int *)&liveObj,&local_10); } else { BVar1 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,(uint)local_1c,(uint)local_18,(uint)targetObj,(uint)liveObj, &local_24,&local_20,(int *)&local_14,0,NULL); if (BVar1 == 0) { return 0; } LegoObject_Route_AllocPtr_FUN_004419c0(liveObj_00,local_14,local_24,local_20,&local_10); io::Mem_Free(local_24); io::Mem_Free(local_20); } liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_GATHERROCK; liveObj_00->routeToObject = liveObj_01; return TRUE; } return FALSE; } BOOL __cdecl lego::game::LegoObject_FUN_00439e40(LegoObject *liveObj,LegoObject *otherObj) { StatsFlags3 sflags3; LegoObject *foundObj; if (liveObj->type == LegoObject_Vehicle) { if (otherObj->id != 0) { return 0; } sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if ((sflags3 & STATS3_ENTERTOOLSTORE) == STATS3_NONE) { foundObj = LegoObject_FindResourceProcessingBuilding (liveObj,NULL,otherObj->type,otherObj->objLevel); return (uint)(foundObj != NULL); } } return TRUE; } BOOL __cdecl lego::game::LegoObject_FUN_00439e90(LegoObject *liveObj,LegoObject *targetObj,BOOL param_3) { BOOL BVar1; StatsFlags1 sflags1; if (liveObj->type == LegoObject_RockMonster) { if ((liveObj->flags3 & LIVEOBJ3_MONSTER_UNK_8000000) == LIVEOBJ3_NONE) { return 0; } } else { if ((*(byte *)&liveObj->flags3 & LIVEOBJ3_UNK_20) == 0) { return 0; } } if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_MOVING) != 0) { return 0; } if (param_3 != 0) { BVar1 = LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(liveObj); if (BVar1 != 0) { return 0; } } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_PROCESSCRYSTAL) != STATS1_NONE) && (targetObj->type != LegoObject_PowerCrystal)) { return 0; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_PROCESSORE) != STATS1_NONE) && (targetObj->type != LegoObject_Ore)) { return 0; } if ((liveObj->numCarriedObjects != 0) && (liveObj->carriedObjects[0]->type != targetObj->type)) { return 0; } return TRUE; } void __cdecl lego::game::LegoObject_CompleteVehicleUpgrade(LegoObject *liveObj) { uint objLevel; if (liveObj->type == LegoObject_Vehicle) { objLevel = gfx::Vehicle_GetUpgradeLevel(liveObj->vehicle); objLevel |= 1 << ((byte)liveObj->upgradingType & 0x1f); gfx::Vehicle_SetUpgradeLevel(liveObj->vehicle,objLevel); stats::StatsObject_SetObjectLevel(liveObj,objLevel); front::Text_DisplayMessage(Text_UnitUpgraded,TRUE,FALSE); } return; } BOOL __cdecl lego::game::LegoObject_SetLevel(LegoObject *liveObj,uint newLevel) { BOOL BVar1; BVar1 = stats::StatsObject_SetObjectLevel(liveObj,newLevel); return BVar1; } BOOL __cdecl lego::game::LegoObject_IsSmallTeleporter(LegoObject *liveObj) { StatsFlags1 sflags1; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); return sflags1 & STATS1_SMALLTELEPORTER; } BOOL __cdecl lego::game::LegoObject_IsBigTeleporter(LegoObject *liveObj) { StatsFlags1 sflags1; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); return sflags1 & STATS1_BIGTELEPORTER; } BOOL __cdecl lego::game::LegoObject_IsWaterTeleporter(LegoObject *liveObj) { StatsFlags1 sflags1; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); return sflags1 & STATS1_WATERTELEPORTER; } BOOL __cdecl lego::game::LegoObject_UnkGetTerrainCrossBlock_FUN_0043a010 (LegoObject *liveObj,Point2I *optout_blockPos) { uint bx; BOOL BVar1; int iVar2; uint by; uint i; Point2I *pDir; Point2I local_28; Point2I DIRECTIONS [4]; DIRECTIONS[0].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[1].x = 1; DIRECTIONS[2].y = 1; DIRECTIONS[0].x = 0; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].y = 0; LegoObject_GetBlockPos(liveObj,&local_28.x,&local_28.y); i = 0; pDir = DIRECTIONS; do { pDir->x = pDir->x + local_28.x; by = pDir->y + local_28.y; pDir->y = by; bx = pDir->x; BVar1 = Level_Block_IsGround(bx,by); if (BVar1 != 0) { iVar2 = Lego_GetCrossTerrainType(NULL,bx,pDir->y,bx,pDir->y,0); if (iVar2 != 0) { if (optout_blockPos != NULL) { iVar2 = DIRECTIONS[i].y; optout_blockPos->x = DIRECTIONS[i].x; optout_blockPos->y = iVar2; } return TRUE; } } i += 1; pDir = pDir + 1; } while (i < 4); return 0; } BOOL __cdecl lego::game::LegoObject_UnkGetTerrainGetOutAtLandBlock_FUN_0043a0d0 (LegoObject *liveObj,Point2I *out_blockPos) { StatsFlags3 SVar1; BOOL BVar2; SVar1 = stats::StatsObject_GetStatsFlags3(liveObj); if ((SVar1 & STATS3_GETOUTATLAND) != STATS3_NONE) { BVar2 = LegoObject_UnkGetTerrainCrossBlock_FUN_0043a010(liveObj,out_blockPos); return BVar2; } return 0; } BOOL __cdecl lego::game::LegoObject_CheckUnkGetInAtLand_FUN_0043a100(LegoObject *liveObj,Point2I *blockPos) { StatsFlags3 SVar1; BOOL BVar2; SVar1 = stats::StatsObject_GetStatsFlags3(liveObj); if ((SVar1 & STATS3_GETINATLAND) != STATS3_NONE) { BVar2 = LegoObject_UnkGetTerrainCrossBlock_FUN_0043a010(liveObj,blockPos); return BVar2; } return 0; } void __cdecl lego::game::LegoObject_DropCarriedObject(LegoObject *liveObj,BOOL putAway) { RouteAction RVar1; LegoObject *liveObj_00; LegoObject *liveObj_01; LegoObject *liveObj_02; StatsFlags1 sflags1; BOOL BVar2; Container *cont; int iVar3; uint i; LegoObject **ppLVar4; AITask_Type taskType; Point2I local_20; float local_18; float local_14 [2]; Vector3F local_c; LiveFlags1 lflags1; liveObj_02 = liveObj; lflags1 = liveObj->flags1; if (((lflags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && (((lflags1 & LIVEOBJ1_STORING) == LIVEOBJ1_NONE || (putAway != 0)))) { liveObj_00 = liveObj->routeToObject; i = 0; liveObj = NULL; if (liveObj_00 != NULL) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); liveObj = (LegoObject *)(sflags1 & STATS1_STOREOBJECTS); } if ((liveObj == NULL) && (putAway != 0)) { ai::AITask_LiveObject_SetAITaskUnk(liveObj_02,AITask_Type_Dump,NULL,TRUE); ai::AITask_LiveObject_SetAITaskUnk(liveObj_02,AITask_Type_Dynamite,NULL,TRUE); ai::AITask_LiveObject_SetAITaskUnk(liveObj_02,AITask_Type_ElecFence,NULL,TRUE); ai::AITask_LiveObject_SetAITaskUnk(liveObj_02,AITask_Type_BirdScarer,NULL,TRUE); } if (liveObj_02->numCarriedObjects != 0) { ppLVar4 = liveObj_02->carriedObjects; do { liveObj_01 = *ppLVar4; *ppLVar4 = NULL; liveObj_01->carryingThisObject = NULL; liveObj_01->interactObject = NULL; if ((liveObj == NULL) || (putAway == 0)) { LegoObject_GetBlockPos(liveObj_01,&local_20.x,&local_20.y); BVar2 = Level_Block_IsGround(local_20.x,local_20.y); if (BVar2 == 0) { LAB_0043a27e: cont = LegoObject_GetActivityContainer(liveObj_01); LegoObject_GetPosition(liveObj_02,&local_18,local_14); gfx::Container_GetPosition(cont,NULL,&local_c); gfx::Container_SetPosition(cont,NULL,local_18,local_14[0],local_c.z); } else { BVar2 = Level_Block_IsLava(&local_20); if (BVar2 != 0) goto LAB_0043a27e; BVar2 = Level_Block_IsSolidBuilding(local_20.x,local_20.y,0); if (BVar2 != 0) goto LAB_0043a27e; } if (putAway == 0) { if ((lflags1 & LIVEOBJ1_GATHERINGROCK) == LIVEOBJ1_NONE) { ai::AITask_LiveObject_FUN_00403b30(liveObj_02,AITask_Type_Deposit,liveObj_01); ai::AITask_LiveObject_FUN_00403b30(liveObj_02,AITask_Type_Dump,liveObj_01); ai::AITask_LiveObject_FUN_00403b30(liveObj_02,AITask_Type_Dynamite,liveObj_01); ai::AITask_LiveObject_FUN_00403b30(liveObj_02,AITask_Type_ElecFence,liveObj_01); ai::AITask_LiveObject_FUN_00403b30(liveObj_02,AITask_Type_Request,liveObj_01); ai::AITask_LiveObject_FUN_00403b30(liveObj_02,AITask_Type_Gather,NULL); taskType = AITask_Type_BirdScarer; } else { taskType = AITask_Type_Collect; } ai::AITask_LiveObject_FUN_00403b30(liveObj_02,taskType,liveObj_01); } else { ai::AITask_LiveObject_SetAITaskUnk (liveObj_02,AITask_Type_Request,liveObj_01, (uint)(i == liveObj_02->numCarriedObjects - 1)); if ((liveObj_01->type != LegoObject_Ore) && (liveObj_01->type != LegoObject_PowerCrystal)) { liveObj_01->flags1 = liveObj_01->flags1 | LIVEOBJ1_PLACING; } } if (liveObj_01->type == LegoObject_Boulder) { LegoObject_DestroyBoulder_AndCreateExplode(liveObj_01); } } else { ai::AITask_LiveObject_SetAITaskUnk(liveObj_02,AITask_Type_Deposit,liveObj_01,TRUE); LegoObject_PutAwayCarriedObject(liveObj_00,liveObj_01); LegoObject_RequestPowerGridUpdate(); } i += 1; ppLVar4 = ppLVar4 + 1; } while (i < liveObj_02->numCarriedObjects); } i = 0; liveObj_02->numCarriedObjects = 0; // & ~LIVEOBJ1_CARRYING (0x400) liveObj_02->flags1 = liveObj_02->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); if (liveObj_02->routeBlocksTotal != 0) { iVar3 = 0; do { RVar1 = (&liveObj_02->routeBlocks->actionByte)[iVar3]; if ((RVar1 == ROUTE_ACTION_STORE) || (RVar1 == ROUTE_ACTION_UNK_5)) { (&liveObj_02->routeBlocks->actionByte)[iVar3] = 0; } i += 1; iVar3 += 0x14; } while (i < liveObj_02->routeBlocksTotal); } } return; } BOOL __cdecl lego::game::LegoObject_TryRequestOrDumpCarried (LegoObject *liveObj,Point2I *blockPos,Point2F *worldPos,BOOL place,BOOL setRouteFlag8) { float fVar1; RoutingBlock *pRVar2; short sVar3; BOOL BVar4; uint uVar5; BOOL BVar6; float10 fVar7; int *local_1c; int *local_18; uint local_14; uint local_10; uint local_c; float local_8; float local_4; BVar6 = 0; if ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { LegoObject_GetBlockPos(liveObj,(int *)&local_14,(int *)&local_10); if ((local_14 == blockPos->x) && (local_10 == blockPos->y)) { BVar6 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,1,&blockPos->x,&blockPos->y,NULL); } else { BVar4 = LegoObject_Route_Score_FUN_004413b0 (liveObj,local_14,local_10,blockPos->x,blockPos->y,&local_1c,&local_18, (int *)&local_c,0,NULL); if (BVar4 != 0) { BVar6 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,local_c,local_1c,local_18,NULL); io::Mem_Free(local_1c); io::Mem_Free(local_18); } } if (BVar6 != 0) { if (liveObj->type == LegoObject_Vehicle) { fVar7 = math::Maths_RandRange(0.55,0.75); fVar1 = (float)fVar7; sVar3 = math::Maths_Rand(); uVar5 = (int)sVar3 >> 0x1f; setRouteFlag8 = 1; switch((((int)sVar3 ^ uVar5) - uVar5 & 3 ^ uVar5) - uVar5) { case 0: local_8 = 0.5; local_4 = fVar1; break; case 1: local_4 = 0.5; local_8 = fVar1; break; case 2: local_8 = 0.5; local_4 = 1.0 - fVar1; break; case 3: local_4 = 0.5; local_8 = 1.0 - fVar1; } } else { local_8 = worldPos->x; local_4 = worldPos->y; } if (place == 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_DROP; } else { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_PLACE; } if (worldPos != NULL) { uVar5 = liveObj->routeBlocksTotal; pRVar2 = liveObj->routeBlocks; pRVar2[uVar5 - 1].blockOffset.x = local_8; pRVar2[uVar5 - 1].blockOffset.y = local_4; } if (setRouteFlag8 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte = liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_UNK_8; } } } return BVar6; } BOOL __cdecl lego::game::LegoObject_TryDepositCarried(LegoObject *liveObj,LegoObject *destObj) { RouteFlags *pRVar1; LegoObject *liveObj_00; LegoObject *liveObj_01; StatsFlags1 SVar2; BOOL BVar3; Map3D *pMVar4; Container *cont; float in_x; float in_y; LegoObject **ppLVar5; LegoObject **ppLVar6; LegoObject *local_3c; int *local_38; int *local_34; LegoObject *local_30; uint local_2c; Point2F local_28; float local_20; float local_1c; Vector3F local_18; Vector3F local_c; liveObj_00 = liveObj; if ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { SVar2 = stats::StatsObject_GetStatsFlags1(liveObj); if (((SVar2 & STATS1_PROCESSCRYSTAL) != STATS1_NONE) || (SVar2 = stats::StatsObject_GetStatsFlags1(liveObj_00), liveObj_01 = destObj, (SVar2 & STATS1_PROCESSORE) != STATS1_NONE)) { liveObj_00->flags1 = liveObj_00->flags1 | LIVEOBJ1_STORING; LegoObject_SetActivity(liveObj_00,Activity_Deposit,1); LegoObject_UpdateActivityChange(liveObj_00); LegoObject_MoveAnimation(liveObj_00,1.0); return TRUE; } BVar3 = LegoObject_FUN_00439e90(destObj,liveObj_00->carriedObjects[0],0); if ((BVar3 != 0) || (SVar2 = stats::StatsObject_GetStatsFlags1(liveObj_01), (SVar2 & STATS1_STOREOBJECTS) != STATS1_NONE)) { cont = NULL; SVar2 = stats::StatsObject_GetStatsFlags1(liveObj_01); if ((SVar2 & STATS1_STOREOBJECTS) == STATS1_NONE) { if (liveObj_01->type == LegoObject_Building) { cont = gfx::Building_GetDepositNull(liveObj_01->building); } } else { cont = gfx::Building_GetToolNull(liveObj_01->building,globs::objectGlobs.toolNullIndex[10]); } if (cont == NULL) { LegoObject_GetPosition(liveObj_01,&local_28.x,&local_28.y); } else { gfx::Container_GetPosition(cont,NULL,&local_c); gfx::Container_GetOrientation(cont,NULL,&local_18,NULL); local_28.x = local_c.x; local_28.y = local_c.y; if (ABS(local_18.x) <= ABS(local_18.y)) { if ((ushort)((ushort)(local_18.y < 0.0) << 8 | (ushort)(local_18.y == 0.0) << 0xe) == 0) { liveObj._0_1_ = 2; } else { liveObj._0_1_ = ROUTE_FLAG_NONE; } } else { if ((ushort)((ushort)(local_18.x < 0.0) << 8 | (ushort)(local_18.x == 0.0) << 0xe) == 0) { liveObj._0_1_ = ROUTE_DIRECTION_MASK; } else { liveObj._0_1_ = 1; } } } ppLVar6 = &liveObj; ppLVar5 = &destObj; in_x = local_28.x; in_y = local_28.y; pMVar4 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(pMVar4,in_x,in_y,(int *)ppLVar5,(int *)ppLVar6); LegoObject_GetPosition(liveObj_00,&local_20,&local_1c); ppLVar6 = &local_3c; ppLVar5 = &local_30; pMVar4 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(pMVar4,local_20,local_1c,(int *)ppLVar5,(int *)ppLVar6); if ((local_30 == destObj) && (local_3c == liveObj)) { BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,1,(int *)&destObj,(int *)&liveObj,&local_28); } else { BVar3 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,(uint)local_30,(uint)local_3c,(uint)destObj,(uint)liveObj, &local_38,&local_34,(int *)&local_2c,0,NULL); if (BVar3 == 0) { return 0; } BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,local_2c,local_38,local_34,&local_28); io::Mem_Free(local_38); io::Mem_Free(local_34); } if (BVar3 != 0) { liveObj_00->routeToObject = liveObj_01; SVar2 = stats::StatsObject_GetStatsFlags1(liveObj_01); if ((SVar2 & STATS1_STOREOBJECTS) != STATS1_NONE) { liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_PLACE; liveObj_00->routeToObject = liveObj_01; return TRUE; } liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_STORE; liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte = liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_GOTOBUILDING; pRVar1 = &liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte; *pRVar1 = *pRVar1 | (RouteFlags)liveObj & ROUTE_DIRECTION_MASK; } return TRUE; } } return FALSE; } Container * __cdecl lego::game::LegoObject_GetDepositNull(LegoObject *liveObj) { Container *cont; LegoObject_Type objType; cont = NULL; objType = liveObj->type; if (objType == LegoObject_Building) { cont = gfx::Building_GetDepositNull(liveObj->building); } else { if (objType == LegoObject_RockMonster) { cont = gfx::Creature_GetDepositNull(liveObj->rockMonster); } else { if (objType == LegoObject_MiniFigure) { cont = gfx::Creature_GetDepositNull(liveObj->miniFigure); } else { if (objType == LegoObject_Vehicle) { cont = gfx::Vehicle_GetDepositNull(liveObj->vehicle); } } } } if (cont == NULL) { cont = LegoObject_GetActivityContainer(liveObj); } return cont; } LegoObject * __cdecl lego::game::LegoObject_SpawnCarryableObject (LegoObject *liveObj,LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { BOOL BVar1; LegoObject_ToolType toolType; Container *cont; LegoObject *spawnedObj; Message_Type messageType; Vector3F worldPos; BVar1 = LegoObject_CanSpawnCarryableObject(liveObj,objType,objID); if (BVar1 == 0) { return NULL; } switch(objType) { case LegoObject_PowerCrystal: case LegoObject_Ore: toolType = LegoObject_ToolType_CryOre; break; case LegoObject_Dynamite: toolType = LegoObject_ToolType_Dynamite; break; case LegoObject_Barrier: toolType = LegoObject_ToolType_Barrier; break; default: toolType = LegoObject_ToolType_Drill; } cont = gfx::Building_GetToolNull(liveObj->building,globs::objectGlobs.toolNullIndex[toolType]); gfx::Container_GetPosition(cont,NULL,&worldPos); cont = globs::legoGlobs.contCrystal; if (objType == LegoObject_PowerCrystal) { LegoObject_RequestPowerGridUpdate(); Level_SubtractCrystalsStored(1); } else { if (objType == LegoObject_Ore) { cont = globs::legoGlobs.contOresTable[objID]; Level_SubtractOreStored(objID,1); } else { cont = globs::legoGlobs.contBarrier; if ((((objType != LegoObject_Barrier) && (cont = globs::legoGlobs.contDynamite, objType != LegoObject_Dynamite)) && (cont = globs::legoGlobs.contElectricFence, objType != LegoObject_ElectricFence)) && (cont = globs::legoGlobs.contOohScary, objType != LegoObject_OohScary)) { return NULL; } } } spawnedObj = LegoObject_CreateInWorld(cont,objType,objID,objLevel,worldPos.x,worldPos.y,0.0); if (objType == LegoObject_Ore) { messageType = Message_GenerateOreComplete; } else { messageType = Message_GenerateCrystalComplete; } Message_PostEvent(messageType,spawnedObj,0,NULL); if (objType != LegoObject_Barrier) { if (objType == LegoObject_Dynamite) { gfx::Container_SetActivity(spawnedObj->other,"Normal"); } return spawnedObj; } gfx::Container_SetActivity(spawnedObj->other,"Short"); return spawnedObj; } BOOL __cdecl lego::game::LegoObject_CanSpawnCarryableObject (LegoObject *liveObj,LegoObject_Type objType,LegoObject_ID objID) { StatsFlags1 sflags1; int rsrcCount; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_STOREOBJECTS) != STATS1_NONE) { if (objType == LegoObject_PowerCrystal) { rsrcCount = Level_GetCrystalCount(TRUE); if (rsrcCount != 0) { return TRUE; } } if (objType == LegoObject_Ore) { rsrcCount = Level_GetOreCount(objID); if (rsrcCount != 0) { return TRUE; } } if (objType == LegoObject_Barrier) { return TRUE; } if (objType == LegoObject_Dynamite) { return TRUE; } if (objType == LegoObject_ElectricFence) { return TRUE; } if (objType == LegoObject_OohScary) { return TRUE; } } return FALSE; } void __cdecl lego::game::LegoObject_PutAwayCarriedObject(LegoObject *liveObj,LegoObject *carriedObj) { int *newStolenCrystalLevels; int iVar1; if ((liveObj->type == LegoObject_RockMonster) && (liveObj->stolenCrystalLevels == NULL)) { // Support for stealing Crystals level [0,5] newStolenCrystalLevels = (int *)io::Mem_Alloc(0x18); liveObj->stolenCrystalLevels = newStolenCrystalLevels; for (iVar1 = 6; iVar1 != 0; iVar1 += -1) { *newStolenCrystalLevels = 0; newStolenCrystalLevels = newStolenCrystalLevels + 1; } } if (carriedObj->type == LegoObject_PowerCrystal) { if (liveObj->type == LegoObject_RockMonster) { liveObj->stolenCrystalLevels[carriedObj->objLevel] = liveObj->stolenCrystalLevels[carriedObj->objLevel] + 1; } else { Level_IncCrystalsStored(); } } else { if ((carriedObj->type == LegoObject_Ore) && (liveObj->type != LegoObject_RockMonster)) { Level_IncOreStored(carriedObj->id); } } carriedObj->carryingThisObject = NULL; LegoObject_Remove(carriedObj); if (liveObj->type != LegoObject_RockMonster) { ai::AITask_DoRequestObjectCallbacks(liveObj); } return; } void __cdecl lego::game::LegoObject_AddCrystalsStored(LegoObject *unused_liveObj,uint crystalAmount) { if (crystalAmount != 0) { do { Level_IncCrystalsStored(); crystalAmount -= 1; } while (crystalAmount != 0); } LegoObject_RequestPowerGridUpdate(); return; } // Does not allow for adding Processed Ore (studs). void __cdecl lego::game::LegoObject_AddOreStored(LegoObject *liveObj_unused,uint oreAmount) { if (oreAmount != 0) { do { Level_IncOreStored(0); oreAmount -= 1; } while (oreAmount != 0); } return; } void __cdecl lego::game::LegoObject_WaterVehicle_Unregister(LegoObject *liveObj) { LegoObject **pWaterVehicleObj; uint i; i = 0; if (globs::objectGlobs.uintCount_c5cc != 0) { pWaterVehicleObj = globs::objectGlobs.liveObjArray100_c43c; do { if (liveObj == *pWaterVehicleObj) { *pWaterVehicleObj = NULL; } i += 1; pWaterVehicleObj = pWaterVehicleObj + 1; } while (i < globs::objectGlobs.uintCount_c5cc); } return; } void __cdecl lego::game::LegoObject_WaterVehicle_Register(LegoObject *liveObj) { StatsFlags1 sflags1; Point2I objBlockPos; if (liveObj->type == LegoObject_Vehicle) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) { LegoObject_GetBlockPos(liveObj,&objBlockPos.x,&objBlockPos.y); if (((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * objBlockPos.y + objBlockPos.x].terrain == Lego_SurfaceType8_Lake) && (globs::objectGlobs.uintCount_c5cc < 100)) { globs::objectGlobs.liveObjArray100_c43c[globs::objectGlobs.uintCount_c5cc] = liveObj; globs::objectGlobs.uintCount_c5cc += 1; } } } return; } void __cdecl lego::game::LegoObject_RegisterVehicle__callsForWater(LegoObject *liveObj) { LegoObject_WaterVehicle_Register(liveObj); return; } void __cdecl lego::game::LegoObject_FUN_0043acb0(LegoObject *liveObj1,LegoObject *liveObj2) { int bx1; int by1; int bx2; int by2; if (((((liveObj1->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) && ((*(byte *)&liveObj1->flags2 & LIVEOBJ2_THROWING) == 0)) && ((liveObj1->flags1 & (LIVEOBJ1_EXPANDING|LIVEOBJ1_REPAIRDRAINING)) == LIVEOBJ1_NONE)) && ((((ushort)((ushort)(liveObj1->health < 0.0) << 8 | (ushort)(liveObj1->health == 0.0) << 0xe) == 0 && ((liveObj2->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) && (liveObj2->carriedObjects[0]->type == LegoObject_PowerCrystal)))) { LegoObject_GetBlockPos(liveObj1,&bx1,&by1); LegoObject_GetBlockPos(liveObj2,&bx2,&by2); // Activity_Stamp (36) if (globs::objectGlobs.activityName[36] != liveObj1->activityName1) { LegoObject_SetActivity(liveObj1,Activity_Stamp,0); LegoObject_UpdateActivityChange(liveObj1); liveObj1->flags2 = liveObj1->flags2 | LIVEOBJ2_UNK_200000; } } return; } void __cdecl lego::game::LegoObject_RockMonster_FUN_0043ad70(LegoObject *liveObj) { StatsFlags2 sflags2; BOOL BVar1; Map3D *map; float10 fVar2; float10 fVar3; float *out_x; float *out_y; Point2I local_18; float local_10; float local_c; float local_8; float local_4; if (liveObj->type == LegoObject_RockMonster) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_ATTACKPATHS) != STATS2_NONE) { fVar2 = stats::StatsObject_GetPainThreshold(liveObj); if (((fVar2 < (float10)liveObj->health) && (globs::objectGlobs.activityName[36] != liveObj->activityName1)) && ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE)) { LegoObject_GetBlockPos(liveObj,&local_18.x,&local_18.y); BVar1 = Level_Block_IsPath(&local_18); if (BVar1 != 0) { BVar1 = Level_Block_IsPathBuilding(&local_18); if (BVar1 == 0) { LegoObject_GetPosition(liveObj,&local_10,&local_c); out_y = &local_4; out_x = &local_8; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,local_18.x,local_18.y,out_x,out_y); map = lrr::Lego_GetMap(); fVar3 = lego::map::Map3D_BlockSize(map); fVar2 = (float10)SQRT((local_c - local_4) * (local_c - local_4) + (local_10 - local_8) * (local_10 - local_8)); if ((ushort)((ushort)(fVar3 * (float10)0.3333333 < fVar2) << 8 | (ushort)(fVar3 * (float10)0.3333333 == fVar2) << 0xe) == 0) { LegoObject_SetActivity(liveObj,Activity_Stamp,0); LegoObject_UpdateActivityChange(liveObj); liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_200000; } } } } } } return; } void __cdecl lego::game::LegoObject_FUN_0043aeb0(LegoObject *liveObj) { short rng; BOOL BVar1; Point2I local_8; LegoObject_GetBlockPos(liveObj,&local_8.x,&local_8.y); rng = math::Maths_Rand(); if ((int)rng % 5 == 0) { Level_GenerateFallin_InRadius(&local_8,3,TRUE); } BVar1 = Level_Block_IsPath(&local_8); if (BVar1 != 0) { effect::Effect_Spawn_SmashPath(liveObj,NULL); ai::AITask_DoClearTypeAction(&local_8,Message_ClearRemovePathComplete); Level_BlockUpdateSurface(globs::legoGlobs.currLevel,local_8.x,local_8.y,0); } LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_TryStampMiniFigureWithCrystal,liveObj); return; } BOOL __cdecl lego::game::LegoObject_Callback_TryStampMiniFigureWithCrystal (LegoObject *targetObj,LegoObject *stamperObj) { float10 stampRadius; Point2F targetPos; Point2F stamperPos; if (((targetObj->type == LegoObject_MiniFigure) && ((targetObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) && (targetObj->carriedObjects[0]->type == LegoObject_PowerCrystal)) { LegoObject_GetPosition(stamperObj,&stamperPos.x,&stamperPos.y); LegoObject_GetPosition(targetObj,&targetPos.x,&targetPos.y); // is liveObj within stamp radius stampRadius = stats::StatsObject_GetStampRadius(stamperObj); if ((float10)SQRT((targetPos.y - stamperPos.y) * (targetPos.y - stamperPos.y) + (targetPos.x - stamperPos.x) * (targetPos.x - stamperPos.x)) < stampRadius) { LegoObject_DropCarriedObject(targetObj,FALSE); LegoObject_Route_End(targetObj,FALSE); } } return FALSE; } LegoObject * __cdecl lego::game::LegoObject_TryGenerateSlug(LegoObject *originObj,LegoObject_ID objID) { short sVar1; Map3D *map; LegoObject *slugObj; float10 theta; float10 fVar2; float10 fVar3; uint bx; uint by; Point2F *out_x; float *out_y; Point2F blockWorldPos; Point2I blockPos; slugObj = NULL; if (globs::objectGlobs.slugHoleCount != 0) { theta = math::Maths_RandRange(0.0,6.283185); fVar2 = (float10)fsin(theta); fVar3 = (float10)fcos((float10)(float)theta); if (originObj == NULL) { sVar1 = math::Maths_Rand(); blockPos.x = globs::objectGlobs.slugHoleBlocks [(uint)(int)sVar1 % globs::objectGlobs.slugHoleCount].x; blockPos.y = globs::objectGlobs.slugHoleBlocks [(uint)(int)sVar1 % globs::objectGlobs.slugHoleCount].y; } else { LegoObject_FindNearestSlugHole(originObj,&blockPos); } out_y = &blockWorldPos.y; out_x = &blockWorldPos; bx = blockPos.x; by = blockPos.y; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,by,&out_x->x,out_y); blockWorldPos.x = (float)fVar2 * 12.75 + blockWorldPos.x; blockWorldPos.y = (float)fVar3 * 12.75 + blockWorldPos.y; slugObj = LegoObject_CreateInWorld (globs::legoGlobs.rockMonsterData + objID,LegoObject_RockMonster,objID,0, blockWorldPos.x,blockWorldPos.y,(float)theta); if (slugObj != NULL) { slugObj->flags1 = slugObj->flags1 | LIVEOBJ1_EXPANDING; // & ~LIVEOBJ3_POWEROFF (0x80000000) slugObj->flags3 = slugObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING |LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000); LegoObject_SetActivity(slugObj,Activity_Emerge,0); LegoObject_UpdateActivityChange(slugObj); ai::AITask_DoAnimationWait(slugObj); front::Info_Send(Info_SlugEmerge,NULL,slugObj,NULL); } } return slugObj; } LegoObject * __cdecl lego::game::LegoObject_TryGenerateRMonsterAtRandomBlock(void) { short rngBX; short rngBY; LegoObject_ID objID; Map3D *map; LegoObject *rmonsterObj; uint i; uint height; uint width; objID = lrr::Lego_GetEmergeCreatureID(); map = lrr::Lego_GetMap(); width = map->blockWidth; map = lrr::Lego_GetMap(); height = map->blockHeight; i = 0; do { rngBX = math::Maths_Rand(); rngBY = math::Maths_Rand(); rmonsterObj = LegoObject_TryGenerateRMonster (globs::legoGlobs.rockMonsterData + objID,LegoObject_RockMonster,objID, (int)rngBX % (int)width,(int)rngBY % (int)height); if (rmonsterObj != NULL) { return rmonsterObj; } i += 1; } while (i < 1000); return NULL; } // Fails if `objType != LegoObject_RockMonster`. LegoObject * __cdecl lego::game::LegoObject_TryGenerateRMonster (CreatureModel *objModel,LegoObject_Type objType,LegoObject_ID objID,uint bx,uint by) { BOOL BVar1; int iVar2; Map3D *surfMap; LegoObject *liveObj; Container *cont; uint uVar3; Point2I *blockPos; bool bVar4; uint uVar5; LegoObject_Type bx_00; uint uVar6; float *pfVar7; float *pfVar8; float local_44; float local_40; float local_3c; Point2I local_38; float local_30 [4]; Point2I local_20; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; uVar6 = by; bx_00 = bx; local_38.x = bx; local_38.y = by; if ((float)objType != 4.203895e-45) { return NULL; } BVar1 = Level_Block_IsWall(bx,by); if (BVar1 == 0) { return NULL; } BVar1 = Level_Block_IsReinforced(bx_00,uVar6); if (BVar1 != 0) { return NULL; } BVar1 = Level_Block_IsCorner(bx_00,uVar6); if (BVar1 != 0) { return NULL; } BVar1 = Level_Block_IsImmovable(&local_38); if (BVar1 != 0) { return NULL; } BVar1 = Level_Block_IsBusy(&local_38); if (BVar1 != 0) { return NULL; } uVar5 = 0; local_20.x = 0; local_20.y = -1; local_18 = 1; local_14 = 0; local_10 = 0; local_c = 1; local_8 = 0xffffffff; local_4 = 0; local_30[0] = 0.0; local_30[1] = 1.570796; local_30[2] = 3.141593; local_30[3] = 4.712389; blockPos = &local_20; do { blockPos->x = blockPos->x + bx_00; uVar3 = blockPos->y + uVar6; blockPos->y = uVar3; BVar1 = Level_Block_IsGround(blockPos->x,uVar3); if (((BVar1 != 0) && (BVar1 = Level_Block_IsFoundationOrBusyFloor(blockPos), BVar1 == 0)) && (iVar2 = Lego_GetCrossTerrainType(NULL,blockPos->x,blockPos->y,blockPos->x,blockPos->y,FALSE) , iVar2 != 0)) break; uVar5 += 1; blockPos = blockPos + 1; } while (uVar5 < 4); if (3 < uVar5) { return NULL; } pfVar8 = &local_3c; pfVar7 = &local_40; surfMap = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(surfMap,bx_00,uVar6,pfVar7,pfVar8); uVar6 = (&local_20)[uVar5].y; pfVar8 = (float *)&objType; pfVar7 = &local_44; uVar3 = (&local_20)[uVar5].x; surfMap = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(surfMap,uVar3,uVar6,pfVar7,pfVar8); local_44 = (local_40 * 9.0 + local_44 * 10.0) * 0.05263158; objType = (LegoObject_Type)((local_3c * 9.0 + (float)objType * 10.0) * 0.05263158); liveObj = LegoObject_CreateInWorld (objModel,LegoObject_RockMonster,objID,0,local_44,(float)objType, local_30[uVar5]); liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_EXPANDING; LegoObject_RockMonster_DoWakeUp(liveObj); LegoObject_SetActivity(liveObj,Activity_Emerge,0); LegoObject_UpdateActivityChange(liveObj); ai::AITask_DoAnimationWait(liveObj); cont = LegoObject_GetActivityContainer(liveObj); snd::SFX_Random_PlaySound3DOnContainer(cont,SFX_RockMonster2,FALSE,TRUE,NULL); Level_Block_SetBusy(&local_38,TRUE); bVar4 = false; (liveObj->targetBlockPos).x = (float)local_38.x; (liveObj->targetBlockPos).y = (float)local_38.y; BVar1 = lrr::Lego_GetObjectByName("RockMonster",&bx,&by,NULL); if (((BVar1 != 0) && (bx == liveObj->type)) && (by == liveObj->id)) { front::Info_Send(Info_RockMonster,NULL,liveObj,NULL); bVar4 = true; } if (!bVar4) { BVar1 = lrr::Lego_GetObjectByName("Lavamonster",&bx,&by,NULL); if (((BVar1 != 0) && (bx == liveObj->type)) && (by == liveObj->id)) { front::Info_Send(Info_LavaRockMonster,NULL,liveObj,NULL); bVar4 = true; } if (!bVar4) { BVar1 = lrr::Lego_GetObjectByName("Icemonster",&bx,&by,NULL); if (((BVar1 != 0) && (bx == liveObj->type)) && (by == liveObj->id)) { front::Info_Send(Info_IceRockMonster,NULL,liveObj,NULL); bVar4 = true; } if (!bVar4) goto LAB_0043b517; } } front::Info_Send(Info_GenericMonster,NULL,liveObj,NULL); LAB_0043b517: reward::RewardQuota_RockMonsterGenerated(); return liveObj; } void __cdecl lego::game::LegoObject_UpdateAll(float elapsedGame) { LegoObject_GlobFlags flagUnsetUpdating; LegoObject_GlobFlags flagPowerRecalc; // Were we updating our power grid after the update loop, last tick? if ((globs::objectGlobs.flags & OBJECT_GLOB_FLAG_POWERUPDATING) != OBJECT_GLOB_FLAG_NONE) { Level_PowerGrid_UnpowerPoweredBlocks(); } globs::objectGlobs.flags |= OBJECT_GLOB_FLAG_UPDATING; LegoObject_RunThroughLists(LegoObject_Callback_Update,&elapsedGame,FALSE); flagUnsetUpdating = globs::objectGlobs.flags & ~OBJECT_GLOB_FLAG_UPDATING; flagPowerRecalc = globs::objectGlobs.flags & OBJECT_GLOB_FLAG_POWERUPDATING; globs::objectGlobs.flags = flagUnsetUpdating; // Were we updating our power grid after the update loop, last tick? if (flagPowerRecalc != OBJECT_GLOB_FLAG_NONE) { Level_PowerGrid_UpdateUnpoweredBlockSurfaces(); } // Turn off power updating if an update is no longer needed. if ((globs::objectGlobs.flags & OBJECT_GLOB_FLAG_POWERNEEDSUPDATE) == OBJECT_GLOB_FLAG_NONE) { globs::objectGlobs.flags &= ~OBJECT_GLOB_FLAG_POWERUPDATING; } else { // Otherwise, restart the request for a power grid update (turns on POWERUPDATING flag). LegoObject_RequestPowerGridUpdate(); globs::objectGlobs.flags &= ~OBJECT_GLOB_FLAG_POWERNEEDSUPDATE; } LegoObject_Flocks_Update_FUN_0044c1c0(&elapsedGame); globs::objectGlobs.s_sound3DUpdateTimer = globs::objectGlobs.s_sound3DUpdateTimer - elapsedGame; if ((ushort)((ushort)(globs::objectGlobs.s_sound3DUpdateTimer < 0.0) << 8 | (ushort)(globs::objectGlobs.s_sound3DUpdateTimer == 0.0) << 0xe) != 0) { globs::objectGlobs.s_sound3DUpdateTimer = 125.0; lrr::Lego_UpdateAll3DSounds(TRUE); } return; } void __cdecl lego::game::LegoObject_RemoveAll(void) { globs::objectGlobs.flags |= OBJECT_GLOB_FLAG_REMOVING; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_Remove,NULL); globs::objectGlobs.flags = globs::objectGlobs.flags & ~OBJECT_GLOB_FLAG_REMOVING; return; } // RunThroughLists wrapper for LegoObject_Remove BOOL __cdecl lego::game::LegoObject_Callback_Remove(LegoObject *liveObj,void *data_unused) { BOOL BVar1; BVar1 = LegoObject_Remove(liveObj); return BVar1; } BOOL __cdecl lego::game::LegoObject_DoPickSphereSelection(uint mouseX,uint mouseY,LegoObject **selectedObj) { BOOL BVar1; SearchObjectMouseXY_c search; search.refObj = selectedObj; *selectedObj = NULL; search.mouseX = (float)(ulonglong)mouseX; search.mouseY = (float)(ulonglong)mouseY; BVar1 = LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_PickSphereSelection,&search); return BVar1; } // WARNING: Type propagation algorithm not settling BOOL __cdecl lego::game::LegoObject_Callback_PickSphereSelection (LegoObject *liveObj,SearchObjectMouseXY_c *search) { BOOL BVar1; Map3D *map; Container *cont; Point2I *pPVar2; uint uVar3; uint uVar4; Direction rotation; Vector3F *pVVar5; Viewport *view; float10 fVar6; uint bx; Vector3F *pVVar7; float xPos; Vector3F *camera; float *out_y; float yPos; uint local_d0; uint local_cc; Point2I *local_c8; Viewport *local_c4; Vector4F local_c0; Vector3F local_b0; Vector3F local_a4; Point2I local_98; Vector3F local_90; Vector3F local_84; Vector3F local_78 [10]; view = globs::legoGlobs.viewMain; local_c0.x = search->mouseX; local_c0.y = search->mouseY; rotation = DIRECTION_RIGHT; local_c4 = globs::legoGlobs.viewMain; local_c0.z = 0.0; local_c0.w = 1.0; BVar1 = LegoObject_IsActive(liveObj,1); if (BVar1 != 0) { LegoObject_GetBlockPos(liveObj,&local_98.x,&local_98.y); LegoObject_GetPosition(liveObj,&local_78[0].x,&local_78[0].y); map = lrr::Lego_GetMap(); fVar6 = lego::map::Map3D_GetWorldZ(map,local_78[0].x,local_78[0].y); local_78[0].z = (float)fVar6; fVar6 = stats::StatsObject_GetCollHeight(liveObj); local_78[0].z = (float)((float10)local_78[0].z - fVar6 * (float10)0.5); if (liveObj->type == LegoObject_Building) { cont = LegoObject_GetActivityContainer(liveObj); uVar4 = 0; gfx::Container_GetOrientation(cont,NULL,&local_b0,NULL); if (ABS(local_b0.x) <= ABS(local_b0.y)) { if ((ushort)((ushort)(local_b0.y < 0.0) << 8 | (ushort)(local_b0.y == 0.0) << 0xe) == 0) { rotation = DIRECTION_UP; } else { rotation = DIRECTION_DOWN; } } else { if ((ushort)((ushort)(local_b0.x < 0.0) << 8 | (ushort)(local_b0.x == 0.0) << 0xe) != 0) { rotation = DIRECTION_LEFT; } } pPVar2 = gfx::Building_GetShapePoints(globs::legoGlobs.buildingData + liveObj->id,&local_cc); pPVar2 = gfx::SelectPlace_TransformShapePoints(&local_98,pPVar2,local_cc,rotation); local_d0 = 0; if (local_cc != 0) { local_c8 = pPVar2 + 1; pVVar5 = local_78; uVar3 = local_cc; do { if (((uVar4 == uVar3 - 1) || (pPVar2->x != local_c8->x)) || (pPVar2->y != local_c8->y)) { uVar3 = pPVar2->y; bx = pPVar2->x; pVVar7 = pVVar5; out_y = &pVVar5->y; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,uVar3,&pVVar7->x,out_y); yPos = pVVar5->y; xPos = pVVar5->x; map = lrr::Lego_GetMap(); fVar6 = lego::map::Map3D_GetWorldZ(map,xPos,yPos); pVVar5->z = (float)fVar6; fVar6 = stats::StatsObject_GetCollHeight(liveObj); local_d0 += 1; pVVar5->z = (float)((float10)pVVar5->z - fVar6 * (float10)0.5); uVar3 = local_cc; pVVar5 = pVVar5 + 1; } else { uVar4 += 1; local_c8 = local_c8 + 1; pPVar2 = pPVar2 + 1; } uVar4 += 1; local_c8 = local_c8 + 1; pPVar2 = pPVar2 + 1; view = local_c4; } while (uVar4 < uVar3); } } else { local_d0 = 1; } lego::view::Viewport_InverseTransform(view,&local_a4,&local_c0); local_c0.z = 1.0; lego::view::Viewport_InverseTransform(view,&local_84,&local_c0); local_90.x = local_84.x - local_a4.x; local_84.y = local_84.y - local_a4.y; local_84.z = local_84.z - local_a4.z; uVar4 = 0; local_90.z = 1.0 / SQRT(local_84.z * local_84.z + local_84.y * local_84.y + local_90.x * local_90.x); local_90.x = local_90.z * local_90.x; local_90.y = local_90.z * local_84.y; local_90.z = local_90.z * local_84.z; if (local_d0 != 0) { pVVar5 = local_78; do { pVVar7 = &local_90; camera = &local_a4; fVar6 = stats::StatsObject_GetPickSphere(liveObj); BVar1 = math::Maths_RaySphereIntersection(pVVar5,(float)fVar6,camera,pVVar7); if (BVar1 != 0) { *search->refObj = liveObj; return TRUE; } uVar4 += 1; pVVar5 = pVVar5 + 1; } while (uVar4 < local_d0); return 0; } } return 0; } void __cdecl lego::game::LegoObject_DoDragSelection(Viewport *view,Point2F *dragStart,Point2F *dragEnd) { TutorialFlags tflags; SearchViewportWindow_14 search; tflags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if ((tflags & TUTORIAL_FLAG_NOOBJECTS) == TUTORIAL_NONE) { search.view = view; if (dragEnd->x <= dragStart->x) { search.dragStart.x = dragEnd->x; } else { search.dragStart.x = dragStart->x; } if ((ushort)((ushort)(dragEnd->y < dragStart->y) << 8 | (ushort)(dragEnd->y == dragStart->y) << 0xe) == 0) { search.dragStart.y = dragStart->y; } else { search.dragStart.y = dragEnd->y; } if ((ushort)((ushort)(dragStart->x < dragEnd->x) << 8 | (ushort)(dragStart->x == dragEnd->x) << 0xe) == 0) { search.dragEnd.x = dragStart->x; } else { search.dragEnd.x = dragEnd->x; } if (dragStart->y <= dragEnd->y) { search.dragEnd.y = dragEnd->y; } else { search.dragEnd.y = dragStart->y; } LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackDoSelection,&search); Message_PostEvent(Message_ReduceSelection,0,0,NULL); } return; } BOOL __cdecl lego::game::LegoObject_CallbackDoSelection(LegoObject *liveObj,SearchViewportWindow_14 *search) { float fVar1; Container *cont; Vector3F position; Vector4F viewObjPos; cont = LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(cont,NULL,&position); lego::view::Viewport_Transform(search->view,&viewObjPos,&position); viewObjPos.x = viewObjPos.x / viewObjPos.w; viewObjPos.y = viewObjPos.y / viewObjPos.w; if (((((search->dragStart).x <= viewObjPos.x) && ((search->dragStart).y <= viewObjPos.y)) && (fVar1 = (search->dragEnd).x, (ushort)((ushort)(viewObjPos.x < fVar1) << 8 | (ushort)(viewObjPos.x == fVar1) << 0xe) != 0)) && (fVar1 = (search->dragEnd).y, (ushort)((ushort)(viewObjPos.y < fVar1) << 8 | (ushort)(viewObjPos.y == fVar1) << 0xe) != 0) ) { Message_PostEvent(Message_Select,liveObj,1,NULL); } return 0; } void __cdecl lego::game::LegoObject_SwapPolyFP(LegoObject *liveObj,uint cameraNo,BOOL on) { if ((liveObj->type == LegoObject_MiniFigure) || ((liveObj = liveObj->driveObject, liveObj != NULL && (liveObj->type == LegoObject_MiniFigure))) ) { gfx::Creature_SwapPolyFP(liveObj->miniFigure,on,cameraNo); } return; } // if onCont is true, position of cont will be used in search. void __cdecl lego::game::LegoObject_FP_SetRanges (LegoObject *liveObj,Container *cont,float medPolyRange,float highPolyRange,BOOL onCont) { LegoObject *pLVar1; LiveObjectInfo liveInfo; liveInfo.point_8.x = medPolyRange; liveInfo.point_8.y = highPolyRange; liveInfo.liveObj = liveObj; liveInfo.vector_10.x = 0.0; liveInfo.intbool_4 = onCont; liveInfo.vector_10.y = 0.0; liveInfo.vector_10.z = 0.0; if (((liveObj->type != LegoObject_MiniFigure) && (pLVar1 = liveObj->driveObject, pLVar1 != NULL)) && (pLVar1->type == LegoObject_MiniFigure)) { liveInfo.liveObj = pLVar1; } if (onCont != 0) { gfx::Container_GetPosition(cont,NULL,&liveInfo.vector_10); } LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_FP_Callback_SwapPolyMeshParts,&liveInfo); return; } BOOL __cdecl lego::game::LegoObject_FP_Callback_SwapPolyMeshParts(LegoObject *liveObj,LiveObjectInfo *liveInfo) { float fVar1; LOD_PolyLevel LVar2; LegoObject_Type LVar3; float fVar4; float fVar5; Container *cont; Vector3F vector; if (liveObj != liveInfo->liveObj) { LVar2 = liveObj->polyLOD; if (liveInfo->intbool_4 == 0) { if (LVar2 == LOD_MediumPoly) { LVar3 = liveObj->type; if (LVar3 == LegoObject_MiniFigure) { gfx::Creature_SwapPolyMedium(liveObj->miniFigure,FALSE); } else { if (LVar3 == LegoObject_RockMonster) { gfx::Creature_SwapPolyMedium(liveObj->rockMonster,FALSE); } else { if (LVar3 == LegoObject_Vehicle) { gfx::Vehicle_SwapPolyMedium(liveObj->vehicle,FALSE); } } } } else { if (LVar2 == LOD_HighPoly) { LVar3 = liveObj->type; if (LVar3 == LegoObject_MiniFigure) { gfx::Creature_SwapPolyHigh(liveObj->miniFigure,FALSE); } else { if (LVar3 == LegoObject_RockMonster) { gfx::Creature_SwapPolyHigh(liveObj->rockMonster,FALSE); } else { if (LVar3 == LegoObject_Vehicle) { gfx::Vehicle_SwapPolyHigh(liveObj->vehicle,FALSE); } } } } } liveObj->polyLOD = LOD_LowPoly; } else { if (LVar2 == LOD_LowPoly) { cont = LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(cont,NULL,&vector); fVar5 = (liveInfo->vector_10).x - vector.x; fVar1 = (liveInfo->vector_10).y - vector.y; fVar4 = (liveInfo->vector_10).z - vector.z; fVar4 = SQRT(fVar4 * fVar4 + fVar1 * fVar1 + fVar5 * fVar5); fVar1 = (liveInfo->point_8).y; if ((ushort)((ushort)(fVar4 < fVar1) << 8 | (ushort)(fVar4 == fVar1) << 0xe) != 0) { LVar3 = liveObj->type; if (LVar3 == LegoObject_MiniFigure) { gfx::Creature_SwapPolyHigh(liveObj->miniFigure,TRUE); liveObj->polyLOD = LOD_HighPoly; return 0; } if (LVar3 != LegoObject_RockMonster) { if (LVar3 == LegoObject_Vehicle) { gfx::Vehicle_SwapPolyHigh(liveObj->vehicle,TRUE); } liveObj->polyLOD = LOD_HighPoly; return 0; } gfx::Creature_SwapPolyHigh(liveObj->rockMonster,TRUE); liveObj->polyLOD = LOD_HighPoly; return 0; } fVar1 = (liveInfo->point_8).x; if ((ushort)((ushort)(fVar4 < fVar1) << 8 | (ushort)(fVar4 == fVar1) << 0xe) != 0) { LVar3 = liveObj->type; if (LVar3 == LegoObject_MiniFigure) { gfx::Creature_SwapPolyMedium(liveObj->miniFigure,TRUE); liveObj->polyLOD = LOD_MediumPoly; return 0; } if (LVar3 != LegoObject_RockMonster) { if (LVar3 == LegoObject_Vehicle) { gfx::Vehicle_SwapPolyMedium(liveObj->vehicle,TRUE); } liveObj->polyLOD = LOD_MediumPoly; return 0; } gfx::Creature_SwapPolyMedium(liveObj->rockMonster,TRUE); liveObj->polyLOD = LOD_MediumPoly; return 0; } } } } return 0; } BOOL __cdecl lego::game::LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(LegoObject *liveObj) { if ((liveObj->flags1 & (LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART| LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_UNUSED_10000000)) != LIVEOBJ1_NONE) { return TRUE; } return (uint)((liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_BUILDPATH|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER)) != LIVEOBJ2_NONE); } void __cdecl lego::game::LegoObject_FUN_0043bde0(LegoObject *liveObj) { StatsFlags1 sflags1; uint uVar1; uint uVar2; if (liveObj->type == LegoObject_Building) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_PROCESSORE) == STATS1_NONE) { uVar2 = liveObj->numCarriedObjects; } else { uVar2 = liveObj->carryNullFrames; uVar1 = stats::StatsObject_GetMaxCarry(liveObj); if (uVar1 <= uVar2) { uVar2 = stats::StatsObject_GetMaxCarry(liveObj); } } if (((liveObj->numCarriedObjects < uVar2) || ((liveObj->flags1 & LIVEOBJ1_STORING) != LIVEOBJ1_NONE)) || ((liveObj->flags3 & LIVEOBJ3_UNK_1000000) != LIVEOBJ3_NONE)) { // & ~LIVEOBJ3_UNK_1000000 (0x1000000) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING |LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); } else { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_PROCESSCRYSTAL) != STATS1_NONE) || (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj), (sflags1 & STATS1_PROCESSORE) != STATS1_NONE)) { LegoObject_TryDepositCarried(liveObj,NULL); return; } } } return; } void __cdecl lego::game::LegoObject_FinishEnteringWallHole(LegoObject *liveObj) { LegoObject *crystalObj; if (liveObj->type == LegoObject_RockMonster) { crystalObj = liveObj->carriedObjects[0]; if ((crystalObj != NULL) && (crystalObj->type == LegoObject_PowerCrystal)) { liveObj->carriedObjects[0] = NULL; liveObj->numCarriedObjects = 0; crystalObj->carryingThisObject = NULL; // & ~LIVEOBJ1_CARRYING (0x400) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); crystalObj->health = -1.0; } if (liveObj->stolenCrystalLevels != NULL) { Level_AddStolenCrystals(*liveObj->stolenCrystalLevels); } liveObj->health = -1.0; liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_REMOVING; } return; } void __cdecl lego::game::LegoObject_UpdateRemoval(LegoObject *liveObj) { StatsFlags1 sflags1; StatsFlags2 sflags2; Container *cont; StatsFlags3 sflags3; int iVar1; float10 fVar2; Info_Type infoType; float x; float y; float z; Point2I blockPos2; Point2I blockPos; char *actName; LiveFlags3 lflags3; LegoObject_Type objType; LiveFlags1 *pLFlags1; LegoObject *teleObj; if (liveObj->type != LegoObject_Building) { if ((liveObj->flags2 & LIVEOBJ2_FROZEN) != LIVEOBJ2_NONE) { return; } if ((liveObj->flags1 & LIVEOBJ1_TELEPORTINGDOWN) != LIVEOBJ1_NONE) { return; } } if ((ushort)((ushort)(liveObj->health < 0.0) << 8 | (ushort)(liveObj->health == 0.0) << 0xe) == 0) { return; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((((sflags1 & (STATS1_SMALLTELEPORTER|STATS1_BIGTELEPORTER|STATS1_WATERTELEPORTER|STATS1_MANTELEPORTER)) != STATS1_NONE) && (teleObj = liveObj->teleportDownObject, teleObj != NULL)) && ((teleObj->flags1 & LIVEOBJ1_TELEPORTINGDOWN) != LIVEOBJ1_NONE)) { teleObj->health = -1.0; pLFlags1 = &liveObj->teleportDownObject->flags1; // & ~LIVEOBJ1_TELEPORTINGDOWN (0x200000) *pLFlags1 = *pLFlags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); LegoObject_FUN_00438720(liveObj); LegoObject_SetActivity(liveObj->teleportDownObject,Activity_Stand,TRUE); LegoObject_UpdateActivityChange(liveObj->teleportDownObject); } lflags3 = liveObj->flags3; if ((lflags3 & LIVEOBJ3_REMOVING) != LIVEOBJ3_NONE) { if (liveObj->driveObject != NULL) { front::Interface_ChangeMenu_IfPrimarySelectedVehicle_IsLiveObject(liveObj); // & ~LIVEOBJ2_DRIVING (0x8) liveObj->driveObject->flags2 = liveObj->driveObject->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); liveObj->driveObject->driveObject = NULL; liveObj->driveObject = NULL; } if ((liveObj->type == LegoObject_MiniFigure) && ((*(byte *)&liveObj->flags4 & LIVEOBJ4_UNK_8) != 0)) { ObjectRecall_StoreMiniFigure(liveObj); } if (liveObj->type == LegoObject_Vehicle) { gfx::Vehicle_SetUpgradeLevel(liveObj->vehicle,0); } LegoObject_FUN_0044b0a0(liveObj); if (liveObj->type == LegoObject_Boulder) { LegoObject_DestroyBoulder_AndCreateExplode(liveObj); return; } if (liveObj->type == LegoObject_Building) { Construction_RemoveBuildingObject(liveObj); return; } LegoObject_Remove(liveObj); return; } objType = liveObj->type; if (objType == LegoObject_RockMonster) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_SPLITONZEROHEALTH) == STATS2_NONE) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_USEHOLES) == STATS2_NONE) { return; } LegoObject_Interrupt(liveObj,FALSE,TRUE); liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_ENTERING_WALLHOLE; LegoObject_SetActivity(liveObj,Activity_Enter,FALSE); LegoObject_UpdateActivityChange(liveObj); return; } if ((liveObj->flags1 & LIVEOBJ1_CRUMBLING) != LIVEOBJ1_NONE) { return; } LegoObject_StartCrumbling(liveObj); return; } if (((objType != LegoObject_MiniFigure) && (objType != LegoObject_Vehicle)) && (objType != LegoObject_ElectricFence)) { if (objType != LegoObject_Building) { LAB_0043c168: if (objType != LegoObject_PowerCrystal) { return; } liveObj->flags3 = lflags3 | LIVEOBJ3_REMOVING; return; } if (((*(byte *)&liveObj->teleporter_modeFlags & 4) == 0) && ((*(byte *)&liveObj->flags4 & 8) == 0)) { if (false) goto LAB_0043c168; if ((liveObj->flags2 & LIVEOBJ2_UNK_100000) != LIVEOBJ2_NONE) { return; } liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_100000; Construction_CleanupBuildingFoundation(liveObj); LegoObject_SetActivity(liveObj,Activity_Explode,0); LegoObject_UpdateActivityChange(liveObj); ai::AITask_StopRepairForObject(liveObj); goto LAB_0043c4a7; } } if ((lflags3 & LIVEOBJ3_CANDAMAGE) == LIVEOBJ3_NONE) { return; } if ((liveObj->flags1 & LIVEOBJ1_TELEPORTINGUP) != LIVEOBJ1_NONE) { return; } actName = liveObj->activityName1; cont = LegoObject_GetActivityContainer(liveObj); if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_UNK_8) != 0) { LegoObject_FUN_0044b0a0(liveObj); } if (liveObj->type == LegoObject_Building) { Construction_CleanupBuildingFoundation(liveObj); } if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_ENTRANCEOCCUPIED) != 0) { teleObj = liveObj->routeToObject; if (teleObj != NULL) { teleObj->flags4 = teleObj->flags4 & ~LIVEOBJ4_ENTRANCEOCCUPIED; } liveObj->routeToObject = NULL; } if (liveObj->driveObject != NULL) { LegoObject_GetBlockPos(liveObj,&blockPos2.x,&blockPos2.y); sflags3 = stats::StatsObject_GetStatsFlags3(liveObj); if (((((sflags3 & STATS3_CARRYVEHICLES) != STATS3_NONE) && ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) && (liveObj->carriedObjects[0] != NULL)) && (iVar1 = Lego_GetCrossTerrainType (liveObj->carriedObjects[0],blockPos2.x,blockPos2.y,blockPos2.x, blockPos2.y,TRUE), iVar1 == 0)) { liveObj->carriedObjects[0]->health = -1.0; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) || (iVar1 = Lego_GetCrossTerrainType (liveObj->driveObject,blockPos2.x,blockPos2.y,blockPos2.x,blockPos2.y,TRUE ), iVar1 != 0)) { front::Interface_ChangeMenu_IfPrimarySelectedVehicle_IsLiveObject(liveObj); // & ~LIVEOBJ2_DRIVING (0x8) liveObj->driveObject->flags2 = liveObj->driveObject->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); if (liveObj->driveObject->type == LegoObject_MiniFigure) { gfx::Creature_SetActivity (liveObj->driveObject->miniFigure,globs::objectGlobs.activityName[0],0.0); } liveObj->driveObject->driveObject = NULL; liveObj->driveObject = NULL; } else { liveObj->driveObject->health = -1.0; } } if (liveObj->type == LegoObject_ElectricFence) { ElectricFence_RemoveFence(liveObj); } LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); objType = liveObj->type; if (((objType == LegoObject_MiniFigure) || (objType == LegoObject_Vehicle)) || (objType == LegoObject_Building)) { front::Info_Send(Info_GenericDeath,NULL,NULL,&blockPos); } objType = liveObj->type; if (objType == LegoObject_MiniFigure) { infoType = Info_LegoManDeath; LAB_0043c382: front::Info_Send(infoType,NULL,NULL,&blockPos); } else { if (objType == LegoObject_Vehicle) { infoType = Info_VehicleDeath; goto LAB_0043c382; } if (objType == LegoObject_Building) { infoType = Info_BuildingDeath; goto LAB_0043c382; } } if ((*(byte *)&liveObj->flags2 & 2) == 0) { LegoObject_Interrupt(liveObj,FALSE,TRUE); gfx::Container_SetActivity(cont,actName); liveObj->activityName2 = liveObj->activityName1; } else { LegoObject_Interrupt(liveObj,TRUE,TRUE); } liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_TELEPORTINGUP; cont = gfx::Container_Clone(globs::legoGlobs.contMiniTeleportUp); liveObj->contMiniTeleportUp = cont; gfx::Container_SetAnimationTime(cont,0.0); gfx::Container_Hide(liveObj->contMiniTeleportUp,FALSE); z = 0.0; y = 0.0; x = 0.0; cont = LegoObject_GetActivityContainer(liveObj); gfx::Container_SetPosition(liveObj->contMiniTeleportUp,cont,x,y,z); gfx::Container_SetOrientation(liveObj->contMiniTeleportUp,NULL,0.0,1.0,0.0,0.0,0.0,-1.0); if (liveObj->type == LegoObject_Building) { fVar2 = stats::StatsObject_GetCollRadius(liveObj); if ((ushort)((ushort)(fVar2 < (float10)0.0) << 8 | (ushort)(fVar2 == (float10)0.0) << 0xe) != 0) { fVar2 = (float10)4.0; } if ((ushort)((ushort)(fVar2 < (float10)0.0) << 8 | (ushort)(fVar2 == (float10)0.0) << 0xe) == 0) { gfx::Container_AddScale (liveObj->contMiniTeleportUp,Container_Combine_Before,(float)(fVar2 * (float10)0.25) ,1.0,(float)(fVar2 * (float10)0.25)); } } LAB_0043c4a7: Message_DeselectObject(liveObj); Message_RemoveObjectReference(liveObj); return; } // producerType/ID always points to "Barracks" (aka the Support Station). BOOL __cdecl lego::game::LegoObject_CanSupportOxygenForType (LegoObject_Type consumerType,LegoObject_ID consumerID,LegoObject_Type producerType, LegoObject_ID producerID) { float10 producerCoef; float10 consumerCoef; float10 totalCoef; LegoObject_ID consumerID_00; consumerID_00 = consumerID; consumerCoef = stats::Stats_GetOxygenCoef(consumerType,consumerID); if (consumerCoef != (float10)0.0) { consumerID = 0; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_SumOfOxygenCoefs,&consumerID); producerCoef = stats::Stats_GetOxygenCoef(producerType,producerID); consumerCoef = stats::Stats_GetOxygenCoef(consumerType,consumerID_00); totalCoef = consumerCoef + (float10)(float)producerCoef + (float10)(float)consumerID; // if (totalCoef <= 0.0f) if ((ushort)((ushort)(totalCoef < (float10)0.0) << 8 | (ushort)(totalCoef == (float10)0.0) << 0xe) != 0) { return FALSE; } } return TRUE; } BOOL __cdecl lego::game::LegoObject_Callback_SumOfOxygenCoefs(LegoObject *liveObj,float *oxygenCoef) { BOOL powered; float10 coef; if ((liveObj->type == LegoObject_Building) && (powered = LegoObject_IsActive(liveObj,FALSE), powered == 0)) { return 0; } coef = stats::StatsObject_GetOxygenCoef(liveObj); *oxygenCoef = (float)(coef + (float10)*oxygenCoef); return 0; } void __cdecl lego::game::LegoObject_UpdateAllRadarSurvey(float elapsedGame,BOOL isRadarMapView) { globs::objectGlobs.radarSurveyCycleTimer = elapsedGame + globs::objectGlobs.radarSurveyCycleTimer; if ((ushort)((ushort)(globs::objectGlobs.radarSurveyCycleTimer < 25.0) << 8 | (ushort)(globs::objectGlobs.radarSurveyCycleTimer == 25.0) << 0xe) == 0) { globs::objectGlobs.radarSurveyCycleTimer = 0.0; } LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_UpdateRadarSurvey,&isRadarMapView); return; } BOOL __cdecl lego::game::LegoObject_Callback_UpdateRadarSurvey(LegoObject *liveObj,BOOL *pIsRadarMapView) { uint surveyRadius; BOOL BVar1; Map3D *map; RadarMap *radarMap; float10 fVar2; Point2F *center; float fVar3; float brightness; Point2I blockPos; Point2F position; fVar3 = globs::objectGlobs.radarSurveyCycleTimer * 0.04; if (((*(byte *)&liveObj->abilityFlags & LIVEOBJ5_ABILITY_SCANNER) != 0) && (surveyRadius = stats::StatsObject_GetSurveyRadius(liveObj), surveyRadius != 0)) { blockPos.x = surveyRadius; if ((liveObj->type == LegoObject_Building) && (BVar1 = LegoObject_IsActive(liveObj,FALSE), BVar1 == 0)) { return 0; } if (globs::objectGlobs.radarSurveyCycleTimer == 0.0) { LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); Level_Block_UpdateSurveyRadius_FUN_00434f40(&blockPos,surveyRadius); return 0; } // Radar map is in-view, update rendering right now? if (*pIsRadarMapView != FALSE) { LegoObject_GetPosition(liveObj,&position.x,&position.y); brightness = 1.0 - fVar3; map = lrr::Lego_GetMap(); fVar2 = lego::map::Map3D_BlockSize(map); center = &position; fVar3 = (float)(fVar2 * (float10)fVar3 * (float10)blockPos.x); radarMap = lrr::Lego_GetRadarMap(); RadarMap_DrawSurveyDotCircle(radarMap,center,fVar3,brightness); } } return 0; } BOOL __cdecl lego::game::LegoObject_FUN_0043c6a0(LegoObject *liveObj) { BOOL BVar1; AITask *aiTask; if ((((liveObj != NULL) && (liveObj->type == LegoObject_MiniFigure)) && (aiTask = liveObj->aiTask, aiTask != NULL)) && (aiTask->taskType == AITask_Type_AttackRockMonster)) { BVar1 = tools::Weapon_LegoObject_WithinWeaponRange(liveObj,aiTask->targetObject); if (BVar1 != 0) { BVar1 = tools::Weapon_LegoObject_DoCallbacksSearch_FUN_00471b90 (liveObj,liveObj->aiTask->targetObject); if (BVar1 == 0) { return TRUE; } } } return FALSE; } Weapon_KnownType __cdecl lego::game::LegoObject_GetEquippedBeam(LegoObject *liveObj) { BOOL BVar1; BVar1 = LegoObject_HasToolEquipped(liveObj,LegoObject_ToolType_Laser); if (BVar1 != 0) { return Weapon_KnownType_Laser; } BVar1 = LegoObject_HasToolEquipped(liveObj,LegoObject_ToolType_PusherGun); if (BVar1 != 0) { return Weapon_KnownType_Pusher; } BVar1 = LegoObject_HasToolEquipped(liveObj,LegoObject_ToolType_FreezerGun); return -(uint)(BVar1 != 0) & Weapon_KnownType_Freezer; } // Function cannot return true unless param_3 is non-zero. BOOL __cdecl lego::game::LegoObject_FUN_0043c750 (LegoObject *liveObj,LegoObject *routeToObject,Weapon_KnownType knownWeapon) { BOOL BVar1; BVar1 = LegoObject_IsActive(routeToObject,TRUE); if ((BVar1 != 0) && (knownWeapon != Weapon_KnownType_None)) { return TRUE; } return FALSE; } void __cdecl lego::game::LegoObject_Proc_FUN_0043c780(LegoObject *liveObj) { Weapon_KnownType knownWeapon; BOOL BVar1; if (liveObj->routeToObject != NULL) { knownWeapon = LegoObject_GetEquippedBeam(liveObj); BVar1 = LegoObject_FUN_0043c750(liveObj,liveObj->routeToObject,knownWeapon); if (BVar1 != 0) { LegoObject_FireBeamWeaponAtObject(liveObj,liveObj->routeToObject,knownWeapon); } } // & ~LIVEOBJ2_UNK_4000000 (0x4000000) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); ai::AITask_LiveObject_SetAITaskUnk(liveObj,AITask_Type_AttackRockMonster,NULL,TRUE); return; } void __cdecl lego::game::LegoObject_Proc_FUN_0043c7f0(LegoObject *liveObj) { if ((((liveObj != NULL) && (liveObj->type == LegoObject_MiniFigure)) && (liveObj->aiTask != NULL)) && (liveObj->aiTask->taskType == AITask_Type_AttackRockMonster)) { liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_4000000; LegoObject_Proc_FUN_0043c780(liveObj); } return; } void __cdecl lego::game::LegoObject_UpdatePowerConsumption(LegoObject *liveObj) { int crystalDrainedAmount; BOOL BVar1; StatsFlags2 sflags2; int crystals; Point2I blockPos; if ((liveObj->type == LegoObject_Building) && ((liveObj->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE)) { crystalDrainedAmount = stats::StatsObject_GetCrystalDrain(liveObj); LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_GENERATEPOWER) == STATS2_NONE) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_SELFPOWERED) == STATS2_NONE) { BVar1 = Construction_PowerGrid_DrainAdjacentBlocks(&blockPos,crystalDrainedAmount); if (BVar1 == 0) { liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_UNK_40000000| LIVEOBJ3_POWEROFF); front::Bubble_ShowPowerOff(liveObj); return; } } } liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_HASPOWER; sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_GENERATEPOWER) != STATS2_NONE) { // Check if building generates power, and is not "powered-off" (which is normally not // possible outside of debug mode). BVar1 = LegoObject_IsActive(liveObj,FALSE); if (BVar1 != 0) { crystals = Level_GetCrystalCount(TRUE); if (crystals != 0) { Construction_PowerGrid_PowerAdjacentBlocks(&blockPos); } } } } return; } BOOL __cdecl lego::game::LegoObject_CheckCanSteal(LegoObject *liveObj) { StatsFlags1 sflags1; uint capacity; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CANSTEAL) != STATS1_NONE) { capacity = stats::StatsObject_GetCapacity(liveObj); if (((capacity != 0) && (liveObj->stolenCrystalLevels != NULL)) && (capacity = stats::StatsObject_GetCapacity(liveObj), capacity <= (uint)*liveObj->stolenCrystalLevels)) { return 0; } if ((liveObj->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE) { return TRUE; } } return FALSE; } void __cdecl lego::game::LegoObject_UpdateElapsedTimes(LegoObject *liveObj,float elapsed) { float10 fVar1; float10 oldElapsedTime2_f; float lastElapsedTime1; float lastElapsedTime2; float newElapsedTime2; LegoObject_Type objType; newElapsedTime2 = elapsed + liveObj->elapsedTime2; lastElapsedTime2 = liveObj->elapsedTime2; lastElapsedTime1 = liveObj->elapsedTime1; liveObj->elapsedTime2 = newElapsedTime2; objType = liveObj->type; liveObj->elapsedTime1 = elapsed + liveObj->elapsedTime1; liveObj->eatWaitTimer = elapsed + liveObj->eatWaitTimer; if (objType == LegoObject_MiniFigure) { fVar1 = lrr::Lego_GetObjectUpgradeTime(LegoObject_MiniFigure); if (fVar1 != (float10)0.0) { fVar1 = lrr::Lego_GetObjectUpgradeTime(liveObj->type); if ((ushort)((ushort)(fVar1 < (float10)liveObj->elapsedTime2) << 8 | (ushort)(fVar1 == (float10)liveObj->elapsedTime2) << 0xe) != 0) { fVar1 = lrr::Lego_GetObjectUpgradeTime(liveObj->type); oldElapsedTime2_f = (float10)lastElapsedTime2; if ((ushort)((ushort)(fVar1 < oldElapsedTime2_f) << 8 | (ushort)(fVar1 == oldElapsedTime2_f) << 0xe) == 0) { front::Info_Send(Info_CanUpgradeMinifigure,NULL,liveObj,NULL); } } } fVar1 = lrr::Lego_GetTrainTime(); if (fVar1 != (float10)0.0) { fVar1 = lrr::Lego_GetTrainTime(); if ((ushort)((ushort)(fVar1 < (float10)liveObj->elapsedTime1) << 8 | (ushort)(fVar1 == (float10)liveObj->elapsedTime1) << 0xe) != 0) { fVar1 = lrr::Lego_GetTrainTime(); if ((ushort)((ushort)(fVar1 < (float10)lastElapsedTime1) << 8 | (ushort)(fVar1 == (float10)lastElapsedTime1) << 0xe) == 0) { front::Info_Send(Info_CanTrainMinifigure,NULL,liveObj,NULL); return; } } } } else { if (((((objType == LegoObject_PowerCrystal) || (objType == LegoObject_Ore)) || (objType == LegoObject_Barrier)) || ((objType == LegoObject_ElectricFence && ((liveObj->flags2 & LIVEOBJ2_ACTIVEELECTRICFENCE) == LIVEOBJ2_NONE)))) && ((750.0 <= newElapsedTime2 && (lastElapsedTime2 < 750.0)))) { liveObj->elapsedTime2 = 0.0; ai::AITask_LiveObject_FUN_004025f0(liveObj); } } return; } BOOL __cdecl lego::game::LegoObject_Callback_Update(LegoObject *liveObj,float *pElapsed) { float elapsed; ushort uVar1; ushort uVar2; short rng; Container *pCVar3; SFX_ID sfxID; int iVar4; BOOL BVar5; LiveFlags4 lflags4; Lego_Level *level; StatsFlags1 sflags1; LiveFlags3 lflags3; Container *pCVar6; Lego_SurfaceType surfaceType; Map3D *map; StatsFlags2 sflags2; uint uVar7; Construction_Zone *construct; LiveFlags1 lflags1; uint uVar8; float10 fVar9; longlong lVar10; float fVar11; float fVar12; LegoObject *pLVar13; BOOL BVar14; float fVar15; Vector3F *pVVar16; undefined4 uVar17; float fVar18; float upz; float *out_by; float local_34; Vector3F local_30; float local_24; Vector3F local_20; BOOL reinforcingFinished; float local_10; Vector3F local_c; Activity_Type abilityType; LiveFlags2 lflags2; LegoObject *liveObj_00; LegoObject_Type objType; LiveFlags3 *pLFlags3_routeObj; LiveFlags4 *pLFlags4_routeObj; RoutingBlock *routeBlock; bool shouldStopDrillSound; liveObj_00 = liveObj; elapsed = *pElapsed; shouldStopDrillSound = true; s_currentUpdateObject = liveObj; LegoObject_UpdateElapsedTimes(liveObj,elapsed); if ((liveObj_00->flags4 & LIVEOBJ4_UNK_200000) != LIVEOBJ4_NONE) { liveObj_00->activityName1 = NULL; LegoObject_UpdateActivityChange(liveObj_00); liveObj_00->flags4 = liveObj_00->flags4 & ~LIVEOBJ4_UNK_200000; } if ((liveObj_00->flags2 & LIVEOBJ2_FROZEN) != LIVEOBJ2_NONE) { // if (liveObj_00->freezeTimer <= 0.0f) if ((ushort)((ushort)(liveObj_00->freezeTimer < 0.0) << 8 | (ushort)(liveObj_00->freezeTimer == 0.0) << 0xe) != 0) { LegoObject_FUN_0044c3d0(liveObj_00); } liveObj_00->freezeTimer = liveObj_00->freezeTimer - elapsed; return 0; } if ((liveObj_00->flags4 & LIVEOBJ4_UNK_40000) != LIVEOBJ4_NONE) { pCVar3 = LegoObject_GetActivityContainer(liveObj_00); if ((pCVar3 != NULL) && (sfxID = stats::StatsObject_GetEngineSound(liveObj_00), sfxID != SFX_NULL)) { iVar4 = snd::SFX_Random_PlaySound3DOnContainer(pCVar3,sfxID,TRUE,TRUE,NULL); liveObj_00->engineSoundHandle = iVar4; liveObj_00->flags4 = liveObj_00->flags4 | LIVEOBJ4_ENGINESOUNDPLAYING; } liveObj_00->flags4 = liveObj_00->flags4 & ~LIVEOBJ4_UNK_40000; } if ((((byte)globs::legoGlobs.flags2 & GAME2_CALLTOARMS) == 0) || (BVar5 = LegoObject_MiniFigureHasBeamEquipped2(liveObj_00), BVar5 == 0)) { front::Bubble_SetCallToArmsTimer(liveObj_00,0.0); lflags4 = liveObj_00->flags4 & ~LIVEOBJ4_CALLTOARMS; } else { // Update MiniFigure with Call-to-arms behavior? front::Bubble_ShowCallToArms(liveObj_00); lflags4 = liveObj_00->flags4 | LIVEOBJ4_CALLTOARMS; } liveObj_00->flags4 = lflags4; if ((((liveObj_00->type == LegoObject_Vehicle) && ((liveObj_00->flags4 & LIVEOBJ4_DOCKOCCUPIED) != LIVEOBJ4_NONE)) && (liveObj_00->routeToObject == NULL)) && (liveObj_00->driveObject == NULL)) { liveObj_00->flags4 = liveObj_00->flags4 & ~LIVEOBJ4_DOCKOCCUPIED; LegoObject_WaterVehicle_Register(liveObj_00); } if ((liveObj_00->type == LegoObject_MiniFigure) || (liveObj_00->type == LegoObject_Vehicle)) { level = lrr::Lego_GetLevel(); LegoObject_GetBlockPos(liveObj_00,(int *)&local_20,(int *)&local_20.y); if ((*(byte *)&level->blocks[level->width * (int)local_20.y + (int)local_20.x].flags2 & BLOCK2_EMERGE_TRIGGER) != 0) { Level_HandleEmergeTriggers(level,(Point2I *)&local_20,NULL); } } LegoObject_FUN_0043bde0(liveObj_00); if (((liveObj_00->type == LegoObject_MiniFigure) && ((*(byte *)&liveObj_00->flags2 & LIVEOBJ2_DRIVING) != 0)) && ((pLVar13 = liveObj_00->driveObject, pLVar13 != NULL && (pLVar13->type == LegoObject_Vehicle))) ) { fVar9 = gfx::Vehicle_GetAnimationTime(pLVar13->vehicle); gfx::Creature_SetAnimationTime(liveObj_00->miniFigure,(float)fVar9); } else { fVar9 = LegoObject_MoveAnimation(liveObj_00,elapsed); local_10 = (float)fVar9; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); if ((sflags1 & (STATS1_SMALLTELEPORTER|STATS1_BIGTELEPORTER|STATS1_WATERTELEPORTER|STATS1_MANTELEPORTER)) != STATS1_NONE) { LegoObject_UpdateTeleporter(liveObj_00); } if ((liveObj_00->type != LegoObject_Building) || (BVar5 = LegoObject_IsActive(liveObj_00,FALSE), BVar5 != 0)) { Level_ConsumeObjectOxygen(liveObj_00,elapsed); } if (((byte)globs::objectGlobs.flags & OBJECT_GLOB_FLAG_POWERUPDATING) == 0) { // & ~LIVEOBJ3_UNK_40000000 (0x40000000) liveObj_00->flags3 = liveObj_00->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING| LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_POWEROFF); } else { LegoObject_UpdatePowerConsumption(liveObj_00); } lflags1 = liveObj_00->flags1; if ((lflags1 & LIVEOBJ1_TELEPORTINGUP) != LIVEOBJ1_NONE) { if (liveObj_00->contMiniTeleportUp == NULL) { liveObj_00->flags3 = liveObj_00->flags3 | LIVEOBJ3_REMOVING; return 0; } pCVar3 = LegoObject_GetActivityContainer(liveObj_00); gfx::Container_AddTranslation(pCVar3,Container_Combine_After,0.0,0.0,-elapsed); fVar9 = gfx::Container_MoveAnimation(liveObj_00->contMiniTeleportUp,elapsed); // if (fVar13 <= 0.0f) if ((ushort)((ushort)(fVar9 < (float10)0.0) << 8 | (ushort)(fVar9 == (float10)0.0) << 0xe) != 0) { return 0; } liveObj_00->health = -1.0; liveObj_00->flags3 = liveObj_00->flags3 | LIVEOBJ3_REMOVING; // & ~LIVEOBJ1_TELEPORTINGUP (0x400000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB |LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); gfx::Container_Remove(liveObj_00->contMiniTeleportUp); return 0; } if ((lflags1 & LIVEOBJ1_DRILLING) == LIVEOBJ1_NONE) goto LAB_0043d12f; if ((lflags1 & LIVEOBJ1_DRILLINGSTART) != LIVEOBJ1_NONE) { pCVar3 = LegoObject_GetActivityContainer(liveObj_00); pVVar16 = NULL; BVar14 = TRUE; BVar5 = TRUE; sfxID = stats::StatsObject_GetDrillSoundType(liveObj_00,FALSE); iVar4 = snd::SFX_Random_PlaySound3DOnContainer(pCVar3,sfxID,BVar5,BVar14,pVVar16); liveObj_00->drillSoundHandle = iVar4; liveObj_00->flags4 = liveObj_00->flags4 | LIVEOBJ4_DRILLSOUNDPLAYING; // & ~LIVEOBJ1_DRILLINGSTART (0x10) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_UNUSED_20| LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); } routeBlock = liveObj_00->routeBlocks; if (routeBlock == NULL) { LAB_0043d0aa: // & ~LIVEOBJ1_DRILLING (0x8) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLINGSTART| LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); // & ~LIVEOBJ3_UNK_2000000 (0x2000000) liveObj_00->flags3 = liveObj_00->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING| LIVEOBJ3_UNK_1000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); pCVar3 = LegoObject_GetActivityContainer(liveObj_00); iVar4 = liveObj_00->drillSoundHandle; LAB_0043d0dd: snd::SFX_Sound3D_StopSound(iVar4); pVVar16 = NULL; BVar14 = 1; BVar5 = 0; liveObj_00->flags4 = liveObj_00->flags4 & ~LIVEOBJ4_DRILLSOUNDPLAYING; sfxID = stats::StatsObject_GetDrillSoundType(liveObj_00,TRUE); snd::SFX_Random_PlaySound3DOnContainer(pCVar3,sfxID,BVar5,BVar14,pVVar16); util::logf_removed(NULL,0,0); // & ~LIVEOBJ3_UNK_4000 (0x4000) lflags3 = liveObj_00->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); LAB_0043d129: liveObj_00->flags3 = lflags3; } else { fVar18 = (float)routeBlock[liveObj_00->routeBlocksCurrent].blockPos.x; fVar11 = (float)routeBlock[liveObj_00->routeBlocksCurrent].blockPos.y; BVar5 = TRUE; lflags3 = liveObj_00->flags3 & LIVEOBJ3_UNK_2000000; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); uVar7 = (uint)lVar10; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); BVar5 = LiveObject_BlockCheck_FUN_004326a0(liveObj_00,(uint)lVar10,uVar7,lflags3,BVar5); if (BVar5 == 0) goto LAB_0043d0aa; BVar5 = LegoObject_GetDrillNullPosition(liveObj_00,&local_30.x,&local_34); if (BVar5 == 0) goto LAB_0043d12f; if (liveObj_00->type == LegoObject_MiniFigure) { uVar17 = 0; pCVar3 = lrr::Lego_GetCurrentCamera_Container(); pCVar6 = gfx::Creature_GetDrillNull(liveObj_00->miniFigure); util::logf_removed((char *)pCVar6,pCVar3,uVar17); } lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); iVar4 = (int)lVar10; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); surfaceType = lrr::Lego_GetBlockTerrain((int)lVar10,iVar4); fVar9 = stats::StatsObject_GetDrillTimeType(liveObj_00,surfaceType); liveObj = (LegoObject *)(float)fVar9; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); if (((sflags1 & STATS1_SINGLEWIDTHDIG) != STATS1_NONE) && ((liveObj_00->flags3 & LIVEOBJ3_UNK_2000000) != LIVEOBJ3_NONE)) { liveObj = (LegoObject *)((float)liveObj * 0.5); } pLVar13 = liveObj; fVar12 = elapsed; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); uVar7 = (uint)lVar10; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); BVar5 = Level_Block_Damage((uint)lVar10,uVar7,(float)pLVar13,fVar12); if (BVar5 == 0) { BVar5 = Lego_WorldToBlockPos_NoZ(local_30.x,local_34,(int *)&local_24,(int *)&local_20); if (((BVar5 == 0) || (local_24 != fVar18)) || (local_20.x != fVar11)) goto LAB_0043d12f; lflags3 = liveObj_00->flags3 | LIVEOBJ3_UNK_4000; goto LAB_0043d129; } BVar5 = TRUE; lflags3 = liveObj_00->flags3 & LIVEOBJ3_UNK_2000000; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); uVar7 = (uint)lVar10; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); BVar5 = LiveObject_BlockCheck_FUN_004326a0(liveObj_00,(uint)lVar10,uVar7,lflags3,BVar5); if (BVar5 != 0) { lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); fVar12 = (float)lVar10; local_c.x = fVar12; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); fVar15 = (float)lVar10; local_c.y = fVar15; if ((liveObj_00->flags3 & LIVEOBJ3_UNK_2000000) == LIVEOBJ3_NONE) { BVar5 = FALSE; level = lrr::Lego_GetLevel(); iVar4 = Level_DestroyWall(level,(uint)fVar18,(uint)fVar11,BVar5); } else { level = lrr::Lego_GetLevel(); iVar4 = Level_DestroyWallConnection(level,(uint)fVar12,(uint)fVar15); } if (iVar4 == 0) goto LAB_0043d12f; ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Dig,NULL,TRUE); // & ~LIVEOBJ1_DRILLING (0x8) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLINGSTART| LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); Level_Block_SetBusy((Point2I *)&local_c,FALSE); if (liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte == ROUTE_ACTION_UNK_1 ) { liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = 0; } pCVar3 = LegoObject_GetActivityContainer(liveObj_00); iVar4 = liveObj_00->drillSoundHandle; goto LAB_0043d0dd; } } LAB_0043d12f: if ((liveObj_00->flags2 & LIVEOBJ2_PUSHED) != LIVEOBJ2_NONE) { LegoObject_UpdatePushing(liveObj_00,elapsed); } // if (elapsed > 0.0f) if ((((liveObj_00->flags2 & LIVEOBJ2_DAMAGESHAKING) != LIVEOBJ2_NONE) && ((ushort)((ushort)(elapsed < 0.0) << 8 | (ushort)(elapsed == 0.0) << 0xe) == 0)) && (pCVar3 = LegoObject_GetActivityContainer(liveObj_00), pCVar3 != NULL)) { gfx::Container_GetOrientation(pCVar3,NULL,&local_20,&local_c); local_c.x = local_c.x * 10.0; local_c.y = local_c.y * 10.0; local_c.z = local_c.z * 10.0; math::Maths_Vector3DRandom(&local_30); local_c.y = globs::s_objectDamageShakeTimer * 0.1 * (local_30.y + local_c.y); local_c.x = globs::s_objectDamageShakeTimer * 0.1 * (local_30.x + local_c.x); local_c.z = -1.0; gfx::Container_SetOrientation (pCVar3,NULL,local_20.x,local_20.y,local_20.z,local_c.x,local_c.y,-1.0); globs::s_objectDamageShakeTimer = globs::s_objectDamageShakeTimer - elapsed * 0.16; if (globs::s_objectDamageShakeTimer < 0.0) { globs::s_objectDamageShakeTimer = 1.0; // & ~LIVEOBJ2_DAMAGESHAKING (0x40000000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING| LIVEOBJ2_UNK_20000000|LIVEOBJ2_UNK_80000000); } } lflags1 = liveObj_00->flags1; if ((lflags1 & LIVEOBJ1_CRUMBLING) != LIVEOBJ1_NONE) { LegoObject_DestroyRockMonster_FUN_0044c290(liveObj_00); goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_SLIPPING) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_SLIPPING (0x4000000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING |LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN |LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000| LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); } goto objectupdate_end; } lflags4 = liveObj_00->flags4; if ((lflags4 & LIVEOBJ4_UNK_1000) != LIVEOBJ4_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { liveObj_00->flags4 = lflags4 & ~LIVEOBJ4_UNK_1000 | LIVEOBJ4_UNK_2000; } goto objectupdate_end; } if ((lflags4 & LIVEOBJ4_UNK_4000) != LIVEOBJ4_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { liveObj_00->flags4 = lflags4 & ~LIVEOBJ4_UNK_4000; LegoObject_SetActivity(liveObj_00,Activity_Stand,0); } goto objectupdate_end; } if ((lflags4 & LIVEOBJ4_UNK_2000) != LIVEOBJ4_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Open,0); goto objectupdate_end; } lflags2 = liveObj_00->flags2; if ((lflags2 & LIVEOBJ2_PUSHED) != LIVEOBJ2_NONE) goto objectupdate_end; if ((lflags1 & LIVEOBJ1_TURNING) != LIVEOBJ1_NONE) { uVar1 = (ushort)(liveObj_00->animTime < 0.0) << 8; uVar2 = (ushort)(liveObj_00->animTime == 0.0) << 0xe; if ((lflags1 & LIVEOBJ1_TURNRIGHT) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((uVar1 | uVar2) == 0) { pCVar3 = LegoObject_GetActivityContainer(liveObj_00); gfx::Container_AddRotation(pCVar3,Container_Combine_Before,0.0,1.0,0.0,1.570796); gfx::Container_SetAnimationTime(pCVar3,0.0); // & ~LIVEOBJ1_TURNRIGHT (0x80) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER |LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); } goto objectupdate_end; } // if (liveObj_00->animTime <= 0.0f) if ((uVar1 | uVar2) != 0) goto objectupdate_end; pCVar3 = LegoObject_GetActivityContainer(liveObj_00); // Activity_TurnLeft (9) || Activity_CarryTurnLeft (20) if ((globs::objectGlobs.activityName[9] == liveObj_00->activityName1) || (globs::objectGlobs.activityName[20] == liveObj_00->activityName1)) { fVar18 = -1.570796; } else { fVar18 = 1.570796; } gfx::Container_AddRotation(pCVar3,Container_Combine_Before,0.0,1.0,0.0,fVar18); lflags1 = liveObj_00->flags1; // & ~LIVEOBJ1_TURNING (0x4) | LIVEOBJ1_MOVING (0x1) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART| LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING |LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO) | LIVEOBJ1_MOVING; if (liveObj_00->routeBlocksTotal != 0) { if (((lflags1 & LIVEOBJ1_RUNNINGAWAY) != LIVEOBJ1_NONE) && (liveObj_00->type == LegoObject_MiniFigure)) { LegoObject_SetActivity(liveObj_00,Activity_RunPanic,0); goto objectupdate_end; } LAB_0043e732: LegoObject_SetActivity(liveObj_00,Activity_Route,0); goto objectupdate_end; } LAB_0043ecae: LegoObject_SetActivity(liveObj_00,Activity_Stand,0); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_20) != LIVEOBJ2_NONE) { LegoObject_TryDepart_FUN_004499c0(liveObj_00); goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_CANTDO) != LIVEOBJ1_NONE) { LAB_0043eb11: // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_CANTDO (0x80000000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING |LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN |LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_UNUSED_10000000) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { pCVar3 = LegoObject_GetActivityContainer(liveObj_00); fVar18 = (liveObj_00->dirVector_2c8).y; // & ~LIVEOBJ1_UNUSED_10000000 (0x10000000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); gfx::Container_SetOrientation (pCVar3,NULL,(liveObj_00->dirVector_2c8).x,fVar18,0.0,0.0,0.0,-1.0); LegoObject_SetActivity(liveObj_00,Activity_Stand,0); } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_FIRINGLASER) != LIVEOBJ2_NONE) { if ((lflags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) { LegoObject_CreateWeaponProjectile(liveObj_00,Weapon_KnownType_Laser); } // & ~LIVEOBJ2_FIRINGLASER (0x400000) // if (liveObj_00->animTime > 0.0f) if (((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) && (lflags2 = liveObj_00->flags2, liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000 |LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING| LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000), (lflags2 & LIVEOBJ2_UNK_20000) == LIVEOBJ2_NONE)) { LegoObject_CreateWeaponProjectile(liveObj_00,Weapon_KnownType_Laser); } goto objectupdate_end; } if ((lflags4 & LIVEOBJ4_UNK_8000) != LIVEOBJ4_NONE) { // if (liveObj_00->animTime <= 0.0f) // goto objectupdate_end; if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) != 0) goto objectupdate_end; liveObj_00->flags4 = lflags4 & ~LIVEOBJ4_UNK_8000; if (liveObj_00->routeToObject != NULL) { pCVar3 = LegoObject_GetDepositNull(liveObj_00->routeToObject); if (pCVar3 != NULL) { gfx::Container_GetPosition(pCVar3,NULL,&local_c); gfx::Container_GetOrientation(pCVar3,NULL,&local_20,NULL); fVar18 = local_c.x; fVar11 = local_c.y; map = lrr::Lego_GetMap(); fVar9 = lego::map::Map3D_GetWorldZ(map,fVar18,fVar11); fVar18 = (float)fVar9; pCVar6 = NULL; fVar11 = local_c.x; fVar12 = local_c.y; pCVar3 = LegoObject_GetActivityContainer(liveObj_00); gfx::Container_SetPosition(pCVar3,pCVar6,fVar11,fVar12,fVar18); upz = -1.0; fVar15 = 0.0; fVar12 = 0.0; pCVar6 = NULL; fVar18 = local_20.x; fVar11 = local_20.y; pCVar3 = LegoObject_GetActivityContainer(liveObj_00); gfx::Container_SetOrientation(pCVar3,pCVar6,fVar18,fVar11,local_20.z,fVar12,fVar15,upz); } LegoObject_DoOpeningClosing(liveObj_00->routeToObject,FALSE); LegoObject_SetActivity(liveObj_00,Activity_Stand,0); goto objectupdate_end; } goto LAB_0043ecae; } if ((lflags2 & LIVEOBJ2_UNK_80000000) != LIVEOBJ2_NONE) { if (liveObj_00->routeToObject == NULL) { // & ~LIVEOBJ2_UNK_80000000 (0x80000000) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING); } else { pCVar3 = LegoObject_GetActivityContainer(liveObj_00); pCVar6 = LegoObject_GetActivityContainer(liveObj_00->routeToObject); pLVar13 = liveObj_00->routeToObject; gfx::Container_GetPosition(pCVar6,NULL,&local_c); gfx::Container_GetOrientation(pCVar6,NULL,&local_30,&local_20); gfx::Container_SetPosition(pCVar3,NULL,local_c.x,local_c.y,local_c.z); gfx::Container_SetOrientation (pCVar3,NULL,local_30.x,local_30.y,local_30.z,local_20.x,local_20.y,local_20.z); // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { pLVar13->carriedObjects[pLVar13->numCarriedObjects] = liveObj_00; pLVar13->carriedObjects[pLVar13->numCarriedObjects]->carryingThisObject = pLVar13; pLVar13->carriedObjects[pLVar13->numCarriedObjects]->carryingIndex = pLVar13->numCarriedObjects; pLVar13->flags1 = pLVar13->flags1 | LIVEOBJ1_CARRYING; LegoObject_DoOpeningClosing(pLVar13,FALSE); pLVar13->numCarriedObjects = pLVar13->numCarriedObjects + 1; // & ~LIVEOBJ2_UNK_80000000 (0x80000000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS |LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING| LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING); LegoObject_SetActivity(liveObj_00,Activity_Stand,0); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_FindLoad,NULL,TRUE); pLVar13->flags4 = pLVar13->flags4 & ~LIVEOBJ4_UNK_10000; } } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_RECHARGING) != LIVEOBJ2_NONE) { // & ~LIVEOBJ2_RECHARGING (0x10000000) // if (liveObj_00->animTime > 0.0f) if (((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) && (liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000| LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER| LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000| LIVEOBJ2_FROZEN|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000), (lflags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) { // & ~LIVEOBJ3_POWEROFF (0x80000000) pVVar16 = &local_c; pCVar6 = NULL; liveObj_00->carriedObjects[0]->flags3 = liveObj_00->carriedObjects[0]->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING |LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000); pCVar3 = LegoObject_GetActivityContainer(liveObj_00->carriedObjects[0]); gfx::Container_GetPosition(pCVar3,pCVar6,pVVar16); snd::SFX_Random_PlaySound3DOnContainer(NULL,SFX_CrystalRecharge,FALSE,FALSE,&local_c); LegoObject_SetCrystalPoweredColour(liveObj_00->carriedObjects[0],TRUE); } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_FIRINGPUSHER) != LIVEOBJ2_NONE) { if ((lflags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) { LegoObject_CreateWeaponProjectile(liveObj_00,Weapon_KnownType_Pusher); } // & ~LIVEOBJ2_FIRINGPUSHER (0x800000) // if (liveObj_00->animTime > 0.0f) if (((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) && (lflags2 = liveObj_00->flags2, liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000 |LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING| LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000), (lflags2 & LIVEOBJ2_UNK_20000) == LIVEOBJ2_NONE)) { LegoObject_CreateWeaponProjectile(liveObj_00,Weapon_KnownType_Pusher); } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_FIRINGFREEZER) != LIVEOBJ2_NONE) { if ((lflags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) { LegoObject_CreateWeaponProjectile(liveObj_00,Weapon_KnownType_Freezer); } // & ~LIVEOBJ2_FIRINGFREEZER (0x1000000) // if (liveObj_00->animTime > 0.0f) if (((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) && (lflags2 = liveObj_00->flags2, liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000 |LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING| LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000), (lflags2 & LIVEOBJ2_UNK_20000) == LIVEOBJ2_NONE)) { LegoObject_CreateWeaponProjectile(liveObj_00,Weapon_KnownType_Freezer); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_UNK_800) != LIVEOBJ1_NONE) { if ((liveObj_00->type == LegoObject_RockMonster) && (BVar5 = gfx::Creature_CheckThrowNull(liveObj_00->rockMonster), BVar5 != 0)) { LegoObject_FUN_00447a40(liveObj_00); } // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_UNK_800 (0x800) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_UNK_4000) != LIVEOBJ1_NONE) { pLVar13 = liveObj_00->routeToObject; if ((((pLVar13 != NULL) && ((pLVar13->flags1 & LIVEOBJ1_STORING) == LIVEOBJ1_NONE)) && ((pLVar13->flags3 & LIVEOBJ3_UNK_1000000) == LIVEOBJ3_NONE)) && (pLVar13->numCarriedObjects != pLVar13->carryNullFrames)) { // & ~LIVEOBJ1_UNK_4000 (0x4000) | LIVEOBJ1_STORING (0x2000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING |LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO) | LIVEOBJ1_STORING; } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_STORING) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_STORING (0x2000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING |LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Deposit,liveObj_00,TRUE); LegoObject_ProccessCarriedObjects(liveObj_00); } else { if (liveObj_00->routeToObject != NULL) { pLFlags3_routeObj = &liveObj_00->routeToObject->flags3; *pLFlags3_routeObj = *pLFlags3_routeObj | LIVEOBJ3_UNK_1000000; } } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_RESTING) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_RESTING (0x20000000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING |LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN |LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); // & ~LIVEOBJ3_UNK_4000 (0x4000) liveObj_00->flags3 = liveObj_00->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000| LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_200000) != LIVEOBJ2_NONE) { if ((lflags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) { LegoObject_FUN_0043aeb0(liveObj_00); } // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ2_UNK_200000 (0x200000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_AttackPath,NULL,TRUE); if ((liveObj_00->flags2 & LIVEOBJ2_UNK_20000) == LIVEOBJ2_NONE) { LegoObject_FUN_0043aeb0(liveObj_00); } } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_40000) != LIVEOBJ2_NONE) { if ((lflags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) { LegoObject_FUN_004477b0(liveObj_00); } // & ~LIVEOBJ2_UNK_40000 (0x40000) // if (liveObj_00->animTime > 0.0f) if (((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) && (lflags2 = liveObj_00->flags2, liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000), (lflags2 & LIVEOBJ2_UNK_20000) == LIVEOBJ2_NONE)) { LegoObject_FUN_004477b0(liveObj_00); } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_20000000) != LIVEOBJ2_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ2_UNK_20000000 (0x20000000) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); // & ~LIVEOBJ3_POWEROFF (0x80000000) liveObj_00->flags3 = liveObj_00->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING |LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_REPAIRDRAINING) != LIVEOBJ1_NONE) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj_00); if ((((sflags2 & STATS2_DRAINPOWER) != STATS2_NONE) && (pLVar13 = liveObj_00->routeToObject, pLVar13 != NULL)) && ((*(byte *)&pLVar13->flags4 & LIVEOBJ4_UNK_10) == 0)) { BVar5 = LegoObject_IsActive(pLVar13,FALSE); if (BVar5 != 0) { front::Info_Send(Info_PowerDrain,NULL,liveObj_00->routeToObject,NULL); lrr::Lego_SetCallToArmsOn(TRUE); } pLFlags4_routeObj = &liveObj_00->routeToObject->flags4; *pLFlags4_routeObj = *pLFlags4_routeObj | LIVEOBJ4_UNK_10; LegoObject_RequestPowerGridUpdate(); } if (((liveObj_00->flags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) && (iVar4 = LegoObject_FUN_00447880(liveObj_00), iVar4 != 0)) { // & ~LIVEOBJ2_UNK_80000 (0x80000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { if (((liveObj_00->flags2 & LIVEOBJ2_UNK_20000) == LIVEOBJ2_NONE) && (iVar4 = LegoObject_FUN_00447880(liveObj_00), iVar4 != 0)) { // & ~LIVEOBJ2_UNK_80000 (0x80000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS |LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Repair,NULL,TRUE); } if ((liveObj_00->flags2 & LIVEOBJ2_UNK_80000) == LIVEOBJ2_NONE) { // & ~LIVEOBJ1_REPAIRDRAINING (0x1000000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); if (liveObj_00->routeToObject != NULL) { pLFlags4_routeObj = &liveObj_00->routeToObject->flags4; *pLFlags4_routeObj = *pLFlags4_routeObj & ~LIVEOBJ4_UNK_10; LegoObject_RequestPowerGridUpdate(); liveObj_00->routeToObject = NULL; } ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Repair,NULL,TRUE); } else { pCVar3 = LegoObject_GetActivityContainer(liveObj_00); gfx::Container_SetAnimationTime(pCVar3,liveObj_00->animTime); } } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_EATING) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { BVar5 = LegoObject_Add25EnergyAndSetHealth(liveObj_00); if (BVar5 == 0) { pCVar3 = LegoObject_GetActivityContainer(liveObj_00); gfx::Container_SetAnimationTime(pCVar3,liveObj_00->animTime); } else { // & ~LIVEOBJ1_EATING (0x40000000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_CANTDO); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Eat,NULL,TRUE); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_GotoEat,NULL,TRUE); } } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_40) != LIVEOBJ2_NONE) { // & ~LIVEOBJ2_UNK_40 (0x40) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100| LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000| LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); if (liveObj_00->aiTask != NULL) { LegoObject_MiniFigure_EquipTool(liveObj_00,liveObj_00->aiTask->toolType); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_GetTool,NULL,TRUE); } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_TRAINING) != LIVEOBJ2_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ2_TRAINING (0x400) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000| LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Train,NULL,TRUE); } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UPGRADING) == LIVEOBJ2_NONE) { if ((lflags1 & LIVEOBJ1_PLACING) != LIVEOBJ1_NONE) { pCVar3 = LegoObject_GetActivityContainer(liveObj_00); gfx::Container_ForceAnimationUpdate(pCVar3); if ((((liveObj_00->flags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) && ((liveObj_00->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) && (liveObj_00->carriedObjects[0] != NULL)) { pVVar16 = &local_c; pCVar6 = NULL; pCVar3 = LegoObject_GetActivityContainer(liveObj_00->carriedObjects[0]); gfx::Container_GetPosition(pCVar3,pCVar6,pVVar16); objType = liveObj_00->carriedObjects[0]->type; if (objType == LegoObject_Ore) { sfxID = SFX_PlaceOre; } else { if (objType == LegoObject_PowerCrystal) { sfxID = SFX_PlaceCrystal; } else { sfxID = SFX_Place; } } snd::SFX_Random_PlaySound3DOnContainer(NULL,sfxID,FALSE,FALSE,&local_c); } // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_PLACING (0x80000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER |LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); LegoObject_DropCarriedObject(liveObj_00,TRUE); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_GETTINGHIT) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_GETTINGHIT (0x1000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); } goto objectupdate_end; } if (liveObj_00->carryingThisObject != NULL) goto objectupdate_end; if (((lflags1 & LIVEOBJ1_MOVING) != LIVEOBJ1_NONE) && (BVar5 = LegoObject_FUN_0043c6a0(liveObj_00), BVar5 != 0)) { LegoObject_Route_End(liveObj_00,TRUE); LegoObject_Proc_FUN_0043c7f0(liveObj_00); goto objectupdate_end; } lflags1 = liveObj_00->flags1; if ((lflags1 & LIVEOBJ1_MOVING) != LIVEOBJ1_NONE) { LegoObject_Route_UpdateMovement(liveObj_00,elapsed); LegoObject_UpdateCarryingEnergy(liveObj_00,elapsed); LegoObject_RockMonster_FUN_0043ad70(liveObj_00); lflags2 = liveObj_00->flags2; if ((lflags2 & LIVEOBJ2_UNK_4000000) != LIVEOBJ2_NONE) { BVar5 = tools::Weapon_LegoObject_WithinWeaponRange (liveObj_00,liveObj_00->aiTask->targetObject); if ((BVar5 == 0) || (BVar5 = tools::Weapon_LegoObject_DoCallbacksSearch_FUN_00471b90 (liveObj_00,liveObj_00->aiTask->targetObject), BVar5 != 0)) { // & ~LIVEOBJ2_UNK_4000000 (0x4000000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000| LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); } else { LegoObject_Proc_FUN_0043c780(liveObj_00); } goto objectupdate_end; } lflags1 = liveObj_00->flags1; if ((lflags1 & LIVEOBJ1_DRILLING) != LIVEOBJ1_NONE) { lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); local_c.x = (float)lVar10; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); local_c.y = (float)lVar10; LegoObject_SetActivity(liveObj_00,Activity_Drill,0); Level_Block_SetBusy((Point2I *)&local_c,TRUE); goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_LIFTING) != LIVEOBJ1_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Reverse,0); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_TRAINING) != LIVEOBJ2_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Train,0); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_RECHARGING) != LIVEOBJ2_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Recharge,0); goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_CLEARING) != LIVEOBJ1_NONE) { LegoObject_SetActivity (liveObj_00,Activity_Clear,(liveObj_00->type != LegoObject_MiniFigure) - 1 & 2); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_80000000) != LIVEOBJ2_NONE) { LegoObject_SetActivity(liveObj_00,Activity_FloatOn,0); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_4) != LIVEOBJ2_NONE) { if (liveObj_00->routeToObject != NULL) { LegoObject_ClearDockOccupiedFlag(liveObj_00,liveObj_00->routeToObject); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_REINFORCING) != LIVEOBJ1_NONE) { lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); local_c.x = (float)lVar10; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); local_c.y = (float)lVar10; Level_Block_SetBusy((Point2I *)&local_c,TRUE); LegoObject_SetActivity(liveObj_00,Activity_Reinforce,globs::legoGlobs.ReinforceHits); goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_PLACING) != LIVEOBJ1_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Place,0); goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_ENTERING_WALLHOLE) != LIVEOBJ1_NONE) { lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); local_20.x = (float)lVar10; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); local_20.y = (float)lVar10; sflags2 = stats::StatsObject_GetStatsFlags2(liveObj_00); if (((sflags2 & STATS2_USEHOLES) == STATS2_NONE) && (BVar5 = Level_Block_IsWall((uint)local_20.x,(uint)local_20.y), BVar5 == 0)) { // & ~LIVEOBJ1_ENTERING_WALLHOLE (0x20000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); liveObj_00->flags2 = liveObj_00->flags2 | LIVEOBJ2_UNK_20; } else { BVar5 = Level_Block_IsReinforced((uint)local_20.x,(uint)local_20.y); if (BVar5 == 0) { LegoObject_SetActivity(liveObj_00,Activity_Enter,0); } else { LegoObject_SetActivity(liveObj_00,Activity_EnterRein,0); BVar5 = LegoObject_UpdateActivityChange(liveObj_00); if (BVar5 == 0) { LegoObject_SetActivity(liveObj_00,Activity_Enter,0); LegoObject_UpdateActivityChange(liveObj_00); } sflags2 = stats::StatsObject_GetStatsFlags2(liveObj_00); if ((sflags2 & STATS2_REMOVEREINFORCEMENT) != STATS2_NONE) { Level_Block_RemoveReinforcement((Point2I *)&local_20); } } } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_REPAIRDRAINING) != LIVEOBJ1_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Repair,0); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_200000) != LIVEOBJ2_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Stamp,0); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UPGRADING) != LIVEOBJ2_NONE) { if (liveObj_00->type == LegoObject_MiniFigure) { LegoObject_SetActivity(liveObj_00,Activity_Train,100); } else { LegoObject_SetActivity(liveObj_00,Activity_Upgrade,0); LegoObject_SetActivity(liveObj_00->routeToObject,Activity_Upgrade,0); LegoObject_UpdateActivityChange(liveObj_00->routeToObject); liveObj_00->routeToObject->flags2 = liveObj_00->routeToObject->flags2 | LIVEOBJ2_UPGRADING ; } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_EATING) != LIVEOBJ1_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Eat,0); goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_GATHERINGROCK) == LIVEOBJ1_NONE) { if ((lflags1 & LIVEOBJ1_STORING) != LIVEOBJ1_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Deposit,0); pLVar13 = liveObj_00->routeToObject; if ((pLVar13 != NULL) && ((sflags1 = stats::StatsObject_GetStatsFlags1(pLVar13), (sflags1 & STATS1_PROCESSCRYSTAL) != STATS1_NONE || (sflags1 = stats::StatsObject_GetStatsFlags1(pLVar13), (sflags1 & STATS1_PROCESSORE) != STATS1_NONE)))) { pLVar13 = liveObj_00->routeToObject; if (((pLVar13->flags1 & LIVEOBJ1_STORING) == LIVEOBJ1_NONE) && (((pLVar13->flags3 & LIVEOBJ3_UNK_1000000) == LIVEOBJ3_NONE && (pLVar13->numCarriedObjects != pLVar13->carryNullFrames)))) { pLVar13->flags3 = pLVar13->flags3 | LIVEOBJ3_UNK_1000000; } else { // & ~LIVEOBJ1_STORING (0x2000) | LIVEOBJ1_UNK_4000 (0x4000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING| LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING |LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000| LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO) | LIVEOBJ1_UNK_4000; } } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_UNK_800) != LIVEOBJ1_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Throw,0); goto objectupdate_end; } if (((lflags1 & LIVEOBJ1_TURNING) != LIVEOBJ1_NONE) || ((lflags1 & LIVEOBJ1_RESTING) != LIVEOBJ1_NONE)) goto objectupdate_end; if ((lflags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { LegoObject_GetBlockPos(liveObj_00,(int *)&local_20,(int *)&local_20.y); uVar7 = Level_Block_GetRubbleLayers((Point2I *)&local_20); if (((uVar7 < 3) && ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * (int)local_20.y + (int)local_20.x].terrain != Lego_SurfaceType8_Lake)) || ((liveObj_00->flags3 & LIVEOBJ3_CANROUTERUBBLE) == LIVEOBJ3_NONE)) { LegoObject_SetActivity(liveObj_00,Activity_Carry,0); } else { LegoObject_SetActivity(liveObj_00,Activity_CarryRubble,0); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_CANTDO) != LIVEOBJ1_NONE) { LegoObject_Route_End(liveObj_00,FALSE); LegoObject_SetActivity(liveObj_00,Activity_CantDo,1); goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_MOVING) == LIVEOBJ1_NONE) goto objectupdate_end; LegoObject_GetBlockPos(liveObj_00,(int *)&local_20,(int *)&local_20.y); if (((liveObj_00->flags1 & LIVEOBJ1_RUNNINGAWAY) != LIVEOBJ1_NONE) && (liveObj_00->type == LegoObject_MiniFigure)) { LegoObject_SetActivity(liveObj_00,Activity_RunPanic,0); goto objectupdate_end; } uVar7 = Level_Block_GetRubbleLayers((Point2I *)&local_20); if (((2 < uVar7) || ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * (int)local_20.y + (int)local_20.x].terrain == Lego_SurfaceType8_Lake)) && ((liveObj_00->flags3 & LIVEOBJ3_CANROUTERUBBLE) != LIVEOBJ3_NONE)) { LegoObject_SetActivity(liveObj_00,Activity_RouteRubble,0); goto objectupdate_end; } goto LAB_0043e732; } if ((liveObj_00->routeToObject == NULL) || (liveObj_00->routeToObject->carryingThisObject != NULL)) { // & ~LIVEOBJ1_GATHERINGROCK (0x200) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); goto objectupdate_end; } LegoObject_SetActivity(liveObj_00,Activity_Collect,0); if (liveObj_00->type == LegoObject_RockMonster) { objType = liveObj_00->routeToObject->type; if (objType == LegoObject_Boulder) { abilityType = Activity_Gather; } else { if (objType != LegoObject_PowerCrystal) goto LAB_0043e4b7; abilityType = Activity_Eat; } LegoObject_SetActivity(liveObj_00,abilityType,0); } LAB_0043e4b7: liveObj_00->carriedObjects[liveObj_00->numCarriedObjects] = liveObj_00->routeToObject; liveObj_00->routeToObject = NULL; liveObj_00->carriedObjects[liveObj_00->numCarriedObjects]->carryingThisObject = liveObj_00; liveObj_00->carriedObjects[liveObj_00->numCarriedObjects]->carryingIndex = liveObj_00->numCarriedObjects; liveObj_00->flags1 = liveObj_00->flags1 | LIVEOBJ1_CARRYING; ai::AITask_LiveObject_SetAITaskUnk (liveObj_00,AITask_Type_Collect, liveObj_00->carriedObjects[liveObj_00->numCarriedObjects],TRUE); ai::AITask_DoAnimationWait(liveObj_00); liveObj_00->numCarriedObjects = liveObj_00->numCarriedObjects + 1; goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_TELEPORTINGDOWN) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_TELEPORTINGDOWN (0x200000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); if (liveObj_00->type == LegoObject_Vehicle) { LegoObject_SetActivity(liveObj_00,Activity_Route,0); LegoObject_UpdateActivityChange(liveObj_00); } LegoObject_SetActivity(liveObj_00,Activity_Stand,0); LegoObject_FUN_00438720(liveObj_00); } LegoObject_UpdateWorldStickyPosition(liveObj_00,elapsed); pCVar3 = LegoObject_GetActivityContainer(liveObj_00); if (pCVar3 != NULL) { gfx::Container_GetOrientation(pCVar3,NULL,&local_c,NULL); gfx::Container_SetOrientation(pCVar3,NULL,local_c.x,local_c.y,local_c.z,0.0,0.0,-1.0); } goto objectupdate_end; } BVar5 = LegoObject_Update_Reinforcing(liveObj_00,elapsed,&reinforcingFinished); if (BVar5 != 0) { if (reinforcingFinished != 0) { ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Reinforce,NULL,TRUE); } goto objectupdate_end; } lflags1 = liveObj_00->flags1; if ((lflags1 & LIVEOBJ1_EXPANDING) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_EXPANDING (0x100) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800 |LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); BVar5 = LegoObject_IsRockMonsterCanGather(liveObj_00); if (BVar5 != 0) { lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).x); local_c.x = (float)lVar10; lVar10 = __ftol((float10)(liveObj_00->targetBlockPos).y); local_c.y = (float)lVar10; Message_PostEvent(Message_GenerateRockMonsterComplete,liveObj_00,0,NULL); Level_Block_SetBusy((Point2I *)&local_c,FALSE); } } goto objectupdate_end; } lflags2 = liveObj_00->flags2; if ((lflags2 & LIVEOBJ2_UNK_100000) != LIVEOBJ2_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ2_UNK_100000 (0x100000) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); liveObj_00->flags3 = liveObj_00->flags3 | LIVEOBJ3_REMOVING; } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_UNK_4) != LIVEOBJ2_NONE) { pLVar13 = liveObj_00->routeToObject; // & ~LIVEOBJ2_UNK_4 (0x4) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100| LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000 |LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_FindDriver,NULL,TRUE); liveObj_00->flags2 = liveObj_00->flags2 | LIVEOBJ2_DRIVING; pLVar13->flags4 = pLVar13->flags4 & ~LIVEOBJ4_ENTRANCEOCCUPIED; if (pLVar13->routeToObject != NULL) { pLFlags4_routeObj = &pLVar13->routeToObject->flags4; *pLFlags4_routeObj = *pLFlags4_routeObj & ~LIVEOBJ4_ENTRANCEOCCUPIED; } pLVar13->routeToObject = NULL; // & ~LIVEOBJ2_UNK_10 (0x10) pLVar13->flags2 = pLVar13->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); liveObj_00->driveObject = pLVar13; pLVar13->driveObject = liveObj_00; liveObj_00->routeToObject = NULL; front::Interface_ChangeMenu_IfVehicleMounted_IsLiveObject(liveObj_00->driveObject); LegoObject_UpdateWorldStickyPosition(liveObj_00,elapsed); pLVar13->activityName2 = NULL; LegoObject_UpdateActivityChange(pLVar13); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_DRIVING) != LIVEOBJ2_NONE) goto objectupdate_end; if ((lflags1 & LIVEOBJ1_ENTERING_WALLHOLE) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_ENTERING_WALLHOLE (0x20000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); // & ~LIVEOBJ2_UNK_20 (0x20) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100| LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000| LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER| LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000| LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); LegoObject_FinishEnteringWallHole(liveObj_00); } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_BUILDPATH) != LIVEOBJ2_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { LegoObject_GetBlockPos(liveObj_00,(int *)&local_20,(int *)&local_20.y); construct = Construction_Zone_FindByHandleOrAtBlock((Point2I *)&local_20,NULL); if ((construct != NULL) && ((*(byte *)&construct->flags & CONSTRUCTION_FLAG_LAYPATH) != 0)) { Level_Block_SetPath((Point2I *)&local_20); Construction_Zone_CompletePath((Point2I *)&local_20); front::Info_Send(Info_PathCompleted,NULL,NULL,(Point2I *)&local_20); ai::AITask_DoAttackPath((Point2I *)&local_20); } // & ~LIVEOBJ2_BUILDPATH (0x200) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000 |LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_BuildPath,NULL,TRUE); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_CLEARING) != LIVEOBJ1_NONE) { if (liveObj_00->type == LegoObject_Vehicle) { LegoObject_UpdateWorldStickyPosition(liveObj_00,elapsed); } // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_CLEARING (0x40000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER |LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Clear,NULL,TRUE); if (liveObj_00->type == LegoObject_Vehicle) { LegoObject_SetActivity(liveObj_00,Activity_Stand,0); } } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_CANTDO) != LIVEOBJ1_NONE) goto LAB_0043eb11; if ((lflags2 & LIVEOBJ2_UNK_100) != LIVEOBJ2_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ2_UNK_100 (0x100) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000| LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER| LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000| LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_UNK_10000) != LIVEOBJ1_NONE) { rng = math::Maths_Rand(); if ((int)rng % 10 != 0) { LegoObject_FUN_00444520(liveObj_00); } // & ~LIVEOBJ1_UNK_10000 (0x10000) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_THROWN) != LIVEOBJ2_NONE) { // if (liveObj_00->animTime > 0.0f) if (((*(byte *)&liveObj_00->throwObject->flags2 & LIVEOBJ2_THROWING) == 0) || ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0)) { // & ~LIVEOBJ2_THROWN (0x2) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100| LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000| LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER| LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000| LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); LegoObject_SetActivity(liveObj_00,Activity_GetUp,0); LegoObject_UpdateActivityChange(liveObj_00); liveObj_00->flags2 = liveObj_00->flags2 | LIVEOBJ2_UNK_100; } goto objectupdate_end; } if ((lflags2 & LIVEOBJ2_THROWING) != LIVEOBJ2_NONE) { if ((lflags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) { LegoObject_GetPosition(liveObj_00,&local_c.x,&local_c.y); BVar5 = TRUE; fVar9 = LegoObject_GetHeading(liveObj_00); LegoObject_SetPositionAndHeading (liveObj_00->throwObject,local_c.x,local_c.y,(float)fVar9,BVar5); } // if (liveObj_00->animTime <= 0.0f) // goto objectupdate_end; if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) != 0) goto objectupdate_end; pCVar3 = LegoObject_GetDepositNull(liveObj_00); gfx::Container_GetPosition(pCVar3,NULL,&local_c); LegoObject_SetPositionAndHeading(liveObj_00,local_c.x,local_c.y,0.0,FALSE); // & ~LIVEOBJ2_THROWING (0x1) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); LegoObject_AddDamage2(liveObj_00->throwObject,10.0,TRUE,elapsed); goto LAB_0043ecae; } BVar5 = LiveObject_FUN_00433b40(liveObj_00,elapsed,FALSE); if (BVar5 != 0) goto objectupdate_end; iVar4 = LegoObject_FP_UpdateMovement(liveObj_00,elapsed,&local_10); if (iVar4 != 0) { if (iVar4 == 1) { if ((liveObj_00->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { LegoObject_SetActivity(liveObj_00,Activity_Route,0); } else { LegoObject_SetActivity(liveObj_00,Activity_Carry,0); } } else { if (iVar4 == 4) { LegoObject_SetActivity(liveObj_00,Activity_Stand,0); } else { if (iVar4 == 2) { LegoObject_SetActivity(liveObj_00,Activity_Walk,0); } else { if ((iVar4 == 3) && (BVar5 = LegoObject_GetDrillNullPosition(liveObj_00,&local_20.x,(float *)&liveObj), BVar5 != 0)) { out_by = &local_30.y; pVVar16 = &local_30; fVar18 = local_20.x; pLVar13 = liveObj; map = lrr::Lego_GetMap(); BVar5 = lego::map::Map3D_WorldToBlockPos_NoZ (map,fVar18,(float)pLVar13,(int *)pVVar16,(int *)out_by); if ((BVar5 != 0) && (BVar5 = Level_Block_IsWall((uint)local_30.x,(uint)local_30.y), BVar5 != 0)) { surfaceType = lrr::Lego_GetBlockTerrain((int)local_30.x,(int)local_30.y); fVar9 = stats::StatsObject_GetDrillTimeType(liveObj_00,surfaceType); local_24 = (float)fVar9; if ((liveObj_00->flags4 & LIVEOBJ4_UNK_20000) == LIVEOBJ4_NONE) { LegoObject_GetActivityContainer(liveObj_00); BVar5 = TRUE; sfxID = stats::StatsObject_GetDrillSoundType(liveObj_00,FALSE); iVar4 = snd::SFX_Random_PlaySoundNormal(sfxID,BVar5); liveObj_00->drillSoundHandle = iVar4; liveObj_00->flags4 = liveObj_00->flags4 | (LIVEOBJ4_UNK_20000|LIVEOBJ4_DRILLSOUNDPLAYING); } shouldStopDrillSound = false; LegoObject_SetActivity(liveObj_00,Activity_Drill,0); BVar5 = Level_Block_Damage((uint)local_30.x,(uint)local_30.y,local_24,elapsed); if ((BVar5 != 0) && (BVar5 = LiveObject_BlockCheck_FUN_004326a0 (liveObj_00,(uint)local_30.x,(uint)local_30.y,FALSE,TRUE), BVar5 != 0)) { BVar5 = FALSE; level = lrr::Lego_GetLevel(); Level_DestroyWall(level,(uint)local_30.x,(uint)local_30.y,BVar5); } } } } } } if (liveObj_00->type == LegoObject_MiniFigure) { if ((globs::objectGlobs.s_stepCounter_c63c & 3) == 0) { snd::SFX_Random_PlaySoundNormal(SFX_Step,FALSE); } globs::objectGlobs.s_stepCounter_c63c += 1; } goto objectupdate_end; } lflags1 = liveObj_00->flags1; if ((lflags1 & LIVEOBJ1_GATHERINGROCK) != LIVEOBJ1_NONE) { // & ~LIVEOBJ1_GATHERINGROCK (0x200) // if (liveObj_00->animTime > 0.0f) if (((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) && (liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO) , (lflags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) { if (liveObj_00->type == LegoObject_RockMonster) { pLVar13 = liveObj_00->carriedObjects[0]; if (pLVar13->type == LegoObject_Boulder) { uVar17 = LegoObject_Search_FUN_00438e40(liveObj_00,0x400); Message_PostEvent(Message_GatherRockComplete,liveObj_00,uVar17,NULL); } else { liveObj_00->carriedObjects[0] = NULL; liveObj_00->numCarriedObjects = 0; pLVar13->carryingThisObject = NULL; pLVar13->interactObject = NULL; ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Collect,pLVar13,TRUE); LegoObject_PutAwayCarriedObject(liveObj_00,pLVar13); // & ~LIVEOBJ1_CARRYING (0x400) liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); } } else { objType = liveObj_00->carriedObjects[liveObj_00->numCarriedObjects - 1]->type; if (objType == LegoObject_PowerCrystal) { Level_IncCrystalsPickedUp(); } else { if (objType == LegoObject_Ore) { Level_IncOrePickedUp(); front::Info_Send(Info_OreCollected,NULL,liveObj_00,NULL); } } } } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_WAITING) != LIVEOBJ1_NONE) { // if (liveObj_00->animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_WAITING (0x8000) liveObj_00->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); } goto objectupdate_end; } if ((lflags1 & LIVEOBJ1_TURNING) != LIVEOBJ1_NONE) goto objectupdate_end; if ((lflags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { objType = liveObj_00->type; if (objType == LegoObject_Building) { if ((liveObj_00->flags3 & LIVEOBJ3_HASPOWER) != LIVEOBJ3_NONE) { if ((liveObj_00->flags3 & LIVEOBJ3_POWEROFF) != LIVEOBJ3_NONE) { abilityType = Activity_Unpowered; goto LAB_0043f029; } goto LAB_0043eff8; } } else { LAB_0043eff8: if ((objType != LegoObject_RockMonster) || ((liveObj_00->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE)) { if ((objType == LegoObject_Vehicle) && ((liveObj_00->flags4 & LIVEOBJ4_UNK_2000) != LIVEOBJ4_NONE)) { abilityType = Activity_Open; } else { abilityType = Activity_Stand; } goto LAB_0043f029; } } abilityType = Activity_Unpowered; } else { abilityType = Activity_CarryStand; } LAB_0043f029: LegoObject_SetActivity(liveObj_00,abilityType,0); LegoObject_UpdateWorldStickyPosition(liveObj_00,elapsed); goto objectupdate_end; } if (liveObj_00->type == LegoObject_MiniFigure) { if (liveObj_00->routeToObject == NULL) { // & ~LIVEOBJ2_UPGRADING (0x8000) liveObj_00->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); } else { fVar9 = gfx::Creature_GetAnimationTime(liveObj_00->miniFigure); local_20.x = (float)fVar9; fVar9 = stats::StatsObject_GetUpgradeTime(liveObj_00); liveObj = (LegoObject *)(float)fVar9; fVar9 = stats::StatsObject_GetFunctionCoef(liveObj_00->routeToObject); if (fVar9 * (float10)(float)liveObj <= (float10)local_20.x) { ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Upgrade,NULL,TRUE); LegoObject_SetActivity(liveObj_00,Activity_Stand,0); LegoObject_UpdateActivityChange(liveObj_00); uVar8 = liveObj_00->objLevel + 1; uVar7 = stats::Stats_GetLevels(liveObj_00->type,liveObj_00->id); if (uVar8 < uVar7) { stats::StatsObject_SetObjectLevel(liveObj_00,uVar8); front::HelpWindow_RecallDependencies (liveObj_00->type,liveObj_00->id,liveObj_00->objLevel,FALSE); } liveObj_00->routeToObject = NULL; // & ~LIVEOBJ2_UPGRADING (0x8000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS |LIVEOBJ2_PUSHED|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } } goto objectupdate_end; } // if (liveObj_00->animTime <= 0.0f) // goto objectupdate_end; if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) != 0) goto objectupdate_end; if ((liveObj_00->routeToObject == NULL) || (sflags2 = stats::StatsObject_GetStatsFlags2(liveObj_00->routeToObject), (sflags2 & STATS2_UPGRADEBUILDING) == STATS2_NONE)) { // & ~LIVEOBJ2_UPGRADING (0x8000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); goto objectupdate_end; } if ((liveObj_00->routeToObject->flags2 & LIVEOBJ2_UPGRADING) != LIVEOBJ2_NONE) goto objectupdate_end; ai::AITask_LiveObject_SetAITaskUnk(liveObj_00,AITask_Type_Upgrade,NULL,TRUE); uVar7 = stats::Stats_GetUpgradeCostOre(liveObj_00->type,liveObj_00->id,liveObj_00->upgradingType); uVar8 = Level_GetOreCount(0); if (uVar8 < uVar7) { uVar7 = stats::Stats_GetUpgradeCostStuds (liveObj_00->type,liveObj_00->id,liveObj_00->upgradingType); uVar8 = Level_GetOreCount(TRUE); if (uVar7 <= uVar8) { LegoObject_CompleteVehicleUpgrade(liveObj_00); uVar7 = stats::Stats_GetUpgradeCostStuds (liveObj_00->type,liveObj_00->id,liveObj_00->upgradingType); BVar5 = 1; goto LAB_0043df73; } } else { LegoObject_CompleteVehicleUpgrade(liveObj_00); uVar7 = stats::Stats_GetUpgradeCostOre (liveObj_00->type,liveObj_00->id,liveObj_00->upgradingType); BVar5 = 0; LAB_0043df73: Level_SubtractOreStored(BVar5,uVar7); } liveObj_00->routeToObject->interactObject = NULL; liveObj_00->routeToObject = NULL; // & ~LIVEOBJ2_UPGRADING (0x8000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); objectupdate_end: if ((shouldStopDrillSound) && ((liveObj_00->flags4 & LIVEOBJ4_UNK_20000) != LIVEOBJ4_NONE)) { LegoObject_GetActivityContainer(liveObj_00); snd::SFX_Sound3D_StopSound(liveObj_00->drillSoundHandle); BVar5 = FALSE; liveObj_00->flags4 = liveObj_00->flags4 & ~LIVEOBJ4_DRILLSOUNDPLAYING; sfxID = stats::StatsObject_GetDrillSoundType(liveObj_00,TRUE); snd::SFX_Random_PlaySoundNormal(sfxID,BVar5); liveObj_00->flags4 = liveObj_00->flags4 & ~LIVEOBJ4_UNK_20000; } LegoObject_UpdateActivityChange(liveObj_00); if ((liveObj_00->driveObject != NULL) && (liveObj_00->type != LegoObject_MiniFigure)) { LegoObject_UpdateDriverStickyPosition(liveObj_00); } if ((liveObj_00->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { LegoObject_UpdateCarrying(liveObj_00); } BVar5 = tools::Weapon_LegoObject_IsActiveWithTracker(liveObj_00); if (BVar5 != 0) { tools::Weapon_LegoObject_UpdateTracker(liveObj_00,elapsed); } LegoObject_UpdateSlipAndScare(liveObj_00,elapsed); LegoObject_Flocks_FUN_0044bef0(liveObj_00,*pElapsed); LegoObject_UpdateEnergyHealthAndLavaContact(liveObj_00,elapsed); if ((liveObj_00->flags2 & LIVEOBJ2_TRIGGERFRAMECALLBACK) != LIVEOBJ2_NONE) { // & ~LIVEOBJ2_TRIGGERFRAMECALLBACK (0x10000) | LIVEOBJ2_UNK_20000 (0x20000) liveObj_00->flags2 = liveObj_00->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000) | LIVEOBJ2_UNK_20000; } liveObj_00->flags4 = liveObj_00->flags4 & ~LIVEOBJ4_DOUBLESELECTREADY; LegoObject_UpdateRemoval(liveObj_00); return FALSE; } void __cdecl lego::game::LegoObject_ProccessCarriedObjects(LegoObject *in_liveObj) { LegoObject *pLVar1; LegoObject *liveObj; StatsFlags1 sflags1; uint uVar2; Container *depositNull; LegoObject *argument1Obj; int iVar3; int iVar4; LegoObject **pCarriedObjs; uint i; Vector3F depositNullPos; LegoObject *routeToObj; uint j; bool canProcess; liveObj = in_liveObj; routeToObj = in_liveObj->routeToObject; sflags1 = stats::StatsObject_GetStatsFlags1(in_liveObj); if (((sflags1 & STATS1_PROCESSCRYSTAL) == STATS1_NONE) && (sflags1 = stats::StatsObject_GetStatsFlags1(in_liveObj), (sflags1 & STATS1_PROCESSORE) == STATS1_NONE)) { canProcess = false; } else { canProcess = true; } i = 0; if (in_liveObj->numCarriedObjects != 0) { in_liveObj = (LegoObject *)in_liveObj->carriedObjects; do { // = carriedObjects[0] pLVar1 = (LegoObject *)in_liveObj->type; pLVar1->routeToObject = NULL; if (canProcess) { pLVar1->carryingThisObject = NULL; pLVar1->interactObject = NULL; if (pLVar1->type == LegoObject_Ore) { if ((i == 0) || (uVar2 = stats::StatsObject_GetMaxCarry(liveObj), uVar2 <= i)) { depositNull = gfx::Building_GetDepositNull(liveObj->building); if (i == 0) { gfx::Container_GetPosition(depositNull,NULL,&depositNullPos); argument1Obj = LegoObject_CreateInWorld (globs::legoGlobs.contOresTable[1],LegoObject_Ore, LegoObject_ID_ProcessedOre,0,depositNullPos.x, depositNullPos.y,0.0); Message_PostEvent(Message_GenerateOreComplete,argument1Obj,0,NULL); LegoObject_Remove(pLVar1); goto LAB_0043f315; } Level_IncOreStored(0); } LegoObject_Remove(pLVar1); } else { LegoObject_PutAwayCarriedObject(liveObj,pLVar1); if (liveObj->type == LegoObject_Building) { gfx::Building_ChangePowerLevel(liveObj->building,TRUE); } LegoObject_RequestPowerGridUpdate(); } } else { if (routeToObj->numCarriedObjects == routeToObj->carryNullFrames) { // Shift all objects starting at i to the front of the list. if (i < liveObj->numCarriedObjects) { iVar4 = i * 4; pCarriedObjs = liveObj->carriedObjects + i; j = i; do { pLVar1 = *pCarriedObjs; iVar3 = iVar4 + i * -4; j += 1; iVar4 += 4; pCarriedObjs = pCarriedObjs + 1; // liveObj->carriedObjects[j - i] = pLVar1; *(LegoObject **)((int)liveObj + iVar3 + 0x308) = pLVar1; } while (j < liveObj->numCarriedObjects); } liveObj->numCarriedObjects = liveObj->numCarriedObjects - i; return; } routeToObj->carriedObjects[routeToObj->numCarriedObjects] = pLVar1; pLVar1->carryingThisObject = routeToObj; pLVar1->carryingIndex = routeToObj->numCarriedObjects; routeToObj->numCarriedObjects = routeToObj->numCarriedObjects + 1; routeToObj->flags1 = routeToObj->flags1 | LIVEOBJ1_CARRYING; Message_PostEvent(Message_CrystalToRefineryComplete,0,0,NULL); sflags1 = stats::StatsObject_GetStatsFlags1(routeToObj); if ((sflags1 & STATS1_PROCESSCRYSTAL) != STATS1_NONE) { front::Info_Send(Info_CrystalPower,NULL,routeToObj,NULL); } } LAB_0043f315: i += 1; // carriedObjects[i - 1] = nullptr; // carriedObj = carriedObjects[i]; in_liveObj->type = LegoObject_None; in_liveObj = (LegoObject *)&in_liveObj->id; } while (i < liveObj->numCarriedObjects); } liveObj->numCarriedObjects = 0; liveObj->routeToObject = NULL; // & ~LIVEOBJ1_CARRYING (0x400) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART| LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); return; } void __cdecl lego::game::LegoObject_ClearDockOccupiedFlag(LegoObject *unused_liveObj,LegoObject *liveObj) { LiveFlags4 *pLFlags4; liveObj->flags4 = liveObj->flags4 & ~LIVEOBJ4_DOCKOCCUPIED; if (liveObj->routeToObject != NULL) { pLFlags4 = &liveObj->routeToObject->flags4; *pLFlags4 = *pLFlags4 & ~LIVEOBJ4_DOCKOCCUPIED; } return; } void __cdecl lego::game::LegoObject_TriggerFrameCallback(Container *cont,void *data) { LegoObject *liveObj; liveObj = (LegoObject *)gfx::Container_GetUserData(cont); if (liveObj != NULL) { liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_TRIGGERFRAMECALLBACK; } return; } BOOL __cdecl lego::game::LegoObject_QueueTeleport(LegoObject *liveObj,LegoObject_Type objType,int objID) { if (globs::legoGlobs.objTeleportQueue_COUNT < 9) { globs::legoGlobs.objTeleportQueueTypes_TABLE[globs::legoGlobs.objTeleportQueue_COUNT] = objType; globs::legoGlobs.objTeleportQueueIDs_TABLE[globs::legoGlobs.objTeleportQueue_COUNT] = objID; globs::legoGlobs.objTeleportQueue_COUNT = globs::legoGlobs.objTeleportQueue_COUNT + 1; return TRUE; } return FALSE; } void __cdecl lego::game::LegoObject_UpdateTeleporter(LegoObject *liveObj) { BOOL BVar1; StatsFlags2 sflags2; StatsFlags1 sflags1; uint crystalCost; int crystalCount; LegoObject *teleportedObj; uint crystalAmount; Container *cont; Map3D *map; LegoObject_ID *pLVar2; uint i; LegoObject_Type *pLVar3; float in_x; float in_y; Point2I *out_bx; Vector3F *out_x; int *out_by; float *out_y; LegoObject_Type local_2c; int local_28; Container *objModel; Point2I blockPos; Vector3F wPos; Vector3F dir; int teleporterFound; LegoObject *liveObj_00; liveObj_00 = liveObj; local_28 = 0; BVar1 = LegoObject_IsActive(liveObj,FALSE); // !(flags4 & (LIVEOBJ4_DOCKOCCUPIED|LIVEOBJ4_ENTRANCEOCCUPIED)) if ((((BVar1 != 0) && (globs::legoGlobs.objTeleportQueue_COUNT != 0)) && ((liveObj_00->teleportDownObject == NULL || ((liveObj_00->teleportDownObject->flags1 & LIVEOBJ1_TELEPORTINGDOWN) == LIVEOBJ1_NONE)))) && ((*(byte *)&liveObj_00->flags4 & 0xc0) == 0)) { i = 0; teleporterFound = FALSE; if (globs::legoGlobs.objTeleportQueue_COUNT != 0) { pLVar3 = globs::legoGlobs.objTeleportQueueTypes_TABLE; do { sflags2 = stats::Stats_GetStatsFlags2(*pLVar3,pLVar3[0x14]); if (((((sflags2 & STATS2_USESMALLTELEPORTER) != STATS2_NONE) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00), (sflags1 & STATS1_SMALLTELEPORTER) != STATS1_NONE)) || (((sflags2 = stats::Stats_GetStatsFlags2(*pLVar3,pLVar3[0x14]), (sflags2 & STATS2_USEBIGTELEPORTER) != STATS2_NONE && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00), (sflags1 & STATS1_BIGTELEPORTER) != STATS1_NONE)) || ((sflags2 = stats::Stats_GetStatsFlags2(*pLVar3,pLVar3[0x14]), (sflags2 & STATS2_USEWATERTELEPORTER) != STATS2_NONE && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00), (sflags1 & STATS1_WATERTELEPORTER) != STATS1_NONE)))))) || ((sflags2 = stats::Stats_GetStatsFlags2(*pLVar3,pLVar3[0x14]), (sflags2 & STATS2_USELEGOMANTELEPORTER) != STATS2_NONE && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00), (sflags1 & STATS1_MANTELEPORTER) != STATS1_NONE)))) { crystalCost = stats::Stats_GetCostCrystal(*pLVar3,pLVar3[0x14],0); crystalCount = Level_GetCrystalCount(FALSE); if ((int)crystalCost <= crystalCount) { lrr::Lego_GetObjectByName("Barracks",&local_2c,(LegoObject_ID *)&liveObj,NULL); BVar1 = LegoObject_CanSupportOxygenForType (*pLVar3,pLVar3[0x14],local_2c,(LegoObject_ID)liveObj); if (BVar1 != 0) { teleporterFound = TRUE; break; } } } i += 1; pLVar3 = pLVar3 + 1; teleporterFound = local_28; } while (i < globs::legoGlobs.objTeleportQueue_COUNT); } if (teleporterFound != 0) { lrr::Lego_GetObjectTypeModel (globs::legoGlobs.objTeleportQueueTypes_TABLE[i], globs::legoGlobs.objTeleportQueueIDs_TABLE[i],&objModel); teleportedObj = LegoObject_CreateInWorld (objModel,globs::legoGlobs.objTeleportQueueTypes_TABLE[i], globs::legoGlobs.objTeleportQueueIDs_TABLE[i],0,0.0,0.0,0.0); liveObj_00->teleportDownObject = teleportedObj; crystalAmount = stats::Stats_GetCostCrystal (globs::legoGlobs.objTeleportQueueTypes_TABLE[i], globs::legoGlobs.objTeleportQueueIDs_TABLE[i],0); Level_SubtractCrystalsStored(crystalAmount); LegoObject_RequestPowerGridUpdate(); sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); if ((sflags1 & STATS1_WATERTELEPORTER) == STATS1_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00->teleportDownObject); if ((sflags1 & STATS1_CANBEDRIVEN) != STATS1_NONE) { liveObj_00->teleportDownObject->flags4 = liveObj_00->teleportDownObject->flags4 | LIVEOBJ4_ENTRANCEOCCUPIED; liveObj_00->flags4 = liveObj_00->flags4 | LIVEOBJ4_ENTRANCEOCCUPIED; liveObj_00->teleportDownObject->routeToObject = liveObj_00; } } else { liveObj_00->teleportDownObject->flags4 = liveObj_00->teleportDownObject->flags4 | LIVEOBJ4_DOCKOCCUPIED; liveObj_00->flags4 = liveObj_00->flags4 | LIVEOBJ4_DOCKOCCUPIED; liveObj_00->teleportDownObject->routeToObject = liveObj_00; } cont = gfx::Building_GetDepositNull(liveObj_00->building); gfx::Container_GetPosition(cont,NULL,&wPos); gfx::Container_GetOrientation(cont,NULL,&dir,NULL); if ((globs::legoGlobs.objTeleportQueueTypes_TABLE[i] == LegoObject_Vehicle) && (sflags2 = stats::Stats_GetStatsFlags2 (LegoObject_Vehicle,globs::legoGlobs.objTeleportQueueIDs_TABLE[i]), (sflags2 & STATS2_USESMALLTELEPORTER) != STATS2_NONE)) { out_by = &blockPos.y; out_bx = &blockPos; in_x = wPos.x; in_y = wPos.y; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,in_x,in_y,&out_bx->x,out_by); out_y = &wPos.y; out_x = &wPos; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,blockPos.x,blockPos.y,&out_x->x,out_y); } LegoObject_SetPositionAndHeading(liveObj_00->teleportDownObject,wPos.x,wPos.y,0.0,FALSE); LegoObject_SetHeadingOrDirection(liveObj_00->teleportDownObject,0.0,&dir); ObjectRecall_RecallMiniFigure(liveObj_00->teleportDownObject); liveObj_00->teleportDownObject->flags1 = liveObj_00->teleportDownObject->flags1 | LIVEOBJ1_TELEPORTINGDOWN; LegoObject_SetActivity(liveObj_00->teleportDownObject,Activity_TeleportIn,1); LegoObject_UpdateActivityChange(liveObj_00->teleportDownObject); if (liveObj_00->teleportDownObject->type == LegoObject_Vehicle) { gfx::Vehicle_HideWheels(liveObj_00->teleportDownObject->vehicle,TRUE); } globs::legoGlobs.objTeleportQueue_COUNT -= 1; if (i < globs::legoGlobs.objTeleportQueue_COUNT) { pLVar2 = globs::legoGlobs.objTeleportQueueIDs_TABLE + i + 1; do { i += 1; pLVar2[-0x15] = pLVar2[-0x14]; pLVar2[-1] = *pLVar2; pLVar2 = pLVar2 + 1; } while (i < globs::legoGlobs.objTeleportQueue_COUNT); } } } return; } // Removes the first teleport-down reference that matches the specified object. BOOL __cdecl lego::game::LegoObject_RemoveTeleportDownReference(LegoObject *teleportDownObj) { BOOL BVar1; BVar1 = LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_RemoveTeleportDownReference,teleportDownObj); return BVar1; } // Removes the teleport-down reference if it matches the specified object. Returns true on match. BOOL __cdecl lego::game::LegoObject_Callback_RemoveTeleportDownReference (LegoObject *liveObj,LegoObject *teleportDownObj) { if (liveObj->teleportDownObject == teleportDownObj) { liveObj->teleportDownObject = NULL; return TRUE; } return FALSE; } void __cdecl lego::game::LegoObject_TrainMiniFigure_instantunk (LegoObject *liveObj,LegoObject_AbilityFlags trainFlags) { if (liveObj->type == LegoObject_MiniFigure) { liveObj->abilityFlags = liveObj->abilityFlags | trainFlags; globs::objectGlobs.NERPs_TrainFlags |= trainFlags; if ((trainFlags & ABILITY_FLAG_PILOT) != ABILITY_FLAG_NONE) { front::Info_Send(Info_TrainPilot,NULL,liveObj,NULL); liveObj->elapsedTime1 = 0.0; return; } if ((trainFlags & ABILITY_FLAG_SAILOR) != ABILITY_FLAG_NONE) { front::Info_Send(Info_TrainSailor,NULL,liveObj,NULL); liveObj->elapsedTime1 = 0.0; return; } if ((trainFlags & ABILITY_FLAG_DRIVER) != ABILITY_FLAG_NONE) { front::Info_Send(Info_TrainDriver,NULL,liveObj,NULL); liveObj->elapsedTime1 = 0.0; return; } if ((trainFlags & ABILITY_FLAG_DYNAMITE) != ABILITY_FLAG_NONE) { front::Info_Send(Info_TrainDynamite,NULL,liveObj,NULL); liveObj->elapsedTime1 = 0.0; return; } if ((trainFlags & ABILITY_FLAG_REPAIR) != ABILITY_FLAG_NONE) { front::Info_Send(Info_TrainRepair,NULL,liveObj,NULL); liveObj->elapsedTime1 = 0.0; return; } if ((trainFlags & ABILITY_FLAG_SCANNER) != ABILITY_FLAG_NONE) { front::Info_Send(Info_TrainScanner,NULL,liveObj,NULL); } liveObj->elapsedTime1 = 0.0; } return; } void __cdecl lego::game::LegoObject_AddDamage2(LegoObject *liveObj,float damage,BOOL showVisual,float elapsed) { BOOL BVar1; StatsFlags2 sflags2; float10 healthDecayRate; longlong decayVal; longlong decayCap; BVar1 = LegoObject_IsActive(liveObj,TRUE); if ((BVar1 != 0) && (liveObj->carryingThisObject == NULL)) { // == 100.0f if ((liveObj->type == LegoObject_Building) && ((damage != 0.0 && ((undefined *)liveObj->health == &DAT_42c80000)))) { ai::AITask_DoRepair_Target(liveObj,FALSE); } BVar1 = LegoObject_IsRockMonsterCanGather(liveObj); if (BVar1 != 0) { healthDecayRate = stats::StatsObject_GetHealthDecayRate(liveObj); decayVal = __ftol(healthDecayRate * (float10)0.04 * (float10)elapsed * (float10)10010.0); decayCap = __ftol((float10)damage * (float10)10000.0); if ((uint)decayVal < (uint)decayCap) { reward::RewardQuota_RockMonsterDamageDealt(damage); } } if (liveObj->type == LegoObject_MiniFigure) { reward::RewardQuota_MiniFigureDamageTaken(damage); } liveObj->health = liveObj->health - damage; // if (param_3 && damage > 0.0f) if ((showVisual != 0) && ((ushort)((ushort)(damage < 0.0) << 8 | (ushort)(damage == 0.0) << 0xe) == 0)) { liveObj->flags2 = liveObj->flags2 | (LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS); liveObj->damageNumbers = damage + liveObj->damageNumbers; front::Bubble_ShowHealthBar(liveObj); } sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if (((sflags2 & STATS2_DAMAGECAUSESCALLTOARMS) != STATS2_NONE) && ((ushort)((ushort)(damage < 0.0) << 8 | (ushort)(damage == 0.0) << 0xe) == 0)) { lrr::Lego_SetCallToArmsOn(TRUE); } } return; } void __cdecl lego::game::LegoObject_UpdateEnergyHealthAndLavaContact(LegoObject *in_liveObj,float elapsed) { LegoObject *liveObj; StatsFlags2 sflags2; LegoObject *searchObj; uint uVar1; Point2I *pPVar2; float10 fVar3; longlong lVar4; BOOL BVar5; float fVar6; float damage; int *byList; int count; Point2I blockPos2; Point2I searchBlockPos; Point2I blockPos; Point2I DIRECTIONS [4]; liveObj = in_liveObj; damage = 0.0; if ((in_liveObj->type != LegoObject_UpgradePart) && (in_liveObj->type != LegoObject_Boulder)) { if ((ushort)((ushort)(in_liveObj->health < 0.0) << 8 | (ushort)(in_liveObj->health == 0.0) << 0xe) == 0) { if ((in_liveObj->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE) { BVar5 = 0; fVar6 = elapsed; fVar3 = stats::StatsObject_GetHealthDecayRate(in_liveObj); LegoObject_AddDamage2(liveObj,(float)(fVar3 * (float10)0.04 * (float10)elapsed),BVar5,fVar6) ; } } else { in_liveObj->health = 0.0; } uVar1 = 0; if ((ushort)((ushort)(liveObj->energy < 0.0) << 8 | (ushort)(liveObj->energy == 0.0) << 0xe) == 0) { if ((liveObj->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE) { fVar3 = stats::StatsObject_GetEnergyDecayRate(liveObj); liveObj->energy = (float)((float10)liveObj->energy - fVar3 * (float10)0.04 * (float10)elapsed); } } else { liveObj->energy = 0.0; } LegoObject_GetBlockPos(liveObj,&blockPos2.x,&blockPos2.y); if (((liveObj->carryingThisObject == NULL) && ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos2.y + blockPos2.x].terrain == Lego_SurfaceType8_Lava)) && ((liveObj->type == LegoObject_Ore || (liveObj->type == LegoObject_PowerCrystal)))) { Level_AddStolenCrystals(1); liveObj->health = -1.0; liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_REMOVING; } fVar6 = elapsed; BVar5 = Level_GetObjectDamageFromSurface(liveObj,blockPos2.x,blockPos2.y,elapsed,&damage); if (BVar5 != 0) { LegoObject_AddDamage2(liveObj,damage,1,fVar6); } sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((((sflags2 & STATS2_CANBEHITBYFENCE) != STATS2_NONE) && ((liveObj->flags1 & (LIVEOBJ1_EXPANDING|LIVEOBJ1_CRUMBLING)) == LIVEOBJ1_NONE)) && ((liveObj->flags2 & LIVEOBJ2_FROZEN) == LIVEOBJ2_NONE)) { ElectricFence_TrySparkObject(liveObj); } if (((((globs::legoGlobs.flags2 & GAME2_NOAUTOEAT) == GAME2_NONE) && (liveObj->type == LegoObject_MiniFigure)) && (((liveObj->energy < liveObj->health * 0.01 * globs::legoGlobs.MinEnergyForEat && (((ushort)((ushort)(liveObj->eatWaitTimer < 125.0) << 8 | (ushort)(liveObj->eatWaitTimer == 125.0) << 0xe) == 0 && (liveObj->eatWaitTimer = 0.0, liveObj->driveObject == NULL)))) && (BVar5 = ai::AITask_LiveObject_IsCurrentTaskType(liveObj,AITask_Type_GotoEat), BVar5 == 0)) )) && (searchObj = LegoObject_FindSnackServingBuilding(liveObj), searchObj != NULL)) { DIRECTIONS[0].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[0].x = 0; DIRECTIONS[1].x = 1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[2].y = 1; DIRECTIONS[3].y = 0; LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); LegoObject_GetBlockPos(searchObj,&searchBlockPos.x,&searchBlockPos.y); pPVar2 = DIRECTIONS; do { BVar5 = LegoObject_Route_Score_FUN_004413b0 (liveObj,blockPos.x,blockPos.y,searchBlockPos.x + pPVar2->x, pPVar2->y + searchBlockPos.y,(int **)&in_liveObj,&byList,&count,0,NULL); if (BVar5 != 0) { io::Mem_Free(in_liveObj); io::Mem_Free(byList); ai::AITask_QueueGotoEat_Target(liveObj,searchObj); break; } uVar1 += 1; pPVar2 = pPVar2 + 1; } while (uVar1 < 4); } if ((ushort)((ushort)(liveObj->energy < liveObj->health) << 8 | (ushort)(liveObj->energy == liveObj->health) << 0xe) == 0) { liveObj->energy = liveObj->health; } LegoObject_MiniFigurePlayHurtSound(liveObj,elapsed,damage); if (((liveObj->flags2 & LIVEOBJ2_SHOWDAMAGENUMBERS) != LIVEOBJ2_NONE) && ((liveObj->flags2 & LIVEOBJ2_DAMAGE_UNK_1000) == LIVEOBJ2_NONE)) { lVar4 = __ftol((float10)liveObj->damageNumbers); effect::DamageFont_DisplayDamage_OverLiveObject(liveObj,(uint)lVar4); liveObj->damageNumbers = 0.0; // liveObj->flags2 &= ~LIVEOBJ2_UNK_2000; liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } // liveObj->flags2 &= ~LIVEOBJ2_UNK_1000; liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } return; } BOOL __cdecl lego::game::LegoObject_MiniFigurePlayHurtSound(LegoObject *in_liveObj,float elapsed,float damage) { LegoObject *liveObj; BOOL BVar1; Container *cont; float10 fVar2; LegoObject *sfxID; BOOL onCont; Vector3F *opt_wPos; float resetTime; float timer; liveObj = in_liveObj; if ((in_liveObj->type == LegoObject_MiniFigure) && (damage != 0.0)) { BVar1 = snd::SFX_GetType("SND_Hurt",(SFX_ID *)&in_liveObj); if (BVar1 != 0) { if (liveObj->hurtSoundTimer == 0.0) { opt_wPos = NULL; onCont = TRUE; BVar1 = FALSE; sfxID = in_liveObj; cont = LegoObject_GetActivityContainer(liveObj); snd::SFX_Random_PlaySound3DOnContainer(cont,(SFX_ID)sfxID,BVar1,onCont,opt_wPos); liveObj->hurtSoundTimer = elapsed + liveObj->hurtSoundTimer; fVar2 = snd::SFX_Random_GetSamplePlayTime((SFX_ID)in_liveObj); liveObj->hurtSoundDuration = (float)fVar2; } else { timer = liveObj->hurtSoundTimer - elapsed * -0.04; resetTime = liveObj->hurtSoundDuration + liveObj->hurtSoundDuration; liveObj->hurtSoundTimer = timer; if ((ushort)((ushort)(timer < resetTime) << 8 | (ushort)(timer == resetTime) << 0xe) == 0) { liveObj->hurtSoundTimer = 0.0; liveObj->hurtSoundDuration = 0.0; return TRUE; } } } } return TRUE; } BOOL __cdecl lego::game::LegoObject_FUN_0043fee0(LegoObject *carriedObj) { LegoObject *liveObj; Container *depositNull; Map3D *map; BOOL BVar1; int iVar2; Container *carriedCont; Container *cont; float in_x; float in_y; Point2I *out_bx; int *out_by; Point2I blockPos; Vector3F wPos; Vector3F up; Vector3F dir; liveObj = carriedObj->carryingThisObject; if (liveObj != NULL) { depositNull = LegoObject_GetDepositNull(liveObj); if (depositNull != NULL) { gfx::Container_GetPosition(depositNull,NULL,&wPos); out_by = &blockPos.y; out_bx = &blockPos; in_x = wPos.x; in_y = wPos.y; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ(map,in_x,in_y,&out_bx->x,out_by); if (BVar1 != 0) { iVar2 = Lego_GetCrossTerrainType (carriedObj,blockPos.x,blockPos.y,blockPos.x,blockPos.y,FALSE); if (iVar2 != 0) { carriedCont = LegoObject_GetActivityContainer(carriedObj); if (carriedCont != NULL) { cont = LegoObject_GetActivityContainer(liveObj); if (cont != NULL) { carriedObj->carryingThisObject = NULL; liveObj->carriedObjects[0] = NULL; // & ~LIVEOBJ1_CARRYING (0x400) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING |LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000| LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); liveObj->numCarriedObjects = 0; gfx::Container_GetPosition(cont,NULL,&wPos); gfx::Container_GetOrientation(cont,NULL,&dir,&up); gfx::Container_SetPosition(carriedCont,NULL,wPos.x,wPos.y,wPos.z); gfx::Container_SetOrientation(carriedCont,NULL,dir.x,dir.y,dir.z,up.x,up.y,up.z); LegoObject_DoOpeningClosing(liveObj,TRUE); ai::AITask_DoAnimationWait(liveObj); LegoObject_SetActivity(carriedObj,Activity_FloatOff,0); LegoObject_UpdateActivityChange(carriedObj); ai::AITask_DoAnimationWait(carriedObj); carriedObj->routeToObject = liveObj; carriedObj->flags4 = carriedObj->flags4 | LIVEOBJ4_UNK_8000; return TRUE; } } } } } } return 0; } BOOL __cdecl lego::game::LegoObject_UnkCarryingVehicle_FUN_00440080(LegoObject *liveObj) { StatsFlags3 SVar1; Container *cont; Map3D *map; BOOL BVar2; int iVar3; int *out_bx; int *out_by; int local_14; int local_10; Vector3F local_c; SVar1 = stats::StatsObject_GetStatsFlags3(liveObj); if (((((SVar1 & STATS3_CARRYVEHICLES) != STATS3_NONE) && ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) && (liveObj->carriedObjects[0] != NULL)) && (liveObj->carriedObjects[0]->type == LegoObject_Vehicle)) { cont = LegoObject_GetDepositNull(liveObj); if (cont != NULL) { gfx::Container_GetPosition(cont,NULL,&local_c); out_by = &local_10; out_bx = &local_14; map = lrr::Lego_GetMap(); BVar2 = lego::map::Map3D_WorldToBlockPos_NoZ(map,local_c.x,local_c.y,out_bx,out_by); if (BVar2 != 0) { iVar3 = Lego_GetCrossTerrainType (liveObj->carriedObjects[0],local_14,local_10,local_14,local_10,1); if (iVar3 != 0) { return TRUE; } } } } return 0; } BOOL __cdecl lego::game::LegoObject_TryFindLoad_FUN_00440130(LegoObject *in_liveObj,LegoObject *targetObj) { LegoObject *liveObj; LegoObject *liveObj_00; StatsFlags3 SVar1; Container *cont; Map3D *map; BOOL BVar2; BOOL BVar3; uint *out_bx; uint *out_by; uint local_20; uint local_1c; uint local_18; uint local_14; uint local_10; Vector3F local_c; liveObj = in_liveObj; BVar3 = 0; SVar1 = stats::StatsObject_GetStatsFlags3(in_liveObj); liveObj_00 = targetObj; if ((SVar1 & STATS3_VEHICLECANBECARRIED) != STATS3_NONE) { SVar1 = stats::StatsObject_GetStatsFlags3(targetObj); if (((SVar1 & STATS3_CARRYVEHICLES) != STATS3_NONE) && (liveObj->carryingThisObject == NULL)) { LegoObject_GetBlockPos(liveObj,(int *)&local_14,(int *)&local_10); cont = LegoObject_GetDepositNull(liveObj_00); if (cont != NULL) { gfx::Container_GetPosition(cont,NULL,&local_c); out_by = &local_18; out_bx = &local_1c; map = lrr::Lego_GetMap(); BVar2 = lego::map::Map3D_WorldToBlockPos_NoZ (map,local_c.x,local_c.y,(int *)out_bx,(int *)out_by); if (BVar2 != 0) { if ((local_1c == local_14) && (local_18 == local_10)) { BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj,1,(int *)&local_1c,(int *)&local_18,(Point2F *)&local_c); } else { BVar3 = LegoObject_Route_Score_FUN_004413b0 (liveObj,local_14,local_10,local_1c,local_18,(int **)&in_liveObj, (int **)&targetObj,(int *)&local_20,0,NULL); if (BVar3 == 0) { return 0; } BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj,local_20,(int *)in_liveObj,(int *)targetObj, (Point2F *)&local_c); io::Mem_Free(in_liveObj); io::Mem_Free(targetObj); } if (BVar3 != 0) { liveObj->routeToObject = liveObj_00; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_21; LegoObject_DoOpeningClosing(liveObj_00,1); return TRUE; } } } } } return BVar3; } BOOL __cdecl lego::game::LegoObject_TryDock_FUN_004402b0(LegoObject *in_liveObj) { LegoObject *liveObj; LegoObject *liveObj_00; Container *cont; Map3D *map; BOOL BVar1; uint *out_bx; uint *out_by; int *local_24; uint local_20; uint local_1c; uint local_18; uint local_14; uint local_10; Vector3F local_c; liveObj = in_liveObj; LegoObject_GetBlockPos(in_liveObj,(int *)&local_14,(int *)&local_10); liveObj_00 = (LegoObject *)LegoObject_Search_FUN_00438ca0(liveObj,TRUE); if ((liveObj_00 != NULL) && (cont = LegoObject_GetDepositNull(liveObj_00), cont != NULL)) { gfx::Container_GetPosition(cont,NULL,&local_c); out_by = &local_18; out_bx = &local_1c; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ (map,local_c.x,local_c.y,(int *)out_bx,(int *)out_by); if (BVar1 != 0) { if ((local_1c == local_14) && (local_18 == local_10)) { BVar1 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj,1,(int *)&local_1c,(int *)&local_18,(Point2F *)&local_c); } else { BVar1 = LegoObject_Route_Score_FUN_004413b0 (liveObj,local_14,local_10,local_1c,local_18,(int **)&in_liveObj,&local_24 ,(int *)&local_20,0,NULL); if (BVar1 == 0) { return 0; } BVar1 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj,local_20,(int *)in_liveObj,local_24,(Point2F *)&local_c); io::Mem_Free(in_liveObj); io::Mem_Free(local_24); } if (BVar1 != 0) { liveObj->routeToObject = liveObj_00; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_DOCK; return TRUE; } } } return 0; } void __cdecl lego::game::LegoObject_TryDock_AtBlockPos_FUN_004403f0(LegoObject *liveObj,Point2I *blockPos) { uint i; LegoObject **pLiveObjArr; Point2I objBlockPos; LegoObject *liveObj_0; i = 0; if (globs::objectGlobs.uintCount_c5cc != 0) { pLiveObjArr = globs::objectGlobs.liveObjArray100_c43c; do { liveObj_0 = *pLiveObjArr; if (((liveObj_0 != NULL) && (LegoObject_GetBlockPos(liveObj_0,&objBlockPos.x,&objBlockPos.y), objBlockPos.x == blockPos->x)) && (objBlockPos.y == blockPos->y)) { liveObj_0->routeToObject = liveObj; LegoObject_TryDock_AtObject2FC(liveObj_0); *pLiveObjArr = NULL; } i += 1; pLiveObjArr = pLiveObjArr + 1; } while (i < globs::objectGlobs.uintCount_c5cc); } return; } BOOL __cdecl lego::game::LegoObject_FUN_00440470(LegoObject *liveObj,BOOL param_2) { LegoObject *pLVar1; StatsFlags1 sflags1; Container *pCVar2; Container *cont; Map3D *pMVar3; BOOL BVar4; int iVar5; float10 fVar6; float fVar7; float fVar8; int *out_bx; Vector3F *out_x; int *out_by; float *out_y; int local_28; int local_24; Point2I local_20; Vector3F local_18; Vector3F local_c; LegoObject *drivenObj; drivenObj = liveObj->driveObject; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) { return 0; } if (drivenObj == NULL) { return 0; } if ((*(byte *)&drivenObj->flags1 & LIVEOBJ1_MOVING) != 0) { return 0; } pCVar2 = LegoObject_GetDepositNull(liveObj); cont = LegoObject_GetActivityContainer(drivenObj); gfx::Container_GetPosition(pCVar2,NULL,&local_18); out_by = &local_24; out_bx = &local_28; fVar7 = local_18.x; fVar8 = local_18.y; pMVar3 = lrr::Lego_GetMap(); BVar4 = lego::map::Map3D_WorldToBlockPos_NoZ(pMVar3,fVar7,fVar8,out_bx,out_by); if (BVar4 == 0) { return 0; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_CROSSLAND) != STATS1_NONE) && (iVar5 = Lego_GetCrossTerrainType(drivenObj,local_28,local_24,local_28,local_24,TRUE), iVar5 != 0)) { LAB_004405c7: liveObj->driveObject = NULL; drivenObj->driveObject = NULL; // & ~LIVEOBJ2_DRIVING (0x8) drivenObj->flags2 = drivenObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); fVar7 = local_18.x; fVar8 = local_18.y; pMVar3 = lrr::Lego_GetMap(); fVar6 = lego::map::Map3D_GetWorldZ(pMVar3,fVar7,fVar8); gfx::Container_SetPosition(cont,NULL,local_18.x,local_18.y,(float)fVar6); gfx::Container_SetOrientation(cont,NULL,local_c.x,local_c.y,0.0,0.0,0.0,-1.0); LegoObject_SetActivity(drivenObj,Activity_Stand,0); drivenObj->activityName2 = NULL; LegoObject_UpdateActivityChange(drivenObj); Message_DeselectObject(liveObj); return 1; } if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_DOCKOCCUPIED) == 0) { if ((param_2 == 0) && (BVar4 = LegoObject_UnkGetTerrainGetOutAtLandBlock_FUN_0043a0d0(liveObj,&local_20), BVar4 != 0)) { out_y = &local_18.y; out_x = &local_18; pMVar3 = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(pMVar3,local_20.x,local_20.y,&out_x->x,out_y); goto LAB_004405c7; } sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) { ai::AITask_DoDock(liveObj); } } else { pLVar1 = liveObj->routeToObject; if (((pLVar1 != NULL) && (pLVar1->type == LegoObject_Building)) && (pCVar2 = gfx::Building_GetEntranceNull(pLVar1->building), pCVar2 != NULL)) { gfx::Container_GetPosition(pCVar2,NULL,&local_18); gfx::Container_GetOrientation(pCVar2,NULL,&local_c,NULL); goto LAB_004405c7; } } return 0; } BOOL __cdecl lego::game::LegoObject_TryFindDriver_FUN_00440690(LegoObject *liveObj,LegoObject *drivableObj) { RouteFlags *pRVar1; AITask *pAVar2; LegoObject *pLVar3; LegoObject *liveObj_00; LegoObject *liveObj_01; StatsFlags1 SVar4; Map3D *pMVar5; BOOL BVar6; RouteFlags RVar7; Container *cont; uint *puVar8; uint *puVar9; uint local_44; uint local_40; Direction local_3c; uint local_38; uint local_34; uint local_30; uint local_2c; uint local_28; Vector3F local_24; Vector3F local_18; float local_c; float local_8 [2]; liveObj_01 = drivableObj; liveObj_00 = liveObj; cont = NULL; pAVar2 = liveObj->aiTask; if (pAVar2 != NULL) { if (pAVar2->taskType != AITask_Type_FindDriver) { return 0; } if (pAVar2->next != NULL) { return 0; } } if (liveObj->driveObject != NULL) { return 0; } if (drivableObj->driveObject != NULL) { return 0; } if (liveObj->type != LegoObject_MiniFigure) { return 0; } if (((((liveObj->abilityFlags & (ABILITY_FLAG_PILOT|ABILITY_FLAG_DRIVER)) == ABILITY_FLAG_NONE) || (SVar4 = stats::StatsObject_GetStatsFlags1(drivableObj), (SVar4 & STATS1_CROSSLAND) == STATS1_NONE)) || (SVar4 = stats::StatsObject_GetStatsFlags1(liveObj_01), (SVar4 & STATS1_CANBEDRIVEN) == STATS1_NONE)) || ((*(byte *)&liveObj_01->flags4 & 0x40) != 0)) { if ((*(byte *)&liveObj_00->abilityFlags & 2) != 0) { SVar4 = stats::StatsObject_GetStatsFlags1(liveObj_01); if ((((SVar4 & STATS1_CANBEDRIVEN) == STATS1_NONE) || ((*(byte *)&liveObj_01->flags4 & 0x40) == 0)) || ((pLVar3 = liveObj_01->routeToObject, pLVar3 == NULL || (pLVar3->type != LegoObject_Building)))) { if ((((*(byte *)&liveObj_00->abilityFlags & 2) != 0) && (SVar4 = stats::StatsObject_GetStatsFlags1(liveObj_01), (SVar4 & STATS1_CANBEDRIVEN) != STATS1_NONE)) && (BVar6 = LegoObject_CheckUnkGetInAtLand_FUN_0043a100(liveObj_01,NULL), BVar6 != 0)) { LegoObject_GetBlockPos(liveObj_01,(int *)&local_40,(int *)&local_44); BVar6 = LegoObject_BlockRoute_FUN_00446c80(liveObj_00,local_40,local_44,0,&local_3c,1); if (BVar6 != 0) { liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].blockOffset.y = 0.5; liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].blockOffset.x = 0.5; switch(local_3c) { case DIRECTION_UP: liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].blockOffset.y = 0.1; break; case DIRECTION_RIGHT: liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].blockOffset.x = 0.1; break; case DIRECTION_DOWN: liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].blockOffset.y = 0.9; break; case DIRECTION_LEFT: liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].blockOffset.x = 0.9; } liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte = liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_UNK_8; liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UNK_12; liveObj_00->routeToObject = liveObj_01; return TRUE; } } } else { cont = gfx::Building_GetEntranceNull(pLVar3->building); } } } else { cont = LegoObject_GetActivityContainer(liveObj_01); } if (cont != NULL) { gfx::Container_GetPosition(cont,NULL,&local_18); gfx::Container_GetOrientation(cont,NULL,&local_24,NULL); if (ABS(local_24.x) <= ABS(local_24.y)) { if ((ushort)((ushort)(local_24.y < 0.0) << 8 | (ushort)(local_24.y == 0.0) << 0xe) == 0) { RVar7 = ROUTE_FLAG_NONE; } else { RVar7 = 2; } } else { if ((ushort)((ushort)(local_24.x < 0.0) << 8 | (ushort)(local_24.x == 0.0) << 0xe) == 0) { RVar7 = 1; } else { RVar7 = ROUTE_DIRECTION_MASK; } } puVar9 = &local_30; puVar8 = &local_34; pMVar5 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(pMVar5,local_18.x,local_18.y,(int *)puVar8,(int *)puVar9); LegoObject_GetPosition(liveObj_00,&local_c,local_8); puVar9 = &local_28; puVar8 = &local_2c; pMVar5 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(pMVar5,local_c,local_8[0],(int *)puVar8,(int *)puVar9); if ((local_2c == local_34) && (local_28 == local_30)) { BVar6 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,1,(int *)&local_34,(int *)&local_30,(Point2F *)&local_18); } else { BVar6 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,local_2c,local_28,local_34,local_30,(int **)&liveObj, (int **)&drivableObj,(int *)&local_38,0,NULL); if (BVar6 == 0) { return 0; } BVar6 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,local_38,(int *)liveObj,(int *)drivableObj,(Point2F *)&local_18) ; io::Mem_Free(liveObj); io::Mem_Free(drivableObj); } if (BVar6 != 0) { liveObj_00->routeToObject = liveObj_01; liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UNK_12; liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte = liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_GOTOBUILDING; pRVar1 = &liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte; *pRVar1 = *pRVar1 | RVar7; return TRUE; } } return 0; } void __cdecl lego::game::LegoObject_DoDynamiteExplosionRadiusCallbacks (LegoObject *liveObj,float damageRadius,float maxDamage,float wakeRadius) { SearchDynamiteRadius searchDynamite; searchDynamite.liveObj = liveObj; LegoObject_GetPosition(liveObj,&searchDynamite.worldPos.x,&searchDynamite.worldPos.y); searchDynamite.radius = damageRadius; searchDynamite.maxDamage = maxDamage; searchDynamite.wakeRadius = wakeRadius; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_DynamiteExplosion,&searchDynamite); return; } // Affect live objects within the radius of an exploding dynamite object BOOL __cdecl lego::game::LegoObject_Callback_DynamiteExplosion(LegoObject *liveObj,SearchDynamiteRadius *search) { float fVar1; float fVar2; Point2F distance; if ((liveObj != search->liveObj) && ((liveObj->flags3 & LIVEOBJ3_CANDAMAGE) != LIVEOBJ3_NONE)) { LegoObject_GetPosition(liveObj,&distance.x,&distance.y); fVar2 = distance.y - (search->worldPos).y; fVar1 = distance.x - (search->worldPos).x; fVar1 = SQRT(fVar1 * fVar1 + fVar2 * fVar2); if (fVar1 < search->radius) { LegoObject_AddDamage2(liveObj,(1.0 - fVar1 / search->radius) * search->maxDamage,TRUE,1.0); } if ((liveObj->type == LegoObject_RockMonster) && (fVar1 < search->wakeRadius)) { LegoObject_RockMonster_DoWakeUp(liveObj); } } return FALSE; } void __cdecl lego::game::LegoObject_DoBirdScarerRadiusCallbacks (LegoObject *optor_liveObj,Point2F *optor_position,float radius) { LegoObject *local_18; float local_14; float local_10; float local_c; local_18 = optor_liveObj; if (optor_position == NULL) { LegoObject_GetPosition(optor_liveObj,&local_14,&local_10); } else { local_14 = optor_position->x; local_10 = optor_position->y; } local_c = radius; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_BirdScarer,&local_18); return; } BOOL __cdecl lego::game::LegoObject_Callback_BirdScarer(LegoObject *liveObj,SearchDynamiteRadius *search) { StatsFlags2 sflags2; Point2F local_10; Point2F objectPos; float dist; if (liveObj != search->liveObj) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_SCAREDBYBIGBANGS) != STATS2_NONE) { LegoObject_GetPosition(liveObj,&objectPos.x,&objectPos.y); local_10.x = objectPos.x - (search->worldPos).x; local_10.y = objectPos.y - (search->worldPos).y; dist = SQRT(local_10.y * local_10.y + local_10.x * local_10.x); if (dist < search->radius) { if (liveObj->type == LegoObject_RockMonster) { LegoObject_RockMonster_DoWakeUp(liveObj); } local_10.x = (1.0 / dist) * local_10.x; local_10.y = (1.0 / dist) * local_10.y; LegoObject_TryRunAway(liveObj,&local_10); } } } return FALSE; } void __cdecl lego::game::LegoObject_SetActivity(LegoObject *liveObj,Activity_Type activityType,uint repeatCount) { liveObj->activityName1 = globs::objectGlobs.activityName[activityType]; liveObj->animRepeat = repeatCount; liveObj->animTime = 0.0; return; } void __cdecl lego::game::LegoObject_UpdateCarrying(LegoObject *in_liveObj) { LegoObject *liveObj; LegoObject_Type LVar1; float fVar2; float fVar3; LegoObject *pLVar4; uint uVar5; Container *cont; VehicleModel *vehicle; LegoObject **local_14; uint local_10; Vector3F local_c; local_10 = 0; if (in_liveObj->numCarriedObjects != 0) { local_14 = in_liveObj->carriedObjects; pLVar4 = in_liveObj; do { liveObj = *local_14; if ((liveObj->flags3 & LIVEOBJ3_UNK_2000) == LIVEOBJ3_NONE) { LVar1 = in_liveObj->type; if (LVar1 == LegoObject_RockMonster) { pLVar4 = (LegoObject *)gfx::Creature_GetCarryNull(in_liveObj->rockMonster); } else { if (LVar1 == LegoObject_MiniFigure) { pLVar4 = in_liveObj->driveObject; if ((pLVar4 == NULL) || (pLVar4->type != LegoObject_Vehicle)) { pLVar4 = (LegoObject *)gfx::Creature_GetCarryNull(in_liveObj->miniFigure); } else { uVar5 = stats::StatsObject_GetCarryStart(pLVar4); vehicle = in_liveObj->driveObject->vehicle; LAB_00440d93: pLVar4 = (LegoObject *)gfx::Vehicle_GetCarryNull(vehicle,uVar5); } } else { if (LVar1 == LegoObject_Building) { pLVar4 = (LegoObject *) gfx::Building_GetCarryNull(in_liveObj->building,liveObj->carryingIndex); } else { if (LVar1 == LegoObject_Vehicle) { uVar5 = stats::StatsObject_GetCarryStart(in_liveObj); vehicle = in_liveObj->vehicle; uVar5 += liveObj->carryingIndex; goto LAB_00440d93; } } } } if (pLVar4 != NULL) { cont = LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(cont,NULL,&liveObj->tempPosition); gfx::Container_SetPosition(cont,(Container *)pLVar4,0.0,0.0,0.0); gfx::Container_SetOrientation(cont,(Container *)pLVar4,0.0,0.0,1.0,0.0,1.0,0.0); gfx::Container_GetPosition(cont,NULL,&local_c); local_c.x = local_c.x - (liveObj->tempPosition).x; local_c.y = local_c.y - (liveObj->tempPosition).y; local_c.z = local_c.z - (liveObj->tempPosition).z; fVar2 = SQRT(local_c.z * local_c.z + local_c.y * local_c.y + local_c.x * local_c.x); fVar3 = 1.0 / fVar2; liveObj->faceDirectionLength = fVar2; (liveObj->faceDirection).x = fVar3 * local_c.x; (liveObj->faceDirection).y = fVar3 * local_c.y; (liveObj->faceDirection).z = fVar3 * local_c.z; } } local_10 += 1; local_14 = local_14 + 1; } while (local_10 < in_liveObj->numCarriedObjects); } return; } void __cdecl lego::game::LegoObject_InitBoulderMesh_FUN_00440eb0 (LegoObject *liveObj,Container_Texture *contTexture) { D3DRMGroupIndex DVar1; D3DRMGroupIndex groupID; if (liveObj->type == LegoObject_Boulder) { DVar1 = gfx::Container_Mesh_GetGroupCount(liveObj->other); groupID = D3DRMGROUP_0; if (DVar1 != D3DRMGROUP_0) { do { gfx::Container_Mesh_SetTexture(liveObj->other,groupID,contTexture); groupID += 1; } while (groupID < DVar1); } } return; } BOOL __cdecl lego::game::LegoObject_Route_ScoreNoCallback_FUN_00440ef0 (LegoObject *liveObj,uint bx,uint by,uint bx2,uint by2,int **out_param_6,int **out_param_7 ,int *out_count) { BOOL BVar1; BVar1 = LegoObject_Route_Score_FUN_004413b0 (liveObj,bx,by,bx2,by2,out_param_6,out_param_7,out_count,0,NULL); return BVar1; } BOOL __cdecl lego::game::LegoObject_Route_ScoreSub_FUN_00440f30 (LegoObject *liveObj,uint bx,uint by,uint bx2,uint by2,uint **out_param_6, uint **out_param_7,uint *out_count,undefined *callback,void *data) { uint uVar1; Map3D *map; int iVar2; int iVar3; uint uVar4; uint *puVar5; uint *puVar6; int iVar7; void *pvVar8; uint uVar9; uint uVar10; undefined4 *puVar11; uint by1; uint *local_ff0; uint local_fec; uint *local_fe8; uint local_fe4; uint local_fe0; uint local_fdc; uint local_fd0 [4]; uint local_fc0 [9]; uint local_f9c; uint blockHeight; uint blockWidth; local_fc0[0] = 0; local_fc0[1] = 0xffffffff; local_fc0[2] = 1; local_fc0[3] = 0; local_fc0[4] = 0; local_fc0[5] = 1; local_fc0[6] = 0xffffffff; local_fc0[7] = 0; local_fec = 0; map = lrr::Lego_GetMap(); blockWidth = map->blockWidth; blockHeight = map->blockHeight; if (blockWidth <= bx) { return 0; } if (blockHeight <= by) { return 0; } if (callback == NULL) { if (blockWidth <= bx2) { return 0; } if (blockHeight <= by2) { return 0; } iVar2 = Lego_GetCrossTerrainType(liveObj,bx2,by2,bx2,by2,0); if (iVar2 == 0) { return 0; } } if (globs::objectGlobs.UnkSurfaceGrid_2_TABLE != NULL) { if (globs::objectGlobs.UnkSurfaceGrid_COUNT == blockHeight * blockWidth) goto LAB_00441021; if (globs::objectGlobs.UnkSurfaceGrid_2_TABLE != NULL) { io::Mem_Free(globs::objectGlobs.UnkSurfaceGrid_2_TABLE); } } globs::objectGlobs.UnkSurfaceGrid_COUNT = blockHeight * blockWidth; globs::objectGlobs.UnkSurfaceGrid_2_TABLE = io::Mem_Alloc(globs::objectGlobs.UnkSurfaceGrid_COUNT * 4); LAB_00441021: iVar2 = blockHeight * blockWidth; puVar11 = (undefined4 *)globs::objectGlobs.UnkSurfaceGrid_2_TABLE; if (globs::objectGlobs.UnkSurfaceGrid_2_TABLE != NULL) { // std::memset(globs::objectGlobs.UnkSurfaceGrid_2_TABLE, 0, (blockHeight * // blockWidth)); for (; iVar2 != 0; iVar2 += -1) { *puVar11 = 0; puVar11 = puVar11 + 1; } local_fe4 = 0; local_f9c = by; *(undefined4 *)((int)globs::objectGlobs.UnkSurfaceGrid_2_TABLE + (blockWidth * by + bx) * 4) = 1 ; local_ff0 = local_fd0; local_fc0[8] = bx; local_fd0[0] = 1; local_fd0[1] = 0; uVar9 = 1; do { local_fe0 = uVar9; uVar9 = local_fe0 + 1; local_fdc = 0; if (*local_ff0 != 0) { iVar2 = 0; local_fe8 = local_fc0 + local_fe4 * 500 + 9; while( true ) { do { uVar10 = local_fe8[-1]; by1 = *local_fe8; if (iVar2 == 0) { by1 -= 1; } else { if (iVar2 == 1) { uVar10 += 1; } else { if (iVar2 == 2) { by1 += 1; } else { if (iVar2 == 3) { uVar10 -= 1; } } } } if ((uVar10 < blockWidth) && (by1 < blockHeight)) { iVar3 = Lego_GetCrossTerrainType (liveObj,uVar10,by1,local_fc0[iVar2 * 2] + uVar10, local_fc0[iVar2 * 2 + 1] + by1,0); iVar7 = by1 * blockWidth + uVar10; if ((*(int *)((int)globs::objectGlobs.UnkSurfaceGrid_2_TABLE + iVar7 * 4) == 0) && (iVar3 != 0)) { uVar4 = (uint)(local_fe4 == 0); uVar1 = local_fd0[uVar4]; iVar3 = uVar1 + uVar4 * 100; local_fc0[iVar3 * 5 + 8] = uVar10; local_fc0[iVar3 * 5 + 9] = by1; local_fd0[uVar4] = uVar1 + 1; *(uint *)((int)globs::objectGlobs.UnkSurfaceGrid_2_TABLE + iVar7 * 4) = uVar9; if (callback == NULL) { if ((uVar10 == bx2) && (by1 == by2)) { local_fec = 1; } } else { local_fd0[2] = uVar10; local_fd0[3] = by1; iVar3 = (*(code *)callback)(liveObj,local_fd0 + 2,data); if (iVar3 != 0) { local_fec = 1; bx2 = uVar10; by2 = by1; } } } } iVar2 += 1; } while (iVar2 < 4); local_fdc += 1; local_fe8 = local_fe8 + 5; if (*local_ff0 <= local_fdc) break; iVar2 = 0; } } iVar2 = 0; *local_ff0 = 0; local_fe4 = (uint)(local_fe4 == 0); local_ff0 = local_fd0 + local_fe4; if (local_fd0[local_fe4] == 0) { local_fec = -1; } } while (local_fec == 0); if (local_fec == -1) { return 0; } local_fd0[0] = uVar9; puVar5 = (uint *)io::Mem_Alloc(uVar9 * 4); if ((puVar5 != NULL) && (puVar6 = (uint *)io::Mem_Alloc(uVar9 * 4), puVar6 != NULL)) { local_fec = by2; local_ff0 = puVar6 + local_fe0; puVar5[local_fe0] = bx2; *local_ff0 = by2; *puVar5 = bx; *puVar6 = by; if (local_fe0 != 1) { pvVar8 = globs::objectGlobs.UnkSurfaceGrid_2_TABLE; do { local_fdc = 0; uVar9 = by2; do { uVar10 = bx2; if (iVar2 == 0) { by2 = uVar9 - 1; } else { by2 = uVar9; if (iVar2 == 1) { uVar10 = bx2 + 1; } else { if (iVar2 == 2) { by2 = uVar9 + 1; } else { if (iVar2 == 3) { uVar10 = bx2 - 1; } } } } if (((uVar10 < blockWidth) && (by2 < blockHeight)) && (uVar9 = local_fec, *(uint *)((int)pvVar8 + (by2 * blockWidth + uVar10) * 4) == local_fe0)) { *(uint *)((int)puVar5 + (-4 - (int)puVar6) + (int)local_ff0) = uVar10; local_ff0[-1] = by2; pvVar8 = globs::objectGlobs.UnkSurfaceGrid_2_TABLE; bx2 = uVar10; local_fec = by2; break; } by2 = uVar9; iVar2 += 1; if (3 < iVar2) { iVar2 = 0; } local_fdc += 1; uVar9 = by2; } while ((int)local_fdc < 4); local_fe0 -= 1; local_ff0 = local_ff0 + -1; } while (local_fe0 != 1); } *out_param_6 = puVar5; *out_param_7 = puVar6; *out_count = local_fd0[0]; } } return TRUE; } // WARNING: Function: _alloca4k replaced with injection: alloca_probe BOOL __cdecl lego::game::LegoObject_Route_Score_FUN_004413b0 (LegoObject *liveObj,uint bx,uint by,uint bx2,uint by2,int **out_new_bxs,int **out_new_bys ,int *out_count,code *callback,void *data) { float *pfVar1; float fVar2; float fVar3; int iVar4; float fVar5; bool bVar6; Map3D *map; int iVar7; BOOL BVar8; uint uVar9; uint *puVar10; uint *buffer; uint uVar11; uint uVar12; undefined4 *puVar13; uint uVar14; int iStack4108; uint *puStack4104; uint uStack4096; float fStack4092; float fStack4088; uint *puStack4080; int iStack4076; uint uStack4068; uint auStack4060 [2]; float fStack4052; Point2I PStack4048; Point2I PStack4040; int aiStack4032 [4]; undefined4 uStack4016; undefined4 uStack4012; undefined4 uStack4008; undefined4 uStack4004; uint auStack4000 [999]; undefined4 uStack4; uint blockWidth; uint blockHeight; uStack4 = 0x4413ba; aiStack4032[0] = 0; aiStack4032[1] = 0xffffffff; aiStack4032[2] = 1; aiStack4032[3] = 0; uStack4016 = 0; uStack4012 = 1; uStack4008 = 0xffffffff; uStack4004 = 0; iStack4076 = 0; bVar6 = false; map = lrr::Lego_GetMap(); blockWidth = map->blockWidth; blockHeight = map->blockHeight; if (blockWidth <= bx) { return 0; } if (blockHeight <= by) { return 0; } if (callback == NULL) { if (blockWidth <= bx2) { return 0; } if (blockHeight <= by2) { return 0; } iVar7 = Lego_GetCrossTerrainType(liveObj,bx2,by2,bx2,by2,0); if (iVar7 == 0) { return 0; } } if (globs::objectGlobs.UnkSurfaceGrid_1_TABLE != NULL) { if (globs::objectGlobs.UnkSurfaceGrid_COUNT == blockHeight * blockWidth) goto LAB_004414be; if (globs::objectGlobs.UnkSurfaceGrid_1_TABLE != NULL) { io::Mem_Free(globs::objectGlobs.UnkSurfaceGrid_1_TABLE); } } globs::objectGlobs.UnkSurfaceGrid_COUNT = blockHeight * blockWidth; globs::objectGlobs.UnkSurfaceGrid_1_TABLE = io::Mem_Alloc(globs::objectGlobs.UnkSurfaceGrid_COUNT * 4); LAB_004414be: iVar7 = blockHeight * blockWidth; puVar13 = (undefined4 *)globs::objectGlobs.UnkSurfaceGrid_1_TABLE; if (globs::objectGlobs.UnkSurfaceGrid_1_TABLE != NULL) { // std::memset(globs::objectGlobs.UnkSurfaceGrid_1_TABLE, 0, (blockHeight * // blockWidth)); for (; iVar7 != 0; iVar7 += -1) { *puVar13 = 0; puVar13 = puVar13 + 1; } fStack4092 = 1.401298e-45; auStack4060[0] = 1; puStack4104 = auStack4060; uStack4096 = 0; *(undefined4 *)((int)globs::objectGlobs.UnkSurfaceGrid_1_TABLE + (blockWidth * by + bx) * 4) = 0x3f800000; auStack4000[0] = bx; auStack4000[1] = by; auStack4060[1] = 0; do { fStack4092 = (float)((int)fStack4092 + 1); uStack4068 = 0; if (*puStack4104 != 0) { puVar10 = auStack4000 + uStack4096 * 500 + 1; do { fVar2 = *(float *)((int)globs::objectGlobs.UnkSurfaceGrid_1_TABLE + (blockWidth * *puVar10 + puVar10[-1]) * 4); iStack4108 = 0; do { uVar11 = puVar10[-1]; uVar14 = *puVar10; if (iStack4108 == 0) { uVar14 -= 1; } else { if (iStack4108 == 1) { uVar11 += 1; } else { if (iStack4108 == 2) { uVar14 += 1; } else { if (iStack4108 == 3) { uVar11 -= 1; } } } } if ((uVar11 < blockWidth) && (uVar14 < blockHeight)) { fStack4088 = 1.0; iVar7 = aiStack4032[iStack4108 * 2]; iVar4 = aiStack4032[iStack4108 * 2 + 1]; PStack4040.x = iVar7 + uVar11; PStack4040.y = iVar4 + uVar14; BVar8 = Level_Block_IsPath(&PStack4040); if (BVar8 != 0) { fStack4088 = 0.5; } iVar7 = Lego_GetCrossTerrainType (liveObj,uVar11,uVar14,iVar7 + uVar11,iVar4 + uVar14,0); if ((iVar7 != 0) && ((iVar7 = uVar14 * blockWidth + uVar11, pfVar1 = (float *)((int)globs::objectGlobs.UnkSurfaceGrid_1_TABLE + iVar7 * 4), *(float *)((int)globs::objectGlobs.UnkSurfaceGrid_1_TABLE + iVar7 * 4) == 0.0 || (fVar5 = fStack4088 + fVar2, fVar3 = *pfVar1, (ushort)((ushort)(fVar3 < fVar5) << 8 | (ushort)(fVar3 == fVar5) << 0xe) == 0)))) { uVar9 = (uint)(uStack4096 == 0); uVar12 = auStack4060[uVar9]; iVar7 = uVar12 + uVar9 * 100; *pfVar1 = fStack4088 + fVar2; auStack4000[iVar7 * 5] = uVar11; auStack4000[iVar7 * 5 + 1] = uVar14; auStack4060[uVar9] = uVar12 + 1; if (callback == NULL) { if ((uVar11 == bx2) && (uVar14 == by2)) { bVar6 = true; fStack4052 = fStack4092; } } else { PStack4048.x = uVar11; PStack4048.y = uVar14; iVar7 = (*callback)(liveObj,&PStack4048,data); if (iVar7 != 0) { iStack4076 = 1; bx2 = uVar11; by2 = uVar14; } } } } iStack4108 += 1; } while (iStack4108 < 4); uStack4068 += 1; puVar10 = puVar10 + 5; } while (uStack4068 < *puStack4104); } *puStack4104 = 0; uStack4096 = (uint)(uStack4096 == 0); puStack4104 = auStack4060 + uStack4096; if (auStack4060[uStack4096] == 0) { iStack4076 = -1; } } while (iStack4076 == 0); if (bVar6) { iStack4076 = 1; fStack4092 = fStack4052; } if (iStack4076 == -1) { return 0; } puVar10 = (uint *)io::Mem_Alloc((int)fStack4092 * 4); if ((puVar10 != NULL) && (buffer = (uint *)io::Mem_Alloc((int)fStack4092 * 4), buffer != NULL)) { iVar7 = (int)fStack4092 + -1; puVar10[iVar7] = bx2; puStack4080 = buffer + iVar7; *puStack4080 = by2; *puVar10 = bx; *buffer = by; if (iVar7 != 1) { uStack4068 = (int)fStack4092 + -2; uVar11 = bx2; uVar14 = by2; do { puStack4104 = (uint *)0x461c4000; iStack4108 = 0; do { uVar12 = uVar11; if (iStack4108 == 0) { uVar9 = uVar14 - 1; } else { uVar9 = uVar14; if (iStack4108 == 1) { uVar12 = uVar11 + 1; } else { if (iStack4108 == 2) { uVar9 = uVar14 + 1; } else { if (iStack4108 == 3) { uVar12 = uVar11 - 1; } } } } PStack4048.x = uVar12; PStack4048.y = uVar9; if (((uVar12 < blockWidth) && (uVar9 < blockHeight)) && (((fStack4052 = *(float *)((int)globs::objectGlobs.UnkSurfaceGrid_1_TABLE + (uVar14 * blockWidth + uVar11) * 4) - *(float *)((int)globs::objectGlobs.UnkSurfaceGrid_1_TABLE + (uVar9 * blockWidth + uVar12) * 4), (ushort)((ushort)(fStack4052 < 0.0) << 8 | (ushort)(fStack4052 == 0.0) << 0xe) == 0 && (fStack4052 < (float)puStack4104)) || ((fStack4052 == (float)puStack4104 && (BVar8 = Level_Block_IsPath(&PStack4048), BVar8 != 0)))))) { puStack4104 = (uint *)fStack4052; auStack4060[0] = uVar12; auStack4060[1] = uVar9; } iStack4108 += 1; } while (iStack4108 < 4); puStack4080 = puStack4080 + -1; *(uint *)(((int)puVar10 - (int)buffer) + (int)puStack4080) = auStack4060[0]; *puStack4080 = auStack4060[1]; uStack4068 += -1; uVar11 = auStack4060[0]; uVar14 = auStack4060[1]; } while (uStack4068 != 0); } *out_new_bxs = (int *)puVar10; *out_new_bys = (int *)buffer; *out_count = (int)fStack4092; if (((*puVar10 != puVar10[1]) || (uVar11 = (int)(*buffer - buffer[1]) >> 0x1f, (*buffer - buffer[1] ^ uVar11) - uVar11 != 1 )) && ((*buffer != buffer[1] || (uVar11 = *puVar10 - puVar10[1], uVar14 = (int)uVar11 >> 0x1f, (uVar11 ^ uVar14) - uVar14 != 1)))) { io::Mem_Free(puVar10); io::Mem_Free(buffer); BVar8 = LegoObject_Route_ScoreSub_FUN_00440f30 (liveObj,bx,by,bx2,by2,(uint **)out_new_bxs,(uint **)out_new_bys, (uint *)out_count,callback,data); return BVar8; } } } return TRUE; } BOOL __cdecl lego::game::LegoObject_Route_AllocPtr_FUN_004419c0 (LegoObject *liveObj,uint count,int *bxList,int *byList,Point2F *opt_point) { bool bVar1; BOOL BVar2; RoutingBlock *buffer; Map3D *map; StatsFlags1 SVar3; int iVar4; int iVar5; int iVar6; Point2F *pPVar7; float *pfVar8; float10 fVar9; Point2F *wPos2D; Point2F *optout_blockPosf; Point2F *optout_centerDir; uint i; int local_14; Point2F local_8; BVar2 = LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(liveObj); if (BVar2 == 0) { local_14 = -1; bVar1 = false; local_8.x = 0.5; local_8.y = 0.5; if ((liveObj->flags4 & LIVEOBJ4_DOCKOCCUPIED) != LIVEOBJ4_NONE) { liveObj->routeToObject = NULL; liveObj->flags4 = liveObj->flags4 & ~LIVEOBJ4_DOCKOCCUPIED; } buffer = (RoutingBlock *)io::Mem_Alloc(count * 0x14); if ((buffer != NULL) && (i = 0, count != 0)) { pPVar7 = &buffer->blockOffset; iVar6 = (int)byList - (int)bxList; do { pfVar8 = (float *)bxList + 1; pPVar7[-1].x = (float)*bxList; pPVar7[-1].y = (float)*byList; if ((opt_point == NULL) || (i != count - 1)) { if (((liveObj->flags3 & LIVEOBJ3_CENTERBLOCKIDLE) == LIVEOBJ3_NONE) && (SVar3 = stats::StatsObject_GetStatsFlags1(liveObj), (SVar3 & STATS1_ROUTEAVOIDANCE) != STATS1_NONE)) { fVar9 = math::Maths_RandRange(0.3,0.7); pPVar7->x = (float)fVar9; fVar9 = math::Maths_RandRange(0.3,0.7); pPVar7->y = (float)fVar9; } else { pPVar7->y = 0.5; pPVar7->x = 0.5; } } else { optout_centerDir = &local_8; optout_blockPosf = NULL; wPos2D = opt_point; map = lrr::Lego_GetMap(); lego::map::Map3D_FUN_0044fb30(map,wPos2D,optout_blockPosf,optout_centerDir); pPVar7->x = local_8.x; pPVar7->y = local_8.y; } *(undefined *)&pPVar7[1].x = 0; *(undefined *)((int)&pPVar7[1].x + 1) = 0; iVar4 = local_14; if (i < count - 1) { iVar4 = lego::map::Map3D_CheckRoutingComparison_FUN_00450b60 ((int)*pfVar8,*(int *)(iVar6 + (int)pfVar8),*bxList,*byList); if (iVar4 == -1) { bVar1 = true; break; } if (((i != 0) && (local_14 != iVar4)) && (iVar5 = Lego_GetCrossTerrainType (liveObj,(int)*pfVar8,*(int *)(iVar6 + (int)pfVar8), (int)((float *)bxList)[-1],(int)((float *)byList)[-1],0), iVar5 == 2)) { *(byte *)&pPVar7[1].x = *(byte *)&pPVar7[1].x | 0x10; } } local_14 = iVar4; i += 1; byList = (int *)((float *)byList + 1); pPVar7 = (Point2F *)&pPVar7[2].y; bxList = (int *)pfVar8; } while (i < count); } if (!bVar1) { LegoObject_Route_End(liveObj,FALSE); // & ~LIVEOBJ3_UNK_400 (0x400) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000| LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_MOVING; liveObj->routeBlocks = buffer; liveObj->routeBlocksTotal = count; liveObj->routeBlocksCurrent = 0; liveObj->routeCurveCurrDist = 0.0; liveObj->routeCurveTotalDist = 0.0; return TRUE; } io::Mem_Free(buffer); } return FALSE; } void __cdecl lego::game::LegoObject_Route_End(LegoObject *liveObj,BOOL completed) { float fVar1; LegoObject *liveObj_00; uint index; RouteAction *pRAction; longlong lVar2; Point2I blockPos; LiveFlags4 *pLFlags4; if (liveObj->routeBlocks != NULL) { if (completed == 0) { // Loop from current block to total blocks (ignoring 0-current) index = liveObj->routeBlocksCurrent; if (index < liveObj->routeBlocksTotal) { pRAction = &liveObj->routeBlocks[index].actionByte; do { if (*pRAction == ROUTE_ACTION_GATHERROCK) { liveObj_00 = liveObj->routeToObject; if (liveObj_00 != NULL) { if (liveObj_00->type == LegoObject_Boulder) { LegoObject_DestroyBoulder_AndCreateExplode(liveObj_00); } else { liveObj_00->interactObject = NULL; } LAB_00441ca7: liveObj->routeToObject = NULL; } break; } if (*pRAction == ROUTE_ACTION_STORE) goto LAB_00441ca7; index += 1; pRAction = pRAction + 0x14; } while (index < liveObj->routeBlocksTotal); } if (liveObj->type == LegoObject_RockMonster) { if (((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && (liveObj->carriedObjects[0]->type == LegoObject_Boulder)) { LegoObject_DropCarriedObject(liveObj,0); } ai::AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Gather,NULL); ai::AITask_LiveObject_FUN_00403b30(liveObj,AITask_Type_Repair,NULL); } if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_DRILLING) != 0) { lVar2 = __ftol((float10)(liveObj->targetBlockPos).x); blockPos.x = (int)lVar2; lVar2 = __ftol((float10)(liveObj->targetBlockPos).y); blockPos.y = (int)lVar2; Level_Block_SetBusy(&blockPos,0); } ai::AITask_Game_UnkLiveObjectHandleDynamite(liveObj); } else { if (liveObj->type == LegoObject_MiniFigure) { gfx::Creature_SetOrientation (liveObj->miniFigure,(liveObj->point_298).x,(liveObj->point_298).y); fVar1 = (liveObj->point_298).y; (liveObj->faceDirection).x = (liveObj->point_298).x; (liveObj->faceDirection).y = fVar1; } } io::Mem_Free(liveObj->routeBlocks); liveObj->routeBlocks = NULL; ai::AITask_Route_End(liveObj,completed); } liveObj->routeBlocksTotal = 0; liveObj->routeBlocksCurrent = 0; liveObj->routeCurveCurrDist = 0.0; liveObj->routeCurveTotalDist = 0.0; liveObj->routeCurveInitialDist = 0.0; // & ~(LIVEOBJ1_MOVING|LIVEOBJ1_RUNNINGAWAY) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART| LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB |LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); // & ~(LIVEOBJ3_UNK_400|LIVEOBJ3_UNK_4000) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT| LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED| LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000| LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); if (liveObj->routeToObject != NULL) { pLFlags4 = &liveObj->routeToObject->flags4; *pLFlags4 = *pLFlags4 & ~LIVEOBJ4_UNK_10; } if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_LIFTING) != 0) { (liveObj->faceDirection).x = (liveObj->faceDirection).x * -1.0; (liveObj->faceDirection).y = (liveObj->faceDirection).y * -1.0; (liveObj->faceDirection).z = (liveObj->faceDirection).z * -1.0; // & ~LIVEOBJ1_LIFTING (0x2) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART| LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); } LegoObject_SetActivity(liveObj,Activity_Stand,0); return; } void __cdecl lego::game::LegoObject_Interrupt(LegoObject *liveObj,BOOL actStand,BOOL dropCarried) { StatsFlags2 sflags2; longlong lVar1; Point2I local_8; LiveFlags1 lflags1; LiveFlags2 lflags2; LiveFlags2 *pLFlags2; LiveFlags3 *pLFlags3; LegoObject_Route_End(liveObj,FALSE); if (dropCarried != 0) { LegoObject_DropCarriedObject(liveObj,FALSE); } if ((liveObj->flags2 & LIVEOBJ2_THROWN) != LIVEOBJ2_NONE) { // & ~LIVEOBJ2_THROWN (0x2) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); LegoObject_SetActivity(liveObj,Activity_GetUp,0); LegoObject_UpdateActivityChange(liveObj); // & ~LIVEOBJ2_THROWING (0x1) liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_100; lflags2 = liveObj->throwObject->flags2; if ((lflags2 & LIVEOBJ2_THROWING) != LIVEOBJ2_NONE) { liveObj->throwObject->flags2 = lflags2 & (LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100| LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000 |LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); LegoObject_SetActivity(liveObj,Activity_Stand,0); } } if ((liveObj->flags2 & LIVEOBJ2_THROWING) != LIVEOBJ2_NONE) { // & ~LIVEOBJ2_THROWING (0x1) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); LegoObject_SetActivity(liveObj,Activity_Stand,0); // & ~LIVEOBJ2_THROWN (0x2) lflags2 = liveObj->throwObject->flags2; if ((lflags2 & LIVEOBJ2_THROWN) != LIVEOBJ2_NONE) { liveObj->throwObject->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100| LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000 |LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN| LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); LegoObject_SetActivity(liveObj->throwObject,Activity_GetUp,0); LegoObject_UpdateActivityChange(liveObj->throwObject); pLFlags2 = &liveObj->throwObject->flags2; *pLFlags2 = *pLFlags2 | LIVEOBJ2_UNK_100; } } lflags1 = liveObj->flags1; // & // ~(LIVEOBJ2_UNK_20|LIVEOBJ2_PUSHED|LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000| LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000| LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); // & ~(LIVEOBJ1_UNK_800|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_CANTDO) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_RESTING|LIVEOBJ1_EATING); if ((lflags1 & LIVEOBJ1_STORING) != LIVEOBJ1_NONE) { // & ~(LIVEOBJ1_UNK_800|LIVEOBJ1_STORING|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_CANTDO) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING |LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_RESTING|LIVEOBJ1_EATING); ai::AITask_LiveObject_SetAITaskUnk(liveObj,AITask_Type_Deposit,liveObj,TRUE); LegoObject_ProccessCarriedObjects(liveObj); if (liveObj->routeToObject != NULL) { pLFlags3 = &liveObj->routeToObject->flags3; // & ~LIVEOBJ3_UNK_1000000 (0x1000000) *pLFlags3 = *pLFlags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE |LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART |LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); } } lflags1 = liveObj->flags1; // & ~(LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_RESTING) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); // & ~LIVEOBJ3_UNK_4000 (0x4000) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000| LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE |LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); if ((liveObj->flags2 & LIVEOBJ2_UNK_200000) != LIVEOBJ2_NONE) { // & ~LIVEOBJ2_UNK_200000 (0x200000) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } lflags2 = liveObj->flags2; // & ~LIVEOBJ2_UNK_40000 (0x40000) liveObj->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100| LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000| LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_80000| LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER |LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000| LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING| LIVEOBJ2_UNK_80000000); if ((lflags1 & LIVEOBJ1_REPAIRDRAINING) != LIVEOBJ1_NONE) { // & ~(LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000) liveObj->flags2 = lflags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100 |LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000| LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_100000| LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER| LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000| LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING |LIVEOBJ2_UNK_80000000); ai::AITask_LiveObject_SetAITaskUnk(liveObj,AITask_Type_Repair,NULL,TRUE); // & ~LIVEOBJ1_REPAIRDRAINING (0x1000000) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); } if ((liveObj->flags1 & LIVEOBJ1_EATING) != LIVEOBJ1_NONE) { // & ~LIVEOBJ1_EATING (0x40000000) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_CANTDO); } if ((liveObj->flags2 & LIVEOBJ2_UNK_40) != LIVEOBJ2_NONE) { // & ~LIVEOBJ2_UNK_40 (0x40) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } if ((liveObj->flags2 & LIVEOBJ2_TRAINING) != LIVEOBJ2_NONE) { // & ~LIVEOBJ2_TRAINING (0x400) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } if ((liveObj->flags2 & LIVEOBJ2_UPGRADING) != LIVEOBJ2_NONE) { if (liveObj->routeToObject != NULL) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj->routeToObject); if ((sflags2 & STATS2_UPGRADEBUILDING) != STATS2_NONE) { if ((liveObj->routeToObject->flags2 & LIVEOBJ2_UPGRADING) != LIVEOBJ2_NONE) goto LAB_00442065; ai::AITask_LiveObject_SetAITaskUnk(liveObj,AITask_Type_Upgrade,NULL,TRUE); liveObj->routeToObject->interactObject = NULL; liveObj->routeToObject = NULL; } } // & ~LIVEOBJ2_UPGRADING (0x8000) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } LAB_00442065: if ((liveObj->flags1 & LIVEOBJ1_PLACING) != LIVEOBJ1_NONE) { // & ~LIVEOBJ1_PLACING (0x80000) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); LegoObject_DropCarriedObject(liveObj,TRUE); } lflags1 = liveObj->flags1; // & ~LIVEOBJ1_GETTINGHIT (0x1000) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); if ((lflags1 & LIVEOBJ1_REINFORCING) != LIVEOBJ1_NONE) { lVar1 = __ftol((float10)(liveObj->targetBlockPos).x); local_8.x = (int)lVar1; lVar1 = __ftol((float10)(liveObj->targetBlockPos).y); local_8.y = (int)lVar1; // & ~(LIVEOBJ1_REINFORCING|LIVEOBJ1_GETTINGHIT) | LIVEOBJ1_CANTDO liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE |LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO) | LIVEOBJ1_CANTDO; Level_Block_SetBusy(&local_8,FALSE); } lflags1 = liveObj->flags1; // & ~LIVEOBJ1_SLIPPING (0x4000000) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); if ((liveObj->flags2 & LIVEOBJ2_UNK_4) != LIVEOBJ2_NONE) { liveObj->routeToObject = NULL; // & ~LIVEOBJ2_UNK_4 (0x4) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } // & // ~(LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_CLEARING|LIVEOBJ1_SLIPPING|LIVEOBJ1_CANTDO) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING| LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000| LIVEOBJ1_RESTING|LIVEOBJ1_EATING); // & // ~(LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800| LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING| LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000| LIVEOBJ2_FIRINGLASER|LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING| LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); if (actStand != 0) { ai::AITask_LiveObject_Unk_UpdateAITask_AnimationWait(liveObj); LegoObject_SetActivity(liveObj,Activity_Stand,1); LegoObject_UpdateActivityChange(liveObj); } return; } void __cdecl lego::game::LegoObject_DestroyBoulder_AndCreateExplode(LegoObject *liveObj) { if ((((byte)globs::objectGlobs.flags & 2) == 0) && (liveObj->type == LegoObject_Boulder)) { effect::Effect_Spawn_BoulderExplode_AtObjectOther(liveObj); LegoObject_Remove(liveObj); } return; } BOOL __cdecl lego::game::LegoObject_FireBeamWeaponAtObject (LegoObject *liveObj,LegoObject *targetObj,Weapon_KnownType knownWeapon) { float fVar1; float fVar2; float fVar3; BOOL BVar4; Container *pCVar5; LiveFlags2 lflags2; float10 fVar6; Container *pCVar7; Vector3F *pVVar8; Vector3F dir; Vector3F local_18; Vector3F local_c; if ((((ushort)((ushort)(liveObj->weaponRechargeTimer < 0.0) << 8 | (ushort)(liveObj->weaponRechargeTimer == 0.0) << 0xe) == 0) || (((byte)globs::legoGlobs.flags2 & OBJECT_GLOB_FLAG_POWERUPDATING) != 0)) || (targetObj->type != LegoObject_RockMonster)) { return 0; } BVar4 = LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(liveObj); if (BVar4 != 0) { return 0; } LegoObject_Route_End(liveObj,FALSE); pVVar8 = &local_18; pCVar7 = NULL; pCVar5 = LegoObject_GetActivityContainer(targetObj); gfx::Container_GetPosition(pCVar5,pCVar7,pVVar8); pVVar8 = &local_c; pCVar7 = NULL; pCVar5 = LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(pCVar5,pCVar7,pVVar8); fVar6 = stats::StatsObject_GetCollHeight(liveObj); local_c.z = (float)((float10)local_c.z - fVar6 * (float10)0.5); fVar6 = stats::StatsObject_GetCollHeight(targetObj); fVar6 = (float10)local_18.z - fVar6 * (float10)0.5; local_18.z = (float)fVar6; fVar6 = fVar6 - (float10)local_c.z; fVar1 = (float)((float10)local_18.x - (float10)local_c.x); fVar2 = (float)((float10)local_18.y - (float10)local_c.y); fVar3 = (float)fVar6; fVar6 = (float10)1.0 / SQRT(fVar6 * (float10)fVar3 + ((float10)local_18.y - (float10)local_c.y) * (float10)fVar2 + ((float10)local_18.x - (float10)local_c.x) * (float10)fVar1); dir.x = (float)(fVar6 * (float10)fVar1); dir.y = (float)(fVar6 * (float10)fVar2); dir.z = (float)(fVar6 * (float10)fVar3); LegoObject_SetHeadingOrDirection(liveObj,0.0,&dir); if (knownWeapon == Weapon_KnownType_Laser) { LegoObject_SetActivity(liveObj,Activity_FireLaser,1); LegoObject_UpdateActivityChange(liveObj); lflags2 = liveObj->flags2 | LIVEOBJ2_FIRINGLASER; } else { if (knownWeapon == Weapon_KnownType_Pusher) { LegoObject_SetActivity(liveObj,Activity_FireLaser,1); LegoObject_UpdateActivityChange(liveObj); lflags2 = liveObj->flags2 | LIVEOBJ2_FIRINGPUSHER; } else { if (knownWeapon != Weapon_KnownType_Freezer) goto LAB_0044233f; LegoObject_SetActivity(liveObj,Activity_FireLaser,1); LegoObject_UpdateActivityChange(liveObj); lflags2 = liveObj->flags2 | LIVEOBJ2_FIRINGFREEZER; } } liveObj->flags2 = lflags2; LAB_0044233f: (liveObj->weaponVector_3a8).x = local_18.x; (liveObj->weaponVector_3a8).y = local_18.y; (liveObj->beamVector_39c).x = dir.x; (liveObj->weaponVector_3a8).z = local_18.z; (liveObj->beamVector_39c).y = dir.y; (liveObj->beamVector_39c).z = dir.z; return TRUE; } void __cdecl lego::game::LegoObject_CreateWeaponProjectile(LegoObject *liveObj,Weapon_KnownType knownWeapon) { Map3D *map; float weaponID; float10 fVar1; Vector3F wPos; LegoObject_GetPosition(liveObj,&wPos.x,&wPos.y); map = lrr::Lego_GetMap(); fVar1 = lego::map::Map3D_GetWorldZ(map,wPos.x,wPos.y); weaponID = (float)fVar1; fVar1 = stats::StatsObject_GetCollHeight(liveObj); wPos.z = (float)((float10)weaponID - fVar1 * (float10)0.5); switch(knownWeapon) { case Weapon_KnownType_Laser: weaponID = (float)tools::Weapon_GetWeaponIDByName("Lazer"); tools::Weapon_Projectile_AddStraightPath (liveObj,&wPos,&liveObj->beamVector_39c,(int)weaponID,Weapon_KnownType_Laser); break; case Weapon_KnownType_Pusher: weaponID = (float)tools::Weapon_GetWeaponIDByName("Pusher"); tools::Weapon_Projectile_AddStraightPath (liveObj,&wPos,&liveObj->beamVector_39c,(int)weaponID,Weapon_KnownType_Pusher); break; case Weapon_KnownType_Freezer: weaponID = (float)tools::Weapon_GetWeaponIDByName("Freezer"); tools::Weapon_Projectile_AddStraightPath (liveObj,&wPos,&liveObj->beamVector_39c,(int)weaponID,Weapon_KnownType_Freezer); break; case Weapon_KnownType_Boulder: weaponID = (float)tools::Weapon_GetWeaponIDByName("Lazer"); tools::Weapon_Projectile_AddCurvedPath (liveObj,&wPos,&liveObj->weaponVector_3a8,(int)weaponID,Weapon_KnownType_Boulder); } fVar1 = tools::Weapon_GetRechargeTime((uint)weaponID); liveObj->weaponRechargeTimer = (float)fVar1; return; } void __cdecl lego::game::LegoObject_StartCrumbling(LegoObject *liveObj) { BOOL BVar1; LegoObject_Interrupt(liveObj,FALSE,TRUE); LegoObject_SetActivity(liveObj,Activity_Crumble,1); BVar1 = LegoObject_UpdateActivityChange(liveObj); if (BVar1 != 0) { liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_CRUMBLING; } liveObj->health = -1.0; return; } void __cdecl lego::game::LegoObject_GetPosition(LegoObject *liveObj,float *out_x,float *out_y) { Container *cont; Vector3F wPos; cont = LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(cont,NULL,&wPos); *out_x = wPos.x; *out_y = wPos.y; return; } void __cdecl lego::game::LegoObject_GetFaceDirection(LegoObject *liveObj,Point2F *out_direction) { Container *cont; Vector3F dir3D; float norm; cont = LegoObject_GetActivityContainer(liveObj); gfx::Container_GetOrientation(cont,NULL,&dir3D,NULL); norm = 1.0 / SQRT(dir3D.x * dir3D.x + dir3D.y * dir3D.y); out_direction->x = norm * dir3D.x; out_direction->y = norm * dir3D.y; return; } void __cdecl lego::game::LegoObject_SetHeadingOrDirection(LegoObject *liveObj,float theta,Vector3F *opt_vecDir) { Vector3F newDir; Vector3F axis; LegoObject_Type objType; if (opt_vecDir == NULL) { newDir.z = 0.0; newDir.x = 0.0; newDir.y = 1.0; axis.y = 0.0; axis.x = 0.0; axis.z = -1.0; math::Maths_Vector3DRotate(&newDir,&newDir,&axis,theta); } else { newDir.x = opt_vecDir->x; newDir.y = opt_vecDir->y; newDir.z = opt_vecDir->z; } objType = liveObj->type; if (objType == LegoObject_Vehicle) { gfx::Vehicle_SetOrientation(liveObj->vehicle,newDir.x,newDir.y,newDir.z); } else { if (objType == LegoObject_MiniFigure) { gfx::Creature_SetOrientation(liveObj->miniFigure,newDir.x,newDir.y); } else { if (objType == LegoObject_RockMonster) { gfx::Creature_SetOrientation(liveObj->rockMonster,newDir.x,newDir.y); } else { if (objType == LegoObject_Building) { gfx::Building_SetOrientation(liveObj->building,newDir.x,newDir.y); } else { if ((liveObj->flags3 & LIVEOBJ3_SIMPLEOBJECT) != LIVEOBJ3_NONE) { gfx::Container_SetOrientation (liveObj->other,NULL,newDir.x,newDir.y,newDir.z,0.0,0.0,-1.0); } } } } } liveObj->faceDirectionLength = 0.01; (liveObj->faceDirection).x = newDir.x; (liveObj->faceDirection).y = newDir.y; (liveObj->faceDirection).z = newDir.z; (liveObj->tempPosition).x = (liveObj->faceDirection).x * -0.01; (liveObj->tempPosition).y = (liveObj->faceDirection).y * -0.01; (liveObj->tempPosition).z = (liveObj->faceDirection).z * -0.01; return; } // Returns faceDirection in radians (always positive value between 0 and M_PI*2) float10 __cdecl lego::game::LegoObject_GetHeading(LegoObject *liveObj) { float10 theta; Point2F dir2D; LegoObject_GetFaceDirection(liveObj,&dir2D); // Ignoring the insane double-sqrt going on here... shoudn't this be std::atan??? // Dividing by the modulus is pointless, since LegoObject_GetFaceDirection normalizes // the output. theta = std::acos((float10)dir2D.y / (SQRT((float10)1.0) * SQRT((float10)dir2D.y * (float10)dir2D.y + (float10)dir2D.x * (float10)dir2D.x)) ); if (dir2D.x < 0.0) { // Handle ranges between [M_PI, M_PI*2]. theta = (float10)6.283185 - theta; } return theta; } BOOL __cdecl lego::game::LegoObject_GetBlockPos(LegoObject *liveObj,int *out_bx,int *out_by) { Container *cont; Map3D *map; BOOL BVar1; Vector3F wPos; cont = LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(cont,NULL,&wPos); map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ(map,wPos.x,wPos.y,out_bx,out_by); return BVar1; } float10 __cdecl lego::game::LegoObject_GetWorldZCallback(float xPos,float yPos,Map3D *map) { float10 fVar1; fVar1 = lego::map::Map3D_GetWorldZ(map,xPos,yPos); return fVar1; } // The same as `LegoObject_GetWorldZCallback`, but returns a lower Z value with over Lake terrain. // Objects wading in a lake (aka, not sailing) will have their Z lowered a bit, and have it at the // lowest near the center of a lake BLOCK. float10 __cdecl lego::game::LegoObject_GetWorldZCallback_Lake(float xPos,float yPos,Map3D *map) { BOOL BVar1; float10 zPos; float zModifier; Point2I blockPos; zModifier = 0.0; BVar1 = lego::map::Map3D_WorldToBlockPos(map,xPos,yPos,&blockPos.x,&blockPos.y,&zModifier); if (BVar1 != 0) { if ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos.y + blockPos.x].terrain == Lego_SurfaceType8_Lake) { zModifier = zModifier * 8.0; } else { zModifier = 0.0; } } zPos = lego::map::Map3D_GetWorldZ(map,xPos,yPos); return zPos + (float10)zModifier; } void __cdecl lego::game::LegoObject_UpdateRoutingVectors(LegoObject *liveObj,float xPos,float yPos) { Container *cont; Map3D *map; VehicleModel *vehicle; float fVar1; float fVar2; float fVar3; Vector3F oldPos; float length; LegoObject_Type objType; objType = liveObj->type; if (objType == LegoObject_Vehicle) { cont = gfx::Vehicle_GetActivityContainer(liveObj->vehicle); } else { if (objType == LegoObject_MiniFigure) { cont = gfx::Object_GetActivityContainer((BasicObjectModel *)liveObj->miniFigure); } else { cont = (Container *)yPos; if (objType == LegoObject_RockMonster) { cont = gfx::Object_GetActivityContainer((BasicObjectModel *)liveObj->rockMonster); } } } gfx::Container_GetPosition(cont,NULL,&oldPos); if ((xPos != oldPos.x) || (yPos != oldPos.y)) { (liveObj->faceDirection).z = 0.0; (liveObj->faceDirection).x = xPos; (liveObj->faceDirection).y = yPos; (liveObj->tempPosition).x = oldPos.x; (liveObj->tempPosition).y = oldPos.y; (liveObj->tempPosition).z = oldPos.z; (liveObj->faceDirection).x = (liveObj->faceDirection).x - (liveObj->tempPosition).x; (liveObj->faceDirection).y = (liveObj->faceDirection).y - (liveObj->tempPosition).y; (liveObj->faceDirection).z = (liveObj->faceDirection).z - (liveObj->tempPosition).z; (liveObj->faceDirection).z = 0.0; fVar2 = (liveObj->faceDirection).z; fVar1 = (liveObj->faceDirection).y; fVar3 = (liveObj->faceDirection).x; length = SQRT(fVar3 * fVar3 + fVar2 * fVar2 + fVar1 * fVar1); fVar3 = 1.0 / length; liveObj->faceDirectionLength = length; (liveObj->faceDirection).x = fVar3 * (liveObj->faceDirection).x; (liveObj->faceDirection).y = (liveObj->faceDirection).y * fVar3; (liveObj->faceDirection).z = (liveObj->faceDirection).z * fVar3; } objType = liveObj->type; if (objType != LegoObject_Vehicle) { if (objType != LegoObject_MiniFigure) { if (objType == LegoObject_RockMonster) { gfx::Creature_SetOrientation (liveObj->rockMonster,(liveObj->faceDirection).x,(liveObj->faceDirection).y); map = lrr::Lego_GetMap(); gfx::Creature_SetPosition(liveObj->rockMonster,xPos,yPos,LegoObject_GetWorldZCallback,map); } return; } if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_LIFTING) == 0) { fVar3 = (liveObj->faceDirection).y; fVar2 = (liveObj->faceDirection).x; } else { fVar3 = -(liveObj->faceDirection).y; fVar2 = -(liveObj->faceDirection).x; } gfx::Creature_SetOrientation(liveObj->miniFigure,fVar2,fVar3); map = lrr::Lego_GetMap(); gfx::Creature_SetPosition(liveObj->miniFigure,xPos,yPos,LegoObject_GetWorldZCallback_Lake,map); return; } if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_LIFTING) == 0) { fVar3 = (liveObj->faceDirection).z; fVar2 = (liveObj->faceDirection).y; fVar1 = (liveObj->faceDirection).x; vehicle = liveObj->vehicle; } else { vehicle = liveObj->vehicle; fVar3 = -(liveObj->faceDirection).z; fVar2 = -(liveObj->faceDirection).y; fVar1 = -(liveObj->faceDirection).x; } gfx::Vehicle_SetOrientation(vehicle,fVar1,fVar2,fVar3); map = lrr::Lego_GetMap(); gfx::Vehicle_SetPosition(liveObj->vehicle,xPos,yPos,LegoObject_GetWorldZCallback,map); return; } void __cdecl lego::game::LegoObject_SetPositionAndHeading (LegoObject *liveObj,float xPos,float yPos,float theta,BOOL assignHeading) { Map3D *map; float10 zPos; float xPos_00; float yPos_00; Vector3F newDir; Vector3F axis; LegoObject_Type objType; if (assignHeading != 0) { newDir.z = 0.0; newDir.x = 0.0; newDir.y = 1.0; axis.y = 0.0; axis.x = 0.0; axis.z = -1.0; math::Maths_Vector3DRotate(&newDir,&newDir,&axis,theta); } objType = liveObj->type; if (objType == LegoObject_Vehicle) { if (assignHeading != 0) { gfx::Vehicle_SetOrientation(liveObj->vehicle,newDir.x,newDir.y,newDir.z); } map = lrr::Lego_GetMap(); gfx::Vehicle_SetPosition(liveObj->vehicle,xPos,yPos,LegoObject_GetWorldZCallback,map); } else { if (objType == LegoObject_MiniFigure) { if (assignHeading != 0) { gfx::Creature_SetOrientation(liveObj->miniFigure,newDir.x,newDir.y); } map = lrr::Lego_GetMap(); gfx::Creature_SetPosition(liveObj->miniFigure,xPos,yPos,LegoObject_GetWorldZCallback_Lake,map) ; } else { if (objType == LegoObject_RockMonster) { if (assignHeading != 0) { gfx::Creature_SetOrientation(liveObj->rockMonster,newDir.x,newDir.y); } map = lrr::Lego_GetMap(); gfx::Creature_SetPosition(liveObj->rockMonster,xPos,yPos,LegoObject_GetWorldZCallback,map); } else { if (objType == LegoObject_Building) { if (assignHeading != 0) { gfx::Building_SetOrientation(liveObj->building,newDir.x,newDir.y); } map = lrr::Lego_GetMap(); gfx::Building_SetPosition(liveObj->building,xPos,yPos,LegoObject_GetWorldZCallback,map); } else { if ((liveObj->flags3 & LIVEOBJ3_SIMPLEOBJECT) != LIVEOBJ3_NONE) { if (assignHeading != 0) { gfx::Container_SetOrientation (liveObj->other,NULL,newDir.x,newDir.y,newDir.z,0.0,0.0,-1.0); } xPos_00 = xPos; yPos_00 = yPos; map = lrr::Lego_GetMap(); zPos = lego::map::Map3D_GetWorldZ(map,xPos_00,yPos_00); gfx::Container_SetPosition(liveObj->other,NULL,xPos,yPos,(float)zPos); } } } } } if (assignHeading != 0) { (liveObj->faceDirection).x = newDir.x; (liveObj->faceDirection).y = newDir.y; (liveObj->faceDirection).z = newDir.z; } liveObj->faceDirectionLength = 0.01; (liveObj->tempPosition).x = (liveObj->faceDirection).x * -0.01; (liveObj->tempPosition).y = (liveObj->faceDirection).y * -0.01; (liveObj->tempPosition).z = (liveObj->faceDirection).z * -0.01; (liveObj->tempPosition).x = (liveObj->tempPosition).x + xPos; (liveObj->tempPosition).y = (liveObj->tempPosition).y + yPos; (liveObj->tempPosition).z = (liveObj->tempPosition).z; return; } int __cdecl lego::game::LegoObject_FP_UpdateMovement(LegoObject *liveObj,float elapsed,float *out_transSpeed) { bool bVar1; LegoObject *liveObj_00; Container *cont; LegoObject *collideObj; BOOL BVar2; int iVar3; Map3D *map; StatsFlags1 sflags1; CreatureModel *creature; uint isBackward; int actionResult; float fVar4; float fVar5; float fVar6; Point2F *out_xOut; code *zCallback; float *out_yOut; uint bx; float routeSpeed; uint local_48; float tmp_transSpeed; Point2F local_40; float local_38; float local_34; Point2F local_30; Vector3F origDir; Vector3F origPos; Vector3F origUp; float backingUpInv; LegoObject_Type objType; liveObj_00 = liveObj; cont = LegoObject_GetActivityContainer(liveObj); actionResult = 0; isBackward = (uint)(liveObj_00->forwardSignFP < 0); local_48 = isBackward; LegoObject_CalculateSpeeds(liveObj_00,elapsed,&routeSpeed,&tmp_transSpeed); gfx::Container_GetOrientation(cont,NULL,&origDir,&origUp); gfx::Container_GetPosition(cont,NULL,&origPos); local_38 = origPos.x; local_34 = origPos.y; if (liveObj_00->rotateSpeedFP != 0.0) { // When backing up in a vehicle, reverse the direction of rotation for controls. backingUpInv = 1.0; if (liveObj_00->type == LegoObject_Vehicle) { if (isBackward == 0) { backingUpInv = 1.0; } else { backingUpInv = -1.0; } } gfx::Container_AddRotation (cont,Container_Combine_Before,0.0,1.0,0.0, backingUpInv * elapsed * liveObj_00->rotateSpeedFP); actionResult = 1; (liveObj_00->faceDirection).x = origDir.x; (liveObj_00->faceDirection).y = origDir.y; (liveObj_00->faceDirection).z = origDir.z; } elapsed = (float)liveObj_00->strafeSignFP; if ((elapsed != 0.0) || (liveObj_00->forwardSignFP != 0)) { fVar6 = (float)liveObj_00->forwardSignFP; fVar5 = (float)(int)elapsed; local_30.y = 0.0; fVar4 = 1.0 / SQRT(fVar6 * fVar6 + fVar5 * fVar5); local_30.x = fVar4 * fVar5 * routeSpeed; gfx::Container_AddTranslation (cont,Container_Combine_Before,local_30.x,0.0,fVar4 * fVar6 * routeSpeed); actionResult = 1; } if (actionResult == 0) goto LAB_00443210; bVar1 = false; LegoObject_GetBlockPos(liveObj_00,(int *)&bx,(int *)&liveObj); LegoObject_GetPosition(liveObj_00,&local_40.x,&local_40.y); collideObj = LegoObject_DoCollisionCallbacks_FUN_00446030(liveObj_00,&local_40,0.0,TRUE); if (collideObj != NULL) { LegoObject_GetPosition(collideObj,&local_30.x,&local_30.y); local_30.x = local_40.x - local_30.x; local_30.y = local_40.y - local_30.y; local_38 = local_40.x - local_38; local_34 = local_40.y - local_34; fVar4 = 1.0 / SQRT(local_34 * local_34 + local_38 * local_38); elapsed = 1.0 / SQRT(local_30.y * local_30.y + local_30.x * local_30.x); fVar4 = elapsed * local_30.y * fVar4 * local_34 + elapsed * local_30.x * fVar4 * local_38; if ((ushort)((ushort)(fVar4 < 0.0) << 8 | (ushort)(fVar4 == 0.0) << 0xe) != 0) { bVar1 = true; } } BVar2 = Lego_IsNoclipOn(); if ((BVar2 == 0) && (((iVar3 = Lego_GetCrossTerrainType(liveObj_00,bx,(int)liveObj,bx,(int)liveObj,TRUE), iVar3 == 0 || (bVar1)) || (BVar2 = Level_Block_IsSeamWall(bx,(uint)liveObj), BVar2 != 0)))) { // Block movement when colliding with a wall (and noclip is off). gfx::Container_SetPosition(cont,NULL,origPos.x,origPos.y,origPos.z); gfx::Container_SetOrientation (cont,NULL,origDir.x,origDir.y,origDir.z,origUp.x,origUp.y,origUp.z); (liveObj_00->faceDirection).x = origDir.x; (liveObj_00->faceDirection).y = origDir.y; (liveObj_00->faceDirection).z = origDir.z; } else { BVar2 = Level_Block_IsWall(bx,(uint)liveObj); if (BVar2 != 0) { out_yOut = &local_40.y; out_xOut = &local_40; fVar6 = 0.0; BVar2 = Level_Block_IsGap(bx,(uint)liveObj); fVar4 = local_40.x; fVar5 = local_40.y; map = lrr::Lego_GetMap(); lego::map::Map3D_FUN_0044fe50(map,fVar4,fVar5,BVar2,fVar6,&out_xOut->x,out_yOut); } objType = liveObj_00->type; if (objType == LegoObject_Vehicle) { map = lrr::Lego_GetMap(); gfx::Vehicle_SetPosition (liveObj_00->vehicle,local_40.x,local_40.y,LegoObject_GetWorldZCallback,map); } else { if (objType == LegoObject_MiniFigure) { // Minifigure Z positioning dips them down a little when over Lake terrain. map = lrr::Lego_GetMap(); creature = liveObj_00->miniFigure; zCallback = LegoObject_GetWorldZCallback_Lake; } else { if (objType != LegoObject_RockMonster) goto LAB_004431a9; map = lrr::Lego_GetMap(); creature = liveObj_00->rockMonster; zCallback = LegoObject_GetWorldZCallback; } gfx::Creature_SetPosition(creature,local_40.x,local_40.y,zCallback,map); } } LAB_004431a9: BVar2 = Level_Block_IsWall(bx,(uint)liveObj); if (((BVar2 != 0) && (BVar2 = LiveObject_BlockCheck_FUN_004326a0(liveObj_00,bx,(uint)liveObj,FALSE,TRUE), BVar2 != 0)) && ((liveObj_00->type != LegoObject_MiniFigure || (BVar2 = LegoObject_HasToolEquipped(liveObj_00,LegoObject_ToolType_Drill), BVar2 != 0)))) { actionResult = 3; } if ((local_48 != 0) && (sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00), (sflags1 & STATS1_CROSSLAND) == STATS1_NONE)) { actionResult = 4; } LAB_00443210: liveObj_00->strafeSignFP = 0; liveObj_00->forwardSignFP = 0; liveObj_00->rotateSpeedFP = 0.0; if (actionResult != 0) { *out_transSpeed = tmp_transSpeed; } return actionResult; } // Recalculates the "sticky" position (and sometimes orientation) of an object based on the world. // This refers to behaviours that have objects snap to certain planes and face certain directions. // Example: All units' Z positions try to match the world's surface Z position. void __cdecl lego::game::LegoObject_UpdateWorldStickyPosition(LegoObject *liveObj,float elapsed) { Map3D *map; Container *cont; BOOL BVar1; uint by; float10 fVar2; longlong lVar3; float fVar4; float fVar5; float unkMultiplier; Vector3F *out_xOut; float *out_yOut; uint local_30; float local_2c; float local_28; Vector3F local_24; Vector3F local_18; Vector3F local_c; LiveFlags3 lflags3; LegoObject *liveObj_00; LegoObject_Type objType; liveObj_00 = liveObj; ai::AITask_LiveObject_FUN_00403a70(liveObj); objType = liveObj_00->type; if (objType == LegoObject_Vehicle) { LegoObject_GetPosition(liveObj_00,(float *)&liveObj,&elapsed); map = lrr::Lego_GetMap(); gfx::Vehicle_SetPosition (liveObj_00->vehicle,(float)liveObj,elapsed,LegoObject_GetWorldZCallback,map); return; } if (objType == LegoObject_Building) { LegoObject_GetPosition(liveObj_00,(float *)&liveObj,&elapsed); map = lrr::Lego_GetMap(); gfx::Building_SetPosition (liveObj_00->building,(float)liveObj,elapsed,LegoObject_GetWorldZCallback,map); return; } if (objType == LegoObject_RockMonster) { LegoObject_GetPosition(liveObj_00,(float *)&liveObj,&elapsed); map = lrr::Lego_GetMap(); gfx::Creature_SetPosition (liveObj_00->rockMonster,(float)liveObj,elapsed,LegoObject_GetWorldZCallback,map); return; } if (objType == LegoObject_MiniFigure) { cont = LegoObject_GetActivityContainer(liveObj_00); gfx::Container_GetPosition(cont,NULL,&local_18); local_2c = local_18.x; local_28 = local_18.y; LegoObject_GetBlockPos(liveObj_00,(int *)&local_30,(int *)&liveObj); BVar1 = Level_Block_IsWall(local_30,(uint)liveObj); if ((BVar1 != 0) && (BVar1 = Level_Block_IsSeamWall(local_30,(uint)liveObj), BVar1 == 0)) { out_yOut = &local_24.y; out_xOut = &local_24; unkMultiplier = 0.0; BVar1 = Level_Block_IsGap(local_30,(uint)liveObj); fVar4 = local_2c; fVar5 = local_28; map = lrr::Lego_GetMap(); lego::map::Map3D_FUN_0044fe50(map,fVar4,fVar5,BVar1,unkMultiplier,&out_xOut->x,out_yOut); local_24.x = local_24.x - local_2c; local_24.y = local_24.y - local_28; fVar5 = elapsed * 0.5; fVar4 = SQRT(local_24.y * local_24.y + local_24.x * local_24.x); if ((ushort)((ushort)(fVar4 < fVar5) << 8 | (ushort)(fVar4 == fVar5) << 0xe) == 0) { local_2c = (fVar5 / fVar4) * local_24.x + local_2c; local_28 = (fVar5 / fVar4) * local_24.y + local_28; } } map = lrr::Lego_GetMap(); fVar5 = local_28; fVar4 = local_2c; fVar2 = LegoObject_GetWorldZCallback(local_2c,local_28,map); local_c.z = (float)fVar2; if (((local_18.x == local_2c) && (local_18.y == local_28)) && (local_18.z == local_c.z)) { return; } map = lrr::Lego_GetMap(); gfx::Creature_SetPosition (liveObj_00->miniFigure,fVar4,fVar5,LegoObject_GetWorldZCallback_Lake,map); return; } if ((((objType != LegoObject_PowerCrystal) && (objType != LegoObject_Ore)) && ((objType != LegoObject_Barrier && ((objType != LegoObject_Dynamite && (objType != LegoObject_ElectricFence)))))) && (objType != LegoObject_OohScary)) { return; } if (liveObj_00->carryingThisObject != NULL) { return; } LegoObject_GetBlockPos(liveObj_00,(int *)&local_30,(int *)&local_2c); if ((liveObj_00->type == LegoObject_Barrier) || (BVar1 = Level_Block_IsRockFallFX(local_30,(uint)local_2c), BVar1 == 0)) { LAB_00443554: if (liveObj_00->cameraNull == NULL) goto LAB_00443614; } else { if (liveObj_00->cameraNull == NULL) { cont = effect::Effect_Unk_RockFall_FUN_0040c4e0(local_30,(uint)local_2c); liveObj_00->cameraNull = cont; local_24.y = 0.0; local_24.x = local_2c; lflags3 = liveObj_00->flags3; (liveObj_00->targetBlockPos).x = (float)(ulonglong)local_30; liveObj_00->flags3 = lflags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP| LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400| LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000| LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING| LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); (liveObj_00->targetBlockPos).y = (float)(ulonglong)(uint)local_2c; goto LAB_00443554; } } lVar3 = __ftol((float10)(liveObj_00->targetBlockPos).y); by = (uint)lVar3; lVar3 = __ftol((float10)(liveObj_00->targetBlockPos).x); BVar1 = Level_Block_IsRockFallFX((uint)lVar3,by); if (BVar1 != 0) { gfx::Container_GetPosition(liveObj_00->cameraNull,NULL,&local_18); fVar4 = local_18.x; fVar5 = local_18.y; map = lrr::Lego_GetMap(); fVar2 = lego::map::Map3D_GetWorldZ(map,fVar4,fVar5); fVar2 = fVar2 - (float10)1.2285; if ((ushort)((ushort)((float10)local_18.z < fVar2) << 8 | (ushort)((float10)local_18.z == fVar2) << 0xe) == 0) { local_18.z = (float)fVar2; } gfx::Container_SetPosition(liveObj_00->other,NULL,local_18.x,local_18.y,local_18.z); gfx::Container_SetOrientation(liveObj_00->other,liveObj_00->cameraNull,0.0,0.0,1.0,0.0,1.0,0.0); return; } LAB_00443614: liveObj_00->cameraNull = NULL; gfx::Container_GetPosition(liveObj_00->other,NULL,&local_24); fVar4 = local_24.x; fVar5 = local_24.y; map = lrr::Lego_GetMap(); fVar2 = lego::map::Map3D_GetWorldZ(map,fVar4,fVar5); liveObj = (LegoObject *)(float)(fVar2 - (float10)1.2285); fVar2 = (fVar2 - (float10)1.2285) - (float10)0.5; if ((ushort)((ushort)(fVar2 < (float10)local_24.z) << 8 | (ushort)(fVar2 == (float10)local_24.z) << 0xe) == 0) { local_24.z = local_24.z + elapsed; if ((ushort)((ushort)(local_24.z < (float)liveObj) << 8 | (ushort)(local_24.z == (float)liveObj) << 0xe) == 0) { local_24.z = (float)liveObj; } gfx::Container_SetPosition(liveObj_00->other,NULL,local_24.x,local_24.y,local_24.z); } if ((ushort)((ushort)(local_24.z < (float)liveObj - -0.5) << 8 | (ushort)(local_24.z == (float)liveObj - -0.5) << 0xe) == 0) { local_24.z = local_24.z - elapsed; if (local_24.z < (float)liveObj) { local_24.z = (float)liveObj; } gfx::Container_SetPosition(liveObj_00->other,NULL,local_24.x,local_24.y,local_24.z); } gfx::Container_GetOrientation(liveObj_00->other,NULL,&local_18,&local_c); if (0.0 <= local_18.z) { if ((ushort)((ushort)(local_18.z < 0.0) << 8 | (ushort)(local_18.z == 0.0) << 0xe) == 0) { local_18.z = local_18.z - elapsed * 0.05; if (local_18.z < 0.0) { local_18.z = 0.0; } gfx::Container_SetOrientation (liveObj_00->other,NULL,local_18.x,local_18.y,local_18.z,0.0,0.0,-1.0); } return; } local_18.z = local_18.z - elapsed * -0.05; if ((ushort)((ushort)(local_18.z < 0.0) << 8 | (ushort)(local_18.z == 0.0) << 0xe) == 0) { local_18.z = 0.0; } gfx::Container_SetOrientation (liveObj_00->other,NULL,local_18.x,local_18.y,local_18.z,0.0,0.0,-1.0); return; } // Updates the sticky position/orientation of a vehicle's driver to match that of the vehicle. // REQUIRES: liveObj->vehicle != NULL and liveObj->driveObject != NULL void __cdecl lego::game::LegoObject_UpdateDriverStickyPosition(LegoObject *liveObj) { Container *driverCont; Container *vehicleCont; Vector3F vehiclePos; Vector3F vehicleUp; Vector3F vehicleDir; Vector3F driverPos; Vector3F driverDir; Vector3F driverUp; driverCont = LegoObject_GetActivityContainer(liveObj->driveObject); if (liveObj->type == LegoObject_Vehicle) { vehicleCont = gfx::Vehicle_GetDriverNull(liveObj->vehicle); if (vehicleCont != NULL) goto LAB_0044380f; } vehicleCont = LegoObject_GetActivityContainer(liveObj); LAB_0044380f: gfx::Container_GetPosition(driverCont,NULL,&driverPos); gfx::Container_GetPosition(vehicleCont,NULL,&vehiclePos); if (((driverPos.x != vehiclePos.x) || (driverPos.y != vehiclePos.y)) || (driverPos.z != vehiclePos.z)) { gfx::Container_SetPosition(driverCont,NULL,vehiclePos.x,vehiclePos.y,vehiclePos.z); } gfx::Container_GetOrientation(driverCont,NULL,&driverDir,&driverUp); gfx::Container_GetOrientation(vehicleCont,NULL,&vehicleDir,&vehicleUp); if ((((driverDir.x != vehicleDir.x) || (driverDir.y != vehicleDir.y)) || ((driverDir.z != vehicleDir.z || ((driverUp.x != vehicleUp.x || (driverUp.y != vehicleUp.y)))) )) || (driverUp.z != vehicleUp.z)) { gfx::Container_SetOrientation (driverCont,NULL,vehicleDir.x,vehicleDir.y,vehicleDir.z,vehicleUp.x,vehicleUp.y, vehicleUp.z); } return; } BOOL __cdecl lego::game::LegoObject_TryWaiting(LegoObject *liveObj) { short rng; BOOL BVar1; uint attempt; uint repeatCount; if ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { BVar1 = LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(liveObj); if (BVar1 == 0) { // 5 Attempts to pick a valid waiting animation attempt = 0; do { repeatCount = 1; rng = math::Maths_Rand(); LegoObject_SetActivity(liveObj,(int)rng % 0x15 + Activity_Waiting1,repeatCount); BVar1 = LegoObject_UpdateActivityChange(liveObj); if (BVar1 != 0) { liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_WAITING; return TRUE; } attempt += 1; } while (attempt < 5); return FALSE; } } return FALSE; } BOOL __cdecl lego::game::LegoObject_IsRockMonsterCanGather(LegoObject *liveObj) { if ((liveObj->type == LegoObject_RockMonster) && ((liveObj->flags3 & LIVEOBJ3_CANGATHER) != LIVEOBJ3_NONE)) { return TRUE; } return 0; } BOOL __cdecl lego::game::LegoObject_FUN_004439d0 (LegoObject *liveObj,Point2I *blockPos,Point2I *out_blockPos,undefined4 unused) { LegoObject *liveObj_00; BOOL BVar1; BOOL allowWall; int *newBXs; Point2I *blockPos_00; blockPos_00 = blockPos; liveObj_00 = liveObj; allowWall = FALSE; BVar1 = LegoObject_CheckBlock_FUN_00443b00(liveObj,blockPos,&allowWall); if (BVar1 != 0) { return 0; } // LegoObject_Route_Score_FUN_004413b0(liveObj,blockPos->x,blockPos->y,0,0, // &newBXs, &newBYs, &newCount, ...) BVar1 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,blockPos_00->x,blockPos_00->y,0,0,&newBXs,(int **)&blockPos, (int *)&liveObj,LegoObject_CheckBlock_FUN_00443b00,&allowWall); // So calling this function a second time with the same arguments seems to have a // different result. Most likely because of the utilized global variables within. // Note that none of the out variables are read during the function call, only written. if ((BVar1 == 0) && (BVar1 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,blockPos_00->x,blockPos_00->y,0,0,&newBXs,(int **)&blockPos, (int *)&liveObj,LegoObject_CheckBlock_FUN_00443b00,&allowWall), BVar1 == 0) ) { return 0; } out_blockPos->x = newBXs[(int)&liveObj[-1].nextFree + 3]; out_blockPos->y = *(int *)((int)blockPos + (int)liveObj * 4 + -4); io::Mem_Free(newBXs); io::Mem_Free(blockPos); return TRUE; } void __cdecl lego::game::LegoObject_RockMonster_DoWakeUp(LegoObject *liveObj) { if (((liveObj->type == LegoObject_RockMonster) && ((liveObj->flags3 & LIVEOBJ3_POWEROFF) != LIVEOBJ3_NONE)) && ((liveObj->flags2 & LIVEOBJ2_UNK_20000000) == LIVEOBJ2_NONE)) { liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_20000000; LegoObject_SetActivity(liveObj,Activity_WakeUp,0); LegoObject_UpdateActivityChange(liveObj); } return; } BOOL __cdecl lego::game::LegoObject_CheckBlock_FUN_00443b00 (LegoObject *liveObj,Point2I *blockPos,BOOL *pAllowWall) { BOOL BVar1; int iVar2; if ((*pAllowWall == 0) && (BVar1 = Level_Block_IsWall(blockPos->x,blockPos->y), BVar1 != 0)) { return 0; } iVar2 = Lego_GetCrossTerrainType(liveObj,blockPos->x,blockPos->y,blockPos->x,blockPos->y,TRUE); if (((iVar2 != 0) && (BVar1 = Level_GetObjectDamageFromSurface(liveObj,blockPos->x,blockPos->y,0.0,NULL), BVar1 == 0)) && (BVar1 = Level_Block_IsFoundationOrBusyFloor(blockPos), BVar1 == 0)) { return TRUE; } return FALSE; } void __cdecl lego::game::LegoObject_Route_UpdateMovement(LegoObject *liveObj,float elapsed) { float fVar1; RoutingBlock *pRVar2; short sVar3; LiveFlags3 lflags3; LiveFlags1 lflags1; LegoObject *pLVar4; StatsFlags1 sflags1; Map3D *map; BOOL BVar5; uint uVar6; int useRoutingPos; float10 fVar7; ulonglong uVar8; longlong lVar9; float *out_bx; float *out_by; uint local_2c; float local_28; float local_24; float local_20; float local_1c; Point2F curveInter; float local_10; float local_c; float local_8; float local_4; RouteAction action; LegoObject *liveObj_00; liveObj_00 = liveObj; useRoutingPos = 0; pRVar2 = liveObj->routeBlocks; local_1c = elapsed; BVar5 = 1; if (pRVar2 == NULL) { LegoObject_Route_End(liveObj,0); } else { if (liveObj->type == LegoObject_Vehicle) { liveObj->elapsedTime1 = 0.0; } if (liveObj->routeCurveTotalDist <= liveObj->routeCurveCurrDist) { lflags3 = liveObj->flags3; if ((lflags3 & LIVEOBJ3_UNK_400) != LIVEOBJ3_NONE) { uVar6 = liveObj->routeBlocksCurrent; liveObj->flags3 = lflags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP| LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000| LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT| LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING| LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); switch(pRVar2[uVar6].actionByte) { case ROUTE_ACTION_REINFORCE: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_REINFORCING; break; case ROUTE_ACTION_GATHERROCK: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_GATHERINGROCK; break; case ROUTE_ACTION_CLEAR: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_CLEARING; break; case ROUTE_ACTION_UNK_5: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_UNK_800; break; case ROUTE_ACTION_REPAIRDRAIN: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_REPAIRDRAINING; break; case ROUTE_ACTION_STORE: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_STORING; break; case ROUTE_ACTION_DROP: LegoObject_DropCarriedObject(liveObj,TRUE); break; case ROUTE_ACTION_PLACE: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_PLACING; break; case ROUTE_ACTION_UNK_10: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_ENTERING_WALLHOLE; break; case ROUTE_ACTION_EAT: liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_EATING; break; case ROUTE_ACTION_UNK_12: liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_4; break; case ROUTE_ACTION_UNK_13: liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_40; break; case ROUTE_ACTION_TRAIN: liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_TRAINING; break; case ROUTE_ACTION_UPGRADE: liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UPGRADING; break; case ROUTE_ACTION_UNK_16: liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_200000; break; case ROUTE_ACTION_UNK_17: liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_4000000; break; case ROUTE_ACTION_RECHARGE: liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_RECHARGING; break; case ROUTE_ACTION_DOCK: LegoObject_TryDock_AtObject2FC(liveObj); break; case ROUTE_ACTION_ATTACK: ai::AITask_LiveObject_SetAITaskUnk(liveObj,AITask_Type_AttackObject,NULL,TRUE); break; case ROUTE_ACTION_21: liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_80000000; } if ((pRVar2[uVar6].flagsByte & ROUTE_FLAG_UNK_20) != ROUTE_FLAG_NONE) { liveObj_00->flags2 = liveObj_00->flags2 | LIVEOBJ2_UNK_80000; } LegoObject_Route_End(liveObj_00,TRUE); if ((liveObj_00->flags1 & LIVEOBJ1_SCAREDBYPLAYER) != LIVEOBJ1_NONE) { sVar3 = math::Maths_Rand(); uVar8 = __ftol((float10)10.0 / (float10)elapsed); if ((int)((ulonglong)(uint)(int)sVar3 % (uVar8 & 0xffffffff)) == 0) { liveObj_00->flags1 = liveObj_00->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); return; } LiveObject_FUN_00433b40(liveObj_00,150.0,TRUE); return; } return; } if (liveObj->routeBlocksTotal < 2) { liveObj->flags3 = lflags3 | LIVEOBJ3_UNK_400; pRVar2[liveObj->routeBlocksCurrent].flagsByte = pRVar2[liveObj->routeBlocksCurrent].flagsByte | ROUTE_FLAG_UNK_8; } else { uVar6 = liveObj->routeBlocksCurrent + 1; liveObj->routeBlocksCurrent = uVar6; if (((pRVar2[uVar6].flagsByte & ROUTE_FLAG_UNK_10) != ROUTE_FLAG_NONE) && (pRVar2[uVar6].actionByte != ROUTE_ACTION_UNK_1)) { useRoutingPos = 1; } } uVar6 = liveObj->routeBlocksCurrent; if (useRoutingPos != 0) { uVar6 += 1; } if (pRVar2[uVar6].actionByte == ROUTE_ACTION_UNK_5) { LegoObject_Routing_FUN_00447a90(liveObj); } // ~liveObj_00->flags1 >> 0x10 & 1 => !(LIVEOBJ1_UNK_10000) BVar5 = LegoObject_RoutingUnk_FUN_00444940 (liveObj_00,useRoutingPos,liveObj_00->flags3 & LIVEOBJ3_CANTURN, ~liveObj_00->flags1 >> 10 & 1); if (liveObj_00->routeBlocksTotal - 1 <= liveObj_00->routeBlocksCurrent) { liveObj_00->flags3 = liveObj_00->flags3 | LIVEOBJ3_UNK_400; } } if (BVar5 != 0) { if ((((((*(byte *)&liveObj_00->flags1 & 8) == 0) && (pRVar2[liveObj_00->routeBlocksCurrent].actionByte == ROUTE_ACTION_UNK_1)) && (BVar5 = LegoObject_GetDrillNullPosition(liveObj_00,&local_20,&local_24), BVar5 != 0)) && ((BVar5 = Lego_WorldToBlockPos_NoZ(local_20,local_24,(int *)&liveObj,(int *)&local_2c), BVar5 != 0 && (BVar5 = Level_Block_IsWall((uint)liveObj,local_2c), BVar5 != 0)))) && ((liveObj == (LegoObject *)pRVar2[liveObj_00->routeBlocksCurrent].blockPos.x && (local_2c == pRVar2[liveObj_00->routeBlocksCurrent].blockPos.y)))) { BVar5 = 1; lflags3 = liveObj_00->flags3 & LIVEOBJ3_UNK_2000000; lVar9 = __ftol((float10)(liveObj_00->targetBlockPos).y); uVar6 = (uint)lVar9; lVar9 = __ftol((float10)(liveObj_00->targetBlockPos).x); BVar5 = LiveObject_BlockCheck_FUN_004326a0(liveObj_00,(uint)lVar9,uVar6,lflags3,BVar5); if (BVar5 == 0) { lflags1 = liveObj_00->flags1 | LIVEOBJ1_CANTDO; } else { lflags1 = liveObj_00->flags1 | (LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART); } liveObj_00->flags1 = lflags1; } LegoObject_CalculateSpeeds(liveObj_00,elapsed,&local_28,&local_1c); if ((liveObj_00->flags3 & LIVEOBJ3_UNK_4000) == LIVEOBJ3_NONE) { liveObj_00->routeCurveCurrDist = local_28 + liveObj_00->routeCurveCurrDist; } if ((ushort)((ushort)(liveObj_00->routeCurveCurrDist < liveObj_00->routeCurveTotalDist) << 8 | (ushort)(liveObj_00->routeCurveCurrDist == liveObj_00->routeCurveTotalDist) << 0xe ) == 0) { fVar1 = liveObj_00->routeCurveCurrDist; liveObj_00->routeCurveCurrDist = liveObj_00->routeCurveTotalDist; liveObj_00->routeCurveInitialDist = fVar1 - liveObj_00->routeCurveTotalDist; } math::BezierCurve_Interpolate (&liveObj_00->routeCurve,liveObj_00->routeCurveCurrDist,&curveInter); action = pRVar2[liveObj_00->routeBlocksCurrent].actionByte; if (action == ROUTE_ACTION_GATHERROCK) { if (liveObj_00->routeToObject != NULL) { LegoObject_GetPosition(liveObj_00->routeToObject,&local_8,&local_4); local_10 = local_8 - curveInter.x; local_c = local_4 - curveInter.y; elapsed = SQRT(local_c * local_c + local_10 * local_10); if ((ushort)((ushort)(elapsed < 6.6) << 8 | (ushort)(elapsed == 6.6) << 0xe) != 0) { liveObj_00->flags1 = liveObj_00->flags1 | LIVEOBJ1_GATHERINGROCK; LegoObject_Route_End(liveObj_00,TRUE); if (liveObj_00->type != LegoObject_MiniFigure) { return; } if (elapsed != 0.0) { gfx::Creature_SetOrientation(liveObj_00->miniFigure,local_10,local_c); (liveObj_00->faceDirection).x = local_10; (liveObj_00->faceDirection).y = local_c; return; } return; } } } else { if (action == ROUTE_ACTION_UNK_12) { if (liveObj_00->routeToObject != NULL) { LegoObject_GetPosition(liveObj_00->routeToObject,&local_8,&local_4); elapsed = SQRT((curveInter.y - local_4) * (curveInter.y - local_4) + (curveInter.x - local_8) * (curveInter.x - local_8)); fVar7 = stats::StatsObject_GetCollRadius(liveObj_00->routeToObject); if ((ushort)((ushort)((float10)elapsed < fVar7) << 8 | (ushort)((float10)elapsed == fVar7) << 0xe) != 0) { liveObj_00->flags2 = liveObj_00->flags2 | LIVEOBJ2_UNK_4; LegoObject_Route_End(liveObj_00,TRUE); return; } } } else { if ((action == ROUTE_ACTION_PLACE) && ((pRVar2[liveObj_00->routeBlocksCurrent].flagsByte & ROUTE_UNK_MASK_c) == ROUTE_FLAG_NONE)) { uVar6 = (liveObj_00->routeCurve).count; local_8 = (liveObj_00->routeCurve).points[uVar6 - 1].x; local_4 = (liveObj_00->routeCurve).points[uVar6 - 1].y; elapsed = curveInter.x - local_8; fVar1 = SQRT((curveInter.y - local_4) * (curveInter.y - local_4) + elapsed * elapsed); if ((ushort)((ushort)(fVar1 < 6.0) << 8 | (ushort)(fVar1 == 6.0) << 0xe) != 0) { liveObj_00->flags1 = liveObj_00->flags1 | LIVEOBJ1_PLACING; LegoObject_Route_End(liveObj_00,TRUE); return; } } } } if (((((liveObj_00->flags3 & LIVEOBJ3_UNUSED_800) == LIVEOBJ3_NONE) && (action = pRVar2[liveObj_00->routeBlocksCurrent].actionByte, action != ROUTE_ACTION_STORE )) && (action != ROUTE_ACTION_REPAIRDRAIN)) && (((action != ROUTE_ACTION_GATHERROCK && (action != ROUTE_ACTION_UNK_5)) && (pLVar4 = LegoObject_DoCollisionCallbacks_FUN_00446030(liveObj_00,&curveInter,0.0,FALSE), pLVar4 != NULL)))) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); if (((sflags1 & STATS1_BUMPDAMAGE) != STATS1_NONE) && (pLVar4->type == LegoObject_Vehicle)) { LegoObject_Route_End(liveObj_00,FALSE); LegoObject_SetActivity(liveObj_00,Activity_Repair,0); LegoObject_UpdateActivityChange(liveObj_00); liveObj_00->routeToObject = pLVar4; liveObj_00->flags2 = liveObj_00->flags2 | LIVEOBJ2_UNK_40000; return; } LegoObject_RoutingUnk_FUN_00444940(liveObj_00,0,0,0); liveObj_00->flags3 = liveObj_00->flags3 | LIVEOBJ3_UNUSED_800; liveObj_00->routeCurveCurrDist = local_28 + liveObj_00->routeCurveCurrDist; } if ((liveObj_00->flags3 & LIVEOBJ3_UNK_4000) == LIVEOBJ3_NONE) { LegoObject_UpdateRoutingVectors(liveObj_00,curveInter.x,curveInter.y); } if ((pRVar2[liveObj_00->routeBlocksTotal - 1].actionByte == ROUTE_ACTION_CLEAR) && (liveObj_00->type == LegoObject_Vehicle)) { out_by = &local_4; out_bx = &local_8; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ (map,curveInter.x,curveInter.y,(int *)out_bx,(int *)out_by); if ((local_8 == (float)pRVar2[liveObj_00->routeBlocksTotal - 1].blockPos.x) && (local_4 == (float)pRVar2[liveObj_00->routeBlocksTotal - 1].blockPos.y)) { liveObj_00->flags1 = liveObj_00->flags1 | LIVEOBJ1_CLEARING; LegoObject_Route_End(liveObj_00,TRUE); return; } } } } return; } void __cdecl lego::game::LegoObject_TryDock_AtObject2FC(LegoObject *liveObj) { LegoObject *routeToObj; routeToObj = liveObj->routeToObject; if ((routeToObj != NULL) && (routeToObj->type == LegoObject_Building)) { liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_DOCKOCCUPIED; routeToObj->flags4 = routeToObj->flags4 | LIVEOBJ4_DOCKOCCUPIED; ai::AITask_LiveObject_SetAITaskUnk(liveObj,AITask_Type_Dock,NULL,TRUE); } return; } // Update energy drain while carrying and attempt to rest when needed. void __cdecl lego::game::LegoObject_UpdateCarryingEnergy(LegoObject *liveObj,float elapsed) { BOOL BVar1; float10 fVar2; Point2I blockPos; if (((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && ((liveObj->type != LegoObject_RockMonster || (liveObj->carriedObjects[0]->type == LegoObject_Boulder)))) { fVar2 = stats::StatsObject_GetCarryMinHealth(liveObj); if ((fVar2 < (float10)liveObj->health) && ((*(byte *)&liveObj->flags4 & 0x20) == 0)) { fVar2 = stats::StatsObject_GetRestPercent(liveObj); if ((((float)(fVar2 * (float10)0.01) != 0.0) && ((*(byte *)&liveObj->flags1 & 4) == 0)) && ((float)(fVar2 * (float10)0.01) * liveObj->health < liveObj->carryRestTimer_33c * 0.04)) { LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); BVar1 = Level_Block_IsLava(&blockPos); if (((BVar1 == 0) && ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos.y + blockPos.x].terrain != Lego_SurfaceType8_Lake)) && (liveObj->routeBlocksCurrent != liveObj->routeBlocksTotal - 1)) { liveObj->carryRestTimer_33c = 0.0; liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_UNK_4000; liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_RESTING; LegoObject_SetActivity(liveObj,Activity_Rest,FALSE); LegoObject_UpdateActivityChange(liveObj); } } liveObj->carryRestTimer_33c = elapsed + liveObj->carryRestTimer_33c; return; } LegoObject_DropCarriedObject(liveObj,FALSE); } return; } BOOL __cdecl lego::game::LegoObject_FUN_00444520(LegoObject *liveObj) { int iVar1; short sVar2; BOOL BVar3; int iVar4; int iVar5; Map3D *map; uint uVar6; uint by; float10 fVar7; Vector3F *out_vertPoses; uint local_90; int *local_8c; uint local_88; int *local_84; uint local_80; uint local_7c; Point2F local_78; Point2I ANGLES [8]; Vector3F local_30 [2]; float local_18; float local_14; ANGLES[0].x = -1; ANGLES[0].y = 0; ANGLES[1].x = -1; ANGLES[1].y = 1; ANGLES[2].x = 0; ANGLES[2].y = 1; ANGLES[3].x = 1; ANGLES[3].y = 1; ANGLES[4].x = 1; ANGLES[4].y = 0; ANGLES[5].x = 1; ANGLES[5].y = -1; ANGLES[6].x = 0; ANGLES[6].y = -1; ANGLES[7].x = -1; ANGLES[7].y = -1; BVar3 = LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(liveObj); if (BVar3 != 0) { return 0; } LegoObject_GetBlockPos(liveObj,(int *)&local_90,(int *)&local_88); local_80 = 0; do { sVar2 = math::Maths_Rand(); uVar6 = (int)sVar2 >> 0x1f; // positive modulus 8 (???) iVar4 = (((int)sVar2 ^ uVar6) - uVar6 & 7 ^ uVar6) - uVar6; iVar1 = ANGLES[iVar4].y; iVar4 = ANGLES[iVar4].x; iVar5 = Lego_GetCrossTerrainType (liveObj,local_90 + iVar4,local_88 + iVar1,local_90 + iVar4,local_88 + iVar1,0 ); if (iVar5 != 0) { out_vertPoses = local_30; by = local_88 + iVar1; uVar6 = local_90 + iVar4; map = lrr::Lego_GetMap(); lego::map::Map3D_GetBlockVertexPositions(map,uVar6,by,out_vertPoses); fVar7 = math::Maths_RandRange(local_30[0].x - -1.0,local_18 - 1.0); local_78.x = (float)fVar7; fVar7 = math::Maths_RandRange(local_30[0].y - -1.0,local_14 - 1.0); local_78.y = (float)fVar7; BVar3 = LegoObject_Route_Score_FUN_004413b0 (liveObj,local_90,local_88,local_90 + iVar4,local_88 + iVar1,&local_8c, &local_84,(int *)&local_7c,0,NULL); if (BVar3 != 0) { BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,local_7c,local_8c,local_84,&local_78) ; if (BVar3 != 0) { io::Mem_Free(local_8c); io::Mem_Free(local_84); return TRUE; } io::Mem_Free(local_8c); io::Mem_Free(local_84); } } local_80 += 1; } while (local_80 < 0x10); return 0; } void __cdecl lego::game::LegoObject_TryRunAway(LegoObject *liveObj,Point2F *dir) { BOOL BVar1; Map3D *map; float in_x; float in_y; Point2I *out_bx; int *out_by; int *byList; uint count; Point2F awayPos; Point2I blockPos; Point2I awayBlockPos; LegoObject *liveObj_00; liveObj_00 = liveObj; LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); if (((((liveObj_00->flags1 & LIVEOBJ1_RUNNINGAWAY) == LIVEOBJ1_NONE) && (BVar1 = LegoObject_IsActive(liveObj_00,TRUE), BVar1 != 0)) && (BVar1 = lrr::Lego_IsFPObject(liveObj_00), BVar1 == 0)) && ((liveObj_00->driveObject == NULL && (BVar1 = Level_Block_IsWall(blockPos.x,blockPos.y), BVar1 == 0)))) { LegoObject_Interrupt(liveObj_00,1,1); LegoObject_GetPosition(liveObj_00,&awayPos.x,&awayPos.y); out_bx = &awayBlockPos; in_x = globs::legoGlobs.MiniFigureRunAway * dir->x + awayPos.x; out_by = &awayBlockPos.y; in_y = dir->y * globs::legoGlobs.MiniFigureRunAway + awayPos.y; awayPos.x = in_x; awayPos.y = in_y; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ(map,in_x,in_y,&out_bx->x,out_by); if (BVar1 != 0) { if ((awayBlockPos.x == blockPos.x) && (awayBlockPos.y == blockPos.y)) { liveObj = (LegoObject *)&blockPos; byList = &blockPos.y; count = 1; } else { BVar1 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,blockPos.x,blockPos.y,awayBlockPos.x,awayBlockPos.y, (int **)&liveObj,&byList,(int *)&count,0,NULL); if (BVar1 == 0) { return; } } BVar1 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,count,(int *)liveObj,byList,&awayPos); if (BVar1 != 0) { liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte = liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_RUNAWAY; } // BAD BAD BAD! Freeing memory that may be pointing to the stack!!! io::Mem_Free(liveObj); io::Mem_Free(byList); liveObj_00->flags1 = liveObj_00->flags1 | LIVEOBJ1_RUNNINGAWAY; front::Bubble_ShowBubble(liveObj_00); } } return; } void __cdecl lego::ai::LegoObject_DoSlip(LegoObject *liveObj) { if (((liveObj->flags1 & LIVEOBJ1_SLIPPING) == LIVEOBJ1_NONE) && (liveObj->driveObject == NULL)) { game::LegoObject_Interrupt(liveObj,FALSE,TRUE); liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_SLIPPING; game::LegoObject_SetActivity(liveObj,Activity_Slip,FALSE); game::LegoObject_UpdateActivityChange(liveObj); AITask_DoAnimationWait(liveObj); } return; } BOOL __cdecl lego::game::LegoObject_RoutingUnk_FUN_00444940 (LegoObject *liveObj,BOOL useRoutingPos,BOOL flags3_8,BOOL notFlags1_10000) { Vector3F *out_vector; Map3D *map; uint uVar1; float fVar2; BOOL BVar3; uint uVar4; Point2F *pPVar5; float fVar6; float10 fVar7; float fVar8; uint uVar9; uint by; float unkMultiplier; float *pfVar10; float *pfVar11; float local_74; float local_70; float local_6c; float local_68; undefined4 local_64; BOOL local_60; uint objBlock_y; uint objBlock_x; Point2F local_54; Point2F local_4c; Point2F local_44; Point2F objWorldPos; float local_34; float local_30; Vector3F local_2c; Point2F local_20 [4]; Activity_Type activityType; LiveFlags1 lflags1; LiveFlags3 lflags3; RouteFlags rflags; local_6c = 0.0; local_70 = 0.0; local_60 = 1; uVar4 = liveObj->routeBlocks[liveObj->routeBlocksCurrent].blockPos.x; by = liveObj->routeBlocks[liveObj->routeBlocksCurrent].blockPos.y; LegoObject_GetBlockPos(liveObj,(int *)&objBlock_x,(int *)&objBlock_y); LegoObject_GetPosition(liveObj,&objWorldPos.x,&objWorldPos.y); local_44.x = (liveObj->faceDirection).x; local_44.y = (liveObj->faceDirection).y; out_vector = &liveObj->faceDirection; if (useRoutingPos == 0) { pfVar11 = &local_4c.y; pPVar5 = &local_4c; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,uVar4,by,&pPVar5->x,pfVar11); } else { pfVar11 = &local_30; uVar9 = liveObj->routeBlocks[liveObj->routeBlocksCurrent].blockPos.y; pfVar10 = &local_34; uVar1 = liveObj->routeBlocks[liveObj->routeBlocksCurrent].blockPos.x; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,uVar1,uVar9,pfVar10,pfVar11); uVar1 = liveObj->routeBlocksCurrent + 1; liveObj->routeBlocksCurrent = uVar1; pfVar11 = &local_4c.y; pPVar5 = &local_4c; uVar9 = liveObj->routeBlocks[uVar1].blockPos.x; uVar1 = liveObj->routeBlocks[uVar1].blockPos.y; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,uVar9,uVar1,&pPVar5->x,pfVar11); objBlock_x = uVar4; objBlock_y = by; } pfVar11 = &local_54.y; pPVar5 = &local_54; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,objBlock_x,objBlock_y,&pPVar5->x,pfVar11); fVar6 = local_6c; fVar2 = local_70; if (liveObj->routeBlocks[liveObj->routeBlocksCurrent].actionByte != ROUTE_ACTION_UNK_1) { pfVar11 = &local_74; pfVar10 = &local_70; fVar6 = local_4c.x; fVar2 = local_4c.y; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar6,fVar2,(int *)pfVar10,(int *)pfVar11); fVar2 = (float)Level_Block_IsGap((uint)local_70,(uint)local_74); BVar3 = Level_Block_IsWall((uint)local_70,(uint)local_74); fVar6 = local_6c; if ((BVar3 != 0) && (BVar3 = Level_Block_IsSeamWall((uint)local_70,(uint)local_74), fVar6 = local_6c, BVar3 == 0) ) { BVar3 = Level_Block_IsCornerInner((uint)local_70,(uint)local_74); if (BVar3 != 0) { if (ABS(local_4c.x - local_54.x) <= ABS(local_4c.y - local_54.y)) { local_20[0].x = 0.1; local_20[0].y = 0.0; local_20[1].x = -0.1; local_20[1].y = 0.0; local_20[2].x = -0.1; local_20[2].y = 0.0; local_20[3].x = 0.1; local_20[3].y = 0.0; uVar4 = Level_Block_GetDirection((uint)local_70,(uint)local_74); pPVar5 = local_20 + uVar4; } else { local_20[0].x = 0.0; local_20[0].y = -0.1; local_20[1].x = 0.0; local_20[1].y = -0.1; local_20[2].x = 0.0; local_20[2].y = 0.1; local_20[3].x = 0.0; local_20[3].y = 0.1; uVar4 = Level_Block_GetDirection((uint)local_70,(uint)local_74); pPVar5 = local_20 + uVar4; } local_4c.x = pPVar5->x + local_4c.x; local_4c.y = pPVar5->y + local_4c.y; } pfVar11 = &local_4c.y; pPVar5 = &local_4c; unkMultiplier = 0.05; BVar3 = Level_Block_IsGap((uint)local_70,(uint)local_74); fVar6 = local_4c.x; fVar8 = local_4c.y; map = lrr::Lego_GetMap(); lego::map::Map3D_FUN_0044fe50(map,fVar6,fVar8,BVar3,unkMultiplier,&pPVar5->x,pfVar11); fVar6 = 1.401298e-45; } } if (fVar6 == 0.0) { map = lrr::Lego_GetMap(); fVar7 = lego::map::Map3D_BlockSize(map); local_6c = (float)(((float10)liveObj->routeBlocks[liveObj->routeBlocksCurrent].blockOffset.x - (float10)0.5) * fVar7); map = lrr::Lego_GetMap(); fVar7 = lego::map::Map3D_BlockSize(map); local_68 = (float)(((float10)liveObj->routeBlocks[liveObj->routeBlocksCurrent].blockOffset.y - (float10)0.5) * fVar7); local_4c.x = local_6c + local_4c.x; local_4c.y = local_68 + local_4c.y; } rflags = liveObj->routeBlocks[liveObj->routeBlocksCurrent].flagsByte; if ((rflags & ROUTE_FLAG_GOTOBUILDING) == ROUTE_FLAG_NONE) { if ((rflags & ROUTE_FLAG_RUNAWAY) == ROUTE_FLAG_NONE) { if (((rflags & ROUTE_FLAG_UNK_8) != ROUTE_FLAG_NONE) && ((local_6c != 0.0 || (local_68 != 0.0)))) { local_54.x = local_6c; local_54.y = local_68; goto LAB_00444e0b; } local_54.x = local_4c.x - local_54.x; fVar8 = local_4c.y - local_54.y; local_54.y = fVar8; if ((fVar6 != 0.0) && (fVar2 == 0.0)) { local_54.y = fVar2; if (ABS(local_54.x) <= ABS(fVar8)) { local_54.x = 0.0; local_54.y = fVar8; } goto LAB_00444e0b; } if ((local_54.x != 0.0) || (fVar8 != 0.0)) goto LAB_00444e0b; } local_54.x = local_4c.x - objWorldPos.x; local_54.y = local_4c.y - objWorldPos.y; goto LAB_00444e0b; } switch(rflags & ROUTE_DIRECTION_MASK) { case ROUTE_FLAG_NONE: local_54.x = 0.0; local_54.y = 1.0; flags3_8 = 0; goto LAB_00444e0b; case 1: local_54.x = 1.0; break; case 2: local_54.x = 0.0; local_54.y = -1.0; flags3_8 = 0; goto LAB_00444e0b; case ROUTE_DIRECTION_MASK: local_54.x = -1.0; break; default: goto switchD_00444cce_caseD_4; } local_54.y = 0.0; switchD_00444cce_caseD_4: flags3_8 = 0; LAB_00444e0b: if (flags3_8 != 0) { local_2c.x = local_4c.x - objWorldPos.x; fVar6 = local_4c.y - objWorldPos.y; local_2c.z = 0.0; local_64 = 0; local_2c.y = 1.0 / SQRT(fVar6 * fVar6 + local_2c.x * local_2c.x); local_68 = 1.0 / SQRT(local_44.y * local_44.y + local_44.x * local_44.x); fVar2 = 1.0 / SQRT(local_54.y * local_54.y + local_54.x * local_54.x); local_2c.x = local_2c.y * local_2c.x; local_2c.y = local_2c.y * fVar6; local_6c = local_68 * local_44.x; local_68 = local_68 * local_44.y; local_74 = fVar2 * local_54.y * local_68 + fVar2 * local_54.x * local_6c; local_70 = local_2c.y * local_68 + local_2c.x * local_6c + 0.0; if (((notFlags1_10000 == 0) || ((ushort)((ushort)(local_74 < 0.7) << 8 | (ushort)(local_74 == 0.7) << 0xe) != 0)) || (-0.7 <= local_70)) { if (((((ushort)((ushort)(local_74 < 0.0) << 8 | (ushort)(local_74 == 0.0) << 0xe) != 0) && (local_70 < 0.7)) && ((ushort)((ushort)(ABS(local_70) < 0.1) << 8 | (ushort)(ABS(local_70) == 0.1) << 0xe) == 0 )) || (BVar3 = LegoObject_Route_SolidBlockCheck_FUN_00445860(liveObj), BVar3 != 0)) { if (-0.9 <= local_74) { fVar6 = local_2c.x * (liveObj->faceDirection).z; fVar2 = local_2c.x * (liveObj->faceDirection).y; fVar8 = out_vector->x * local_2c.y; local_2c.x = local_2c.y * (liveObj->faceDirection).z - local_2c.z * (liveObj->faceDirection).y; local_2c.y = out_vector->x * local_2c.z - fVar6; local_2c.z = fVar2 - fVar8; // SIDE EFFECTS: local_2c (axis) is normalised by internal D3DRMVectorRotate call. math::Maths_Vector3DRotate(out_vector,out_vector,&local_2c,-1.570796); if (liveObj->type != LegoObject_Vehicle) { local_44.x = out_vector->x; local_44.y = (liveObj->faceDirection).y; } if ((ushort)((ushort)(local_2c.z < 0.0) << 8 | (ushort)(local_2c.z == 0.0) << 0xe) == 0) { if ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { activityType = Activity_TurnRight; } else { activityType = Activity_CarryTurnRight; } } else { if ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { activityType = Activity_TurnLeft; } else { activityType = Activity_CarryTurnLeft; } } LegoObject_SetActivity(liveObj,activityType,1); } else { if (liveObj->type != LegoObject_Vehicle) { local_44.x = -out_vector->x; out_vector->x = local_44.x; local_44.y = -(liveObj->faceDirection).y; (liveObj->faceDirection).y = local_44.y; } if ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { activityType = Activity_TurnRight; } else { activityType = Activity_CarryTurnRight; } LegoObject_SetActivity(liveObj,activityType,0); if (liveObj->type != LegoObject_Vehicle) { liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_TURNRIGHT; } } lflags1 = liveObj->flags1; liveObj->flags1 = lflags1 | LIVEOBJ1_TURNING; if (liveObj->type != LegoObject_Vehicle) { local_60 = 0; liveObj->flags1 = lflags1 & (LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING| LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO) | LIVEOBJ1_TURNING; } } } else { local_44.x = -local_44.x; local_44.y = -local_44.y; local_54.x = -local_54.x; local_54.y = -local_54.y; liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_LIFTING; } } local_6c = SQRT((objWorldPos.y - local_4c.y) * (objWorldPos.y - local_4c.y) + (objWorldPos.x - local_4c.x) * (objWorldPos.x - local_4c.x)) * 0.2; if ((ushort)((ushort)(local_6c < 0.1) << 8 | (ushort)(local_6c == 0.1) << 0xe) == 0) { fVar6 = (float)std::_finite((double)local_44.x); if (fVar6 == 0.0) { local_44.x = 1.0; local_44.y = fVar6; } math::BezierCurve_Vector2DChangeLength(&local_44,local_6c); math::BezierCurve_Vector2DChangeLength(&local_54,local_6c * 1.6); math::BezierCurve_BuildPoints (&liveObj->routeCurve,&objWorldPos,&local_44,&local_4c,&local_54,50); LegoObject_Route_CurveSolid_FUN_004454a0(liveObj); } else { (liveObj->routeCurve).points[0].x = objWorldPos.x; (liveObj->routeCurve).points[0].y = objWorldPos.y; (liveObj->routeCurve).count = 0; } fVar7 = math::BezierCurve_UpdateDistances(&liveObj->routeCurve); lflags3 = liveObj->flags3; fVar6 = liveObj->routeCurveInitialDist; liveObj->routeCurveTotalDist = (float)fVar7; (liveObj->point_298).x = local_54.x; liveObj->flags3 = lflags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); liveObj->routeCurveCurrDist = fVar6; (liveObj->point_298).y = local_54.y; return local_60; } void __cdecl lego::game::LegoObject_FaceTowardsCamera(LegoObject *liveObj,Point2F *newFaceDir) { Vector3F *out_vector; float fVar1; float fVar2; float fVar3; Activity_Type activityType; float10 fVar4; Vector3F local_c; LiveFlags1 lflags1; if (liveObj->type != LegoObject_MiniFigure) { return; } fVar1 = (liveObj->faceDirection).y; fVar2 = (liveObj->faceDirection).z; out_vector = &liveObj->faceDirection; local_c.x = newFaceDir->x; fVar3 = newFaceDir->y; local_c.z = 0.0; fVar1 = 1.0 / SQRT(out_vector->x * out_vector->x + fVar2 * fVar2 + fVar1 * fVar1); local_c.y = 1.0 / SQRT(fVar3 * fVar3 + local_c.x * local_c.x); local_c.x = local_c.y * local_c.x; out_vector->x = out_vector->x * fVar1; local_c.y = local_c.y * fVar3; (liveObj->faceDirection).y = fVar1 * (liveObj->faceDirection).y; (liveObj->faceDirection).z = fVar1 * (liveObj->faceDirection).z; fVar4 = std::acos((float10)(liveObj->faceDirection).y * (float10)local_c.y + (float10)(liveObj->faceDirection).z * (float10)0.0 + (float10)out_vector->x * (float10)local_c.x); fVar1 = (float)fVar4; LegoObject_Route_End(liveObj,FALSE); // if (fVar1 <= (M_PI * 3.0f/4.0f)) if ((ushort)((ushort)(fVar1 < 2.356194) << 8 | (ushort)(fVar1 == 2.356194) << 0xe) == 0) { lflags1 = liveObj->flags1; out_vector->x = -out_vector->x; (liveObj->faceDirection).y = -(liveObj->faceDirection).y; liveObj->flags1 = lflags1 | LIVEOBJ1_TURNRIGHT; } else { // if (fVar1 <= (M_PI * 1.0f/4.0f)) if ((ushort)((ushort)(fVar1 < 0.7853982) << 8 | (ushort)(fVar1 == 0.7853982) << 0xe) != 0) { return; } fVar1 = local_c.x * (liveObj->faceDirection).z; fVar2 = local_c.x * (liveObj->faceDirection).y; fVar3 = out_vector->x * local_c.y; local_c.x = local_c.y * (liveObj->faceDirection).z - local_c.z * (liveObj->faceDirection).y; local_c.y = out_vector->x * local_c.z - fVar1; local_c.z = fVar2 - fVar3; // -(M_PI / 2.0f) // // SIDE EFFECTS: local_c (axis) is normalised by internal D3DRMVectorRotate call. math::Maths_Vector3DRotate(out_vector,out_vector,&local_c,-1.570796); activityType = Activity_TurnLeft; if (local_c.z < 0.0) goto LAB_00445461; } activityType = Activity_TurnRight; LAB_00445461: if ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { activityType = (activityType == Activity_TurnRight) + Activity_CarryTurnLeft; } liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_TURNING; LegoObject_SetActivity(liveObj,activityType,0); LegoObject_UpdateActivityChange(liveObj); return; } void __cdecl lego::game::LegoObject_Route_CurveSolid_FUN_004454a0(LegoObject *liveObj) { StatsFlags1 sflags1; Map3D *map; BOOL BVar1; Point2F *pCurvePoint; uint i; float10 blockSize; float fVar2; uint bx; float fVar3; LegoObject *by; uint *out_bx; float *out_x; LegoObject **out_by; float *out_y; uint local_14; LegoObject *otherObj; float local_c; float local_8; float local_4; RouteAction action; LegoObject *liveObj_00; liveObj_00 = liveObj; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((((sflags1 & STATS1_ROUTEAVOIDANCE) != STATS1_NONE) && (action = liveObj_00->routeBlocks[liveObj_00->routeBlocksCurrent].actionByte, action != ROUTE_ACTION_STORE)) && (action != ROUTE_ACTION_GATHERROCK)) && ((action != ROUTE_ACTION_REPAIRDRAIN && (action != ROUTE_ACTION_UNK_5)))) { otherObj = liveObj_00; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj_00); if ((sflags1 & STATS1_COLLRADIUS) != STATS1_NONE) { LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_CurveSolidCollRadius_FUN_00445600,&otherObj); } i = 0; if ((liveObj_00->routeCurve).count != 0) { pCurvePoint = (liveObj_00->routeCurve).points; do { fVar3 = pCurvePoint->y; out_by = &liveObj; out_bx = &local_14; fVar2 = pCurvePoint->x; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar2,fVar3,(int *)out_bx,(int *)out_by); BVar1 = Level_Block_IsSolidBuilding(local_14,(uint)liveObj,FALSE); if (BVar1 != 0) { out_y = &local_4; out_x = &local_8; bx = local_14; by = liveObj; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,(uint)by,out_x,out_y); fVar2 = pCurvePoint->x - local_8; fVar3 = pCurvePoint->y - local_4; local_c = SQRT(fVar2 * fVar2 + fVar3 * fVar3); pCurvePoint->x = (1.0 / local_c) * fVar2; pCurvePoint->y = (1.0 / local_c) * fVar3; map = lrr::Lego_GetMap(); blockSize = lego::map::Map3D_BlockSize(map); pCurvePoint->x = (float)(blockSize * (float10)0.71 * (float10)pCurvePoint->x + (float10)local_8); pCurvePoint->y = (float)(blockSize * (float10)0.71 * (float10)pCurvePoint->y + (float10)local_4); } i += 1; pCurvePoint = pCurvePoint + 1; } while (i < (liveObj_00->routeCurve).count); } } return; } BOOL __cdecl lego::game::LegoObject_Callback_CurveSolidCollRadius_FUN_00445600 (LegoObject *liveObj,LegoObject **pOtherObj) { float fVar1; uint uVar2; float fVar3; StatsFlags1 sflags1; uint i; float *pfVar4; float10 otherCollRadius; float10 thisCollRadius; float10 fVar5; float local_10; float local_c; Point2F objWorldPos; LegoObject *otherObj; otherObj = *pOtherObj; if ((((liveObj != otherObj) && (liveObj->carryingThisObject != otherObj)) && (liveObj->interactObject != otherObj)) && ((liveObj->flags3 & LIVEOBJ3_UNK_2000) == LIVEOBJ3_NONE)) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CAUSESLIP) == STATS1_NONE) { otherObj = *pOtherObj; otherCollRadius = stats::StatsObject_GetCollRadius(otherObj); LegoObject_GetPosition(liveObj,&objWorldPos.x,&objWorldPos.y); i = 1; if (1 < (otherObj->routeCurve).count - 1) { pfVar4 = &(otherObj->routeCurve).points[1].y; do { fVar3 = objWorldPos.y - *pfVar4; fVar1 = objWorldPos.x - pfVar4[-1]; thisCollRadius = stats::StatsObject_GetCollRadius(liveObj); if ((float10)SQRT(fVar1 * fVar1 + fVar3 * fVar3) < thisCollRadius + (float10)(float)otherCollRadius) { local_10 = pfVar4[-1] - objWorldPos.x; fVar1 = *pfVar4 - objWorldPos.y; local_c = SQRT(fVar1 * fVar1 + local_10 * local_10); if (local_c == 0.0) { thisCollRadius = math::Maths_RandRange(0.0,1.0); fVar1 = (float)thisCollRadius; thisCollRadius = math::Maths_RandRange(0.0,1.0); fVar5 = (float10)1.0 / SQRT(thisCollRadius * (float10)(float)thisCollRadius + (float10)fVar1 * (float10)fVar1); local_10 = (float)(fVar5 * (float10)fVar1); local_c = (float)(fVar5 * (float10)(float)thisCollRadius); } else { local_c = 1.0 / local_c; local_10 = local_c * local_10; local_c = local_c * fVar1; } thisCollRadius = stats::StatsObject_GetCollRadius(liveObj); thisCollRadius = thisCollRadius + (float10)(float)otherCollRadius; pfVar4[-1] = (pfVar4[-3] + pfVar4[1] + (float)(thisCollRadius * (float10)local_10 + (float10)objWorldPos.x)) * 0.3333333; *pfVar4 = (pfVar4[-2] + pfVar4[2] + (float)thisCollRadius * local_c + objWorldPos.y) * 0.3333333; } i += 1; pfVar4 = pfVar4 + 2; } while (i < (otherObj->routeCurve).count - 1); } uVar2 = (otherObj->routeCurve).count; fVar1 = (otherObj->routeCurve).points[uVar2 - 2].y; pfVar4 = &(otherObj->routeCurve).points[uVar2 - 1].y; pfVar4[-1] = ((otherObj->routeCurve).points[uVar2 - 2].x - (otherObj->routeCurve).points[uVar2 - 3].x) + pfVar4[-3]; *pfVar4 = pfVar4[-2] + (fVar1 - pfVar4[-4]); } } return 0; } BOOL __cdecl lego::game::LegoObject_Route_SolidBlockCheck_FUN_00445860(LegoObject *liveObj) { BOOL BVar1; Map3D *map; float10 blockSize; float fVar2; float in_y; uint *out_bx; uint *out_by; uint local_20; uint local_1c; int objBlock_y; int objBlock_x; float local_10; float local_c; Point2F objWorldPos; LegoObject_GetBlockPos(liveObj,&objBlock_x,&objBlock_y); BVar1 = Level_Block_IsWall(objBlock_x,objBlock_y); if (BVar1 != 0) { return 0; } LegoObject_GetPosition(liveObj,&objWorldPos.x,&objWorldPos.y); local_10 = (liveObj->faceDirection).x; local_c = (liveObj->faceDirection).y; fVar2 = 1.0 / SQRT(local_c * local_c + local_10 * local_10); map = lrr::Lego_GetMap(); blockSize = lego::map::Map3D_BlockSize(map); out_by = &local_20; local_c = fVar2 * local_c * (float)(blockSize * (float10)0.3333333); local_10 = fVar2 * local_10 * (float)(blockSize * (float10)0.3333333); in_y = local_c + objWorldPos.y; fVar2 = local_10 + objWorldPos.x; out_bx = &local_1c; objWorldPos.x = fVar2; objWorldPos.y = in_y; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar2,in_y,(int *)out_bx,(int *)out_by); BVar1 = Level_Block_IsWall(local_1c,local_20); if ((BVar1 == 0) && (BVar1 = Level_Block_IsSolidBuilding(local_1c,local_20,0), BVar1 == 0)) { return 0; } return TRUE; } void __cdecl lego::game::LegoObject_UpdateSlipAndScare(LegoObject *liveObj,float elapsed) { uint animFrames; float10 animTime; if (liveObj->type == LegoObject_RockMonster) { LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_SlipAndScare,liveObj); } if (((liveObj->type == LegoObject_Dynamite) || (liveObj->type == LegoObject_OohScary)) && ((liveObj->flags3 & LIVEOBJ3_UNK_10000) != LIVEOBJ3_NONE)) { animFrames = gfx::Container_GetAnimationFrames(liveObj->other); // Some dangerous looking hardcoded time constants(?) animTime = gfx::Container_GetAnimationTime(liveObj->other); if ((float10)(ulonglong)animFrames - (float10)75.0 < animTime) { LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_ScareTrainedMiniFiguresAwayFromTickingDynamite,liveObj); } } return; } // Only mini-figure units trained to use explosives are effected. BOOL __cdecl lego::game::LegoObject_Callback_ScareTrainedMiniFiguresAwayFromTickingDynamite (LegoObject *liveObj,LegoObject *explosiveObj) { Point2F thisPos; Point2F otherPos; Point2F dir2D; float dist; float dist_x; float dist_y; if ((liveObj->type == LegoObject_MiniFigure) && ((*(byte *)&liveObj->abilityFlags & ABILITY_FLAG_DYNAMITE) != 0)) { LegoObject_GetPosition(liveObj,&thisPos.x,&thisPos.y); LegoObject_GetPosition(explosiveObj,&otherPos.x,&otherPos.y); dist_x = thisPos.x - otherPos.x; dist_y = thisPos.y - otherPos.y; dist = SQRT(dist_y * dist_y + dist_x * dist_x); if (dist < globs::legoGlobs.DynamiteDamageRadius) { dir2D.x = (1.0 / dist) * dist_x; dir2D.y = (1.0 / dist) * dist_y; LegoObject_TryRunAway(liveObj,&dir2D); return FALSE; } } return FALSE; } BOOL __cdecl lego::game::LegoObject_Callback_SlipAndScare(LegoObject *liveObj,LegoObject *monsterObj) { float fVar1; StatsFlags1 sflags1; Container *cont; Map3D *map; BOOL BVar2; uint weaponID; float10 alertRadius_; float10 wakeRadius; float10 otherCollRadius; float10 collRadius; float10 painThreshold; float10 stampRadius; float10 damage; float in_x; float in_y; LegoObject *liveObj_00; uint *out_bx; float *out_by; float fVar3; LegoObject_Type objType; LegoObject_ID objID; Point2F dir2D; Point2F thisPos; Point2F otherPos; uint local_14; float local_10; Vector3F dir; float flocksDiff_x; BOOL showVisual; float alertRadius; float dist; FlocksFlags *pFlocksFlags; LegoObject_GetPosition(monsterObj,&otherPos.x,&otherPos.y); LegoObject_GetPosition(liveObj,&thisPos.x,&thisPos.y); dir2D.x = thisPos.x - otherPos.x; dir2D.y = thisPos.y - otherPos.y; dist = SQRT(dir2D.y * dir2D.y + dir2D.x * dir2D.x); alertRadius_ = stats::StatsObject_GetAlertRadius(monsterObj); alertRadius = (float)alertRadius_; if ((monsterObj->flags3 & LIVEOBJ3_POWEROFF) == LIVEOBJ3_NONE) { if (((((liveObj->flags2 & LIVEOBJ2_THROWN) == LIVEOBJ2_NONE) && ((liveObj->flags2 & LIVEOBJ2_UNK_100) == LIVEOBJ2_NONE)) && ((((byte)globs::legoGlobs.flags2 & GAME2_CALLTOARMS) == 0 || ((*(byte *)&liveObj->flags4 & LIVEOBJ4_UNK_4) == 0)))) && (liveObj->driveObject == NULL)) { if (liveObj->type == LegoObject_MiniFigure) { sflags1 = stats::StatsObject_GetStatsFlags1(monsterObj); if ((sflags1 & STATS1_GRABMINIFIGURE) != STATS1_NONE) { cont = LegoObject_GetActivityContainer(monsterObj); gfx::Container_GetOrientation(cont,NULL,&dir,NULL); // local_10 is reused. Store as int here. out_by = &local_10; out_bx = &local_14; fVar3 = 1.0 / SQRT(dir.y * dir.y + dir.x * dir.x); fVar1 = fVar3 * dir.y * 15.0 + otherPos.y; fVar3 = fVar3 * dir.x * 15.0 + otherPos.x; in_x = fVar3; in_y = fVar1; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,in_x,in_y,(int *)out_bx,(int *)out_by); BVar2 = Level_Block_IsWall(local_14,(uint)local_10); if (BVar2 == 0) { BVar2 = Level_Block_IsSolidBuilding(local_14,(uint)local_10,TRUE); if (BVar2 == 0) { fVar3 = thisPos.x - fVar3; fVar1 = thisPos.y - fVar1; collRadius = stats::StatsObject_GetCollRadius(liveObj); if ((float10)SQRT(fVar1 * fVar1 + fVar3 * fVar3) < collRadius) { ai::LegoObject_DoThrowLegoman(monsterObj,liveObj); return 0; } } } } sflags1 = stats::StatsObject_GetStatsFlags1(monsterObj); if ((sflags1 & STATS1_CAUSESLIP) != STATS1_NONE) { otherCollRadius = stats::StatsObject_GetCollRadius(monsterObj); collRadius = stats::StatsObject_GetCollRadius(liveObj); if ((ushort)((ushort)(collRadius + (float10)(float)otherCollRadius < (float10)dist) << 8 | (ushort)(collRadius + (float10)(float)otherCollRadius == (float10)dist) << 0xe ) == 0) { ai::LegoObject_DoSlip(liveObj); monsterObj->health = -1.0; monsterObj->flags3 = monsterObj->flags3 | LIVEOBJ3_REMOVING; } } sflags1 = stats::StatsObject_GetStatsFlags1(monsterObj); if (((sflags1 & STATS1_CANSCARE) != STATS1_NONE) && (alertRadius != 0.0)) { collRadius = stats::StatsObject_GetCollRadius(liveObj); if ((float10)dist < collRadius + (float10)alertRadius) { dir2D.x = (1.0 / dist) * dir2D.x; dir2D.y = (1.0 / dist) * dir2D.y; LegoObject_TryRunAway(liveObj,&dir2D); } } } if (((liveObj->type == LegoObject_Vehicle) || (liveObj->type == LegoObject_MiniFigure)) && ((liveObj->flags1 & LIVEOBJ1_GATHERINGROCK) == LIVEOBJ1_NONE)) { painThreshold = stats::StatsObject_GetPainThreshold(monsterObj); if (painThreshold < (float10)monsterObj->health) { stampRadius = stats::StatsObject_GetStampRadius(monsterObj); if ((ushort)((ushort)(stampRadius < (float10)dist) << 8 | (ushort)(stampRadius == (float10)dist) << 0xe) == 0) { LegoObject_FUN_0043acb0(monsterObj,liveObj); } } } if ((liveObj->type == LegoObject_MiniFigure) || (liveObj->type == LegoObject_Vehicle)) { sflags1 = stats::StatsObject_GetStatsFlags1(monsterObj); if (((sflags1 & STATS1_SCAREDBYPLAYER) != STATS1_NONE) && ((monsterObj->flags1 & LIVEOBJ1_SCAREDBYPLAYER) == LIVEOBJ1_NONE)) { collRadius = stats::StatsObject_GetCollRadius(liveObj); if ((float10)dist < collRadius + (float10)alertRadius) { BVar2 = LegoObject_FUN_00444520(monsterObj); if (BVar2 != 0) { monsterObj->flags1 = monsterObj->flags1 | LIVEOBJ1_SCAREDBYPLAYER; } } } } if (liveObj->type == LegoObject_MiniFigure) { sflags1 = stats::StatsObject_GetStatsFlags1(monsterObj); if ((sflags1 & STATS1_FLOCKS) != STATS1_NONE) { // local_10 is reused. Store as float here. flocksDiff_x = thisPos.x - monsterObj->flocks->floatx_18; local_10 = thisPos.y - monsterObj->flocks->floaty_20; fVar3 = local_10 * local_10; collRadius = stats::StatsObject_GetCollRadius(liveObj); if ((float10)SQRT(fVar3 + flocksDiff_x * flocksDiff_x) < collRadius + (float10)alertRadius ) { fVar3 = 1.0; showVisual = TRUE; liveObj_00 = liveObj; weaponID = tools::Weapon_GetWeaponIDByName("BatAttack"); damage = tools::Weapon_GetDamageForObject(weaponID,liveObj_00); LegoObject_AddDamage2(liveObj,(float)damage,showVisual,fVar3); monsterObj->flags2 = monsterObj->flags2 | LIVEOBJ2_UNK_80; if ((*(byte *)&monsterObj->flocks->flags & FLOCKS_FLAG_UNK_1) == 0) { ai::AITask_PushFollowObject_Group(&monsterObj,1,liveObj); pFlocksFlags = &monsterObj->flocks->flags; *pFlocksFlags = *pFlocksFlags | FLOCKS_FLAG_UNK_1; } } } } sflags1 = stats::StatsObject_GetStatsFlags1(monsterObj); if ((sflags1 & STATS1_CANSCARESCORPION) != STATS1_NONE) { BVar2 = lrr::Lego_GetObjectByName("Scorpion",&objType,&objID,NULL); if (((BVar2 != 0) && (objType == liveObj->type)) && ((objID == liveObj->id && (alertRadius != 0.0)))) { collRadius = stats::StatsObject_GetCollRadius(liveObj); if ((float10)dist < collRadius + (float10)alertRadius) { dir2D.x = (1.0 / dist) * dir2D.x; dir2D.y = (1.0 / dist) * dir2D.y; LegoObject_TryRunAway(liveObj,&dir2D); } } } } } else { if ((liveObj->type == LegoObject_MiniFigure) || (liveObj->type == LegoObject_Vehicle)) { wakeRadius = stats::StatsObject_GetWakeRadius(monsterObj); if ((ushort)((ushort)(wakeRadius < (float10)dist) << 8 | (ushort)(wakeRadius == (float10)dist) << 0xe) == 0) { LegoObject_RockMonster_DoWakeUp(monsterObj); return TRUE; } } } return 0; } LegoObject * __cdecl lego::game::LegoObject_DoCollisionCallbacks_FUN_00446030 (LegoObject *liveObj,Point2F *param_2,float param_3,BOOL param_4) { StatsFlags1 SVar1; SearchCollision_14 search; search.pointf_4 = param_2; search.targetObj = liveObj; search.float_8 = param_3; search.result = NULL; search.bool_10 = param_4; SVar1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((SVar1 & STATS1_COLLBOX) != STATS1_NONE) { LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_CallbackCollisionBox_FUN_004463b0,&search) ; } SVar1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((SVar1 & STATS1_COLLRADIUS) != STATS1_NONE) { LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_CallbackCollisionRadius_FUN_004460b0,&search); } return search.result; } BOOL __cdecl lego::game::LegoObject_CallbackCollisionRadius_FUN_004460b0 (LegoObject *in_liveObj,SearchCollision_14 *search) { LegoObject *liveObj; float fVar1; float fVar2; StatsFlags1 SVar3; Container *cont; Size2F *size; BOOL BVar4; int i; Vector3F *pVector; Point2F *pPoint; float10 fVar5; float10 fVar6; float10 fVar7; Point2F local_60; Point2F pointList [5]; Vector3F vectorList [4]; liveObj = search->targetObj; if (((((search->bool_10 == 0) || (SVar3 = stats::StatsObject_GetStatsFlags1(liveObj), (SVar3 & STATS1_STOREOBJECTS) == STATS1_NONE)) && (in_liveObj != liveObj)) && ((in_liveObj->carryingThisObject != liveObj && (liveObj->carryingThisObject != in_liveObj)))) && ((in_liveObj != liveObj->driveObject && (((liveObj->flags1 & (LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE && ((in_liveObj->flags1 & (LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE )))))) { fVar5 = stats::StatsObject_GetCollHeight(in_liveObj); if ((ushort)((ushort)(fVar5 < (float10)search->float_8) << 8 | (ushort)(fVar5 == (float10)search->float_8) << 0xe) == 0) { LegoObject_GetPosition(in_liveObj,&local_60.x,&local_60.y); cont = LegoObject_GetActivityContainer(in_liveObj); fVar1 = local_60.x - search->pointf_4->x; fVar2 = local_60.y - search->pointf_4->y; fVar1 = SQRT(fVar2 * fVar2 + fVar1 * fVar1); SVar3 = stats::StatsObject_GetStatsFlags1(in_liveObj); if ((SVar3 & STATS1_COLLRADIUS) == STATS1_NONE) { SVar3 = stats::StatsObject_GetStatsFlags1(in_liveObj); if ((SVar3 & STATS1_COLLBOX) != STATS1_NONE) { fVar6 = stats::StatsObject_GetCollRadius(liveObj); fVar7 = stats::StatsObject_GetCollRadius(in_liveObj); fVar5 = (float10)fVar1; if ((ushort)((ushort)(fVar7 + (float10)(float)fVar6 < fVar5) << 8 | (ushort)(fVar7 + (float10)(float)fVar6 == fVar5) << 0xe) == 0) { size = stats::StatsObject_GetCollBox(in_liveObj); vectorList[0].x = size->width * -0.5; size = stats::StatsObject_GetCollBox(in_liveObj); vectorList[0].z = size->height * 0.5; size = stats::StatsObject_GetCollBox(in_liveObj); vectorList[1].x = size->width * 0.5; size = stats::StatsObject_GetCollBox(in_liveObj); vectorList[1].z = size->height * 0.5; size = stats::StatsObject_GetCollBox(in_liveObj); vectorList[2].x = size->width * 0.5; size = stats::StatsObject_GetCollBox(in_liveObj); vectorList[2].z = size->height * -0.5; size = stats::StatsObject_GetCollBox(in_liveObj); vectorList[3].x = size->width * -0.5; size = stats::StatsObject_GetCollBox(in_liveObj); vectorList[3].z = size->height * -0.5; vectorList[3].y = 0.0; vectorList[2].y = 0.0; vectorList[1].y = 0.0; vectorList[0].y = 0.0; pPoint = pointList; pVector = vectorList; i = 4; do { gfx::Container_Transform(cont,pVector,pVector); fVar1 = pVector->y; pPoint->x = pVector->x; pPoint->y = fVar1; pVector = pVector + 1; pPoint = pPoint + 1; i += -1; } while (i != 0); pointList[4].x = pointList[0].x; pointList[4].y = pointList[0].y; BVar4 = math::Maths_PointInsidePoly(search->pointf_4,pointList,pointList + 1,4); if (BVar4 == 0) { fVar5 = math::Collision_DistanceToPolyOutline (search->pointf_4,pointList,pointList + 1,4); fVar6 = stats::StatsObject_GetCollRadius(liveObj); if ((ushort)((ushort)(fVar6 < (float10)(float)fVar5) << 8 | (ushort)(fVar6 == (float10)(float)fVar5) << 0xe) == 0) { search->result = in_liveObj; } } else { search->result = in_liveObj; } } } } else { fVar6 = stats::StatsObject_GetCollRadius(liveObj); fVar7 = stats::StatsObject_GetCollRadius(in_liveObj); fVar5 = (float10)fVar1; if ((ushort)((ushort)(fVar7 + (float10)(float)fVar6 < fVar5) << 8 | (ushort)(fVar7 + (float10)(float)fVar6 == fVar5) << 0xe) == 0) { search->result = in_liveObj; } } } if (search->result != NULL) { return TRUE; } } return 0; } BOOL __cdecl lego::game::LegoObject_CallbackCollisionBox_FUN_004463b0 (LegoObject *in_liveObj,SearchCollision_14 *search) { float fVar1; LegoObject *liveObj; StatsFlags1 SVar2; Size2F *pSVar3; BOOL BVar4; float *pfVar5; LegoObject **ppLVar6; int iVar7; Point2F *pPVar8; Vector3F *out_vector; Vector3F *pVVar9; float10 fVar10; float10 fVar11; float local_f8; float local_f4; Point2F local_f0; LegoObject *local_e8 [2]; Container *local_e0; Container *local_dc; Vector3F local_d8; float local_cc; undefined4 local_c8; float local_c4; float local_c0; undefined4 local_bc; float local_b8; float local_b4; Point2F local_b0; Point2F local_a8 [4]; Point2F local_88; Point2F local_80 [3]; float local_68; float local_64; Vector3F local_60 [4]; Vector3F local_30 [4]; local_e8[1] = search->targetObj; if (((((search->bool_10 == 0) || (SVar2 = stats::StatsObject_GetStatsFlags1(local_e8[1]), (SVar2 & STATS1_STOREOBJECTS) == STATS1_NONE)) && (in_liveObj != local_e8[1])) && ((in_liveObj->carryingThisObject != local_e8[1] && (local_e8[1]->carryingThisObject != in_liveObj)))) && (((local_e8[1]->flags1 & (LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE && (((in_liveObj->flags1 & (LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP)) == LIVEOBJ1_NONE && (fVar10 = stats::StatsObject_GetCollHeight(in_liveObj), (ushort)((ushort)(fVar10 < (float10)search->float_8) << 8 | (ushort)(fVar10 == (float10)search->float_8) << 0xe) == 0)))))) { LegoObject_GetPosition(in_liveObj,&local_f0.x,&local_f0.y); LegoObject_GetPosition(local_e8[1],&local_f8,&local_f4); local_f8 = local_f8 - search->pointf_4->x; local_f4 = local_f4 - search->pointf_4->y; local_dc = LegoObject_GetActivityContainer(in_liveObj); local_e0 = LegoObject_GetActivityContainer(local_e8[1]); SVar2 = stats::StatsObject_GetStatsFlags1(in_liveObj); if ((SVar2 & STATS1_COLLRADIUS) == STATS1_NONE) { SVar2 = stats::StatsObject_GetStatsFlags1(in_liveObj); if ((SVar2 & STATS1_COLLBOX) != STATS1_NONE) { local_f0.y = local_f0.y - search->pointf_4->y; local_f0.x = local_f0.x - search->pointf_4->x; fVar10 = stats::StatsObject_GetCollRadius(in_liveObj); local_e8[0] = (LegoObject *)(float)fVar10; fVar10 = stats::StatsObject_GetCollRadius(local_e8[1]); if ((float10)SQRT(local_f0.x * local_f0.x + local_f0.y * local_f0.y) < fVar10 + (float10)(float)local_e8[0]) { local_e8[0] = in_liveObj; ppLVar6 = local_e8; iVar7 = 2; pfVar5 = &local_60[0].z; do { liveObj = *ppLVar6; pSVar3 = stats::StatsObject_GetCollBox(liveObj); pfVar5[-2] = pSVar3->width * -0.5; pSVar3 = stats::StatsObject_GetCollBox(liveObj); *pfVar5 = pSVar3->height * 0.5; pSVar3 = stats::StatsObject_GetCollBox(liveObj); pfVar5[1] = pSVar3->width * 0.5; pSVar3 = stats::StatsObject_GetCollBox(liveObj); pfVar5[3] = pSVar3->height * 0.5; pSVar3 = stats::StatsObject_GetCollBox(liveObj); pfVar5[4] = pSVar3->width * 0.5; pSVar3 = stats::StatsObject_GetCollBox(liveObj); pfVar5[6] = pSVar3->height * -0.5; pSVar3 = stats::StatsObject_GetCollBox(liveObj); pfVar5[7] = pSVar3->width * -0.5; pSVar3 = stats::StatsObject_GetCollBox(liveObj); ppLVar6 = ppLVar6 + 1; iVar7 += -1; pfVar5[9] = pSVar3->height * -0.5; pfVar5[8] = 0.0; pfVar5[5] = 0.0; pfVar5[2] = 0.0; pfVar5[-1] = 0.0; pfVar5 = pfVar5 + 0xc; } while (iVar7 != 0); pPVar8 = &local_b0; pVVar9 = local_30; iVar7 = 4; do { gfx::Container_Transform(local_e0,pVVar9,pVVar9); fVar1 = pVVar9->y; pPVar8->x = pVVar9->x; pPVar8->y = fVar1; pVVar9 = pVVar9 + 1; pPVar8 = pPVar8 + 1; iVar7 += -1; } while (iVar7 != 0); pVVar9 = &local_d8; out_vector = local_60; iVar7 = 4; do { gfx::Container_Transform(local_dc,out_vector,out_vector); fVar1 = out_vector->y; pVVar9->x = out_vector->x; pVVar9->y = fVar1; out_vector = out_vector + 1; pVVar9 = (Vector3F *)&pVVar9->z; iVar7 += -1; } while (iVar7 != 0); pfVar5 = &local_b8; iVar7 = 2; do { *pfVar5 = pfVar5[-8]; pfVar5[1] = pfVar5[-7]; pfVar5 = pfVar5 + 10; iVar7 += -1; } while (iVar7 != 0); pVVar9 = &local_d8; iVar7 = 4; do { BVar4 = math::Maths_PointInsidePoly((Point2F *)pVVar9,&local_b0,local_a8,4); if (BVar4 != 0) { search->result = in_liveObj; } pVVar9 = (Vector3F *)&pVVar9->z; iVar7 += -1; } while (iVar7 != 0); } } } else { local_f0.y = local_f0.y - search->pointf_4->y; local_f0.x = local_f0.x - search->pointf_4->x; fVar10 = stats::StatsObject_GetCollRadius(in_liveObj); local_e8[0] = (LegoObject *)(float)fVar10; fVar10 = stats::StatsObject_GetCollRadius(local_e8[1]); if ((float10)SQRT(local_f0.x * local_f0.x + local_f0.y * local_f0.y) < fVar10 + (float10)(float)local_e8[0]) { pSVar3 = stats::StatsObject_GetCollBox(local_e8[1]); local_d8.x = pSVar3->width * -0.5; pSVar3 = stats::StatsObject_GetCollBox(local_e8[1]); local_d8.z = pSVar3->height * 0.5; pSVar3 = stats::StatsObject_GetCollBox(local_e8[1]); local_cc = pSVar3->width * 0.5; pSVar3 = stats::StatsObject_GetCollBox(local_e8[1]); local_c4 = pSVar3->height * 0.5; pSVar3 = stats::StatsObject_GetCollBox(local_e8[1]); local_c0 = pSVar3->width * 0.5; pSVar3 = stats::StatsObject_GetCollBox(local_e8[1]); local_b8 = pSVar3->height * -0.5; pSVar3 = stats::StatsObject_GetCollBox(local_e8[1]); local_b4 = pSVar3->width * -0.5; pSVar3 = stats::StatsObject_GetCollBox(local_e8[1]); local_b0.y = pSVar3->height * -0.5; local_b0.x = 0.0; local_bc = 0; local_c8 = 0; local_d8.y = 0.0; pVVar9 = &local_d8; iVar7 = 4; pPVar8 = &local_88; do { gfx::Container_Transform(local_e0,pVVar9,pVVar9); fVar1 = pVVar9->y; pPVar8->x = pVVar9->x; pPVar8->y = fVar1; pVVar9 = pVVar9 + 1; iVar7 += -1; pPVar8->x = local_f8 + pPVar8->x; pPVar8->y = local_f4 + pPVar8->y; pPVar8 = pPVar8 + 1; } while (iVar7 != 0); local_68 = local_88.x; local_64 = local_88.y; BVar4 = math::Maths_PointInsidePoly(&local_f0,&local_88,local_80,4); if (BVar4 == 0) { fVar10 = math::Collision_DistanceToPolyOutline(&local_f0,&local_88,local_80,4); fVar11 = stats::StatsObject_GetCollRadius(in_liveObj); if ((ushort)((ushort)(fVar11 < (float10)(float)fVar10) << 8 | (ushort)(fVar11 == (float10)(float)fVar10) << 0xe) == 0) { search->result = in_liveObj; } } else { search->result = in_liveObj; } } } if (search->result != NULL) { return TRUE; } } return 0; } void __cdecl lego::game::LegoObject_CalculateSpeeds (LegoObject *liveObj,float elapsed,float *out_routeSpeed,float *out_transSpeed) { LegoObject *liveObj_00; Map3D *map; BOOL BVar1; uint layers; StatsFlags2 sflags2; float10 fVar2; float10 rubbleCoef; Point2I *out_bx; int *out_by; float *out_unk_z; float local_1c; Point2I blockPos; Point2F objectPos; LiveFlags1 lflags1; LegoObject_Type objType; float *out_routeSpeed_00; out_routeSpeed_00 = out_routeSpeed; liveObj_00 = liveObj; lflags1 = liveObj->flags1; local_1c = (float)(lflags1 & LIVEOBJ1_CAUGHTINWEB); objType = liveObj->type; if (objType == LegoObject_Vehicle) { fVar2 = gfx::Vehicle_GetTransCoef(liveObj->vehicle); liveObj = (LegoObject *)(float)fVar2; } else { if (objType == LegoObject_MiniFigure) { fVar2 = gfx::Creature_GetTransCoef(liveObj->miniFigure); liveObj = (LegoObject *)(float)fVar2; } else { if (objType == LegoObject_RockMonster) { fVar2 = gfx::Creature_GetTransCoef(liveObj->rockMonster); liveObj = (LegoObject *)(float)fVar2; } else { if (objType == LegoObject_Building) { fVar2 = gfx::Building_GetTransCoef(liveObj->building); liveObj = (LegoObject *)(float)fVar2; } else { if (((liveObj->flags3 & LIVEOBJ3_SIMPLEOBJECT) != LIVEOBJ3_NONE) || (objType == LegoObject_UpgradePart)) { *out_transSpeed = elapsed; return; } } } } } if ((lflags1 & LIVEOBJ1_DRILLING) == LIVEOBJ1_NONE) { if (((lflags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) || (liveObj_00->type == LegoObject_Vehicle) ) { fVar2 = stats::StatsObject_GetRouteSpeed(liveObj_00); *out_routeSpeed = (float)fVar2; if ((lflags1 & LIVEOBJ1_LIFTING) != LIVEOBJ1_NONE) { *out_routeSpeed = (float)(fVar2 * (float10)0.5); } } else { fVar2 = stats::StatsObject_GetRouteSpeed(liveObj_00); *out_routeSpeed = (float)(fVar2 * (float10)0.5); } } else { fVar2 = stats::StatsObject_GetRouteSpeed(liveObj_00); *out_routeSpeed = (float)(fVar2 * (float10)0.05); } if (local_1c != 0.0) { *out_routeSpeed = *out_routeSpeed * 0.05; } local_1c = 1.0; LegoObject_GetPosition(liveObj_00,&objectPos.x,&objectPos.y); out_unk_z = &local_1c; out_by = &blockPos.y; out_bx = &blockPos; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos(map,objectPos.x,objectPos.y,&out_bx->x,out_by,out_unk_z); if (BVar1 != 0) { layers = Level_Block_GetRubbleLayers(&blockPos); rubbleCoef = stats::StatsObject_GetRubbleCoef(liveObj_00); // Delta between rubbleCoef and 1.0f based on number of rubble layers out of 4. out_routeSpeed = (float *)(float)((float10)1.0 - ((float10)1.0 - rubbleCoef) * (float10)((float)(ulonglong)layers * 0.25)); BVar1 = Level_Block_IsPath(&blockPos); if (BVar1 != 0) { fVar2 = stats::StatsObject_GetPathCoef(liveObj_00); out_routeSpeed = (float *)(float)(fVar2 * (float10)(float)out_routeSpeed); } if ((liveObj_00->type == LegoObject_MiniFigure) && ((globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * blockPos.y + blockPos.x].terrain == Lego_SurfaceType8_Lake)) { out_routeSpeed = (float *)((1.0 - local_1c * 0.8) * (float)out_routeSpeed); } BVar1 = Level_Block_IsGround(blockPos.x,blockPos.y); if (BVar1 != 0) { *out_routeSpeed_00 = *out_routeSpeed_00 * (float)out_routeSpeed; } } if ((float)liveObj == 0.0) { *out_transSpeed = 1.0; } else { *out_transSpeed = *out_routeSpeed_00 / (float)liveObj; } if (((liveObj_00->type == LegoObject_Building) && (sflags2 = stats::StatsObject_GetStatsFlags2(liveObj_00), (sflags2 & STATS2_UPGRADEBUILDING) != STATS2_NONE)) && ((liveObj_00->flags2 & LIVEOBJ2_UPGRADING) != LIVEOBJ2_NONE)) { fVar2 = stats::StatsObject_GetFunctionCoef(liveObj_00); *out_transSpeed = (float)(fVar2 * (float10)*out_transSpeed); } *out_transSpeed = *out_transSpeed * elapsed; *out_routeSpeed_00 = *out_routeSpeed_00 * elapsed; return; } BOOL __cdecl lego::game::LegoObject_RoutingPtr_Realloc_FUN_00446b80(LegoObject *liveObj,uint bx,uint by) { RoutingBlock *routeBlocks; uint bx2; uint by2; uint oldCount; if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_MOVING) != 0) { oldCount = liveObj->routeBlocksTotal; routeBlocks = liveObj->routeBlocks; bx2 = routeBlocks[oldCount - 1].blockPos.x; by2 = routeBlocks[oldCount - 1].blockPos.y; if ((((bx == bx2) && ((by == by2 - 1 || (by == by2 + 1)))) || ((by == by2 && ((bx == bx2 - 1 || (bx == bx2 + 1)))))) && (routeBlocks = (RoutingBlock *)io::Mem_ReAlloc(routeBlocks,(oldCount + 1) * 0x14), routeBlocks != NULL)) { liveObj->routeBlocks = routeBlocks; routeBlocks[liveObj->routeBlocksTotal].blockPos.x = bx; liveObj->routeBlocks[liveObj->routeBlocksTotal].blockPos.y = by; liveObj->routeBlocks[liveObj->routeBlocksTotal].blockOffset.x = 0.5; liveObj->routeBlocks[liveObj->routeBlocksTotal].blockOffset.y = 0.5; liveObj->routeBlocks[liveObj->routeBlocksTotal].flagsByte = ROUTE_FLAG_NONE; liveObj->routeBlocks[liveObj->routeBlocksTotal].actionByte = ROUTE_ACTION_UNK_1; liveObj->routeBlocksTotal = liveObj->routeBlocksTotal + 1; // & ~LIVEOBJ3_UNK_400 (0x400) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000| LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); return TRUE; } } return 0; } BOOL __cdecl lego::game::LegoObject_BlockRoute_FUN_00446c80 (LegoObject *liveObj,uint bx,uint by,BOOL useWideRange,Direction *optout_direction, BOOL countIs8) { float fVar1; bool bVar2; Map3D *map; BOOL BVar3; uint by_00; int iVar4; Direction DVar5; int **ppiVar6; Direction count; Point2F *pPVar7; uint i4; BOOL *pBVar8; uint i1; uint i2; uint i3; longlong lVar9; int **out_new_bxs; int **out_new_bys; uint by_01; uint *out_count; undefined4 callback; float *out_y; void *data; BOOL *local_11c; Point2F *directions; BOOL result; Point2I objBlockPos; Direction local_108; uint local_f8; Direction local_f4; Point2F blockWorldPos; Point2F objWorldPos; Point2F DIRECTIONS_THIN [4]; Point2F DIRECTIONS_WIDE [8]; BOOL local_80 [8]; int *local_60 [8]; int *local_40 [8]; uint local_20 [8]; local_108 = ~DIRECTION_UP; local_f8 = 0xffffffff; local_f4 = ~DIRECTION_UP; pBVar8 = local_80; local_80[0] = 0; DIRECTIONS_WIDE[1].x = 0.0; for (iVar4 = 7; pBVar8 = pBVar8 + 1, iVar4 != 0; iVar4 += -1) { *pBVar8 = 0; } // Point2I local_c0[8]; // \X -2 -1 0 1 // Y\ __ __ __ __ // -2 |__|_0|_1|__| // -1 |_7|__|__|_2| // 0 |_6|__|__|_3| // 1 |__|_5|_4|__| DIRECTIONS_WIDE[3].y = 0.0; DIRECTIONS_WIDE[4].x = 0.0; DIRECTIONS_WIDE[6].y = 0.0; DIRECTIONS_THIN[0].x = 0.0; DIRECTIONS_THIN[1].y = 0.0; DIRECTIONS_THIN[2].x = 0.0; DIRECTIONS_THIN[3].y = 0.0; result = 0; DIRECTIONS_WIDE[0].x = -1.0; DIRECTIONS_WIDE[0].y = -2.0; DIRECTIONS_WIDE[1].y = -2.0; DIRECTIONS_WIDE[2].x = 1.0; DIRECTIONS_WIDE[2].y = -1.0; DIRECTIONS_WIDE[3].x = 1.0; DIRECTIONS_WIDE[4].y = 1.0; DIRECTIONS_WIDE[5].x = -1.0; DIRECTIONS_WIDE[5].y = 1.0; DIRECTIONS_WIDE[6].x = -2.0; DIRECTIONS_WIDE[7].x = -2.0; DIRECTIONS_WIDE[7].y = -1.0; DIRECTIONS_THIN[0].y = -1.0; DIRECTIONS_THIN[1].x = 1.0; DIRECTIONS_THIN[2].y = 1.0; DIRECTIONS_THIN[3].x = -1.0; bVar2 = true; if (useWideRange == 0) { directions = DIRECTIONS_THIN; count = DIRECTION__COUNT; } else { directions = DIRECTIONS_WIDE; count = 8; } LegoObject_GetBlockPos(liveObj,&objBlockPos.x,&objBlockPos.y); if (countIs8 == 0) { out_y = &blockWorldPos.y; pPVar7 = &blockWorldPos; by_00 = bx; by_01 = by; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,by_00,by_01,&pPVar7->x,out_y); LegoObject_GetPosition(liveObj,&objWorldPos.x,&objWorldPos.y); map = lrr::Lego_GetMap(); if (SQRT((blockWorldPos.y - objWorldPos.y) * (blockWorldPos.y - objWorldPos.y) + (blockWorldPos.x - objWorldPos.x) * (blockWorldPos.x - objWorldPos.x)) < map->blockSize ) { bVar2 = false; } } i1 = 0; DVar5 = local_f4; if (count != DIRECTION_UP) { pPVar7 = directions; do { pPVar7->x = pPVar7->x + (float)(ulonglong)bx; fVar1 = pPVar7->y + (float)(ulonglong)by; pPVar7->y = fVar1; if ((((pPVar7->x == (float)objBlockPos.x) && (fVar1 == (float)objBlockPos.y)) && (bVar2)) && ((DVar5 = i1, useWideRange != 0 || (BVar3 = Level_Block_IsWall(objBlockPos.x,objBlockPos.y), BVar3 == 0)))) break; i1 += DIRECTION_RIGHT; pPVar7 = pPVar7 + 1; DVar5 = local_f4; } while (i1 < count); } if (DVar5 != ~DIRECTION_UP) { BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,1,&objBlockPos.x,&objBlockPos.y,NULL); if (BVar3 == 0) { return FALSE; } if (optout_direction != NULL) { *optout_direction = DVar5; } return TRUE; } i2 = 0; if (count != DIRECTION_UP) { local_11c = local_80; ppiVar6 = local_40; pPVar7 = directions; do { if (((float)objBlockPos.x != pPVar7->x) || ((float)objBlockPos.y != pPVar7->y)) { lVar9 = __ftol((float10)pPVar7->y); by_00 = (uint)lVar9; data = NULL; out_count = local_20 + i2; callback = 0; out_new_bys = local_60 + i2; out_new_bxs = ppiVar6; lVar9 = __ftol((float10)pPVar7->x); BVar3 = LegoObject_Route_Score_FUN_004413b0 (liveObj,objBlockPos.x,objBlockPos.y,(uint)lVar9,by_00,out_new_bxs, out_new_bys,(int *)out_count,callback,data); if (BVar3 != 0) { *local_11c = TRUE; } } i2 += DIRECTION_RIGHT; pPVar7 = pPVar7 + 1; ppiVar6 = ppiVar6 + 1; local_11c = local_11c + 1; } while (i2 < count); } i3 = 0; if (count != DIRECTION_UP) { do { if ((local_108 != ~DIRECTION_UP) && (i3 == count)) break; DVar5 = i3 % count; if (local_80[DVar5] != 0) { if (i3 < count) { lVar9 = __ftol((float10)directions[DVar5].y); by_00 = (uint)lVar9; lVar9 = __ftol((float10)directions[DVar5].x); BVar3 = Level_Block_IsWall((uint)lVar9,by_00); if (BVar3 != 0) goto LAB_0044704f; } if (local_20[DVar5] < local_f8) { local_108 = DVar5; local_f8 = local_20[DVar5]; } } LAB_0044704f: i3 += DIRECTION_RIGHT; } while (i3 < count * 2); } if (local_108 != ~DIRECTION_UP) { BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj,local_20[local_108],local_40[local_108],local_60[local_108],NULL); if (BVar3 == 0) { result = FALSE; } else { if (optout_direction != NULL) { *optout_direction = local_108; } result = TRUE; } } i4 = 0; if (count != DIRECTION_UP) { ppiVar6 = local_60; do { if (local_80[i4] != 0) { io::Mem_Free(local_40[i4]); io::Mem_Free(*ppiVar6); } i4 += DIRECTION_RIGHT; ppiVar6 = ppiVar6 + 1; } while (i4 < count); } return result; } BOOL __cdecl lego::game::LegoObject_RouteToDig_FUN_00447100(LegoObject *liveObj,uint bx,uint by,BOOL tunnelDig) { uint uVar1; float fVar2; BOOL BVar3; float10 fVar4; Direction direction; Point2I DIRECTIONS [4]; int INDEXES [8]; Point2F BLOCK_OFFSETS [8]; LiveFlags3 lflags3; RoutingBlock *routeBlock; // Note that direction is a value between 0-7, because True is passed to the output // function. BVar3 = LiveObject_BlockCheck_FUN_004326a0(liveObj,bx,by,tunnelDig,TRUE); if (BVar3 != 0) { BVar3 = LegoObject_BlockRoute_FUN_00446c80(liveObj,bx,by,tunnelDig,&direction,TRUE); if (BVar3 != 0) { if (tunnelDig != 0) { INDEXES[0] = 0; INDEXES[1] = 1; INDEXES[2] = 1; INDEXES[7] = 0; INDEXES[3] = 2; INDEXES[4] = 2; DIRECTIONS[1].x = 0; INDEXES[5] = 3; INDEXES[6] = 3; DIRECTIONS[2].x = 0; DIRECTIONS[0].x = -1; DIRECTIONS[0].y = -1; DIRECTIONS[1].y = -1; DIRECTIONS[3].x = -1; DIRECTIONS[2].y = 0; DIRECTIONS[3].y = 0; BLOCK_OFFSETS[0].x = 0.9; BLOCK_OFFSETS[0].y = 0.5; BLOCK_OFFSETS[1].x = 0.1; BLOCK_OFFSETS[1].y = 0.5; BLOCK_OFFSETS[2].x = 0.5; BLOCK_OFFSETS[2].y = 0.1; BLOCK_OFFSETS[3].x = 0.5; BLOCK_OFFSETS[3].y = 0.9; BLOCK_OFFSETS[4].x = 0.1; BLOCK_OFFSETS[4].y = 0.5; BLOCK_OFFSETS[5].x = 0.9; BLOCK_OFFSETS[5].y = 0.5; BLOCK_OFFSETS[6].x = 0.5; BLOCK_OFFSETS[6].y = 0.9; BLOCK_OFFSETS[7].x = 0.5; BLOCK_OFFSETS[7].y = 0.1; LegoObject_RoutingPtr_Realloc_FUN_00446b80 (liveObj,DIRECTIONS[INDEXES[direction]].x + bx, DIRECTIONS[INDEXES[direction]].y + by); uVar1 = liveObj->routeBlocksTotal; routeBlock = liveObj->routeBlocks; fVar2 = BLOCK_OFFSETS[direction].y; routeBlock[uVar1 - 1].blockOffset.x = BLOCK_OFFSETS[direction].x; routeBlock[uVar1 - 1].blockOffset.y = fVar2; lflags3 = liveObj->flags3; (liveObj->targetBlockPos).x = (float)(ulonglong)bx; liveObj->flags3 = lflags3 | LIVEOBJ3_UNK_2000000; (liveObj->targetBlockPos).y = (float)(ulonglong)by; return TRUE; } LegoObject_RoutingPtr_Realloc_FUN_00446b80(liveObj,bx,by); fVar4 = math::Maths_RandRange(0.3,0.7); liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].blockOffset.x = (float)fVar4; fVar4 = math::Maths_RandRange(0.3,0.7); liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].blockOffset.y = (float)fVar4; lflags3 = liveObj->flags3; (liveObj->targetBlockPos).x = (float)(ulonglong)bx; // & ~LIVEOBJ3_UNK_2000000 (0x2000000) liveObj->flags3 = lflags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP| LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400| LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000| LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); (liveObj->targetBlockPos).y = (float)(ulonglong)by; return TRUE; } } return 0; } BOOL __cdecl lego::game::LegoObject_PTL_GatherRock(LegoObject *liveObj) { BOOL BVar1; LegoObject *rockObj; Container_Texture *contTexture; float10 fVar2; Point2I point; if ((liveObj->flags3 & LIVEOBJ3_CANGATHER) != LIVEOBJ3_NONE) { fVar2 = stats::StatsObject_GetCarryMinHealth(liveObj); if (fVar2 < (float10)liveObj->health) { BVar1 = LegoObject_FindNearestWall(liveObj,&point.x,&point.y,TRUE,FALSE,FALSE); if (BVar1 != 0) { rockObj = LegoObject_Create((int **)globs::legoGlobs.contBoulder,LegoObject_Boulder,0); LegoObject_SetPositionAndHeading(rockObj,10000.0,10000.0,0.0,TRUE); LegoObject_Hide(rockObj,TRUE); BVar1 = LegoObject_RoutingNoCarry_FUN_00447470(liveObj,point.x,point.y,rockObj); if (BVar1 != 0) { contTexture = lrr::Lego_GetBlockDetail_ContainerTexture(&point); LegoObject_InitBoulderMesh_FUN_00440eb0(rockObj,contTexture); liveObj->carryRestTimer_33c = 0.0; return TRUE; } LegoObject_DestroyBoulder_AndCreateExplode(rockObj); } } } return FALSE; } BOOL __cdecl lego::game::LegoObject_RoutingNoCarry_FUN_00447470 (LegoObject *liveObj,uint bx,uint by,LegoObject *boulderObj) { BOOL BVar1; if ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { BVar1 = LegoObject_RouteToFaceBlock(liveObj,bx,by,4.0); if (BVar1 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_GATHERROCK; liveObj->routeToObject = boulderObj; boulderObj->interactObject = liveObj; return TRUE; } } return FALSE; } BOOL __cdecl lego::game::LegoObject_PTL_AttackBuilding(LegoObject *liveObj1,LegoObject *targetObj) { short sVar1; short sVar2; uint uVar3; BOOL BVar4; int iVar5; uint uVar6; uint j; uint uVar7; uint i; Point2I offsetBlockPos; Point2I blockPos; Point2I OFFSETS [12]; if (liveObj1->type == LegoObject_RockMonster) { if (targetObj != NULL) { OFFSETS[0].x = 2; OFFSETS[0].y = 0; OFFSETS[1].x = 0; OFFSETS[1].y = 2; OFFSETS[2].x = -2; OFFSETS[2].y = 0; OFFSETS[3].x = 0; OFFSETS[3].y = -2; OFFSETS[4].x = 2; OFFSETS[4].y = -1; OFFSETS[5].x = 2; OFFSETS[5].y = 1; OFFSETS[6].x = 1; OFFSETS[6].y = 2; OFFSETS[7].x = -1; OFFSETS[7].y = 2; OFFSETS[8].x = -2; OFFSETS[8].y = 1; OFFSETS[9].x = -2; OFFSETS[9].y = -1; OFFSETS[10].x = -1; OFFSETS[10].y = -2; OFFSETS[11].x = 1; OFFSETS[11].y = -2; sVar1 = math::Maths_Rand(); sVar2 = math::Maths_Rand(); uVar6 = (int)sVar2 >> 0x1f; LegoObject_GetBlockPos(targetObj,&blockPos.x,&blockPos.y); i = 0; do { j = 0; uVar7 = (int)sVar1 % 0xc; do { uVar3 = uVar7; if ((((int)sVar2 ^ uVar6) - uVar6 & 1 ^ uVar6) - uVar6 == 1) { uVar3 = 0x18 - uVar7; } offsetBlockPos.x = OFFSETS[uVar3 % 0xc].x + blockPos.x; offsetBlockPos.y = OFFSETS[uVar3 % 0xc].y + blockPos.y; if (((i == 1) || (BVar4 = Level_Block_IsFoundationOrBusyFloor(&offsetBlockPos), BVar4 == 0)) && (iVar5 = LegoObject_FUN_00447670(liveObj1,offsetBlockPos.x,offsetBlockPos.y,targetObj), iVar5 != 0)) { return 1; } j += 1; uVar7 += 1; } while (j < 0xc); i += 1; if (1 < i) { return 0; } } while( true ); } LegoObject_DropCarriedObject(liveObj1,0); } return 0; } int __cdecl lego::game::LegoObject_FUN_00447670(LegoObject *in_liveObj,int bx,int by,LegoObject *liveObj2) { LegoObject *liveObj; int bx2; int by2; BOOL BVar1; BOOL BVar2; int *local_10; int local_c; int *local_8; uint local_4; liveObj = in_liveObj; BVar2 = 0; if ((in_liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { BVar1 = LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(in_liveObj); if (BVar1 == 0) { LegoObject_GetBlockPos(liveObj2,&local_c,(int *)&local_8); by2 = by; bx2 = bx; if ((local_c != bx) || (local_8 != (int *)by)) { LegoObject_GetBlockPos(liveObj,&bx,(int *)&in_liveObj); if ((bx == bx2) && (in_liveObj == (LegoObject *)by2)) { BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,1,&bx,(int *)&in_liveObj,NULL); } else { BVar2 = LegoObject_Route_Score_FUN_004413b0 (liveObj,bx,(uint)in_liveObj,bx2,by2,(int **)&by,&local_10, (int *)&local_4,0,NULL); if (BVar2 == 0) { return 0; } BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,local_4,(int *)by,local_10,NULL); io::Mem_Free((void *)by); io::Mem_Free(local_10); } if (BVar2 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UNK_5; liveObj->carriedObjects[0]->routeToObject = liveObj2; return BVar2; } } } } return BVar2; } void __cdecl lego::game::LegoObject_FUN_004477b0(LegoObject *liveObj) { float fVar1; float fVar2; float10 fVar3; float10 fVar4; Point2F local_18; Point2F local_10; Point2F local_8; LegoObject *liveObj_00; liveObj_00 = liveObj->routeToObject; liveObj->routeToObject = NULL; if (liveObj_00 != NULL) { LegoObject_GetPosition(liveObj_00,&local_10.x,&local_10.y); LegoObject_GetPosition(liveObj,&local_8.x,&local_8.y); local_18.x = local_10.x - local_8.x; local_18.y = local_10.y - local_8.y; fVar2 = local_18.x * local_18.x; fVar1 = local_18.y * local_18.y; fVar3 = stats::StatsObject_GetCollRadius(liveObj_00); fVar4 = stats::StatsObject_GetCollRadius(liveObj); if ((float10)SQRT(fVar1 + fVar2) < fVar4 + fVar4 + (float10)(float)fVar3) { LegoObject_Hit(liveObj_00,&local_18,TRUE); LegoObject_AddDamage2(liveObj_00,10.0,TRUE,1.0); } } return; } int __cdecl lego::game::LegoObject_FUN_00447880(LegoObject *in_liveObj) { LegoObject *opt_liveObj; StatsFlags2 sflags2; BOOL BVar1; int iVar2; float10 fVar3; iVar2 = 0; opt_liveObj = in_liveObj->routeToObject; if ((opt_liveObj != NULL) && ((opt_liveObj->flags2 & LIVEOBJ2_UNK_100000) == LIVEOBJ2_NONE)) { sflags2 = stats::StatsObject_GetStatsFlags2(in_liveObj); if ((sflags2 & STATS2_DRAINPOWER) == STATS2_NONE) { if ((in_liveObj->flags4 & LIVEOBJ4_UNK_400000) == LIVEOBJ4_NONE) { if (in_liveObj->type == LegoObject_RockMonster) { front::Info_Send(Info_UnderAttack,NULL,opt_liveObj,NULL); } fVar3 = stats::StatsObject_GetRepairValue(in_liveObj); if ((float10)0.0 <= fVar3) { opt_liveObj->health = (float)(fVar3 + (float10)opt_liveObj->health); } else { LegoObject_AddDamage2(opt_liveObj,(float)-fVar3,TRUE,1.0); opt_liveObj->flags2 = opt_liveObj->flags2 | LIVEOBJ2_DAMAGESHAKING; } if (opt_liveObj->health < 100.0) { ai::AITask_DoRepair_Target(opt_liveObj,FALSE); } else { opt_liveObj->health = (float)&DAT_42c80000; iVar2 = TRUE; } } else { LegoObject_UpgradeBuilding(opt_liveObj); in_liveObj->flags4 = in_liveObj->flags4 & ~LIVEOBJ4_UNK_400000; } } else { BVar1 = LegoObject_IsActive(opt_liveObj,FALSE); if (BVar1 == 0) { return TRUE; } if (globs::legoGlobs.DrainTime <= in_liveObj->elapsedTime2) { LegoObject_Weapon_FUN_004375c0(in_liveObj,-1,1.0); in_liveObj->elapsedTime2 = 0.0; } } if ((ushort)((ushort)(opt_liveObj->health < 0.0) << 8 | (ushort)(opt_liveObj->health == 0.0) << 0xe) == 0) goto LAB_004479d1; } iVar2 = TRUE; LAB_004479d1: if (iVar2 != 0) { in_liveObj->routeToObject = NULL; } return iVar2; } BOOL __cdecl lego::game::LegoObject_Add25EnergyAndSetHealth(LegoObject *liveObj) { float newEnergy; newEnergy = liveObj->energy - -25.0; liveObj->routeToObject = NULL; liveObj->energy = newEnergy; if ((ushort)((ushort)(newEnergy < liveObj->health) << 8 | (ushort)(newEnergy == liveObj->health) << 0xe) == 0) { liveObj->energy = liveObj->health; return TRUE; } return 0; } void __cdecl lego::game::LegoObject_FUN_00447a40(LegoObject *liveObj) { LegoObject *liveObj2; if ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) { liveObj2 = liveObj->carriedObjects[0]; // & ~LIVEOBJ1_CARRYING (0x400) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); liveObj->numCarriedObjects = 0; liveObj->carriedObjects[0] = NULL; liveObj2->flags3 = liveObj2->flags3 | LIVEOBJ3_UNK_2000; ai::AITask_LiveObject_SetAITaskUnk(liveObj,AITask_Type_Gather,liveObj2,TRUE); } return; } void __cdecl lego::game::LegoObject_Routing_FUN_00447a90(LegoObject *liveObj) { LegoObject *pLVar1; RoutingBlock *pRVar2; float fVar3; float fVar4; float fVar5; Map3D *map; uint bx; uint uVar6; Point2F *wPos2D; Point2F *pPVar7; Point2F *optout_blockPosf; float *out_y; Point2F local_20; float local_14; float local_10; float local_c; Point2F local_8; pLVar1 = liveObj->carriedObjects[0]->routeToObject; out_y = &local_20.y; pPVar7 = &local_20; uVar6 = (liveObj->routeBlocks + liveObj->routeBlocksTotal)[-1].blockPos.y; bx = (liveObj->routeBlocks + liveObj->routeBlocksTotal)[-1].blockPos.x; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,uVar6,&pPVar7->x,out_y); LegoObject_GetPosition(pLVar1,&local_10,&local_c); fVar3 = local_10 - local_20.x; fVar5 = local_c - local_20.y; pPVar7 = &local_8; wPos2D = &local_20; optout_blockPosf = NULL; fVar4 = 1.0 / SQRT(fVar5 * fVar5 + fVar3 * fVar3); local_14 = fVar4 * fVar5 * 0.1; local_20.x = fVar4 * fVar3 * 0.1 + local_20.x; local_20.y = local_14 + local_20.y; map = lrr::Lego_GetMap(); lego::map::Map3D_FUN_0044fb30(map,wPos2D,optout_blockPosf,pPVar7); uVar6 = liveObj->routeBlocksTotal; pRVar2 = liveObj->routeBlocks; pRVar2[uVar6 - 1].blockOffset.x = local_8.x; pRVar2[uVar6 - 1].blockOffset.y = local_8.y; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte = liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_UNK_8; pLVar1 = liveObj->carriedObjects[0]; (pLVar1->targetBlockPos).x = local_10; (pLVar1->targetBlockPos).y = local_c; liveObj->carriedObjects[0]->routeToObject = NULL; return; } void __cdecl lego::game::LegoObject_DoBuildingsCallback_AttackByBoulder(LegoObject *liveObj) { if (liveObj->type == LegoObject_Building) { LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_CallbackBoulderAttackBuilding_FUN_00447be0,liveObj); } return; } BOOL __cdecl lego::game::LegoObject_CallbackBoulderAttackBuilding_FUN_00447be0 (LegoObject *liveObj,LegoObject *buildingLiveObj) { if (((liveObj->type == LegoObject_Boulder) && (liveObj->routeToObject == buildingLiveObj)) && (liveObj->carryingThisObject != NULL)) { LegoObject_Route_End(liveObj->carryingThisObject,FALSE); } return 0; } void __cdecl lego::game::LegoObject_Hit(LegoObject *liveObj,Point2F *opt_dir,BOOL reactToHit) { float fVar1; float fVar2; float fVar3; float fVar4; BOOL BVar5; Activity_Type activityType; float10 fVar6; if (((*(byte *)&liveObj->flags2 & LIVEOBJ2_THROWN) != 0) && (liveObj->throwObject != NULL)) { liveObj = liveObj->throwObject; } if ((liveObj->flags1 & LIVEOBJ1_GETTINGHIT) == LIVEOBJ1_NONE) { BVar5 = LegoObject_IsActive(liveObj,TRUE); if (BVar5 != 0) { if (opt_dir == NULL) { // activityType = (param_3 ? Activity_HitHard : Activity_Stamp); activityType = (-(uint)(reactToHit != 0) & 0xfffffff7) + Activity_Stamp; } else { fVar1 = (liveObj->faceDirection).x; fVar2 = (liveObj->faceDirection).y; // M_PI / 4.0f fVar6 = (float10)fcos((float10)0.7853981852531433); fVar3 = 1.0 / SQRT(fVar2 * fVar2 + fVar1 * fVar1); fVar1 = fVar3 * fVar1; fVar3 = fVar3 * fVar2; fVar4 = 1.0 - (float)fVar6; fVar2 = fVar3 * opt_dir->y + fVar1 * opt_dir->x; if ((ushort)((ushort)(fVar2 < fVar4) << 8 | (ushort)(fVar2 == fVar4) << 0xe) == 0) { activityType = Activity_HitBack; } else { if (-fVar4 <= fVar2) { fVar1 = fVar3 * opt_dir->x - fVar1 * opt_dir->y; if ((ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) == 0) { activityType = Activity_HitRight; } else { activityType = Activity_HitLeft; } } else { activityType = Activity_HitFront; } } } LegoObject_Interrupt(liveObj,FALSE,TRUE); LegoObject_SetActivity(liveObj,activityType,1); BVar5 = LegoObject_UpdateActivityChange(liveObj); if (BVar5 == 0) { LegoObject_SetActivity(liveObj,Activity_Stand,1); LegoObject_UpdateActivityChange(liveObj); } LegoObject_MoveAnimation(liveObj,1.0); liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_GETTINGHIT; if (liveObj->type == LegoObject_RockMonster) { // Wake up Rock monsters after getting damaged. // & ~LIVEOBJ3_POWEROFF (0x80000000) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000); } } } return; } void __cdecl lego::game::LegoObject_TeleportDownBuilding(LegoObject *liveObj) { LegoObject_SetActivity(liveObj,Activity_Teleport,0); LegoObject_UpdateActivityChange(liveObj); liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_TELEPORTINGDOWN; return; } float10 __cdecl lego::game::LegoObject_MoveAnimation(LegoObject *liveObj,float elapsed) { float elapsed_00; float10 animTime; LegoObject *liveObj_00; LegoObject_Type objType; elapsed_00 = elapsed; liveObj_00 = liveObj; LegoObject_CalculateSpeeds(liveObj,elapsed,(float *)&liveObj,&elapsed); if ((liveObj_00->flags1 & LIVEOBJ1_UNK_4000) != LIVEOBJ1_NONE) goto LAB_00447ed1; objType = liveObj_00->type; if (objType == LegoObject_Vehicle) { animTime = gfx::Vehicle_MoveAnimation (liveObj_00->vehicle,elapsed,elapsed_00,liveObj_00->animRepeat); } else { if (objType == LegoObject_MiniFigure) { animTime = gfx::Creature_MoveAnimation(liveObj_00->miniFigure,elapsed,liveObj_00->animRepeat); } else { if (objType == LegoObject_RockMonster) { animTime = gfx::Creature_MoveAnimation (liveObj_00->rockMonster,elapsed,liveObj_00->animRepeat); } else { if (objType == LegoObject_Building) { animTime = gfx::Building_MoveAnimation (liveObj_00->building,elapsed,liveObj_00->animRepeat); } else { if ((liveObj_00->flags3 & LIVEOBJ3_SIMPLEOBJECT) != LIVEOBJ3_NONE) { LegoObject_SimpleObject_MoveAnimation(liveObj_00,elapsed_00); goto LAB_00447ed1; } if (objType != LegoObject_UpgradePart) goto LAB_00447ed1; animTime = gfx::Upgrade_Part_MoveAnimation (liveObj_00->upgradePart,elapsed,liveObj_00->animRepeat); } } } } liveObj_00->animTime = (float)animTime; LAB_00447ed1: // if (animTime > 0.0f) if ((ushort)((ushort)(liveObj_00->animTime < 0.0) << 8 | (ushort)(liveObj_00->animTime == 0.0) << 0xe) == 0) { ai::AITask_LiveObject_Unk_UpdateAITask_AnimationWait(liveObj_00); } return (float10)elapsed; } BOOL __cdecl lego::game::LegoObject_UpdateActivityChange(LegoObject *liveObj) { StatsFlags1 sflags1; int cmp; char *pcVar1; Container *camCont; BOOL success; char *pcVar2; char actBuff [256]; char *actName; success = 0; actName = liveObj->activityName1; if (actName == liveObj->activityName2) { return 0; } if ((((actName != globs::objectGlobs.activityName[0]) && (actName != globs::objectGlobs.activityName[1])) && (actName != globs::objectGlobs.activityName[4])) && (((actName != globs::objectGlobs.activityName[6] && (actName != globs::objectGlobs.activityName[8])) && ((actName != globs::objectGlobs.activityName[17] && ((actName != globs::objectGlobs.activityName[22] && (actName != globs::objectGlobs.activityName[2])))))))) { ai::AITask_DoAnimationWait(liveObj); } switch(liveObj->type) { case LegoObject_Vehicle: success = gfx::Vehicle_SetActivity(liveObj->vehicle,liveObj->activityName1,liveObj->animTime); camCont = gfx::Vehicle_GetCameraNull(liveObj->vehicle,liveObj->cameraFrame); break; case LegoObject_MiniFigure: success = gfx::Creature_SetActivity (liveObj->miniFigure,liveObj->activityName1,liveObj->animTime); camCont = gfx::Creature_GetCameraNull(liveObj->miniFigure,liveObj->cameraFrame); break; case LegoObject_RockMonster: success = gfx::Creature_SetActivity (liveObj->rockMonster,liveObj->activityName1,liveObj->animTime); camCont = gfx::Creature_GetCameraNull(liveObj->rockMonster,liveObj->cameraFrame); break; case LegoObject_Building: success = gfx::Building_SetActivity(liveObj->building,liveObj->activityName1,liveObj->animTime); camCont = gfx::Building_GetCameraNull(liveObj->building,liveObj->cameraFrame); break; default: goto switchD_00447f7d_caseD_4; } liveObj->cameraNull = camCont; switchD_00447f7d_caseD_4: sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((((sflags1 & STATS1_CANBEDRIVEN) != STATS1_NONE) && (liveObj->driveObject != NULL)) && (liveObj->driveObject->type == LegoObject_MiniFigure)) { cmp = std::_stricmp(globs::objectGlobs.activityName[1],liveObj->activityName1); pcVar2 = "Activity_"; if (cmp != 0) { pcVar2 = liveObj->activityName1; } pcVar1 = Object_GetTypeName(liveObj->type,liveObj->id); std::sprintf(actBuff,"%s%s",pcVar2,pcVar1); gfx::Creature_SetActivity(liveObj->driveObject->miniFigure,actBuff,0.0); camCont = gfx::Creature_GetCameraNull (liveObj->driveObject->miniFigure,liveObj->driveObject->cameraFrame); liveObj->driveObject->cameraNull = camCont; liveObj->driveObject->activityName1 = liveObj->driveObject->activityName2; } liveObj->animTime = 0.0; liveObj->activityName2 = liveObj->activityName1; // liveObj->flags2 &= ~LIVEOBJ2_UNK_20000; liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); return success; } void __cdecl lego::game::LegoObject_SimpleObject_MoveAnimation(LegoObject *in_liveObj,float elapsed) { LegoObject *liveObj; Map3D *map; LegoObject *pLVar1; uint uVar2; LiveFlags1 lflags1; uint by; Lego_Level *level; int by_00; int bx; LiveFlags3 lflags3; float10 fVar3; float10 fVar4; float10 fVar5; longlong lVar6; float fVar7; BOOL BVar8; Point2I *out_bx; float fVar9; float *out_x; Container *cont; int *out_by; Point2F *dir; float *out_y; char *pcVar10; float local_4c; float local_48; Point2I local_44; Point2I local_3c; Point2F local_34; Point2F local_2c; Vector3F local_24; float local_18; float local_14; float local_10; Vector3F local_c; LegoObject_Type objType; LiveFlags2 *pLFlags2; liveObj = in_liveObj; objType = in_liveObj->type; if (objType == LegoObject_Boulder) { if ((in_liveObj->flags3 & LIVEOBJ3_UNK_2000) != LIVEOBJ3_NONE) { gfx::Container_GetPosition(in_liveObj->other,NULL,&local_c); fVar9 = (liveObj->targetBlockPos).y; fVar7 = (liveObj->targetBlockPos).x; local_24.z = 0.0; local_24.x = fVar7; local_24.y = fVar9; map = lrr::Lego_GetMap(); fVar3 = lego::map::Map3D_GetWorldZ(map,fVar7,fVar9); in_liveObj = (LegoObject *)(float)fVar3; fVar4 = stats::StatsObject_GetCollRadius(liveObj); fVar3 = (float10)(float)in_liveObj; fVar5 = (fVar3 - fVar4) - (float10)local_c.z; fVar9 = (float)((float10)local_24.x - (float10)local_c.x); fVar7 = (float)((float10)local_24.y - (float10)local_c.y); local_10 = (float)fVar5; in_liveObj = (LegoObject *)(elapsed * 3.5); local_4c = (float)SQRT(fVar5 * (float10)local_10 + ((float10)local_24.y - (float10)local_c.y) * (float10)fVar7 + ((float10)local_24.x - (float10)local_c.x) * (float10)fVar9); elapsed = 1.0 / local_4c; local_18 = elapsed * fVar9 * (float)in_liveObj; local_c.x = local_18 + local_c.x; local_14 = elapsed * fVar7 * (float)in_liveObj; local_c.y = local_14 + local_c.y; local_c.z = elapsed * local_10 * (float)in_liveObj + local_c.z; fVar9 = local_c.x; fVar7 = local_c.y; local_24.z = local_c.z; if (local_4c < (float)in_liveObj) { liveObj->carryingThisObject = NULL; liveObj->health = -1.0; // & ~LIVEOBJ3_UNK_2000 (0x2000) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF) | LIVEOBJ3_REMOVING; fVar9 = local_24.x; fVar7 = local_24.y; local_24.z = (float)(fVar3 - fVar4); } local_24.y = fVar7; local_24.x = fVar9; local_34.x = local_24.x; out_by = &local_3c.y; out_bx = &local_3c; local_34.y = local_24.y; fVar9 = local_24.x; fVar7 = local_24.y; local_44.x = (int)in_liveObj; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar9,fVar7,&out_bx->x,out_by); fVar9 = local_24.x; fVar7 = local_24.y; map = lrr::Lego_GetMap(); fVar3 = lego::map::Map3D_GetWorldZ(map,fVar9,fVar7); elapsed = (float)(fVar3 - (float10)local_24.z); pLVar1 = LegoObject_DoCollisionCallbacks_FUN_00446030(liveObj,&local_34,elapsed,TRUE); if (pLVar1 != NULL) { liveObj->carryingThisObject = NULL; // & ~LIVEOBJ3_UNK_2000 (0x2000) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000| LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); dir = &local_2c; fVar9 = 0.0; BVar8 = TRUE; local_2c.y = 1.0 / SQRT(local_14 * local_14 + local_18 * local_18); local_2c.x = local_2c.y * local_18; local_2c.y = local_2c.y * local_14; uVar2 = tools::Weapon_GetWeaponIDByName("Boulder"); tools::Weapon_GenericDamageObject(pLVar1,uVar2,BVar8,fVar9,dir); liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_REMOVING; liveObj->health = -1.0; snd::SFX_Random_PlaySound3DOnContainer(NULL,SFX_BoulderHit,FALSE,FALSE,&local_24); } gfx::Container_SetPosition(liveObj->other,NULL,local_24.x,local_24.y,local_24.z); return; } } else { if (objType == LegoObject_PowerCrystal) { if (in_liveObj->carryingThisObject == NULL) { gfx::Container_AddRotation (in_liveObj->other,Container_Combine_Before,0.0,1.0,0.0,elapsed * 0.01); return; } } else { if ((objType == LegoObject_Dynamite) || (objType == LegoObject_OohScary)) { if ((in_liveObj->flags3 & LIVEOBJ3_UNK_10000) == LIVEOBJ3_NONE) { if ((in_liveObj->flags1 & LIVEOBJ1_PLACING) != LIVEOBJ1_NONE) { // & ~LIVEOBJ1_PLACING (0x80000) in_liveObj->flags1 = in_liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_CRUMBLING |LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); in_liveObj->flags3 = in_liveObj->flags3 | LIVEOBJ3_UNK_10000; gfx::Container_SetActivity(in_liveObj->other,"TickDown"); gfx::Container_SetAnimationTime(liveObj->other,0.0); LegoObject_GetBlockPos(liveObj,&local_44.x,&local_44.y); Level_Block_SetBusyFloor(&local_44,TRUE); front::Info_Send(Info_DynamitePlaced,NULL,liveObj,NULL); lVar6 = __ftol((float10)(liveObj->targetBlockPos).y); by_00 = (int)lVar6; lVar6 = __ftol((float10)(liveObj->targetBlockPos).x); bx = (int)lVar6; map = lrr::Lego_GetMap(); lego::map::Map3D_ClearBlockHighlight(map,bx,by_00); return; } gfx::Container_MoveAnimation(in_liveObj->other,elapsed); } else { if (((ushort)((ushort)(in_liveObj->health < 0.0) << 8 | (ushort)(in_liveObj->health == 0.0) << 0xe) != 0) || (fVar3 = gfx::Container_MoveAnimation(in_liveObj->other,elapsed), fVar3 != (float10)0.0 )) { lVar6 = __ftol((float10)(liveObj->targetBlockPos).x); uVar2 = (uint)lVar6; local_3c.x = uVar2; lVar6 = __ftol((float10)(liveObj->targetBlockPos).y); by = (uint)lVar6; local_3c.y = by; if ((uVar2 != 0) && (by != 0)) { BVar8 = 0; level = lrr::Lego_GetLevel(); Level_DestroyWall(level,uVar2,by,BVar8); } if (liveObj->type == LegoObject_Dynamite) { LegoObject_GetBlockPos(liveObj,&local_3c.x,&local_3c.y); Level_Block_SetBusyFloor(&local_3c,FALSE); LegoObject_DoDynamiteExplosionRadiusCallbacks (liveObj,globs::legoGlobs.DynamiteDamageRadius, globs::legoGlobs.DynamiteMaxDamage,globs::legoGlobs.DynamiteWakeRadius); snd::SFX_Random_PlaySoundNormal(SFX_Dynamite,FALSE); effect::Effect_Spawn_Explosion(liveObj,NULL); lego::view::Camera_Shake(globs::legoGlobs.cameraMain,5.0,50.0); } else { if (liveObj->type == LegoObject_OohScary) { LegoObject_GetPosition(liveObj,&local_c.x,&local_c.y); LegoObject_GetBlockPos(liveObj,&local_44.x,&local_44.y); map = lrr::Lego_GetMap(); fVar3 = lego::map::Map3D_GetWorldZ(map,local_c.x,local_c.y); local_c.z = (float)fVar3; effect::Effect_Spawn_Particle(MISCOBJECT_BIRDSCARER,&local_c,NULL); // 2.0f, 100.0f lego::view::Camera_Shake(globs::legoGlobs.cameraMain,2.0,(float)&DAT_42c80000); Level_Block_SetBusyFloor(&local_44,FALSE); } } liveObj->health = -1.0; liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_REMOVING; return; } } } else { if (objType == LegoObject_ElectricFence) { if ((in_liveObj->flags1 & LIVEOBJ1_PLACING) != LIVEOBJ1_NONE) { // & ~LIVEOBJ1_PLACING (0x80000) in_liveObj->flags1 = in_liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_CRUMBLING |LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); ElectricFence_CreateFence(in_liveObj); LegoObject_GetBlockPos(liveObj,&local_44.x,(int *)&in_liveObj); out_y = &local_48; out_x = &local_4c; uVar2 = local_44.x; pLVar1 = in_liveObj; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,uVar2,(uint)pLVar1,out_x,out_y); fVar3 = LegoObject_GetHeading(liveObj); BVar8 = 1; elapsed = (float)(fVar3 - (float10)-0.7853982); fVar3 = std::fmod((float10)elapsed,(float10)1.570796370506287); LegoObject_SetPositionAndHeading (liveObj,local_4c,local_48,(float)((float10)elapsed - fVar3),BVar8); Level_Block_SetFenceRequest(local_44.x,(int)in_liveObj,FALSE); return; } } else { if (objType == LegoObject_Barrier) { fVar3 = gfx::Container_MoveAnimation(in_liveObj->other,elapsed); if (fVar3 == (float10)0.0) { return; } lflags1 = liveObj->flags1; if ((lflags1 & LIVEOBJ1_PLACING) != LIVEOBJ1_NONE) { pcVar10 = "Expand"; // & ~LIVEOBJ1_PLACING (0x80000) | LIVEOBJ1_EXPANDING liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000 |LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO) | LIVEOBJ1_EXPANDING; goto LAB_0044872d; } if ((lflags1 & LIVEOBJ1_EXPANDING) != LIVEOBJ1_NONE) { // & ~LIVEOBJ1_EXPANDING (0x100) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING| LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000| LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_UNK_10000; pcVar10 = "Long"; goto LAB_00448783; } lflags3 = liveObj->flags3; if ((lflags3 & LIVEOBJ3_REMOVING) != LIVEOBJ3_NONE) { liveObj->health = (float)&DAT_42c80000; // & ~LIVEOBJ3_REMOVING (0x800000) liveObj->flags3 = lflags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP| LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200| LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE| LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED| LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000| LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000| LIVEOBJ3_POWEROFF); liveObj->flags1 = lflags1 | LIVEOBJ1_TELEPORTINGDOWN; gfx::Container_SetActivity(liveObj->other,"Teleport"); gfx::Container_SetAnimationTime(liveObj->other,0.0); return; } } else { if (objType != LegoObject_SpiderWeb) { if (objType != LegoObject_IceCube) { if ((((objType != LegoObject_ElectricFenceStud) && (objType != LegoObject_Pusher)) && (objType != LegoObject_Freezer)) && (objType != LegoObject_LaserShot)) { return; } gfx::Container_MoveAnimation(in_liveObj->other,elapsed); return; } fVar3 = gfx::Container_MoveAnimation(in_liveObj->other,elapsed); if (fVar3 == (float10)0.0) { return; } lflags1 = liveObj->flags1; if ((lflags1 & LIVEOBJ1_EXPANDING) == LIVEOBJ1_NONE) { lflags3 = liveObj->flags3; if ((lflags3 & LIVEOBJ3_REMOVING) == LIVEOBJ3_NONE) { if ((lflags1 & LIVEOBJ1_TELEPORTINGDOWN) == LIVEOBJ1_NONE) { return; } // flags1 &= ~LIVEOBJ1_TELEPORTINGDOWN; liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING| LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20| LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE| LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); liveObj->health = -1.0; liveObj->flags3 = lflags3 | LIVEOBJ3_REMOVING; pLFlags2 = &liveObj->freezeObject->flags2; // flags2 &= ~LIVEOBJ2_FROZEN; *pLFlags2 = *pLFlags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING| LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80| LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_PUSHED|LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK| LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000|LIVEOBJ2_UNK_80000| LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER| LIVEOBJ2_ACTIVEELECTRICFENCE|LIVEOBJ2_UNK_4000000|LIVEOBJ2_RECHARGING |LIVEOBJ2_UNK_20000000|LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); return; } // health = 100.0f; liveObj->health = (float)&DAT_42c80000; // & ~LIVEOBJ3_REMOVING (0x800000) liveObj->flags3 = lflags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE| LIVEOBJ3_CANTURN|LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY| LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT| LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000| LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT| LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_UNK_1000000| LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000 |LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000| LIVEOBJ3_POWEROFF); liveObj->flags1 = lflags1 | LIVEOBJ1_TELEPORTINGDOWN; pcVar10 = "Melt"; LAB_00448783: gfx::Container_SetActivity(liveObj->other,pcVar10); gfx::Container_SetAnimationTime(liveObj->other,0.0); return; } // & ~LIVEOBJ1_EXPANDING (0x100) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING| LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000| LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_UNK_10000; pcVar10 = "Normal"; LAB_0044872d: gfx::Container_SetActivity(liveObj->other,pcVar10); gfx::Container_SetAnimationTime(liveObj->other,0.0); return; } if (((in_liveObj->flags1 & LIVEOBJ1_CAUGHTINWEB) == LIVEOBJ1_NONE) || ((in_liveObj->flags1 & LIVEOBJ1_EXPANDING) != LIVEOBJ1_NONE)) { cont = in_liveObj->other; fVar9 = elapsed; } else { cont = in_liveObj->other; fVar9 = 0.0; } fVar3 = gfx::Container_MoveAnimation(cont,fVar9); if (fVar3 == (float10)0.0) { return; } lflags1 = liveObj->flags1; if ((lflags1 & LIVEOBJ1_EXPANDING) != LIVEOBJ1_NONE) { // & ~LIVEOBJ1_EXPANDING (0x100) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING| LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000| LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_UNK_10000; pcVar10 = "FlapInWind"; goto LAB_0044872d; } lflags3 = liveObj->flags3; if ((lflags3 & LIVEOBJ3_REMOVING) != LIVEOBJ3_NONE) { liveObj->health = (float)&DAT_42c80000; // & ~LIVEOBJ3_REMOVING (0x800000) liveObj->flags3 = lflags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP| LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200| LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE| LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE| LIVEOBJ3_UPGRADEPART|LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_SELECTED| LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000| LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000| LIVEOBJ3_POWEROFF); liveObj->flags1 = lflags1 | LIVEOBJ1_TELEPORTINGDOWN; pcVar10 = "Disintegrate"; goto LAB_00448783; } } if ((lflags1 & LIVEOBJ1_TELEPORTINGDOWN) != LIVEOBJ1_NONE) { // & ~LIVEOBJ1_TELEPORTINGDOWN (0x200000) liveObj->flags1 = lflags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING| LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING| LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); liveObj->health = -1.0; liveObj->flags3 = lflags3 | LIVEOBJ3_REMOVING; return; } } } } } return; } void __cdecl lego::debug::LegoObject_Debug_DropActivateDynamite(LegoObject *liveObj) { if (((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE) && (liveObj->carriedObjects[0]->type == LegoObject_Dynamite)) { (liveObj->carriedObjects[0]->targetBlockPos).y = 0.0; (liveObj->carriedObjects[0]->targetBlockPos).x = 0.0; game::LegoObject_DropCarriedObject(liveObj,TRUE); } return; } BOOL __cdecl lego::game::LegoObject_TryDynamite_FUN_00448ac0(LegoObject *liveObj,Point2I *blockPos) { LegoObject *pLVar1; BOOL BVar2; if (liveObj->carriedObjects[0]->type == LegoObject_Dynamite) { BVar2 = LiveObject_CanDynamiteBlockPos(liveObj,blockPos->x,blockPos->y); if (BVar2 != 0) { BVar2 = LegoObject_RouteToFaceBlock(liveObj,blockPos->x,blockPos->y,7.0); if (BVar2 != 0) { pLVar1 = liveObj->carriedObjects[0]; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_PLACE; (pLVar1->targetBlockPos).x = (float)blockPos->x; (pLVar1->targetBlockPos).y = (float)blockPos->y; return TRUE; } } } return 0; } BOOL __cdecl lego::game::LegoObject_PlaceCarriedBirdScarerAt(LegoObject *liveObj,Point2I *blockPos) { uint *byList; LegoObject *pLVar1; BOOL BVar2; uint local_c; uint local_8; uint local_4; LegoObject *liveObj_00; Point2I *pBlockPos; pBlockPos = blockPos; liveObj_00 = liveObj; if (liveObj->carriedObjects[0]->type == LegoObject_OohScary) { byList = (uint *)&blockPos->y; BVar2 = Level_Block_IsGround_alt(liveObj,blockPos->x,blockPos->y); if (BVar2 != 0) { LegoObject_GetBlockPos(liveObj_00,(int *)&local_8,(int *)&local_4); if ((local_8 == pBlockPos->x) && (local_4 == *byList)) { LegoObject_Route_AllocPtr_FUN_004419c0(liveObj_00,1,&pBlockPos->x,(int *)byList,NULL); return 0; } BVar2 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,local_8,local_4,pBlockPos->x,*byList,(int **)&liveObj, (int **)&blockPos,(int *)&local_c,0,NULL); if (BVar2 != 0) { BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,local_c,(int *)liveObj,&blockPos->x,NULL); io::Mem_Free(liveObj); io::Mem_Free(blockPos); if (BVar2 != 0) { pLVar1 = liveObj_00->carriedObjects[0]; liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_PLACE; (pLVar1->targetBlockPos).x = (float)pBlockPos->x; (pLVar1->targetBlockPos).y = (float)*byList; return TRUE; } } } } return 0; } BOOL __cdecl lego::game::LegoObject_PlaceBirdScarer_AndTickDown(LegoObject *liveObj) { BOOL BVar1; LegoObject *oohscaryObj; float10 heading; Point2F position; Point2I blockPos; BVar1 = LegoObject_HasToolEquipped(liveObj,LegoObject_ToolType_BirdScarer); if (BVar1 != 0) { LegoObject_GetPosition(liveObj,&position.x,&position.y); LegoObject_GetBlockPos(liveObj,&blockPos.x,&blockPos.y); heading = LegoObject_GetHeading(liveObj); oohscaryObj = LegoObject_CreateInWorld (globs::legoGlobs.contOohScary,LegoObject_OohScary,0,0,position.x, position.y,(float)heading); Level_Block_SetBusyFloor(&blockPos,TRUE); gfx::Container_SetActivity(oohscaryObj->other,"TickDown"); gfx::Container_SetAnimationTime(oohscaryObj->other,0.0); oohscaryObj->flags3 = oohscaryObj->flags3 | LIVEOBJ3_UNK_10000; return TRUE; } return 0; } BOOL __cdecl lego::game::LegoObject_TryElecFence_FUN_00448d20(LegoObject *liveObj,Point2I *blockPos) { uint *byList; float fVar1; RoutingBlock *pRVar2; LegoObject *pLVar3; Point2I *bxList; short sVar4; BOOL BVar5; uint uVar6; float10 fVar7; int *local_18; uint local_14; float local_10; float local_c; uint local_8; uint local_4; bxList = blockPos; if (liveObj->carriedObjects[0]->type == LegoObject_ElectricFence) { byList = (uint *)&blockPos->y; BVar5 = ElectricFence_CanPlaceFenceAtBlock(blockPos->x,blockPos->y); if (BVar5 != 0) { LegoObject_GetBlockPos(liveObj,(int *)&local_8,(int *)&local_4); if ((local_8 == bxList->x) && (local_4 == *byList)) { BVar5 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,1,&bxList->x,(int *)byList,NULL); } else { BVar5 = LegoObject_Route_Score_FUN_004413b0 (liveObj,local_8,local_4,bxList->x,*byList,(int **)&blockPos,&local_18, (int *)&local_14,0,NULL); if (BVar5 == 0) { return 0; } BVar5 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,local_14,&blockPos->x,local_18,NULL); io::Mem_Free(blockPos); io::Mem_Free(local_18); } if (BVar5 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_PLACE; if (liveObj->type == LegoObject_Vehicle) { fVar7 = math::Maths_RandRange(0.55,0.75); fVar1 = (float)fVar7; sVar4 = math::Maths_Rand(); uVar6 = (int)sVar4 >> 0x1f; switch((((int)sVar4 ^ uVar6) - uVar6 & 3 ^ uVar6) - uVar6) { case 0: local_10 = 0.5; local_c = fVar1; break; case 1: local_c = 0.5; local_10 = fVar1; break; case 2: local_10 = 0.5; local_c = 1.0 - fVar1; break; case 3: local_c = 0.5; local_10 = 1.0 - fVar1; } uVar6 = liveObj->routeBlocksTotal; pRVar2 = liveObj->routeBlocks; pRVar2[uVar6 - 1].blockOffset.x = local_10; pRVar2[uVar6 - 1].blockOffset.y = local_c; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte = liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_UNK_8; } pLVar3 = liveObj->carriedObjects[0]; (pLVar3->targetBlockPos).x = (float)bxList->x; (pLVar3->targetBlockPos).y = (float)*byList; return 1; } } } return 0; } BOOL __cdecl lego::game::LegoObject_TryBuildPath_FUN_00448f10(LegoObject *liveObj) { LegoObject_SetActivity(liveObj,Activity_Clear,0); LegoObject_UpdateActivityChange(liveObj); liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_BUILDPATH; return TRUE; } BOOL __cdecl lego::game::LegoObject_TryUpgrade_FUN_00448f50 (LegoObject *in_liveObj,LegoObject *targetObj,int targetObjLevel) { RouteFlags *pRVar1; float fVar2; LegoObject *liveObj; LegoObject *liveObj_00; BOOL BVar3; Container *cont; Map3D *map; RouteFlags RVar4; BOOL BVar5; uint *out_bx; uint *out_by; uint local_30; uint local_2c; uint local_28; uint local_24; uint local_20; int local_1c; int local_18 [2]; float local_10; Vector3F local_c; liveObj_00 = targetObj; liveObj = in_liveObj; BVar5 = 0; if (targetObj->type == LegoObject_Building) { if (in_liveObj->type == LegoObject_MiniFigure) { BVar3 = LegoObject_TryTrain_FUN_00449170(in_liveObj,targetObj,1); if (BVar3 != 0) { return TRUE; } } else { if (in_liveObj->type == LegoObject_Vehicle) { cont = LegoObject_GetDepositNull(targetObj); gfx::Container_GetPosition(cont,NULL,&local_c); out_by = &local_28; out_bx = &local_2c; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,local_c.x,local_c.y,(int *)out_bx,(int *)out_by); LegoObject_GetBlockPos(liveObj,(int *)&local_24,(int *)&local_20); LegoObject_GetBlockPos(liveObj_00,&local_1c,local_18); fVar2 = (float)local_2c - (float)local_1c; local_10 = (float)local_28 - (float)local_18[0]; if (ABS(fVar2) <= ABS(local_10)) { if ((ushort)((ushort)(local_10 < 0.0) << 8 | (ushort)(local_10 == 0.0) << 0xe) == 0) { RVar4 = ROUTE_FLAG_NONE; } else { RVar4 = 2; } } else { if ((ushort)((ushort)(fVar2 < 0.0) << 8 | (ushort)(fVar2 == 0.0) << 0xe) == 0) { RVar4 = 1; } else { RVar4 = ROUTE_DIRECTION_MASK; } } if ((local_24 == local_2c) && (local_20 == local_28)) { BVar5 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj,1,(int *)&local_2c,(int *)&local_28,NULL); } else { BVar5 = LegoObject_Route_Score_FUN_004413b0 (liveObj,local_24,local_20,local_2c,local_28,(int **)&targetObj, (int **)&in_liveObj,(int *)&local_30,0,NULL); if (BVar5 == 0) { return 0; } BVar5 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj,local_30,(int *)targetObj,(int *)in_liveObj,NULL); io::Mem_Free(targetObj); io::Mem_Free(in_liveObj); } if (BVar5 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UPGRADE; pRVar1 = &liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte; *pRVar1 = *pRVar1 | ROUTE_FLAG_GOTOBUILDING; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte = liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte | RVar4; liveObj->upgradingType = targetObjLevel; liveObj->routeToObject = liveObj_00; liveObj_00->interactObject = liveObj; return BVar5; } } } } return BVar5; } BOOL __cdecl lego::game::LegoObject_TryTrain_FUN_00449170 (LegoObject *liveObj,LegoObject *targetObj,BOOL set_0xE_or0xF) { RouteFlags *pRVar1; uint uVar2; RoutingBlock *pRVar3; float fVar4; LegoObject *pLVar5; BOOL BVar6; Map3D *map; uint uVar7; float10 fVar8; uint local_28; uint local_24; float local_20 [4]; float local_10; float local_c; float local_8; float local_4; pLVar5 = targetObj; if ((liveObj->type == LegoObject_MiniFigure) && (targetObj->type == LegoObject_Building)) { LegoObject_GetBlockPos(targetObj,(int *)&local_28,(int *)&local_24); BVar6 = LegoObject_BlockRoute_FUN_00446c80 (liveObj,local_28,local_24,0,(Direction *)&targetObj,1); if (BVar6 != 0) { map = lrr::Lego_GetMap(); fVar8 = lego::map::Map3D_BlockSize(map); local_c = (float)((float10)4.0 / fVar8); fVar8 = math::Maths_RandRange(0.1,0.9); uVar2 = liveObj->routeBlocksTotal; local_20[0] = (float)fVar8; local_8 = local_c; uVar7 = (int)&targetObj[-1].nextFree + 2U & 3; local_20[3] = local_20[0]; local_10 = local_20[0]; local_4 = local_20[0]; local_20[1] = 1.0 - local_c; local_20[2] = 1.0 - local_c; pRVar3 = liveObj->routeBlocks; fVar4 = local_20[uVar7 * 2 + 1]; pRVar3[uVar2 - 1].blockOffset.x = local_20[uVar7 * 2]; pRVar3[uVar2 - 1].blockOffset.y = fVar4; if (set_0xE_or0xF == 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_TRAIN; } else { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UPGRADE; } liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte = liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_GOTOBUILDING; pRVar1 = &liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte; targetObj._0_1_ = (RouteFlags)uVar7; *pRVar1 = *pRVar1 | (RouteFlags)targetObj; liveObj->routeToObject = pLVar5; return TRUE; } } return 0; } BOOL __cdecl lego::game::LegoObject_TryRechargeCarried(LegoObject *liveObj) { BOOL BVar1; Point2I blockPos; if ((((liveObj->type == LegoObject_MiniFigure) && ((liveObj->flags1 & LIVEOBJ1_CARRYING) != LIVEOBJ1_NONE)) && (liveObj->carriedObjects[0]->type == LegoObject_PowerCrystal)) && ((liveObj->carriedObjects[0]->flags3 & LIVEOBJ3_POWEROFF) != LIVEOBJ3_NONE)) { BVar1 = LegoObject_FindNearestRechargeSeam(liveObj,&blockPos); if (BVar1 != 0) { BVar1 = LegoObject_RouteToFaceBlock(liveObj,blockPos.x,blockPos.y,3.0); if (BVar1 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_RECHARGE; (liveObj->targetBlockPos).x = (float)blockPos.x; (liveObj->targetBlockPos).y = (float)blockPos.y; return TRUE; } } } return FALSE; } // For MiniFigures, the action repairs. For RockMonsters (enemies), the action drains. BOOL __cdecl lego::game::LegoObject_TryRepairDrainObject (LegoObject *liveObj,LegoObject *targetObj,BOOL setRouteFlag20,BOOL setLive4Flag400000) { uint uVar1; RoutingBlock *pRVar2; float fVar3; bool bVar4; LegoObject *liveObj_00; StatsFlags2 sflags2; BOOL BVar5; Map3D *map; uint uVar6; float10 fVar7; uint bx; uint by; Point2F DIRECTIONS [4]; LegoObject_Type objType; RouteFlags *rflags; liveObj_00 = targetObj; // Only MiniFigures or Enemies can perform the "Repair" action. objType = liveObj->type; if ((objType != LegoObject_MiniFigure) && (objType != LegoObject_RockMonster)) { return 0; } // Can only repair buildings. if (targetObj->type != LegoObject_Building) { return 0; } if ((objType == LegoObject_RockMonster) && (sflags2 = stats::StatsObject_GetStatsFlags2(liveObj), (sflags2 & STATS2_DRAINPOWER) == STATS2_NONE)) { bVar4 = true; } else { bVar4 = false; } LegoObject_GetBlockPos(liveObj_00,(int *)&bx,(int *)&by); BVar5 = LegoObject_BlockRoute_FUN_00446c80 (liveObj,bx,by,FALSE,(Direction *)&targetObj, (uint)(liveObj->type != LegoObject_RockMonster)); if (BVar5 == 0) { return 0; } map = lrr::Lego_GetMap(); fVar7 = lego::map::Map3D_BlockSize(map); DIRECTIONS[2].y = (float)((float10)4.0 / fVar7); if (bVar4) { fVar7 = (float10)0.5; } else { fVar7 = math::Maths_RandRange(0.2,0.8); } DIRECTIONS[0].x = (float)fVar7; DIRECTIONS[3].x = DIRECTIONS[2].y; uVar6 = (int)&targetObj[-1].nextFree + 2U & 3; DIRECTIONS[0].y = 1.0 - DIRECTIONS[2].y; DIRECTIONS[1].x = 1.0 - DIRECTIONS[2].y; uVar1 = liveObj->routeBlocksTotal; DIRECTIONS[1].y = (float)fVar7; DIRECTIONS[2].x = (float)fVar7; DIRECTIONS[3].y = (float)fVar7; pRVar2 = liveObj->routeBlocks; fVar3 = DIRECTIONS[uVar6].y; pRVar2[uVar1 - 1].blockOffset.x = DIRECTIONS[uVar6].x; pRVar2[uVar1 - 1].blockOffset.y = fVar3; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_REPAIRDRAIN; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte = liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_GOTOBUILDING; targetObj._0_1_ = (RouteFlags)uVar6; rflags = &liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte; *rflags = *rflags | (RouteFlags)targetObj; if (setRouteFlag20 != 0) { rflags = &liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte; *rflags = *rflags | ROUTE_FLAG_UNK_20; } if (setLive4Flag400000 != 0) { liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_UNK_400000; } liveObj->routeToObject = liveObj_00; return TRUE; } BOOL __cdecl lego::game::LegoObject_TryReinforceBlock(LegoObject *liveObj,Point2I *blockPos) { BOOL BVar1; BVar1 = LiveObject_CanReinforceBlock(liveObj,blockPos->x,blockPos->y); if (BVar1 != 0) { BVar1 = LegoObject_RouteToFaceBlock(liveObj,blockPos->x,blockPos->y,3.0); if (BVar1 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_REINFORCE; (liveObj->targetBlockPos).x = (float)blockPos->x; (liveObj->targetBlockPos).y = (float)blockPos->y; return TRUE; } } return FALSE; } BOOL __cdecl lego::game::LegoObject_TryClear_FUN_00449570(LegoObject *liveObj,Point2I *blockPos) { uint uVar1; StatsFlags1 sflags1; BOOL BVar2; uint local_c; Point2I objBlockPos; Point2I *blockPos_00; LegoObject *liveObj_00; blockPos_00 = blockPos; uVar1 = Level_Block_GetRubbleLayers(blockPos); liveObj_00 = liveObj; if (uVar1 != 0) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_CANCLEARRUBBLE) == STATS1_NONE) { return 1; } LegoObject_GetBlockPos(liveObj_00,&objBlockPos.x,&objBlockPos.y); if ((objBlockPos.x == blockPos_00->x) && (objBlockPos.y == blockPos_00->y)) { BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,1,&blockPos_00->x,&blockPos_00->y,NULL); } else { BVar2 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,objBlockPos.x,objBlockPos.y,blockPos_00->x,blockPos_00->y, (int **)&blockPos,(int **)&liveObj,(int *)&local_c,0,NULL); if (BVar2 == 0) { return 0; } BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,local_c,&blockPos->x,(int *)liveObj,NULL); io::Mem_Free(blockPos); io::Mem_Free(liveObj); } if (BVar2 == 0) { return 0; } liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_CLEAR; if (liveObj_00->type == LegoObject_Vehicle) { Level_Block_SetBusyFloor(blockPos_00,TRUE); Level_Block_SetDozerClearing(blockPos_00,TRUE); return TRUE; } } return TRUE; } BOOL __cdecl lego::game::LegoObject_MiniFigureHasBeamEquipped(LegoObject *liveObj) { BOOL BVar1; if (liveObj->type != LegoObject_MiniFigure) { return 0; } BVar1 = LegoObject_HasToolEquipped(liveObj,LegoObject_ToolType_Laser); if (((BVar1 == 0) && (BVar1 = LegoObject_HasToolEquipped(liveObj,LegoObject_ToolType_PusherGun), BVar1 == 0)) && (BVar1 = LegoObject_HasToolEquipped(liveObj,LegoObject_ToolType_FreezerGun), BVar1 == 0)) { return 0; } return 1; } BOOL __cdecl lego::game::LegoObject_TryAttackRockMonster_FUN_004496f0(LegoObject *liveObj,LegoObject *targetObj) { LegoObject *pLVar1; BOOL BVar2; int *local_18; uint local_14; uint local_10; uint local_c; uint local_8; uint local_4; pLVar1 = targetObj; LegoObject_GetBlockPos(targetObj,(int *)&local_10,(int *)&local_c); LegoObject_GetBlockPos(liveObj,(int *)&local_8,(int *)&local_4); if ((local_8 == local_10) && (local_4 == local_c)) { BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,1,(int *)&local_10,(int *)&local_c,NULL); } else { BVar2 = LegoObject_Route_Score_FUN_004413b0 (liveObj,local_8,local_4,local_10,local_c,(int **)&targetObj,&local_18, (int *)&local_14,0,NULL); if (BVar2 == 0) { return 0; } BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,local_14,(int *)targetObj,local_18,NULL); io::Mem_Free(targetObj); io::Mem_Free(local_18); } if (BVar2 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UNK_17; liveObj->routeToObject = pLVar1; } return BVar2; } BOOL __cdecl lego::game::LegoObject_TryAttackObject_FUN_004497e0(LegoObject *in_liveObj,LegoObject *targetObj) { LegoObject *liveObj; BOOL BVar1; int *local_18; uint local_14; uint local_10; uint local_c; uint local_8; uint local_4; liveObj = in_liveObj; LegoObject_GetBlockPos(in_liveObj,(int *)&local_8,(int *)&local_4); LegoObject_GetBlockPos(targetObj,(int *)&local_10,(int *)&local_c); if ((local_8 == local_10) && (local_4 == local_c)) { BVar1 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,1,(int *)&local_10,(int *)&local_c,NULL); } else { BVar1 = LegoObject_Route_Score_FUN_004413b0 (liveObj,local_8,local_4,local_10,local_c,(int **)&in_liveObj,&local_18, (int *)&local_14,0,NULL); if (BVar1 == 0) { return 0; } BVar1 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj,local_14,(int *)in_liveObj,local_18,NULL) ; io::Mem_Free(in_liveObj); io::Mem_Free(local_18); } if (BVar1 != 0) { liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_ATTACK; } return BVar1; } BOOL __cdecl lego::game::LegoObject_TryAttackPath_FUN_004498d0(LegoObject *liveObj,Point2I *blockPos) { LegoObject *liveObj_00; Point2I *pPVar1; BOOL BVar2; int *local_10; uint local_c; uint local_8; uint local_4; liveObj_00 = liveObj; LegoObject_GetBlockPos(liveObj,(int *)&local_8,(int *)&local_4); pPVar1 = blockPos; if ((local_8 == blockPos->x) && (local_4 == blockPos->y)) { BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj_00,1,&blockPos->x,&blockPos->y,NULL); } else { BVar2 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,local_8,local_4,blockPos->x,blockPos->y,(int **)&liveObj,&local_10 ,(int *)&local_c,0,NULL); if (BVar2 == 0) { return 0; } BVar2 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj_00,local_c,(int *)liveObj,local_10,NULL); io::Mem_Free(liveObj); io::Mem_Free(local_10); } if (BVar2 != 0) { liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UNK_16; (liveObj_00->targetBlockPos).x = (float)pPVar1->x; (liveObj_00->targetBlockPos).y = (float)pPVar1->y; } return BVar2; } BOOL __cdecl lego::game::LegoObject_TryDepart_FUN_004499c0(LegoObject *liveObj) { StatsFlags2 SVar1; BOOL BVar2; BOOL BVar3; int *local_18; uint local_14; Point2I local_10; uint local_8; uint local_4; LegoObject *liveObj_00; liveObj_00 = liveObj; BVar3 = 0; SVar1 = stats::StatsObject_GetStatsFlags2(liveObj); if ((SVar1 & STATS2_USEHOLES) == STATS2_NONE) { BVar2 = LegoObject_FindNearestWall(liveObj_00,&local_10.x,&local_10.y,1,0,1); if ((BVar2 != 0) && (BVar2 = LegoObject_RouteToFaceBlock(liveObj_00,local_10.x,local_10.y,3.0), BVar2 != 0)) { BVar3 = TRUE; liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UNK_10; (liveObj_00->targetBlockPos).x = (float)local_10.x; (liveObj_00->targetBlockPos).y = (float)local_10.y; } } else { BVar2 = LegoObject_FindNearestSlugHole(liveObj_00,&local_10); if (BVar2 != 0) { LegoObject_GetBlockPos(liveObj_00,(int *)&local_8,(int *)&local_4); if ((local_8 == local_10.x) && (local_4 == local_10.y)) { BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0(liveObj_00,1,&local_10.x,&local_10.y,NULL); } else { BVar3 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,local_8,local_4,local_10.x,local_10.y,(int **)&liveObj, &local_18,(int *)&local_14,0,NULL); if (BVar3 == 0) { BVar3 = 0; } else { BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,local_14,(int *)liveObj,local_18,NULL); io::Mem_Free(liveObj); io::Mem_Free(local_18); } } if (BVar3 == 0) { return 0; } liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UNK_10; (liveObj_00->targetBlockPos).x = (float)local_10.x; (liveObj_00->targetBlockPos).y = (float)local_10.y; } } if (BVar3 != 0) { ai::AITask_RemoveAttackRockMonsterReferences(liveObj_00); } return BVar3; } BOOL __cdecl lego::game::LegoObject_RouteToFaceBlock(LegoObject *liveObj,uint bx,uint by,float distFrom) { uint by_00; BOOL BVar1; Map3D *map; float10 blockSize; float10 fVar2; RouteFlags *rflags; by_00 = by; BVar1 = Level_Block_IsWall(bx,by); if ((BVar1 != 0) && (BVar1 = LegoObject_BlockRoute_FUN_00446c80(liveObj,bx,by_00,FALSE,&by,TRUE), BVar1 != 0)) { map = lrr::Lego_GetMap(); blockSize = lego::map::Map3D_BlockSize(map); fVar2 = (float10)distFrom / blockSize; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].blockOffset.y = 0.5; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].blockOffset.x = 0.5; switch(by) { case 0: liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].blockOffset.y = (float)fVar2; break; case 1: liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].blockOffset.x = (float)fVar2; break; case 2: liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].blockOffset.y = (float)((float10)1.0 - fVar2); break; case 3: liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].blockOffset.x = (float)((float10)1.0 - fVar2); } rflags = &liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte; *rflags = *rflags | ROUTE_FLAG_UNK_8; return TRUE; } return FALSE; } BOOL __cdecl lego::game::LegoObject_Update_Reinforcing (LegoObject *liveObj,float unused_elapsed,BOOL *out_finished) { BOOL BVar1; longlong lVar2; longlong lVar3; Point2I local_8; *out_finished = FALSE; if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_REINFORCING) == 0) { return 0; } lVar2 = __ftol((float10)(liveObj->targetBlockPos).x); local_8.x = (uint)lVar2; lVar3 = __ftol((float10)(liveObj->targetBlockPos).y); local_8.y = (int)lVar3; BVar1 = LiveObject_CanReinforceBlock(liveObj,(uint)lVar2,local_8.y); if (BVar1 == 0) { LegoObject_SetActivity(liveObj,Activity_CantDo,1); // & ~LIVEOBJ1_REINFORCING (0x40) | LIVEOBJ1_CANTDO liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO) | LIVEOBJ1_CANTDO; } else { if ((ushort)((ushort)(liveObj->animTime < 0.0) << 8 | (ushort)(liveObj->animTime == 0.0) << 0xe) != 0) { return 1; } // & ~LIVEOBJ1_REINFORCING (0x40) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK| LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000| LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING| LIVEOBJ1_PLACING|LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); LegoObject_SetActivity(liveObj,Activity_Stand,0); Level_Block_Reinforce(local_8.x,local_8.y); (liveObj->targetBlockPos).y = -1.0; (liveObj->targetBlockPos).x = -1.0; *out_finished = TRUE; } Level_Block_SetBusy(&local_8,FALSE); return TRUE; } void __cdecl lego::game::LegoObject_GoEat_unk(LegoObject *liveObj) { if (liveObj->type == LegoObject_MiniFigure) { liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_UNK_800; } if ((liveObj->flags1 & LIVEOBJ1_CARRYING) == LIVEOBJ1_NONE) { liveObj->flags1 = liveObj->flags1 | LIVEOBJ1_EATING; LegoObject_SetActivity(liveObj,Activity_Eat,0); LegoObject_UpdateActivityChange(liveObj); ai::AITask_DoAnimationWait(liveObj); } return; } BOOL __cdecl lego::game::LegoObject_TryGoEat_FUN_00449d80(LegoObject *liveObj1,LegoObject *liveObj2) { RouteFlags *pRVar1; uint uVar2; RoutingBlock *pRVar3; LegoObject *liveObj; LegoObject *pLVar4; BOOL BVar5; Map3D *map; uint uVar6; float10 fVar7; uint local_28; uint local_24; float local_20 [4]; undefined4 local_10; float local_c; float local_8; undefined4 local_4; pLVar4 = liveObj2; liveObj = liveObj1; if ((liveObj1->type == LegoObject_MiniFigure) && (liveObj2->type == LegoObject_Building)) { LegoObject_GetBlockPos(liveObj2,(int *)&local_28,(int *)&local_24); BVar5 = LegoObject_BlockRoute_FUN_00446c80(liveObj,local_28,local_24,0,(Direction *)&liveObj1,1) ; if (BVar5 != 0) { map = lrr::Lego_GetMap(); fVar7 = lego::map::Map3D_BlockSize(map); fVar7 = (float10)4.0 / fVar7; local_20[0] = 0.5; local_20[3] = 0.5; local_10 = 0x3f000000; local_4 = 0x3f000000; uVar6 = (int)&liveObj1[-1].nextFree + 2U & 3; uVar2 = liveObj->routeBlocksTotal; pRVar3 = liveObj->routeBlocks; local_20[1] = (float)((float10)1.0 - fVar7); local_20[2] = (float)((float10)1.0 - fVar7); local_c = (float)fVar7; local_8 = (float)fVar7; pRVar3[uVar2 - 1].blockOffset.x = local_20[uVar6 * 2]; pRVar3[uVar2 - 1].blockOffset.y = local_20[uVar6 * 2 + 1]; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_EAT; liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte = liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte | ROUTE_FLAG_GOTOBUILDING; liveObj1._0_1_ = (RouteFlags)uVar6; pRVar1 = &liveObj->routeBlocks[liveObj->routeBlocksTotal - 1].flagsByte; *pRVar1 = *pRVar1 | (RouteFlags)liveObj1; liveObj->routeToObject = pLVar4; return TRUE; } // & ~LIVEOBJ2_UNK_800 (0x800) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } return 0; } void __cdecl lego::game::LegoObject_HideAllCertainObjects(void) { LegoObject_RunThroughLists(LegoObject_Callback_HideCertainObjects,NULL,FALSE); return; } void __cdecl lego::game::LegoObject_FlocksCallback_HideCertainObjects (Flocks *flockData,FlocksItem *subdata,void *data) { Container *cont; Map3D *map; Lego_Level *pLVar1; BOOL BVar2; FlocksItem **out_bx; uint *out_by; uint local_10; Vector3F wPos; cont = subdata->cont; gfx::Container_GetPosition(cont,NULL,&wPos); out_by = &local_10; out_bx = &subdata; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,wPos.x,wPos.y,(int *)out_bx,(int *)out_by); pLVar1 = lrr::Lego_GetLevel(); if (subdata <= (FlocksItem *)pLVar1->width) { pLVar1 = lrr::Lego_GetLevel(); if (local_10 < pLVar1->height || local_10 == pLVar1->height) { BVar2 = Level_Block_IsMeshHidden((uint)subdata,local_10); if (BVar2 == 0) { BVar2 = Level_Block_IsNotWallOrGround((uint)subdata,local_10); if (BVar2 == 0) { gfx::Container_Hide(cont,0); return; } } } } gfx::Container_Hide(cont,TRUE); return; } void __cdecl lego::game::LegoObject_Hide2(LegoObject *liveObj,BOOL hide2) { Container *cont; cont = LegoObject_GetActivityContainer(liveObj); if (cont != NULL) { gfx::Container_Hide2(cont,hide2); } return; } BOOL __cdecl lego::game::LegoObject_Callback_HideCertainObjects(LegoObject *liveObj,void *unused) { bool bVar1; StatsFlags1 sflags1; BOOL BVar2; StatsFlags2 sflags2; Point2I *pPVar3; Point2I *pPVar4; uint uVar5; Point2I *pPVar6; Direction rotation; uint uVar7; uint by; uint bx; uint local_20; BOOL hide; Point2F local_18; Point2I local_10; float local_8; float local_4; uVar7 = 0; hide = 0; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_FLOCKS) != STATS1_NONE) { Flocks_CallbackForAllSubdata(liveObj->flocks,LegoObject_FlocksCallback_HideCertainObjects,NULL); return 0; } BVar2 = LegoObject_GetBlockPos(liveObj,(int *)&bx,(int *)&by); if (BVar2 == 0) { LegoObject_Hide(liveObj,TRUE); return 0; } BVar2 = Level_Block_IsGround(bx,by); if (BVar2 != 0) { // & ~LIVEOBJ3_ALLOWCULLING_UNK (0x100000) liveObj->flags3 = liveObj->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_SELECTED|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING|LIVEOBJ3_UNK_1000000| LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER|LIVEOBJ3_MONSTER_UNK_8000000| LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER|LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); } BVar2 = Level_Block_IsNotWallOrGround(bx,by); if (((BVar2 == 0) && ((liveObj->flags3 & LIVEOBJ3_ALLOWCULLING_UNK) == LIVEOBJ3_NONE)) && ((liveObj->type != LegoObject_MiniFigure || ((liveObj->driveObject == NULL || (sflags2 = stats::StatsObject_GetStatsFlags2(liveObj->driveObject), (sflags2 & STATS2_INVISIBLEDRIVER) == STATS2_NONE)))))) { BVar2 = 0; } else { BVar2 = 1; } LegoObject_Hide(liveObj,BVar2); BVar2 = Level_Block_IsMeshHidden(bx,by); if (((BVar2 != 0) || (BVar2 = Level_Block_IsNotWallOrGround(bx,by), BVar2 != 0)) || ((liveObj->flags3 & LIVEOBJ3_ALLOWCULLING_UNK) != LIVEOBJ3_NONE)) { rotation = DIRECTION_RIGHT; hide = 1; if (liveObj->type == LegoObject_Building) { LegoObject_GetFaceDirection(liveObj,&local_18); LegoObject_GetBlockPos(liveObj,&local_10.x,&local_10.y); LegoObject_GetPosition(liveObj,&local_8,&local_4); if (ABS(local_18.x) <= ABS(local_18.y)) { if ((ushort)((ushort)(local_18.y < 0.0) << 8 | (ushort)(local_18.y == 0.0) << 0xe) == 0) { rotation = DIRECTION_UP; } else { rotation = DIRECTION_DOWN; } } else { if ((ushort)((ushort)(local_18.x < 0.0) << 8 | (ushort)(local_18.x == 0.0) << 0xe) != 0) { rotation = DIRECTION_LEFT; } } pPVar3 = gfx::Building_GetShapePoints(globs::legoGlobs.buildingData + liveObj->id,&local_20); pPVar4 = gfx::SelectPlace_TransformShapePoints(&local_10,pPVar3,local_20,rotation); uVar5 = local_20; pPVar3 = pPVar4; if (local_20 != 0) { do { pPVar6 = pPVar3 + 1; if (((uVar7 == uVar5 - 1) || (pPVar4->x != pPVar6->x)) || (pPVar4->y != pPVar3[1].y)) { bVar1 = false; BVar2 = Level_Block_IsMeshHidden(pPVar4->x,pPVar4->y); uVar5 = local_20; if (BVar2 == 0) { hide = 0; break; } } else { bVar1 = true; } if (bVar1) { uVar7 += 1; pPVar6 = pPVar3 + 2; pPVar4 = pPVar4 + 1; } uVar7 += 1; pPVar4 = pPVar4 + 1; pPVar3 = pPVar6; } while (uVar7 < uVar5); } } } LegoObject_Hide2(liveObj,hide); return 0; } void __cdecl lego::game::LegoObject_Hide(LegoObject *liveObj,BOOL hide) { LegoObject_Type objType; objType = liveObj->type; if (objType == LegoObject_Vehicle) { gfx::Vehicle_Hide(liveObj->vehicle,hide); return; } if (objType == LegoObject_MiniFigure) { gfx::Object_Hide((BasicObjectModel *)liveObj->miniFigure,hide); return; } if (objType == LegoObject_RockMonster) { gfx::Object_Hide((BasicObjectModel *)liveObj->rockMonster,hide); return; } if (objType == LegoObject_Building) { gfx::Building_Hide(liveObj->building,hide); return; } if (objType == LegoObject_UpgradePart) { gfx::Object_Hide((BasicObjectModel *)liveObj->upgradePart,hide); return; } if ((liveObj->flags3 & LIVEOBJ3_SIMPLEOBJECT) != LIVEOBJ3_NONE) { gfx::Container_Hide(liveObj->other,hide); } return; } BOOL __cdecl lego::game::LegoObject_IsHidden(LegoObject *liveObj) { LegoObject_Type LVar1; LVar1 = liveObj->type; if (LVar1 == LegoObject_Vehicle) { LVar1 = gfx::Vehicle_IsHidden(liveObj->vehicle); return LVar1; } if (LVar1 == LegoObject_MiniFigure) { LVar1 = gfx::Object_IsHidden((BasicObjectModel *)liveObj->miniFigure); return LVar1; } if (LVar1 == LegoObject_RockMonster) { LVar1 = gfx::Object_IsHidden((BasicObjectModel *)liveObj->rockMonster); return LVar1; } if (LVar1 == LegoObject_Building) { LVar1 = gfx::Object_IsHidden((BasicObjectModel *)liveObj->building); return LVar1; } if (LVar1 == LegoObject_UpgradePart) { LVar1 = gfx::Object_IsHidden((BasicObjectModel *)liveObj->upgradePart); return LVar1; } if ((liveObj->flags3 & LIVEOBJ3_SIMPLEOBJECT) != LIVEOBJ3_NONE) { LVar1 = gfx::Container_IsHidden(liveObj->other); } return LVar1; } void __cdecl lego::game::LegoObject_FP_GetPositionAndHeading (LegoObject *liveObj,int cameraFrame,Vector3F *out_worldPos,Vector3F *out_dir) { LegoObject_Type LVar1; float fVar2; float fVar3; float fVar4; Container *pCVar5; LegoObject *pLVar6; Vector3F local_c; if ((liveObj->cameraNull != NULL) && (liveObj->cameraFrame == cameraFrame)) goto LAB_0044a3a2; LVar1 = liveObj->type; if (LVar1 == LegoObject_Vehicle) { pCVar5 = gfx::Vehicle_GetCameraNull(liveObj->vehicle,cameraFrame); LAB_0044a371: liveObj->cameraNull = pCVar5; } else { if (LVar1 == LegoObject_MiniFigure) { pCVar5 = gfx::Creature_GetCameraNull(liveObj->miniFigure,cameraFrame); goto LAB_0044a371; } if (LVar1 != LegoObject_RockMonster) goto LAB_0044a3a2; pCVar5 = gfx::Creature_GetCameraNull(liveObj->rockMonster,cameraFrame); liveObj->cameraNull = pCVar5; } if (pCVar5 != NULL) { liveObj->cameraFrame = cameraFrame; } LAB_0044a3a2: LVar1 = liveObj->type; if (LVar1 == LegoObject_Vehicle) { pLVar6 = (LegoObject *)gfx::Vehicle_IsCameraFlipDir(liveObj->vehicle); } else { if (LVar1 == LegoObject_MiniFigure) { pLVar6 = (LegoObject *)gfx::Creature_IsCameraFlipDir(liveObj->miniFigure); } else { pLVar6 = liveObj; if (LVar1 == LegoObject_RockMonster) { pLVar6 = (LegoObject *)gfx::Creature_IsCameraFlipDir(liveObj->rockMonster); } } } if (liveObj->cameraNull != NULL) { gfx::Container_GetPosition(liveObj->cameraNull,NULL,out_worldPos); gfx::Container_GetOrientation(liveObj->cameraNull,NULL,out_dir,&local_c); fVar2 = 1.0 / SQRT(out_dir->x * out_dir->x + out_dir->z * out_dir->z + out_dir->y * out_dir->y); fVar4 = fVar2 * out_dir->x; fVar3 = fVar2 * out_dir->y; fVar2 = fVar2 * out_dir->z; out_dir->x = fVar4; out_dir->y = fVar3; out_dir->z = fVar2; if (pLVar6 != NULL) { out_dir->x = fVar4 * -1.0; out_dir->y = fVar3 * -1.0; out_dir->z = fVar2 * -1.0; return; } } return; } Container * __cdecl lego::game::LegoObject_GetActivityContainer(LegoObject *liveObj) { LegoObject *cont; if (true) { switch(liveObj->type) { case LegoObject_Vehicle: cont = (LegoObject *)gfx::Vehicle_GetActivityContainer(liveObj->vehicle); return (Container *)cont; case LegoObject_MiniFigure: cont = (LegoObject *)gfx::Object_GetActivityContainer((BasicObjectModel *)liveObj->miniFigure) ; return (Container *)cont; case LegoObject_RockMonster: cont = (LegoObject *) gfx::Object_GetActivityContainer((BasicObjectModel *)liveObj->rockMonster); return (Container *)cont; case LegoObject_Building: cont = (LegoObject *)gfx::Object_GetActivityContainer((BasicObjectModel *)liveObj->building); return (Container *)cont; case LegoObject_UpgradePart: cont = (LegoObject *) gfx::Object_GetActivityContainer((BasicObjectModel *)liveObj->upgradePart); return (Container *)cont; } } if ((liveObj->flags3 & LIVEOBJ3_SIMPLEOBJECT) == LIVEOBJ3_NONE) { return (Container *)liveObj; } return (Container *)(LegoObject *)liveObj->other; } BOOL __cdecl lego::game::LegoObject_GetDrillNullPosition(LegoObject *liveObj,float *out_xPos,float *out_yPos) { LegoObject_Type LVar1; Container *cont; CreatureModel *creature; Vector3F vector; LVar1 = liveObj->type; if (LVar1 == LegoObject_Vehicle) { cont = gfx::Vehicle_GetDrillNull(liveObj->vehicle); } else { if (LVar1 == LegoObject_MiniFigure) { creature = liveObj->miniFigure; } else { if (LVar1 != LegoObject_RockMonster) { return 0; } creature = liveObj->rockMonster; } cont = gfx::Creature_GetDrillNull(creature); } if (cont == NULL) { return 0; } gfx::Container_GetPosition(cont,NULL,&vector); *out_xPos = vector.x; *out_yPos = vector.y; return 1; } void __cdecl lego::game::LegoObject_FP_Move(LegoObject *liveObj,int forward,int strafe,float rotate) { StatsFlags3 SVar1; if ((liveObj->type == LegoObject_MiniFigure) && (liveObj->driveObject != NULL)) { liveObj = liveObj->driveObject; } if ((*(byte *)&liveObj->flags1 & LIVEOBJ1_MOVING) != 0) { LegoObject_Route_End(liveObj,FALSE); } SVar1 = stats::StatsObject_GetStatsFlags3(liveObj); if ((SVar1 & STATS3_CANSTRAFE) == STATS3_NONE) { strafe = 0; } liveObj->strafeSignFP = liveObj->strafeSignFP + strafe; liveObj->forwardSignFP = liveObj->forwardSignFP + forward; liveObj->rotateSpeedFP = rotate + liveObj->rotateSpeedFP; return; } void __cdecl lego::game::LegoObject_RegisterRechargeSeam(Point2I *blockPos) { if (globs::objectGlobs.rechargeSeamCount < 10) { globs::objectGlobs.rechargeSeamBlocks[globs::objectGlobs.rechargeSeamCount].x = blockPos->x; globs::objectGlobs.rechargeSeamBlocks[globs::objectGlobs.rechargeSeamCount].y = blockPos->y; globs::objectGlobs.rechargeSeamCount += 1; } return; } BOOL __cdecl lego::game::LegoObject_FindNearestRechargeSeam(LegoObject *liveObj,Point2I *optout_blockPos) { Map3D *map; int foundIndex; uint index; Point2I *pSeamBlock; uint bx; uint by; Point2F *out_x; float *out_y; float minDistToSeam; Point2F objWorldPos; Point2F seamWorldPos; float distToSeam; foundIndex = -1; minDistToSeam = 10000.0; LegoObject_GetPosition(liveObj,&objWorldPos.x,&objWorldPos.y); index = 0; if (globs::objectGlobs.rechargeSeamCount != 0) { pSeamBlock = globs::objectGlobs.rechargeSeamBlocks; do { by = pSeamBlock->y; bx = pSeamBlock->x; out_y = &seamWorldPos.y; out_x = &seamWorldPos; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,by,&out_x->x,out_y); distToSeam = SQRT((objWorldPos.y - seamWorldPos.y) * (objWorldPos.y - seamWorldPos.y) + (objWorldPos.x - seamWorldPos.x) * (objWorldPos.x - seamWorldPos.x)); if (distToSeam < minDistToSeam) { foundIndex = index; minDistToSeam = distToSeam; } index += 1; pSeamBlock = pSeamBlock + 1; } while (index < globs::objectGlobs.rechargeSeamCount); } if (foundIndex == 0xffffffff) { return FALSE; } if (optout_blockPos != NULL) { optout_blockPos->x = globs::objectGlobs.rechargeSeamBlocks[foundIndex].x; optout_blockPos->y = globs::objectGlobs.rechargeSeamBlocks[foundIndex].y; } return TRUE; } void __cdecl lego::game::LegoObject_RegisterSlimySlugHole(Point2I *blockPos) { if (globs::objectGlobs.slugHoleCount < 20) { globs::objectGlobs.slugHoleBlocks[globs::objectGlobs.slugHoleCount].x = blockPos->x; globs::objectGlobs.slugHoleBlocks[globs::objectGlobs.slugHoleCount].y = blockPos->y; globs::objectGlobs.slugHoleCount += 1; } return; } BOOL __cdecl lego::game::LegoObject_FindNearestSlugHole(LegoObject *liveObj,Point2I *optout_blockPos) { Map3D *map; int foundIndex; uint index; Point2I *pPVar1; uint bx; uint by; Point2F *out_x; float *out_y; float minDist; Point2F objectPos; Point2F holeWorldPos; float distToHole; foundIndex = -1; minDist = 10000.0; LegoObject_GetPosition(liveObj,&objectPos.x,&objectPos.y); index = 0; if (globs::objectGlobs.slugHoleCount != 0) { pPVar1 = globs::objectGlobs.slugHoleBlocks; do { by = pPVar1->y; bx = pPVar1->x; out_y = &holeWorldPos.y; out_x = &holeWorldPos; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,bx,by,&out_x->x,out_y); distToHole = SQRT((objectPos.y - holeWorldPos.y) * (objectPos.y - holeWorldPos.y) + (objectPos.x - holeWorldPos.x) * (objectPos.x - holeWorldPos.x)); if (distToHole < minDist) { foundIndex = index; minDist = distToHole; } index += 1; pPVar1 = pPVar1 + 1; } while (index < globs::objectGlobs.slugHoleCount); } if (foundIndex == 0xffffffff) { return FALSE; } if (optout_blockPos != NULL) { optout_blockPos->x = globs::objectGlobs.slugHoleBlocks[foundIndex].x; optout_blockPos->y = globs::objectGlobs.slugHoleBlocks[foundIndex].y; } return TRUE; } BOOL __cdecl lego::game::LegoObject_FindNearestWall (LegoObject *liveObj,int *out_bx,int *out_by,BOOL min1BlockDist,BOOL allowCorner, BOOL allowReinforced) { Map3D *map; BOOL isWall; BOOL BVar1; int objBlockPos_x; int objBlockPos_y; float *pBlockDistY; float *pfVar2; uint found; uint bx; uint by; longlong lVar3; Point2I objBlockPos; Point2F blockWorldPos; Point2F objWorldPos; Vector3F blockPosAndDists [100]; float dist; map = lrr::Lego_GetMap(); found = 0; LegoObject_GetPosition(liveObj,&objWorldPos.x,&objWorldPos.y); LegoObject_GetBlockPos(liveObj,&objBlockPos.x,&objBlockPos.y); by = objBlockPos.y - 10; objBlockPos_x = objBlockPos.x; objBlockPos_y = objBlockPos.y; if ((int)by < objBlockPos.y + 10) { do { bx = objBlockPos_x - 10; if ((int)bx < objBlockPos_x + 10) { pBlockDistY = &blockPosAndDists[found].y; do { isWall = Level_Block_IsWall(bx,by); pfVar2 = pBlockDistY; if (((isWall != 0) && ((allowReinforced != 0 || (BVar1 = Level_Block_IsReinforced(bx,by), BVar1 == 0)))) && ((allowCorner != 0 || (BVar1 = Level_Block_IsCorner(bx,by), BVar1 == 0)))) { lego::map::Map3D_BlockToWorldPos(map,bx,by,&blockWorldPos.x,&blockWorldPos.y); dist = SQRT((blockWorldPos.y - objWorldPos.y) * (blockWorldPos.y - objWorldPos.y) + (blockWorldPos.x - objWorldPos.x) * (blockWorldPos.x - objWorldPos.x)); if (((min1BlockDist == 0) || (map->blockSize <= dist)) && (found < 100)) { found += 1; pfVar2 = pBlockDistY + 3; pBlockDistY[-1] = (float)bx; *pBlockDistY = (float)by; // Distance is stored in the Z field. pBlockDistY[1] = dist; } } bx += 1; objBlockPos_x = objBlockPos.x; objBlockPos_y = objBlockPos.y; pBlockDistY = pfVar2; } while ((int)bx < objBlockPos.x + 10); } by += 1; } while ((int)by < objBlockPos_y + 10); } if (found == 0) { return FALSE; } std::qsort(blockPosAndDists,found,0xc,LegoObject_QsortCompareWallDistances); lVar3 = __ftol((float10)blockPosAndDists[0].x); *out_bx = (int)lVar3; lVar3 = __ftol((float10)blockPosAndDists[0].y); *out_by = (int)lVar3; return TRUE; } BOOL __cdecl lego::game::LegoObject_QsortCompareWallDistances(Vector3F *a,Vector3F *b) { if ((ushort)((ushort)(a->z < b->z) << 8 | (ushort)(a->z == b->z) << 0xe) == 0) { return 1; } if (a->z < b->z) { return -1; } return 0; } MeshLOD * __cdecl lego::game::LegoObject_LoadMeshLOD (Config *act,char *gameName,char *dirname,LOD_PolyLevel polyLOD,uint numCameraFrames) { char *keyPath; Config *prop; int cmp; MeshLOD *lastMeshLOD; uint setID; char *partName; MeshLOD *firstMeshLOD; char buff [256]; char *keyName; setID = 0; lastMeshLOD = NULL; firstMeshLOD = NULL; if (polyLOD != LOD_FPPoly) { numCameraFrames = 1; } if (numCameraFrames != 0) { do { if (polyLOD == LOD_FPPoly) { std::sprintf(buff,"FPPoly::Camera%i",setID + 1); } else { if (polyLOD == LOD_HighPoly) { keyName = "HighPoly"; } else { if (polyLOD != LOD_MediumPoly) goto LAB_0044ab0b; keyName = "MediumPoly"; } std::sprintf(buff,keyName); } LAB_0044ab0b: keyPath = cfg::Config_BuildStringID(gameName,buff,0); for (prop = cfg::Config_FindArray(act,keyPath); prop != NULL; prop = cfg::Config_GetNextItem(prop)) { partName = prop->key; if (*partName == '!') { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEPROMESHES) == MAIN_FLAG_NONE) { if (true) { partName = partName + 1; } goto LAB_0044ab53; } } else { LAB_0044ab53: cmp = std::_stricmp("NULL",prop->value); if (cmp == 0) { lastMeshLOD = gfx::MeshLOD_CreateEmpty(lastMeshLOD,partName,setID); } else { lastMeshLOD = gfx::MeshLOD_Create(lastMeshLOD,partName,dirname,prop->value,setID); } if (firstMeshLOD == NULL) { firstMeshLOD = lastMeshLOD; } } } setID += 1; } while (setID < numCameraFrames); } return firstMeshLOD; } BOOL __cdecl lego::game::LegoObject_UpdateBuildingPlacement (LegoObject_Type objType,LegoObject_ID objID,BOOL leftReleased,BOOL rightReleased, Point2F *opt_mouseWorldPos,uint mouseBlockX,uint mouseBlockY,BOOL execute, SelectPlace *selectPlace) { BOOL BVar1; Point2I *shapePoints; uint waterEntrances; Map3D *map; Point2I *shapeBlocks; uint constructHandle; LegoObject *oreProcessingObj; uint oreTypeCost; StatsFlags1 sflags1; uint crystalsCost; uint dir; uint by; Point2F *out_x; float *out_y; Point2I mouseBlockPos; Point2F wPos; LegoObject_ID oreObjID; float wOffX; float wOffY; by = mouseBlockY; dir = mouseBlockX; mouseBlockPos.x = mouseBlockX; mouseBlockPos.y = mouseBlockY; if (objType == LegoObject_Building) { if (execute != 0) { BVar1 = Level_Block_IsGround(mouseBlockX,mouseBlockY); if (BVar1 == 0) { if ((rightReleased == 0) && (front::Pointer_SetCurrent_IfTimerFinished(Pointer_CannotBuild), leftReleased != 0)) { lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); } gfx::SelectPlace_Hide(selectPlace,TRUE); } else { shapePoints = gfx::Building_GetShapePoints (globs::legoGlobs.buildingData + objID,&mouseBlockX); waterEntrances = stats::Stats_GetWaterEntrances(LegoObject_Building,objID,0); gfx::SelectPlace_Hide(selectPlace,FALSE); out_y = &wPos.y; out_x = &wPos; map = lrr::Lego_GetMap(); lego::map::Map3D_BlockToWorldPos(map,dir,by,&out_x->x,out_y); wOffX = opt_mouseWorldPos->x - wPos.x; wOffY = opt_mouseWorldPos->y - wPos.y; if (((ushort)((ushort)(wOffX < 0.0) << 8 | (ushort)(wOffX == 0.0) << 0xe) != 0) || (wOffX <= ABS(wOffY))) { if ((0.0 <= wOffX) || (mouseBlockY = (uint)ABS(wOffX), (ushort)((ushort)((float)mouseBlockY < ABS(wOffY)) << 8 | (ushort)((float)mouseBlockY == ABS(wOffY)) << 0xe) != 0)) { if (((ushort)((ushort)(wOffY < 0.0) << 8 | (ushort)(wOffY == 0.0) << 0xe) != 0) || (wOffY <= ABS(wOffX))) { if ((wOffY < 0.0) && (mouseBlockY = (uint)ABS(wOffY), (ushort)((ushort)((float)mouseBlockY < ABS(wOffX)) << 8 | (ushort)((float)mouseBlockY == ABS(wOffX)) << 0xe) == 0)) { globs::legoGlobs.placeObjDirection = DIRECTION_DOWN; } } else { globs::legoGlobs.placeObjDirection = DIRECTION_UP; } } else { globs::legoGlobs.placeObjDirection = DIRECTION_LEFT; } } else { globs::legoGlobs.placeObjDirection = DIRECTION_RIGHT; } dir = 0; do { shapeBlocks = gfx::SelectPlace_CheckAndUpdate (selectPlace,&mouseBlockPos,shapePoints,mouseBlockX, dir + globs::legoGlobs.placeObjDirection & DIRECTION_LEFT, (globs::legoGlobs.currLevel)->map,waterEntrances); if (shapeBlocks != NULL) { if ((rightReleased == 0) && (front::Pointer_SetCurrent_IfTimerFinished(Pointer_CanBuild), leftReleased != 0)) { constructHandle = Construction_Zone_StartBuilding (objID,&mouseBlockPos, dir + globs::legoGlobs.placeObjDirection & DIRECTION_LEFT,shapeBlocks, mouseBlockX); oreProcessingObj = LegoObject_FindResourceProcessingBuilding(NULL,&mouseBlockPos,LegoObject_Ore,0); oreTypeCost = stats::Stats_GetCostRefinedOre(LegoObject_Building,objID,0); sflags1 = stats::Stats_GetStatsFlags1(LegoObject_Building,objID); if ((sflags1 & STATS1_STOREOBJECTS) == STATS1_NONE) { // Only non-ToolStore objects require barriers. Construction_Zone_RequestBarriers(&mouseBlockPos,shapeBlocks,mouseBlockX); } crystalsCost = stats::Stats_GetCostCrystal(LegoObject_Building,objID,0); Construction_Zone_RequestResource (&mouseBlockPos,LegoObject_PowerCrystal,0,0,crystalsCost); if ((oreProcessingObj == NULL) || (oreTypeCost == 0)) { oreTypeCost = stats::Stats_GetCostOre(LegoObject_Building,objID,0); oreObjID = LegoObject_ID_Ore; } else { oreObjID = LegoObject_ID_ProcessedOre; } Construction_Zone_RequestResource (&mouseBlockPos,LegoObject_Ore,oreObjID,0,oreTypeCost); Construction_Zone_PlaceResource(constructHandle,NULL); gfx::SelectPlace_Hide(selectPlace,TRUE); front::Interface_BackToMain(); lrr::Lego_SetPointerSFX(PointerSFX_Okay); return 0; } globs::legoGlobs.placeObjDirection = dir + globs::legoGlobs.placeObjDirection & DIRECTION_LEFT; break; } dir += 1; } while (dir < 5); if (dir != 5) { return 1; } if ((rightReleased == 0) && (front::Pointer_SetCurrent_IfTimerFinished(Pointer_CannotBuild), leftReleased != 0)) { lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); front::Text_DisplayMessage(Text_CannotPlaceBuilding,FALSE,FALSE); return TRUE; } } front::Text_DisplayMessage(Text_CannotPlaceBuilding,FALSE,FALSE); return TRUE; } gfx::SelectPlace_Hide(selectPlace,TRUE); } return TRUE; } void __cdecl lego::front::LegoObject_LoadObjTtsSFX(Config *config,char *gameName) { char *keyPath; Config *prop; BOOL BVar1; int iVar2; SFX_ID (*paSVar3) [15]; LegoObject_Type local_8; LegoObject_ID local_4; paSVar3 = globs::objectGlobs.objectTtSFX; for (iVar2 = 300; iVar2 != 0; iVar2 += -1) { (*paSVar3)[0] = SFX_NULL; paSVar3 = (SFX_ID (*) [15])(*paSVar3 + 1); } iVar2 = 0x14; local_8 = LegoObject_Type_Count; do { iVar2 += -1; local_4 = 0xf; } while (iVar2 != 0); keyPath = cfg::Config_BuildStringID(gameName,"ObjTtSFXs",0); for (prop = cfg::Config_FindArray(config,keyPath); prop != NULL; prop = cfg::Config_GetNextItem(prop)) { BVar1 = lrr::Lego_GetObjectByName(prop->key,&local_8,&local_4,NULL); if ((BVar1 != 0) && (BVar1 = snd::SFX_GetType(prop->value,(SFX_ID *)&gameName), BVar1 != 0)) { globs::objectGlobs.objectTtSFX[local_8][local_4] = (SFX_ID)gameName; } } return; } int __cdecl lego::game::LegoObject_GetObjTtSFX(LegoObject *liveObj) { LegoObject_ID local_4; LegoObject_GetTypeAndID(liveObj,(LegoObject_Type *)&liveObj,&local_4); return *(int *)(local_4 * 4 + 0x4df814 + (int)liveObj * 0x3c); } void __cdecl lego::game::LegoObject_SetLevelEnding(BOOL ending) { if (ending != 0) { globs::objectGlobs.flags = globs::objectGlobs.flags | OBJECT_GLOB_FLAG_LEVELENDING; return; } globs::objectGlobs.flags = globs::objectGlobs.flags & ~OBJECT_GLOB_FLAG_LEVELENDING; return; } void __cdecl lego::game::LegoObject_FUN_0044b0a0(LegoObject *liveObj) { LegoObject *routeToObj; uint crystalCost; uint hasRouteToObj; LegoObject *spawnTargetObj; routeToObj = NULL; if (((((byte)globs::objectGlobs.flags & OBJECT_GLOB_FLAG_LEVELENDING) == 0) && (liveObj->type == LegoObject_Vehicle)) && ((liveObj->flags4 & LIVEOBJ4_CRYORECOSTDROPPED) == LIVEOBJ4_NONE)) { if ((liveObj->flags4 & LIVEOBJ4_DOCKOCCUPIED) != LIVEOBJ4_NONE) { routeToObj = liveObj->routeToObject; } spawnTargetObj = routeToObj; if (routeToObj == NULL) { spawnTargetObj = liveObj; } hasRouteToObj = (uint)(routeToObj != NULL); crystalCost = stats::Stats_GetCostCrystal(LegoObject_Vehicle,liveObj->id,0); LegoObject_SpawnDropCrystals_FUN_0044b110(spawnTargetObj,crystalCost,hasRouteToObj); liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_CRYORECOSTDROPPED; } return; } void __cdecl lego::game::LegoObject_SpawnDropCrystals_FUN_0044b110 (LegoObject *in_liveObj,int crystalCount,BOOL param_3) { Container *cont; Map3D *map; BOOL BVar1; LegoObject *liveObj; float10 fVar2; float in_x; float in_y; uint *out_bx; uint *out_by; float local_24; float local_20; float local_1c; float local_18; uint local_14; uint local_10; Vector3F local_c; if (crystalCount != 0) { do { if (((param_3 == 0) || (in_liveObj->type != LegoObject_Building)) || (cont = gfx::Building_GetEntranceNull(in_liveObj->building), cont == NULL)) { LegoObject_GetPosition(in_liveObj,&local_24,&local_20); } else { gfx::Container_GetPosition(cont,NULL,&local_c); local_24 = local_c.x; local_20 = local_c.y; } fVar2 = math::Maths_RandRange(-5.0,5.0); local_1c = (float)fVar2; fVar2 = math::Maths_RandRange(-5.0,5.0); local_18 = (float)fVar2; in_y = local_18 + local_20; out_by = &local_10; out_bx = &local_14; in_x = local_1c + local_24; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ(map,in_x,in_y,(int *)out_bx,(int *)out_by); if ((BVar1 != 0) && (BVar1 = Level_Block_IsGround(local_14,local_10), BVar1 != 0)) { local_24 = local_1c + local_24; local_20 = local_18 + local_20; } liveObj = LegoObject_CreateInWorld (globs::legoGlobs.contCrystal,LegoObject_PowerCrystal,0,0,local_24, local_20,0.0); ai::AITask_DoCollect(liveObj,0.0); crystalCount += -1; } while (crystalCount != 0); } return; } void __cdecl lego::game::LegoObject_CallsSpawnDropCrystals_FUN_0044b250(LegoObject *liveObj) { if (liveObj->stolenCrystalLevels != NULL) { LegoObject_SpawnDropCrystals_FUN_0044b110(liveObj,*liveObj->stolenCrystalLevels,0); } return; } void __cdecl lego::game::LegoObject_GenerateTinyRMs_FUN_0044b270(LegoObject *in_liveObj) { short sVar1; BOOL BVar2; LegoObject *liveObj; bool bVar3; char *objName; uint uVar4; int out_objIndex; LegoObject_Type out_objType; Container *local_c; float local_8; float local_4; bVar3 = false; BVar2 = lrr::Lego_GetObjectByName("RockMonster",&out_objType,(LegoObject_ID *)&out_objIndex,NULL); objName = (char *)in_liveObj; if (((BVar2 != 0) && (out_objType == in_liveObj->type)) && (out_objIndex == in_liveObj->id)) { objName = "TinyRM"; bVar3 = true; } if (!bVar3) { BVar2 = lrr::Lego_GetObjectByName ("Lavamonster",&out_objType,(LegoObject_ID *)&out_objIndex,NULL); if (((BVar2 != 0) && (out_objType == in_liveObj->type)) && (out_objIndex == in_liveObj->id)) { objName = "TinyRM"; bVar3 = true; } if (((!bVar3) && (BVar2 = lrr::Lego_GetObjectByName ("Icemonster",&out_objType,(LegoObject_ID *)&out_objIndex,NULL), BVar2 != 0)) && ((out_objType == in_liveObj->type && (out_objIndex == in_liveObj->id)))) { objName = "TinyIM"; } } BVar2 = lrr::Lego_GetObjectByName(objName,&out_objType,(LegoObject_ID *)&out_objIndex,&local_c); if (BVar2 != 0) { LegoObject_GetPosition(in_liveObj,&local_8,&local_4); uVar4 = 0; while( true ) { sVar1 = math::Maths_Rand(); liveObj = LegoObject_CreateInWorld (local_c,out_objType,out_objIndex,0,local_8,local_4, (float)((int)sVar1 % 7)); liveObj->health = -1.0; BVar2 = LegoObject_TryDepart_FUN_004499c0(liveObj); if (BVar2 == 0) break; uVar4 += 1; in_liveObj->flags2 = in_liveObj->flags2 | LIVEOBJ2_UNK_20; if (2 < uVar4) { return; } } LegoObject_Remove(liveObj); } return; } void __cdecl lego::game::LegoObject_GenerateSmallSpiders(uint bx,uint by,uint randSeed) { short sVar1; BOOL BVar2; Map3D *map; LegoObject *spiderObj; int i; float10 fVar3; Vector3F *out_vertPoses; LegoObject_ID objIndex; LegoObject_Type objType; Container *cont; Point2F genPos; Point2F local_30; Point2F local_18; BVar2 = lrr::Lego_GetObjectByName("SmallSpider",&objType,&objIndex,&cont); if (BVar2 != 0) { out_vertPoses = (Vector3F *)&local_30; map = lrr::Lego_GetMap(); lego::map::Map3D_GetBlockVertexPositions(map,bx,by,out_vertPoses); for (i = (randSeed & 3) + 2; i != 0; i += -1) { sVar1 = math::Maths_Rand(); fVar3 = math::Maths_RandRange(local_30.x - -1.0,local_18.x - 1.0); genPos.x = (float)fVar3; fVar3 = math::Maths_RandRange(local_30.y - 1.0,local_18.y - -1.0); genPos.y = (float)fVar3; spiderObj = LegoObject_CreateInWorld (cont,objType,objIndex,0,genPos.x,genPos.y,(float)((int)sVar1 % 7)); spiderObj->flags1 = spiderObj->flags1 | LIVEOBJ1_UNK_10000; } } return; } void __cdecl lego::ai::LegoObject_DoThrowLegoman(LegoObject *liveObj,LegoObject *thrownObj) { BOOL BVar1; float10 fVar2; BVar1 = game::LegoObject_IsActive(thrownObj,TRUE); if ((((BVar1 != 0) && ((thrownObj->flags2 & LIVEOBJ2_UNK_100) == LIVEOBJ2_NONE)) && ((*(byte *)&liveObj->flags2 & 1) == 0)) && ((thrownObj->flags2 & LIVEOBJ2_THROWN) == LIVEOBJ2_NONE)) { BVar1 = game::LegoObject_Check_LotsOfFlags1AndFlags2_FUN_0043bdb0(liveObj); if (BVar1 == 0) { fVar2 = stats::StatsObject_GetPainThreshold(liveObj); if (fVar2 < (float10)liveObj->health) { front::Interface_BackToMain_IfUnitIsSelected(thrownObj); game::LegoObject_Interrupt(thrownObj,FALSE,TRUE); game::LegoObject_Interrupt(liveObj,FALSE,TRUE); game::LegoObject_SetActivity(liveObj,Activity_ThrowMan,1); game::LegoObject_UpdateActivityChange(liveObj); game::LegoObject_SetActivity(thrownObj,Activity_ThrownByRockMonster,1); game::LegoObject_UpdateActivityChange(thrownObj); AITask_DoAnimationWait(liveObj); AITask_DoAnimationWait(thrownObj); liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_THROWING; thrownObj->flags2 = thrownObj->flags2 | LIVEOBJ2_THROWN; liveObj->throwObject = thrownObj; thrownObj->throwObject = liveObj; } } } return; } BOOL __cdecl lego::tools::LegoObject_Tool_IsBeamWeapon(LegoObject_ToolType toolType) { if (((toolType != LegoObject_ToolType_Laser) && (toolType != LegoObject_ToolType_PusherGun)) && (toolType != LegoObject_ToolType_FreezerGun)) { return FALSE; } return TRUE; } void __cdecl lego::game::LegoObject_MiniFigure_EquipTool(LegoObject *liveObj,LegoObject_ToolType toolType) { uint uVar1; Weapon_KnownType WVar2; BOOL BVar3; LegoObject_ToolType *pLVar4; uint uVar5; uVar1 = stats::StatsObject_GetNumOfToolsCanCarry(liveObj); uVar5 = 0; liveObj->field_3f4 = 0; if (uVar1 != 0) { liveObj->flags4 = liveObj->flags4 & ~LIVEOBJ4_UNK_4; WVar2 = LegoObject_GetEquippedBeam(liveObj); if ((WVar2 != Weapon_KnownType_None) || (BVar3 = tools::LegoObject_Tool_IsBeamWeapon(toolType), BVar3 != 0)) { liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_UNK_4; } BVar3 = tools::LegoObject_Tool_IsBeamWeapon(toolType); if ((BVar3 != 0) && (liveObj->numCarriedTools != 0)) { pLVar4 = liveObj->carriedTools; do { BVar3 = tools::LegoObject_Tool_IsBeamWeapon(*pLVar4); if (BVar3 != 0) { liveObj->carriedTools[uVar5] = toolType; return; } uVar5 += 1; pLVar4 = pLVar4 + 1; } while (uVar5 < liveObj->numCarriedTools); } if (uVar1 != 0) { uVar5 = liveObj->numCarriedTools; if (uVar5 == uVar1) { uVar1 = 0; if (uVar5 != 1) { pLVar4 = liveObj->carriedTools; do { uVar1 += 1; *pLVar4 = pLVar4[1]; pLVar4 = pLVar4 + 1; } while (uVar1 < liveObj->numCarriedTools - 1); } liveObj->carriedTools[liveObj->numCarriedTools - 1] = toolType; return; } liveObj->carriedTools[uVar5] = toolType; liveObj->numCarriedTools = liveObj->numCarriedTools + 1; } } return; } BOOL __cdecl lego::game::LegoObject_HasToolEquipped(LegoObject *liveObj,LegoObject_ToolType toolType) { uint uVar1; LegoObject_ToolType *pLVar2; uVar1 = 0; if (liveObj->numCarriedTools == 0) { return 0; } pLVar2 = liveObj->carriedTools; do { if (*pLVar2 == toolType) { return 1; } uVar1 += 1; pLVar2 = pLVar2 + 1; } while (uVar1 < liveObj->numCarriedTools); return 0; } BOOL __cdecl lego::game::LegoObject_TaskHasTool_FUN_0044b780(LegoObject *in_liveObj,AITask_Type taskType) { LegoObject *liveObj; BOOL BVar1; liveObj = in_liveObj; if (in_liveObj->type == LegoObject_MiniFigure) { BVar1 = stats::Stats_FindToolFromTaskType(taskType,(LegoObject_ToolType *)&in_liveObj); if (BVar1 != 0) { BVar1 = LegoObject_HasToolEquipped(liveObj,(LegoObject_ToolType)in_liveObj); return BVar1; } } return 1; } int __cdecl lego::game::LegoObject_DoGetTool(LegoObject *liveObj,LegoObject_ToolType toolType) { LegoObject *pLVar1; Container *cont; Map3D *pMVar2; BOOL BVar3; int iVar4; uint *puVar5; uint *puVar6; uint local_34; BOOL local_30; uint local_2c; uint local_28; Point2F local_24; uint local_1c; uint local_18; Point2F local_14; Vector3F local_c; LegoObject *liveObj_00; liveObj_00 = liveObj; local_30 = 0; iVar4 = 0; if (liveObj->type == LegoObject_MiniFigure) { LegoObject_GetPosition(liveObj,&local_24.x,&local_24.y); pLVar1 = Level_GetBuildingAtPosition(&local_24); if (pLVar1 != NULL) { cont = gfx::Building_GetToolNull(pLVar1->building,globs::objectGlobs.toolNullIndex[toolType]); gfx::Container_GetPosition(cont,NULL,&local_c); local_14.x = local_c.x; puVar6 = &local_28; puVar5 = &local_2c; local_14.y = local_c.y; pMVar2 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(pMVar2,local_c.x,local_c.y,(int *)puVar5,(int *)puVar6); puVar6 = &local_18; puVar5 = &local_1c; pMVar2 = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(pMVar2,local_24.x,local_24.y,(int *)puVar5,(int *)puVar6) ; if ((local_1c == local_2c) && (local_18 == local_28)) { local_30 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,1,(int *)&local_2c,(int *)&local_28,&local_14); } else { BVar3 = LegoObject_Route_Score_FUN_004413b0 (liveObj_00,local_1c,local_18,local_2c,local_28,(int **)&liveObj, (int **)&toolType,(int *)&local_34,0,NULL); if (BVar3 != 0) { BVar3 = LegoObject_Route_AllocPtr_FUN_004419c0 (liveObj_00,local_34,(int *)liveObj,(int *)toolType,&local_14); io::Mem_Free(liveObj); io::Mem_Free((void *)toolType); local_30 = BVar3; } } iVar4 = local_30; if (local_30 != 0) { liveObj_00->routeToObject = pLVar1; liveObj_00->routeBlocks[liveObj_00->routeBlocksTotal - 1].actionByte = ROUTE_ACTION_UNK_13; } } } return iVar4; } void __cdecl lego::game::LegoObject_Flocks_Initialise(LegoObject *in_liveObj) { LegoObject *liveObj; LegoObject *pLVar1; Container *opt_parent; Container *child; Container *pCVar2; Flocks *pFVar3; FlocksItem *subdata; float10 fVar4; float speed; float fVar5; float fVar6; LegoObject *cont; Vector3F vector2; Vector3F vector1; liveObj = in_liveObj; vector1.x = 0.0; vector1.y = 0.0; vector1.z = 0.0; vector2.x = 0.0; vector2.y = 0.0; vector2.z = 0.0; pLVar1 = (LegoObject *)stats::StatsObject_GetFlocks_Size(in_liveObj); opt_parent = LegoObject_GetActivityContainer(in_liveObj); child = gfx::Container_Create(opt_parent); pCVar2 = gfx::Container_GetRoot(); gfx::Container_SetParent(child,pCVar2); fVar6 = 0.0; cont = in_liveObj; fVar4 = stats::StatsObject_GetFlocks_Speed(in_liveObj); fVar5 = (float)fVar4; fVar4 = stats::StatsObject_GetFlocks_Turn(in_liveObj); pFVar3 = Flocks_LiveObject_Flocks_CreateData(NULL,NULL,(float)fVar4,fVar5,fVar6,(Container *)cont) ; in_liveObj->flocks = pFVar3; pFVar3->flocksSubdata1->cont = child; in_liveObj = pLVar1; if (0 < (int)pLVar1) { do { pCVar2 = gfx::Container_Clone(opt_parent); gfx::Container_SetParent(pCVar2,child); fVar4 = stats::StatsObject_GetFlocks_GoalUpdate(liveObj); fVar5 = (float)fVar4; fVar4 = stats::StatsObject_GetFlocks_Tightness(liveObj); fVar6 = (float)fVar4; fVar4 = stats::StatsObject_GetFlocks_Speed(liveObj); speed = (float)fVar4; fVar4 = stats::StatsObject_GetFlocks_Turn(liveObj); subdata = Flocks_LiveObject_Flocks_CreateSubdata (&vector1,&vector2,(float)fVar4,speed,fVar6,fVar5,pCVar2); Flocks_LiveObject_Flocks_AddSubdata(liveObj->flocks,subdata); in_liveObj = (LegoObject *)((int)&in_liveObj[-1].nextFree + 3); } while (in_liveObj != NULL); } return; } void __cdecl lego::math::LegoObject_FlocksMatrix_FUN_0044ba60(Container *cont,Matrix4F *ref_matrix,float scalar) { float fVar1; float fVar2; float fVar3; Vector3F vector; Matrix4F matrix_b; Matrix4F matrix_a; fVar1 = ref_matrix->values[3][1]; fVar2 = ref_matrix->values[3][0]; fVar3 = ref_matrix->values[3][2]; ref_matrix->values[3][0] = 0.0; ref_matrix->values[3][1] = 0.0; ref_matrix->values[3][2] = 0.0; // M_PI / 2 (1.570796) Matrix_RotX(&matrix_b,1.570796); Matrix_Mult(&matrix_a,&matrix_b,ref_matrix); Matrix_Copy(ref_matrix,&matrix_a); ref_matrix->values[3][0] = fVar2; ref_matrix->values[3][1] = fVar3; ref_matrix->values[3][2] = -fVar1 - scalar; gfx::Container_AddTransform(cont,Container_Combine_Replace,ref_matrix); return; } void __cdecl lego::game::LegoObject_Flocks_Callback_SubdataOrientationAnim (Flocks *flocksData,FlocksItem *subdata,float *pElapsed) { Container *cont; float y; float x; Map3D *pMVar1; float10 fVar2; float fVar3; float fVar4; Vector3F *out_vector; Vector3F local_30; Vector3F local_24; Vector3F local_18; Vector3F local_c; cont = subdata->cont; if (pElapsed[3] == 0.0) { math::LegoObject_FlocksMatrix_FUN_0044ba60(cont,&subdata->matrix,pElapsed[1]); if (pElapsed[2] != 0.0) { gfx::Container_GetOrientation(cont,NULL,&local_24,&local_30); local_30.x = local_30.x * 0.5; local_30.y = local_30.y * 0.5; local_30.z = (local_30.z - 1.0) * 0.5; gfx::Container_SetOrientation (cont,NULL,local_24.x,local_24.y,local_24.z,local_30.x,local_30.y,local_30.z); } } else { y = (subdata->matrix).values[3][2]; x = (subdata->matrix).values[3][0]; local_c.x = 0.0; local_c.y = 1.0; local_c.z = 0.0; local_18.x = 0.0; local_18.y = 0.0; local_18.z = -1.0; fVar3 = x; fVar4 = y; pMVar1 = lrr::Lego_GetMap(); fVar2 = lego::map::Map3D_GetWorldZ(pMVar1,fVar3,fVar4); out_vector = &local_30; fVar3 = x; fVar4 = y; pMVar1 = lrr::Lego_GetMap(); lego::map::Map3D_FUN_0044fd70(pMVar1,fVar3,fVar4,out_vector); math::Maths_Vector3DRotate(&local_24,&local_c,&local_18,-subdata->rotationY_24); gfx::Container_SetOrientation (cont,NULL,local_30.x,local_30.y,local_30.z,local_24.x,local_24.y,local_24.z); gfx::Container_GetOrientation(cont,NULL,&local_30,&local_24); gfx::Container_SetOrientation (cont,NULL,local_24.x,local_24.y,local_24.z,local_30.x,local_30.y,local_30.z); gfx::Container_SetPosition(cont,NULL,x,y,(float)fVar2); } if (pElapsed[4] == 0.0) { gfx::Container_MoveAnimation(cont,*pElapsed); } else { if (0.0 <= subdata->rotationX_28) { gfx::Container_MoveAnimation(cont,*pElapsed); return; } fVar2 = gfx::Container_GetAnimationTime(cont); if (fVar2 != (float10)0.0) { fVar2 = gfx::Container_MoveAnimation(cont,*pElapsed); if ((ushort)((ushort)(fVar2 < (float10)0.0) << 8 | (ushort)(fVar2 == (float10)0.0) << 0xe) == 0) { gfx::Container_SetAnimationTime(cont,0.0); return; } } } return; } void __cdecl lego::game::LegoObject_Flocks_Container_ReleaseCallback (Flocks *flockData,FlocksItem *subdata,void *data) { Container *child; child = subdata->cont; if (child != NULL) { gfx::Container_SetParent(child,NULL); gfx::Container_Remove(child); } return; } void __cdecl lego::game::LegoObject_Flocks_Free(Flocks *flockData) { Container *child; if (flockData != NULL) { Flocks_CallbackForAllSubdata(flockData,LegoObject_Flocks_Container_ReleaseCallback,NULL); child = flockData->flocksSubdata1->cont; gfx::Container_SetParent(child,NULL); gfx::Container_Remove(child); flockData->flocksSubdata1->cont = NULL; Flocks_FreeData(flockData); } return; } void __cdecl lego::game::LegoObject_Flocks_SetParameters(LegoObject *liveObj,BOOL additive) { Flocks *flocksData; float10 fVar1; float fVar2; float fVar3; float fVar4; flocksData = liveObj->flocks; if (additive != 0) { fVar1 = stats::StatsObject_GetFlocks_Tightness(liveObj); fVar4 = (float)(fVar1 + fVar1); fVar1 = stats::StatsObject_GetFlocks_Speed(liveObj); fVar3 = (float)(fVar1 + fVar1); fVar1 = stats::StatsObject_GetFlocks_Turn(liveObj); Flocks_SetParameters1(flocksData,(float)(fVar1 + fVar1),fVar3,fVar4); fVar1 = stats::StatsObject_GetFlocks_GoalUpdate(liveObj); fVar4 = (float)(fVar1 + fVar1); fVar1 = stats::StatsObject_GetFlocks_Tightness(liveObj); fVar3 = (float)(fVar1 + fVar1); fVar1 = stats::StatsObject_GetFlocks_Speed(liveObj); fVar2 = (float)(fVar1 * (float10)3.0); fVar1 = stats::StatsObject_GetFlocks_Turn(liveObj); Flocks_SetGlobal_AndAllSubdataParameters (flocksData,(float)(fVar1 * (float10)4.0),fVar2,fVar3,fVar4); return; } fVar1 = stats::StatsObject_GetFlocks_Tightness(liveObj); fVar4 = (float)fVar1; fVar1 = stats::StatsObject_GetFlocks_Speed(liveObj); fVar3 = (float)fVar1; fVar1 = stats::StatsObject_GetFlocks_Turn(liveObj); Flocks_SetParameters1(flocksData,(float)fVar1,fVar3,fVar4); fVar1 = stats::StatsObject_GetFlocks_GoalUpdate(liveObj); fVar4 = (float)fVar1; fVar1 = stats::StatsObject_GetFlocks_Tightness(liveObj); fVar3 = (float)fVar1; fVar1 = stats::StatsObject_GetFlocks_Speed(liveObj); fVar2 = (float)fVar1; fVar1 = stats::StatsObject_GetFlocks_Turn(liveObj); Flocks_SetGlobal_AndAllSubdataParameters(flocksData,(float)fVar1,fVar2,fVar3,fVar4); return; } void __cdecl lego::game::LegoObject_Flocks_FUN_0044bef0(LegoObject *liveObj,float elapsed) { Flocks *pFVar1; StatsFlags1 sflags1; Container *pCVar2; BOOL BVar3; float10 fVar4; float10 randomness; Container *opt_ref; Vector3F *out_pos; Vector3F local_2c; Vector3F local_20; float local_14; float local_10; uint local_c; uint local_8; uint local_4; FlocksFlags *pFFlags; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_FLOCKS) != STATS1_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_FLOCKS_DEBUG) == STATS1_NONE) { pCVar2 = LegoObject_GetActivityContainer(liveObj); BVar3 = gfx::Container_IsHidden(pCVar2); if (BVar3 == 0) { LegoObject_Hide(liveObj,TRUE); } } pFVar1 = liveObj->flocks; if ((*(byte *)&pFVar1->flags & FLOCKS_FLAG_UNK_1) != 0) { pFVar1->field_14 = elapsed + (float)pFVar1->field_14; } fVar4 = stats::StatsObject_GetFlocks_AttackTime(liveObj); if (((ushort)((ushort)(fVar4 < (float10)elapsed) << 8 | (ushort)(fVar4 == (float10)elapsed) << 0xe) != 0) && ((*(byte *)&liveObj->flags2 & 0x80) == 0)) { ai::AITask_LiveObject_SetAITaskUnk(liveObj,AITask_Type_Follow,NULL,TRUE); pFFlags = &liveObj->flocks->flags; *pFFlags = *pFFlags & 0xfffffffe; } out_pos = &local_20; opt_ref = NULL; pCVar2 = LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(pCVar2,opt_ref,out_pos); local_2c.y = -local_20.z; local_2c.x = local_20.x; local_2c.z = local_20.y; // Flocks_GetNumSubdata(liveObj->flocks); returns uint32; BVar3 = gfx::AnimClone_IsLws__Flic_GetWidth((AnimClone *)liveObj->flocks); if (BVar3 == 0) { Flocks_SetVector1(liveObj->flocks,&local_2c); Flocks_SetAllSubdataVectorC(liveObj->flocks,&local_2c); Flocks_SetAllSubdataVector0(liveObj->flocks,&local_2c); } if ((*(byte *)&liveObj->flags2 & LIVEOBJ2_UNK_80) == 0) { LegoObject_Flocks_SetParameters(liveObj,FALSE); } else { LegoObject_Flocks_SetParameters(liveObj,TRUE); // & ~LIVEOBJ2_UNK_80 (0x80) liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } Flocks_SetVector2(liveObj->flocks,&local_2c); randomness = stats::StatsObject_GetFlocks_Randomness(liveObj); Flocks_FUN_0040fe80(liveObj->flocks,(float)randomness); Flocks_Subdata_UpdateMove(liveObj->flocks,elapsed); local_14 = elapsed; fVar4 = stats::StatsObject_GetFlocks_Height(liveObj); local_10 = (float)fVar4; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); // STATS1_FLOCKS_SMOOTH local_c = sflags1 >> 0x17 & 1; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); // STATS1_FLOCKS_ONGROUND local_8 = sflags1 >> 0x1a & 1; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); // STATS1_FLOCKS_ANIMATEBYPITCH local_4 = sflags1 >> 0x1c & 1; Flocks_CallbackForAllSubdata (liveObj->flocks,LegoObject_Flocks_Callback_SubdataOrientationAnim,&local_14); } return; } void __cdecl lego::game::LegoObject_FlocksDestroy(LegoObject *liveObj) { StatsFlags1 SVar1; Flocks **ppFVar2; Flocks *pFVar3; float10 fVar4; Vector3F local_c; SVar1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((SVar1 & STATS1_FLOCKS_QUICKDESTROY) != STATS1_NONE) { LegoObject_Flocks_Free(liveObj->flocks); return; } ppFVar2 = (Flocks **)io::Mem_Alloc(0x10); if (ppFVar2 == NULL) { LegoObject_Flocks_Free(liveObj->flocks); return; } pFVar3 = liveObj->flocks; local_c.x = (pFVar3->flocksSubdata1->vector_0).x; local_c.y = (pFVar3->flocksSubdata1->vector_0).y; local_c.z = (pFVar3->flocksSubdata1->vector_0).z; *ppFVar2 = pFVar3; pFVar3 = (Flocks *)stats::StatsObject_GetStatsFlags1(liveObj); ppFVar2[2] = pFVar3; ppFVar2[1] = (Flocks *)globs::objectGlobs.s_FlocksDestroy_c640; fVar4 = stats::StatsObject_GetFlocks_Height(liveObj); ppFVar2[3] = (Flocks *)(float)fVar4; globs::objectGlobs.s_FlocksDestroy_c640 = ppFVar2; Flocks_SetVector1(liveObj->flocks,&local_c); Flocks_SetAllSubdataVector0(liveObj->flocks,&local_c); return; } // WARNING: Type propagation algorithm not settling void __cdecl lego::game::LegoObject_Flocks_Update_FUN_0044c1c0(float *pElapsed) { FlocksItem *pFVar1; BOOL BVar2; FlocksItem *pFVar3; FlocksItem *buffer; FlocksItem *pFVar4; float local_14; BOOL local_10; uint local_c; uint local_8; uint local_4; pFVar3 = NULL; buffer = (FlocksItem *)globs::objectGlobs.s_FlocksDestroy_c640; if (globs::objectGlobs.s_FlocksDestroy_c640 != NULL) { do { Flocks_CallbackForAllSubdata (*(Flocks **)&buffer->vector_0,Flocks_Callback_FUN_00410000,pElapsed); local_14 = *pElapsed; local_10 = (BOOL)(buffer->vector_c).x; local_c = (uint)*(float *)((int)&buffer->vector_0 + 8) >> 0x17 & 1; local_8 = (uint)*(float *)((int)&buffer->vector_0 + 8) >> 0x1a & 1; local_4 = (uint)*(float *)((int)&buffer->vector_0 + 8) >> 0x1c & 1; Flocks_CallbackForAllSubdata (*(Flocks **)&buffer->vector_0,LegoObject_Flocks_Callback_SubdataOrientationAnim, &local_14); BVar2 = Flocks_CompareAllVecs_0_c(*(Flocks **)&buffer->vector_0); if (BVar2 == 0) { pFVar4 = *(FlocksItem **)((int)&buffer->vector_0 + 4); } else { pFVar4 = *(FlocksItem **)((int)&buffer->vector_0 + 4); pFVar1 = pFVar4; if (pFVar3 != NULL) { *(FlocksItem **)((int)&pFVar3->vector_0 + 4) = pFVar4; pFVar1 = (FlocksItem *)globs::objectGlobs.s_FlocksDestroy_c640; } globs::objectGlobs.s_FlocksDestroy_c640 = (void **)pFVar1; LegoObject_Flocks_Free(*(Flocks **)&buffer->vector_0); io::Mem_Free(buffer); buffer = pFVar3; } pFVar3 = buffer; buffer = pFVar4; } while (pFVar4 != NULL); } return; } BOOL __cdecl lego::game::LegoObject_DestroyRockMonster_FUN_0044c290(LegoObject *liveObj) { if ((ushort)((ushort)(liveObj->animTime < 0.0) << 8 | (ushort)(liveObj->animTime == 0.0) << 0xe) == 0) { // & ~LIVEOBJ1_CRUMBLING (0x100000) liveObj->flags1 = liveObj->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING|LIVEOBJ1_DRILLINGSTART |LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT|LIVEOBJ1_EXPANDING| LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800|LIVEOBJ1_GETTINGHIT| LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING|LIVEOBJ1_UNK_10000| LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING|LIVEOBJ1_TELEPORTINGDOWN| LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_CAUGHTINWEB| LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING| LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); LegoObject_GenerateTinyRMs_FUN_0044b270(liveObj); LegoObject_CallsSpawnDropCrystals_FUN_0044b250(liveObj); liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_REMOVING; reward::RewardQuota_RockMonsterDestroyed(); return TRUE; } return 0; } BOOL __cdecl lego::game::LegoObject_Freeze(LegoObject *liveObj,float freezerTime) { LegoObject *iceCubeObj; float10 heading; Vector3F position; if (((liveObj->flags2 & LIVEOBJ2_FROZEN) == LIVEOBJ2_NONE) && (liveObj->type == LegoObject_RockMonster)) { liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_FROZEN; liveObj->freezeTimer = freezerTime * 25.0; LegoObject_GetPosition(liveObj,&position.x,&position.y); heading = LegoObject_GetHeading(liveObj); iceCubeObj = LegoObject_CreateInWorld (globs::legoGlobs.contIceCube,LegoObject_IceCube,0,0,position.x, position.y,(float)heading); gfx::Container_SetActivity(iceCubeObj->other,"Start"); gfx::Container_SetAnimationTime(iceCubeObj->other,0.0); iceCubeObj->flags1 = iceCubeObj->flags1 | LIVEOBJ1_EXPANDING; liveObj->freezeObject = iceCubeObj; iceCubeObj->freezeObject = liveObj; return TRUE; } return FALSE; } void __cdecl lego::game::LegoObject_FUN_0044c3d0(LegoObject *liveObj) { LiveFlags3 *pLFlags3; if ((liveObj->freezeObject->flags1 & LIVEOBJ1_TELEPORTINGDOWN) == LIVEOBJ1_NONE) { // 100.0 liveObj->freezeObject->health = (float)&DAT_42c80000; pLFlags3 = &liveObj->freezeObject->flags3; *pLFlags3 = *pLFlags3 | LIVEOBJ3_REMOVING; } return; } BOOL __cdecl lego::game::LegoObject_Push(LegoObject *liveObj,Point2F *pushVec2D,float pushDist) { LegoObject_Type objType; objType = liveObj->type; if (((objType != LegoObject_MiniFigure) && (objType != LegoObject_RockMonster)) && (objType != LegoObject_Vehicle)) { return FALSE; } LegoObject_Interrupt(liveObj,FALSE,TRUE); (liveObj->pushingVec2D).x = pushVec2D->x; (liveObj->pushingVec2D).y = pushVec2D->y; liveObj->pushingDist = pushDist; liveObj->flags2 = liveObj->flags2 | LIVEOBJ2_PUSHED; return TRUE; } void __cdecl lego::game::LegoObject_UpdatePushing(LegoObject *liveObj,float elapsed) { float fVar1; Map3D *map; int iVar2; LegoObject *pLVar3; float fVar4; float fVar5; int *piVar6; int *piVar7; Point2F objectPos; float local_10; float local_c; int bxDest; int byDest; LegoObject_GetPosition(liveObj,&objectPos.x,&objectPos.y); local_10 = (liveObj->pushingVec2D).x * elapsed; piVar7 = &byDest; piVar6 = &bxDest; local_c = (liveObj->pushingVec2D).y * elapsed; fVar4 = local_10 + objectPos.x; fVar5 = local_c + objectPos.y; objectPos.x = fVar4; objectPos.y = fVar5; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar4,fVar5,piVar6,piVar7); iVar2 = Lego_GetCrossTerrainType(liveObj,bxDest,byDest,bxDest,byDest,TRUE); if (iVar2 == 0) { LAB_0044c517: fVar5 = (liveObj->pushingVec2D).x; fVar1 = (liveObj->pushingVec2D).y; fVar4 = (liveObj->pushingVec2D).y; fVar4 = 1.0 / SQRT(fVar5 * fVar5 + fVar4 * fVar4); fVar5 = SQRT(fVar5 * fVar5 + fVar1 * fVar1); (liveObj->pushingVec2D).x = (liveObj->pushingVec2D).x * fVar4; (liveObj->pushingVec2D).y = fVar4 * (liveObj->pushingVec2D).y; fVar4 = (liveObj->pushingVec2D).x; if ((ushort)((ushort)(fVar4 < 0.5) << 8 | (ushort)(fVar4 == 0.5) << 0xe) == 0) { (liveObj->pushingVec2D).x = 1.0; (liveObj->pushingVec2D).y = 0.0; } else { if (-0.5 <= (liveObj->pushingVec2D).x) { fVar4 = (liveObj->pushingVec2D).y; if ((ushort)((ushort)(fVar4 < 0.5) << 8 | (ushort)(fVar4 == 0.5) << 0xe) == 0) { (liveObj->pushingVec2D).x = 0.0; (liveObj->pushingVec2D).y = 1.0; } else { if ((liveObj->pushingVec2D).y < -0.5) { (liveObj->pushingVec2D).x = 0.0; (liveObj->pushingVec2D).y = -1.0; } } } else { (liveObj->pushingVec2D).x = -1.0; (liveObj->pushingVec2D).y = 0.0; } } (liveObj->pushingVec2D).x = (liveObj->pushingVec2D).x * fVar5; (liveObj->pushingVec2D).y = (liveObj->pushingVec2D).y * fVar5; LegoObject_GetPosition(liveObj,&objectPos.x,&objectPos.y); local_10 = (liveObj->pushingVec2D).x * elapsed; piVar7 = &byDest; piVar6 = &bxDest; local_c = (liveObj->pushingVec2D).y * elapsed; fVar4 = local_10 + objectPos.x; fVar5 = local_c + objectPos.y; objectPos.x = fVar4; objectPos.y = fVar5; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar4,fVar5,piVar6,piVar7); iVar2 = Lego_GetCrossTerrainType(liveObj,bxDest,byDest,bxDest,byDest,TRUE); if (iVar2 != 0) { pLVar3 = LegoObject_DoCollisionCallbacks_FUN_00446030(liveObj,&objectPos,0.0,0); if (pLVar3 == NULL) goto LAB_0044c6eb; } liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } else { pLVar3 = LegoObject_DoCollisionCallbacks_FUN_00446030(liveObj,&objectPos,0.0,0); if (pLVar3 != NULL) goto LAB_0044c517; LAB_0044c6eb: LegoObject_SetPositionAndHeading(liveObj,objectPos.x,objectPos.y,0.0,0); } if ((ushort)((ushort)(liveObj->pushingDist < 0.0) << 8 | (ushort)(liveObj->pushingDist == 0.0) << 0xe) != 0) { liveObj->flags2 = liveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_DRIVING|LIVEOBJ2_UNK_10| LIVEOBJ2_UNK_20|LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH| LIVEOBJ2_TRAINING|LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000| LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); } liveObj->pushingDist = liveObj->pushingDist - SQRT(local_c * local_c + local_10 * local_10); return; } void __cdecl lego::game::LegoObject_TryEnterLaserTrackerMode(LegoObject *liveObj) { StatsFlags2 sflags2; StatsFlags1 sflags1; if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_DOUBLESELECTREADY) != 0) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_CANDOUBLESELECT) != STATS2_NONE) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) || (liveObj->driveObject != NULL)) { globs::legoGlobs.flags1 |= GAME1_LASERTRACKER; liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_LASERTRACKERMODE; } } } front::Interface_BackToMain(); return; } BOOL __cdecl lego::game::LegoObject_Callback_ExitLaserTrackerMode(LegoObject *liveObj,void *unused) { if ((*(byte *)&liveObj->flags4 & 1) != 0) { globs::legoGlobs.flags1 &= ~GAME1_LASERTRACKER; } liveObj->flags4 = liveObj->flags4 & ~LIVEOBJ4_LASERTRACKERMODE; return 0; } // Seems to be completely identical to LiveObject_MiniFigureHasBeamEquipped @ 004496a0 BOOL __cdecl lego::game::LegoObject_MiniFigureHasBeamEquipped2(LegoObject *liveObj) { Weapon_KnownType knownWeapon; if (liveObj->type == LegoObject_MiniFigure) { knownWeapon = LegoObject_GetEquippedBeam(liveObj); if (knownWeapon != Weapon_KnownType_None) { return TRUE; } } return 0; } void __cdecl lego::game::LegoObject_CameraCycleUnits(void) { BOOL BVar1; BOOL noBuildings; globs::objectGlobs.flags |= OBJECT_GLOB_FLAG_CYCLEUNITS; BVar1 = LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_CameraCycleFindUnit,NULL); if (BVar1 == 0) { if (globs::objectGlobs.cycleBuildingCount == 0) { noBuildings = TRUE; BVar1 = LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_CameraCycleFindUnit,&noBuildings); if ((BVar1 == 0) && (globs::objectGlobs.cycleUnitCount != 0)) { globs::objectGlobs.cycleUnitCount = 0; globs::objectGlobs.cycleBuildingCount = 0; LegoObject_RunThroughListsSkipUpgradeParts (LegoObject_Callback_CameraCycleFindUnit,&noBuildings); return; } } else { globs::objectGlobs.cycleUnitCount = 0; globs::objectGlobs.cycleBuildingCount = 0; LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_CameraCycleFindUnit,NULL); } } return; } // opt_pNoBuildings : false to check Buildings, true to check MiniFigures BOOL __cdecl lego::game::LegoObject_Callback_CameraCycleFindUnit(LegoObject *liveObj,BOOL *opt_pNoBuildings) { BOOL cycleMiniFigures; uint i; BOOL BVar1; LegoObject **pCycleLiveObj; Vector3F worldMousePos; cycleMiniFigures = FALSE; if (opt_pNoBuildings != NULL) { cycleMiniFigures = *opt_pNoBuildings; } if (cycleMiniFigures == 0) { if (liveObj->type != LegoObject_Building) { return 0; } } else { if (liveObj->type != LegoObject_MiniFigure) { return 0; } } i = 0; if (globs::objectGlobs.cycleUnitCount != 0) { pCycleLiveObj = globs::objectGlobs.cycleUnits; do { if (*pCycleLiveObj == liveObj) { return 0; } i += 1; pCycleLiveObj = pCycleLiveObj + 1; } while (i < globs::objectGlobs.cycleUnitCount); } if (globs::objectGlobs.cycleUnitCount < 0x100) { globs::objectGlobs.cycleUnits[globs::objectGlobs.cycleUnitCount] = liveObj; globs::objectGlobs.cycleUnitCount += 1; if (liveObj->type == LegoObject_Building) { globs::objectGlobs.cycleBuildingCount += 1; } lrr::Lego_Goto(liveObj,NULL,FALSE); BVar1 = lego::map::Map3D_GetIntersections ((globs::legoGlobs.currLevel)->map,globs::legoGlobs.viewMain,globs::INPUT.msx, globs::INPUT.msy,(uint *)&opt_pNoBuildings,(uint *)&liveObj,&worldMousePos); if (BVar1 != 0) { gfx::Container_SetPosition (globs::legoGlobs.rootLight,NULL,worldMousePos.x,worldMousePos.y, worldMousePos.z - 250.0); return TRUE; } } else { globs::objectGlobs.cycleUnitCount = 0; globs::objectGlobs.cycleBuildingCount = 0; } return TRUE; } void __cdecl lego::light::LightEffects_Initialise (Container *rootSpotlight,Container *rootLight,float initialRed,float initialGreen, float initialBlue) { globs::lightGlobs.initialRGB.red = initialRed; globs::lightGlobs.initialRGB.green = initialGreen; globs::lightGlobs.currentRGB.red = initialRed; globs::lightGlobs.currentRGB.green = initialGreen; globs::lightGlobs.initialRGB.blue = initialBlue; globs::lightGlobs.currentRGB.blue = initialBlue; globs::lightGlobs.rootSpotlight = rootSpotlight; globs::lightGlobs.rootLight = rootLight; LightEffects_ResetSpotlightColour(); return; } // Resets LightEffects to its initialRGB colour value (hardcoded as 0.8:0.8:0.8) void __cdecl lego::light::LightEffects_ResetSpotlightColour(void) { gfx::Container_SetColourAlpha (globs::lightGlobs.rootSpotlight,globs::lightGlobs.initialRGB.red, globs::lightGlobs.initialRGB.green,globs::lightGlobs.initialRGB.blue,1.0); return; } void __cdecl lego::light::LightEffects_SetDisabled(BOOL isDisabled) { if (isDisabled != 0) { globs::lightGlobs.flags |= LIGHTFX_GLOB_FLAG_DISABLED; LightEffects_ResetSpotlightColour(); return; } globs::lightGlobs.flags = globs::lightGlobs.flags & ~LIGHTFX_GLOB_FLAG_DISABLED; return; } BOOL __cdecl lego::light::LightEffects_Load(Config *config,char *gameName) { BOOL BVar1; LightEffects_LoadBlink(config,gameName); LightEffects_LoadFade(config,gameName); BVar1 = LightEffects_LoadMove(config,gameName); return BVar1; } BOOL __cdecl lego::light::LightEffects_LoadBlink(Config *config,char *gameName) { char *pcVar1; BOOL BVar2; char *pcVar3; int iVar4; float10 waitMin; float10 waitMax; float *out_r; float *out_g; float *out_b; float blueMax; float greenMax; float redMax; char *stringParts [10]; pcVar3 = gameName; out_b = &blueMax; out_g = &greenMax; out_r = &redMax; pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","BlinkRGBMax",0); BVar2 = cfg::Config_GetRGBValue(config,pcVar1,out_r,out_g,out_b); if (BVar2 != 0) { pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","MaxChangeAllowed",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","MaxChangeAllowed",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); } waitMin = std::atof(pcVar1); // changeMax = gameName = (char *)(float)waitMin; if ((float10)0.0 != waitMin) { // changeMax /= 255.0; gameName = (char *)((float)gameName * 0.003921569); } pcVar3 = cfg::Config_BuildStringID(pcVar3,"LightEffects","RandomRangeForTimeBetweenBlinks",0); pcVar3 = cfg::Config_GetStringValue(config,pcVar3); if (pcVar3 != NULL) { iVar4 = util::Util_Tokenise(pcVar3,stringParts,":"); if (iVar4 == 2) { waitMin = std::atof(stringParts[0]); waitMax = std::atof(stringParts[1]); io::Mem_Free(pcVar3); LightEffects_SetBlink (redMax,greenMax,blueMax,(float)gameName,(float)(waitMin * (float10)25.0), (float)(waitMax * (float10)25.0)); return TRUE; } io::Mem_Free(pcVar3); } } return FALSE; } void __cdecl lego::light::LightEffects_SetBlink (float redMax,float greenMax,float blueMax,float changeMax,float waitMin,float waitMax) { globs::lightGlobs.blinkRGBMax.red = redMax; globs::lightGlobs.blinkRGBMax.green = greenMax; globs::lightGlobs.blinkRGBMax.blue = blueMax; globs::lightGlobs.blinkWaitRange.min = waitMin; globs::lightGlobs.blinkWaitRange.max = waitMax; globs::lightGlobs.blinkChangeMax = changeMax; globs::lightGlobs.flags = globs::lightGlobs.flags | LIGHTFX_GLOB_FLAG_HASBLINK; return; } BOOL __cdecl lego::light::LightEffects_LoadFade(Config *config,char *gameName) { char *pcVar1; BOOL BVar2; int iVar3; float10 waitMin; float10 waitMax; float10 speedMin; float10 speedMax; float10 holdMin; float10 holdMax; float *pfVar4; float *pfVar5; float *pfVar6; float maxFade_; float minFade_; float maxTime_; float minTime_; float blueMax; float greenMax; float redMax; float blueMin; float greenMin; float redMin; char *stringParts [10]; pfVar6 = &blueMin; pfVar5 = &greenMin; pfVar4 = &redMin; pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","FadeRGBMin",0); BVar2 = cfg::Config_GetRGBValue(config,pcVar1,pfVar4,pfVar5,pfVar6); if (BVar2 != 0) { pfVar6 = &blueMax; pfVar5 = &greenMax; pfVar4 = &redMax; pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","FadeRGBMax",0); BVar2 = cfg::Config_GetRGBValue(config,pcVar1,pfVar4,pfVar5,pfVar6); if (BVar2 != 0) { pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","RandomRangeForTimeBetweenFades",0) ; pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 != NULL) { iVar3 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar3 == 2) { waitMin = std::atof(stringParts[0]); waitMax = std::atof(stringParts[1]); io::Mem_Free(pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","RandomRangeForFadeTimeFade",0) ; pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { return 0; } iVar3 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar3 == 2) { speedMin = std::atof(stringParts[0]); speedMax = std::atof(stringParts[1]); io::Mem_Free(pcVar1); pcVar1 = cfg::Config_BuildStringID (gameName,"LightEffects","RandomRangeForHoldTimeOfFade",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { return 0; } iVar3 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar3 == 2) { holdMin = std::atof(stringParts[0]); holdMax = std::atof(stringParts[1]); io::Mem_Free(pcVar1); LightEffects_SetFade (redMin,greenMin,blueMin,redMax,greenMax,blueMax, (float)(waitMin * (float10)25.0),(float)(waitMax * (float10)25.0), (float)(speedMin * (float10)25.0),(float)(speedMax * (float10)25.0), (float)(holdMin * (float10)25.0),(float)(holdMax * (float10)25.0)); return TRUE; } } } // this will free any of the 3 str mallocs above, if any numParts != 2 io::Mem_Free(pcVar1); } } } return FALSE; } void __cdecl lego::light::LightEffects_SetFade (float redMin,float greenMin,float blueMin,float redMax,float greenMax,float blueMax, float waitMin,float waitMax,float speedMin,float speedMax,float holdMin,float holdMax) { globs::lightGlobs.fadeRGBMin.red = redMin; globs::lightGlobs.fadeRGBMin.green = greenMin; globs::lightGlobs.fadeRGBMin.blue = blueMin; globs::lightGlobs.fadeRGBMax.red = redMax; globs::lightGlobs.fadeRGBMax.green = greenMax; globs::lightGlobs.fadeRGBMax.blue = blueMax; globs::lightGlobs.fadeWaitRange.min = waitMin; globs::lightGlobs.fadeWaitRange.max = waitMax; globs::lightGlobs.fadeSpeedRange.min = speedMin; globs::lightGlobs.fadeSpeedRange.max = speedMax; globs::lightGlobs.fadeHoldRange.min = holdMin; globs::lightGlobs.fadeHoldRange.max = holdMax; globs::lightGlobs.flags = globs::lightGlobs.flags | LIGHTFX_GLOB_FLAG_HASFADE; return; } BOOL __cdecl lego::light::LightEffects_LoadMove(Config *config,char *gameName) { char *pcVar1; int iVar2; float10 waitMin; float10 waitMax; float10 speedMin; float10 speedMax; float10 distMin; float10 distMax; float10 limitX; float10 limitY; float10 limitZ; float limitX_; float maxDist_; float minDist_; float maxSpeed_; float minSpeed_; float maxTime_; float minTime_; char *stringParts [10]; pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","RandomRangeForTimeBetweenMoves",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 != NULL) { iVar2 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar2 == 2) { waitMin = std::atof(stringParts[0]); waitMax = std::atof(stringParts[1]); io::Mem_Free(pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","RandomRangeForSpeedOfMove",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { return 0; } iVar2 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar2 == 2) { speedMin = std::atof(stringParts[0]); speedMax = std::atof(stringParts[1]); io::Mem_Free(pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","RandomRangeForDistOfMove",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { return 0; } iVar2 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar2 == 2) { distMin = std::atof(stringParts[0]); distMax = std::atof(stringParts[1]); io::Mem_Free(pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"LightEffects","MoveLimit",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { return 0; } iVar2 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar2 == 3) { limitX = std::atof(stringParts[0]); limitY = std::atof(stringParts[1]); limitZ = std::atof(stringParts[2]); io::Mem_Free(pcVar1); LightEffects_SetMove ((float)(waitMin * (float10)25.0),(float)(waitMax * (float10)25.0), (float)(speedMin * (float10)25.0),(float)(speedMax * (float10)25.0), (float)distMin,(float)distMax,(float)limitX,(float)limitY,(float)limitZ); return TRUE; } } } } // this will free any of the 4 str mallocs above, if any numParts != 2 (or numParts != 3 // for limit) io::Mem_Free(pcVar1); } return FALSE; } void __cdecl lego::light::LightEffects_SetMove (float waitMin,float waitMax,float speedMin,float speedMax,float distMin,float distMax, float limitX,float limitY,float limitZ) { globs::lightGlobs.moveWaitRange.min = waitMin; globs::lightGlobs.moveWaitRange.max = waitMax; globs::lightGlobs.moveSpeedRange.max = speedMax; globs::lightGlobs.moveDistRange.min = distMin; globs::lightGlobs.moveSpeedRange.min = speedMin; globs::lightGlobs.moveDistRange.max = distMax; // Writes position to Vector3F globals::g_Light.resMoveLimit gfx::Container_GetPosition (globs::lightGlobs.rootSpotlight,globs::lightGlobs.rootLight, &globs::lightGlobs.movePosition); globs::lightGlobs.moveLimit.x = limitX; globs::lightGlobs.moveLimit.y = limitY; globs::lightGlobs.moveLimit.z = limitZ; globs::lightGlobs.flags = globs::lightGlobs.flags | LIGHTFX_GLOB_FLAG_HASMOVE; return; } // Forces the LightEffect to re-obtain the resRootSpotlight position, and also restarts movement // effects. void __cdecl lego::light::LightEffects_InvalidatePosition(void) { // Writes position to Vector3F globals::g_Light.resMoveLimit gfx::Container_GetPosition (globs::lightGlobs.rootSpotlight,globs::lightGlobs.rootLight, &globs::lightGlobs.movePosition); globs::lightGlobs.flags = globs::lightGlobs.flags & ~LIGHTFX_GLOB_FLAG_MOVING; return; } void __cdecl lego::light::LightEffects_Update(float elapsed) { if (((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_DISABLED) == LIGHTFX_GLOB_FLAG_NONE) && (globs::lightGlobs.rootSpotlight != NULL)) { LightEffects_UpdateBlink(elapsed); LightEffects_UpdateFade(elapsed); LightEffects_UpdateMove(elapsed); LightEffects_UpdateDimmer(elapsed); LightEffects_UpdateSpotlightColour(); } return; } void __cdecl lego::light::LightEffects_UpdateSpotlightColour(void) { float b; float g; float r; r = globs::lightGlobs.currentRGB.red; g = globs::lightGlobs.currentRGB.green; b = globs::lightGlobs.currentRGB.blue; if (globs::lightGlobs.currentRGB.red < 0.0) { r = 0.0; } if ((ushort)((ushort)(r < 1.0) << 8 | (ushort)(r == 1.0) << 0xe) == 0) { r = 1.0; } if (globs::lightGlobs.currentRGB.green < 0.0) { g = 0.0; } if ((ushort)((ushort)(g < 1.0) << 8 | (ushort)(g == 1.0) << 0xe) == 0) { g = 1.0; } if (globs::lightGlobs.currentRGB.blue < 0.0) { b = 0.0; } if ((ushort)((ushort)(b < 1.0) << 8 | (ushort)(b == 1.0) << 0xe) == 0) { b = 1.0; } gfx::Container_SetColourAlpha(globs::lightGlobs.rootSpotlight,r,g,b,1.0); return; } void __cdecl lego::light::LightEffects_UpdateBlink(float elapsed) { float fVar1; float fVar2; bool bVar3; short sVar4; float10 fVar5; float local_8; float local_4; bVar3 = false; if (((byte)globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_HASBLINK) == 0) { return; } globs::lightGlobs.blinkWait = globs::lightGlobs.blinkWait - elapsed; if ((ushort)((ushort)(globs::lightGlobs.blinkWait < 0.0) << 8 | (ushort)(globs::lightGlobs.blinkWait == 0.0) << 0xe) == 0) { return; } fVar5 = math::Maths_RandRange (globs::lightGlobs.blinkWaitRange.min,globs::lightGlobs.blinkWaitRange.max); globs::lightGlobs.blinkWait = (float)fVar5; sVar4 = math::Maths_Rand(); fVar2 = (float)((int)sVar4 % 1000) * 0.001; elapsed = (globs::lightGlobs.blinkRGBMax.red + globs::lightGlobs.blinkRGBMax.red) * fVar2 - globs::lightGlobs.blinkRGBMax.red; local_8 = (globs::lightGlobs.blinkRGBMax.green + globs::lightGlobs.blinkRGBMax.green) * fVar2 - globs::lightGlobs.blinkRGBMax.green; fVar1 = elapsed + globs::lightGlobs.blinkChange; local_4 = (globs::lightGlobs.blinkRGBMax.blue + globs::lightGlobs.blinkRGBMax.blue) * fVar2 - globs::lightGlobs.blinkRGBMax.blue; if (globs::lightGlobs.blinkChangeMax <= ABS(fVar1)) { LightEffects_FlipSign(&elapsed); LightEffects_FlipSign(&local_8); LightEffects_FlipSign(&local_4); fVar1 = elapsed + globs::lightGlobs.blinkChange; if (globs::lightGlobs.blinkChangeMax <= ABS(fVar1)) goto LAB_0044d4b5; } bVar3 = true; LAB_0044d4b5: if (!bVar3) { return; } globs::lightGlobs.currentRGB.red = elapsed + globs::lightGlobs.currentRGB.red; globs::lightGlobs.currentRGB.green = local_8 + globs::lightGlobs.currentRGB.green; globs::lightGlobs.currentRGB.blue = local_4 + globs::lightGlobs.currentRGB.blue; globs::lightGlobs.blinkChange = fVar1; return; } // ref_value = -ref_value // NOTES: This function is kind of dumb, the way it negates the value is different depending on the // sign, but the end result will always be the same. void __cdecl lego::light::LightEffects_FlipSign(float *ref_value) { if (*ref_value < 0.0) { *ref_value = *ref_value * -1.0; return; } *ref_value = -*ref_value; return; } void __cdecl lego::light::LightEffects_UpdateFade(float elapsed) { float fVar1; short sVar2; float10 fVar3; if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_HASFADE) != LIGHTFX_GLOB_FLAG_NONE) { if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_FADING) == LIGHTFX_GLOB_FLAG_NONE) { globs::lightGlobs.fadeWait = globs::lightGlobs.fadeWait - elapsed; if ((ushort)((ushort)(globs::lightGlobs.fadeWait < 0.0) << 8 | (ushort)(globs::lightGlobs.fadeWait == 0.0) << 0xe) != 0) { fVar3 = math::Maths_RandRange (globs::lightGlobs.fadeWaitRange.min,globs::lightGlobs.fadeWaitRange.max); globs::lightGlobs.fadeWait = (float)fVar3; fVar3 = math::Maths_RandRange (globs::lightGlobs.fadeHoldRange.min,globs::lightGlobs.fadeHoldRange.max); globs::lightGlobs.fadeHold = (float)fVar3; sVar2 = math::Maths_Rand(); globs::lightGlobs.fadePosRGB.red = 0.0; globs::lightGlobs.fadePosRGB.green = 0.0; globs::lightGlobs.fadePosRGB.blue = 0.0; fVar1 = (float)((int)sVar2 % 1000) * 0.001; globs::lightGlobs.fadeDestRGB.red = ABS(globs::lightGlobs.fadeRGBMax.red - globs::lightGlobs.fadeRGBMin.red) * fVar1 + globs::lightGlobs.fadeRGBMin.red; globs::lightGlobs.fadeDestRGB.green = ABS(globs::lightGlobs.fadeRGBMax.green - globs::lightGlobs.fadeRGBMin.green) * fVar1 + globs::lightGlobs.fadeRGBMin.green; globs::lightGlobs.fadeDestRGB.blue = ABS(globs::lightGlobs.fadeRGBMax.blue - globs::lightGlobs.fadeRGBMin.blue) * fVar1 + globs::lightGlobs.fadeRGBMin.blue; LightEffects_RandomizeFadeSpeedRGB(); globs::lightGlobs.flags |= LIGHTFX_GLOB_FLAG_FADING|LIGHTFX_GLOB_FLAG_FADE_FORWARD; } } else { if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_FADE_FORWARD) == LIGHTFX_GLOB_FLAG_NONE) { if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_FADE_REVERSE) == LIGHTFX_GLOB_FLAG_NONE) { globs::lightGlobs.fadeHold = globs::lightGlobs.fadeHold - elapsed; if ((ushort)((ushort)(globs::lightGlobs.fadeHold < 0.0) << 8 | (ushort)(globs::lightGlobs.fadeHold == 0.0) << 0xe) != 0) { LightEffects_RandomizeFadeSpeedRGB(); globs::lightGlobs.fadePosRGB.red = globs::lightGlobs.fadeDestRGB.red; globs::lightGlobs.fadePosRGB.green = globs::lightGlobs.fadeDestRGB.green; globs::lightGlobs.fadePosRGB.blue = globs::lightGlobs.fadeDestRGB.blue; globs::lightGlobs.flags = globs::lightGlobs.flags | LIGHTFX_GLOB_FLAG_FADE_REVERSE; return; } } else { fVar1 = elapsed * globs::lightGlobs.fadeSpeedRGB.red; globs::lightGlobs.currentRGB.red = globs::lightGlobs.currentRGB.red - fVar1; globs::lightGlobs.fadePosRGB.red = globs::lightGlobs.fadePosRGB.red - fVar1; globs::lightGlobs.currentRGB.green = globs::lightGlobs.currentRGB.green - elapsed * globs::lightGlobs.fadeSpeedRGB.green; globs::lightGlobs.fadePosRGB.green = globs::lightGlobs.fadePosRGB.green - elapsed * globs::lightGlobs.fadeSpeedRGB.green; globs::lightGlobs.currentRGB.blue = globs::lightGlobs.currentRGB.blue - elapsed * globs::lightGlobs.fadeSpeedRGB.blue; globs::lightGlobs.fadePosRGB.blue = globs::lightGlobs.fadePosRGB.blue - elapsed * globs::lightGlobs.fadeSpeedRGB.blue; if (fVar1 < 0.0) { if (globs::lightGlobs.fadePosRGB.red >= 0.0) { globs::lightGlobs.currentRGB.red = globs::lightGlobs.currentRGB.red - globs::lightGlobs.fadePosRGB.red; globs::lightGlobs.currentRGB.green = globs::lightGlobs.currentRGB.green - globs::lightGlobs.fadePosRGB.green; globs::lightGlobs.currentRGB.blue = globs::lightGlobs.currentRGB.blue - globs::lightGlobs.fadePosRGB.blue; globs::lightGlobs.flags = globs::lightGlobs.flags & ~(LIGHTFX_GLOB_FLAG_FADING|LIGHTFX_GLOB_FLAG_FADE_REVERSE); return; } } else { if ((ushort)((ushort)(globs::lightGlobs.fadePosRGB.red < 0.0) << 8 | (ushort)(globs::lightGlobs.fadePosRGB.red == 0.0) << 0xe) != 0) { globs::lightGlobs.currentRGB.red = globs::lightGlobs.currentRGB.red - globs::lightGlobs.fadePosRGB.red; globs::lightGlobs.currentRGB.green = globs::lightGlobs.currentRGB.green - globs::lightGlobs.fadePosRGB.green; globs::lightGlobs.currentRGB.blue = globs::lightGlobs.currentRGB.blue - globs::lightGlobs.fadePosRGB.blue; globs::lightGlobs.flags = globs::lightGlobs.flags & ~(LIGHTFX_GLOB_FLAG_FADING|LIGHTFX_GLOB_FLAG_FADE_REVERSE); return; } } } } else { fVar1 = elapsed * globs::lightGlobs.fadeSpeedRGB.red; globs::lightGlobs.currentRGB.red = fVar1 + globs::lightGlobs.currentRGB.red; globs::lightGlobs.currentRGB.green = elapsed * globs::lightGlobs.fadeSpeedRGB.green + globs::lightGlobs.currentRGB.green; globs::lightGlobs.currentRGB.blue = elapsed * globs::lightGlobs.fadeSpeedRGB.blue + globs::lightGlobs.currentRGB.blue; globs::lightGlobs.fadePosRGB.red = fVar1 + globs::lightGlobs.fadePosRGB.red; globs::lightGlobs.fadePosRGB.green = elapsed * globs::lightGlobs.fadeSpeedRGB.green + globs::lightGlobs.fadePosRGB.green; globs::lightGlobs.fadePosRGB.blue = elapsed * globs::lightGlobs.fadeSpeedRGB.blue + globs::lightGlobs.fadePosRGB.blue; if (fVar1 < 0.0) { if ((ushort)((ushort)(globs::lightGlobs.fadePosRGB.red < globs::lightGlobs.fadeDestRGB.red ) << 8 | (ushort)(globs::lightGlobs.fadePosRGB.red == globs::lightGlobs.fadeDestRGB.red ) << 0xe) != 0) { globs::lightGlobs.currentRGB.red = (globs::lightGlobs.fadeDestRGB.red - globs::lightGlobs.fadePosRGB.red) + globs::lightGlobs.currentRGB.red; globs::lightGlobs.currentRGB.green = (globs::lightGlobs.fadeDestRGB.green - globs::lightGlobs.fadePosRGB.green) + globs::lightGlobs.currentRGB.green; globs::lightGlobs.currentRGB.blue = (globs::lightGlobs.fadeDestRGB.blue - globs::lightGlobs.fadePosRGB.blue) + globs::lightGlobs.currentRGB.blue; globs::lightGlobs.flags = globs::lightGlobs.flags & ~LIGHTFX_GLOB_FLAG_FADE_FORWARD; return; } } else { if (globs::lightGlobs.fadePosRGB.red >= globs::lightGlobs.fadeDestRGB.red) { globs::lightGlobs.currentRGB.red = globs::lightGlobs.currentRGB.red - (globs::lightGlobs.fadePosRGB.red - globs::lightGlobs.fadeDestRGB.red); globs::lightGlobs.currentRGB.green = globs::lightGlobs.currentRGB.green - (globs::lightGlobs.fadePosRGB.green - globs::lightGlobs.fadeDestRGB.green); globs::lightGlobs.currentRGB.blue = globs::lightGlobs.currentRGB.blue - (globs::lightGlobs.fadePosRGB.blue - globs::lightGlobs.fadeDestRGB.blue); globs::lightGlobs.flags = globs::lightGlobs.flags & ~LIGHTFX_GLOB_FLAG_FADE_FORWARD; return; } } } } } return; } void __cdecl lego::light::LightEffects_RandomizeFadeSpeedRGB(void) { float10 fVar1; fVar1 = math::Maths_RandRange (globs::lightGlobs.fadeSpeedRange.min,globs::lightGlobs.fadeSpeedRange.max); globs::lightGlobs.fadeSpeedRGB.red = (float)((float10)globs::lightGlobs.fadeDestRGB.red / fVar1); globs::lightGlobs.fadeSpeedRGB.green = (float)((float10)globs::lightGlobs.fadeDestRGB.green / fVar1); globs::lightGlobs.fadeSpeedRGB.blue = (float)((float10)globs::lightGlobs.fadeDestRGB.blue / fVar1) ; return; } void __cdecl lego::light::LightEffects_UpdateMove(float elapsed) { bool bVar1; float fVar2; BOOL BVar3; float10 fVar4; Vector3F newPosition; Vector3F lastPosition; bVar1 = false; if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_HASMOVE) == LIGHTFX_GLOB_FLAG_NONE) { return; } if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_MOVING) == LIGHTFX_GLOB_FLAG_NONE) { globs::lightGlobs.moveWait = globs::lightGlobs.moveWait - elapsed; if ((ushort)((ushort)(globs::lightGlobs.moveWait < 0.0) << 8 | (ushort)(globs::lightGlobs.moveWait == 0.0) << 0xe) == 0) { return; } fVar4 = math::Maths_RandRange (globs::lightGlobs.moveWaitRange.min,globs::lightGlobs.moveWaitRange.max); globs::lightGlobs.moveWait = (float)fVar4; fVar4 = math::Maths_RandRange (globs::lightGlobs.moveSpeedRange.min,globs::lightGlobs.moveSpeedRange.max); globs::lightGlobs.moveSpeed = (float)fVar4; fVar4 = math::Maths_RandRange (globs::lightGlobs.moveDistRange.min,globs::lightGlobs.moveDistRange.max); globs::lightGlobs.moveDist = (float)fVar4; // Randomize + Normalize vector, multiplied by speed. // AKA: speed in a random 3D direction. math::Maths_Vector3DRandom(&globs::lightGlobs.moveVector); fVar2 = 1.0 / SQRT(globs::lightGlobs.moveVector.z * globs::lightGlobs.moveVector.z + globs::lightGlobs.moveVector.y * globs::lightGlobs.moveVector.y + globs::lightGlobs.moveVector.x * globs::lightGlobs.moveVector.x); globs::lightGlobs.moveVector.x = fVar2 * globs::lightGlobs.moveVector.x * globs::lightGlobs.moveSpeed; globs::lightGlobs.moveVector.y = fVar2 * globs::lightGlobs.moveVector.y * globs::lightGlobs.moveSpeed; globs::lightGlobs.moveVector.z = fVar2 * globs::lightGlobs.moveVector.z * globs::lightGlobs.moveSpeed; globs::lightGlobs.flags = globs::lightGlobs.flags | LIGHTFX_GLOB_FLAG_MOVING; return; } gfx::Container_GetPosition (globs::lightGlobs.rootSpotlight,globs::lightGlobs.rootLight,&lastPosition); newPosition.x = lastPosition.x + globs::lightGlobs.moveVector.x; newPosition.y = lastPosition.y + globs::lightGlobs.moveVector.y; newPosition.z = lastPosition.z + globs::lightGlobs.moveVector.z; BVar3 = LightEffects_CheckMoveLimit(&newPosition); if (BVar3 == 0) { // This is the same deal as the `LightEffects_UpdateBlink_FlipSign(float*)` tuple seen // in UpdateBlink // it's just that blink doesn't have extra math involved. newPosition.x = lastPosition.x - globs::lightGlobs.moveVector.x; newPosition.y = lastPosition.y - globs::lightGlobs.moveVector.y; newPosition.z = lastPosition.z - globs::lightGlobs.moveVector.z; BVar3 = LightEffects_CheckMoveLimit(&newPosition); if (BVar3 == 0) goto LAB_0044dae5; } bVar1 = true; LAB_0044dae5: if (!bVar1) { globs::lightGlobs.flags = globs::lightGlobs.flags & ~LIGHTFX_GLOB_FLAG_MOVING; return; } gfx::Container_SetPosition (globs::lightGlobs.rootSpotlight,globs::lightGlobs.rootLight,newPosition.x,newPosition.y ,newPosition.z); globs::lightGlobs.moveDist = globs::lightGlobs.moveDist - globs::lightGlobs.moveSpeed; if ((ushort)((ushort)(globs::lightGlobs.moveDist < 0.0) << 8 | (ushort)(globs::lightGlobs.moveDist == 0.0) << 0xe) == 0) { return; } globs::lightGlobs.flags = globs::lightGlobs.flags & ~LIGHTFX_GLOB_FLAG_MOVING; return; } BOOL __cdecl lego::light::LightEffects_CheckMoveLimit(Vector3F *vector) { float fVar1; fVar1 = ABS(vector->x - globs::lightGlobs.movePosition.x); if ((ushort)((ushort)(fVar1 < globs::lightGlobs.moveLimit.x) << 8 | (ushort)(fVar1 == globs::lightGlobs.moveLimit.x) << 0xe) == 0) { return 0; } fVar1 = ABS(vector->y - globs::lightGlobs.movePosition.y); if ((ushort)((ushort)(fVar1 < globs::lightGlobs.moveLimit.y) << 8 | (ushort)(fVar1 == globs::lightGlobs.moveLimit.y) << 0xe) == 0) { return 0; } fVar1 = ABS(vector->z - globs::lightGlobs.movePosition.z); if ((ushort)((ushort)(fVar1 < globs::lightGlobs.moveLimit.z) << 8 | (ushort)(fVar1 == globs::lightGlobs.moveLimit.z) << 0xe) == 0) { return 0; } return 1; } void __cdecl lego::light::LightEffects_SetDimmerMode(BOOL isDimoutMode) { if (isDimoutMode != 0) { globs::lightGlobs.flags = globs::lightGlobs.flags & ~LIGHTFX_GLOB_FLAG_DIMIN_DONE | LIGHTFX_GLOB_FLAG_DIMOUT; return; } globs::lightGlobs.flags = globs::lightGlobs.flags & ~(LIGHTFX_GLOB_FLAG_DIMOUT|LIGHTFX_GLOB_FLAG_DIMOUT_DONE); return; } void __cdecl lego::light::LightEffects_UpdateDimmer(float elapsed) { float fVar1; if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_DIMOUT) == LIGHTFX_GLOB_FLAG_NONE) { if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_DIMIN_DONE) == LIGHTFX_GLOB_FLAG_NONE) { fVar1 = elapsed * 0.1; globs::lightGlobs.currentRGB.red = fVar1 + globs::lightGlobs.currentRGB.red; globs::lightGlobs.currentRGB.green = fVar1 + globs::lightGlobs.currentRGB.green; globs::lightGlobs.currentRGB.blue = fVar1 + globs::lightGlobs.currentRGB.blue; if (globs::lightGlobs.initialRGB.red <= globs::lightGlobs.currentRGB.red) { globs::lightGlobs.flags |= LIGHTFX_GLOB_FLAG_DIMIN_DONE; // Uhhh... assigning blue to red??? (this has to be a bug) // Actually... why is this only assigning red and no other colors??? globs::lightGlobs.currentRGB.red = globs::lightGlobs.initialRGB.blue; } } } else { if ((globs::lightGlobs.flags & LIGHTFX_GLOB_FLAG_DIMOUT_DONE) != LIGHTFX_GLOB_FLAG_NONE) { globs::lightGlobs.currentRGB.red = 0.0; globs::lightGlobs.currentRGB.green = 0.0; globs::lightGlobs.currentRGB.blue = 0.0; return; } fVar1 = elapsed * 0.1; globs::lightGlobs.currentRGB.red = globs::lightGlobs.currentRGB.red - fVar1; globs::lightGlobs.currentRGB.green = globs::lightGlobs.currentRGB.green - fVar1; globs::lightGlobs.currentRGB.blue = globs::lightGlobs.currentRGB.blue - fVar1; if ((ushort)((ushort)(globs::lightGlobs.currentRGB.red < 0.0) << 8 | (ushort)(globs::lightGlobs.currentRGB.red == 0.0) << 0xe) != 0) { globs::lightGlobs.currentRGB.red = 0.0; globs::lightGlobs.flags = globs::lightGlobs.flags | LIGHTFX_GLOB_FLAG_DIMOUT_DONE; return; } } return; } void __cdecl lego::front::Loader_Initialise (char *loadScreenName,char *shutdownScreenName,Font *font5HI,char *profileName, Direction progressDirection,char *progressBarName,Area2F *progressWindow,char *loadingText ) { char cVar1; char *pcVar2; undefined4 *puVar3; int iVar4; uint uVar5; uint uVar6; File *f; LoaderSection *pLVar7; undefined4 *puVar8; Loader_Globs *pLVar9; char *pcVar10; char *stringParts [10]; char buff [256]; f = NULL; pLVar9 = &globs::loaderGlobs; for (iVar4 = 0xa4; iVar4 != 0; iVar4 += -1) { pLVar9->LoadScreen = NULL; pLVar9 = (Loader_Globs *)&pLVar9->font; } globs::loaderGlobs.LoadScreen = lego::image::Image_LoadBMPScaled(loadScreenName,0,0); globs::loaderGlobs.ShutdownScreen = lego::image::Image_LoadBMPScaled(shutdownScreenName,0,0); globs::loaderGlobs.font = font5HI; globs::loaderGlobs.current = NULL; globs::loaderGlobs.ProgressBar = lego::image::Image_LoadBMPScaled(progressBarName,0,0); globs::loaderGlobs.ProgressWindow.x = progressWindow->x; globs::loaderGlobs.ProgressWindow.y = progressWindow->y; globs::loaderGlobs.ProgressWindow.width = progressWindow->width; globs::loaderGlobs.ProgressWindow.height = progressWindow->height; globs::loaderGlobs.ProgressDirection = progressDirection; if (loadingText == NULL) { globs::loaderGlobs.LoadingText = NULL; } else { pcVar2 = util::Util_StrCpy(loadingText); cVar1 = *pcVar2; globs::loaderGlobs.LoadingText = pcVar2; while (cVar1 != '\0') { if (cVar1 == '_') { *pcVar2 = ' '; } pcVar10 = pcVar2 + 1; pcVar2 = pcVar2 + 1; cVar1 = *pcVar10; } lego::image::Font_GetStringInfo(font5HI,&globs::loaderGlobs.LoadingWidth,NULL,"%s",loadingText); } if (profileName != NULL) { f = io::File_Open(profileName,"r"); } pLVar7 = globs::loaderGlobs.sectionList; do { if (((f == NULL) || (pcVar2 = io::File_GetS(buff,0x100,f), pcVar2 == NULL)) || (iVar4 = util::Util_Tokenise(buff,stringParts,"="), iVar4 != 2)) { pLVar7->name = NULL; } else { uVar5 = 0xffffffff; pcVar2 = stringParts[0]; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); puVar3 = (undefined4 *)io::Mem_Alloc(~uVar5); uVar5 = 0xffffffff; pLVar7->name = (char *)puVar3; pcVar2 = stringParts[0]; do { pcVar10 = pcVar2; if (uVar5 == 0) break; uVar5 -= 1; pcVar10 = pcVar2 + 1; cVar1 = *pcVar2; pcVar2 = pcVar10; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar8 = (undefined4 *)(pcVar10 + -uVar5); for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar3 = *puVar8; puVar8 = puVar8 + 1; puVar3 = puVar3 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar3 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar3 = (undefined4 *)((int)puVar3 + 1); } uVar5 = std::atoi(stringParts[1]); pLVar7->totalSize = uVar5; pLVar7->currentSize = 0; } pLVar7 = pLVar7 + 1; if ((LoaderSection *)((int)&globs::loaderGlobs.sectionList[0x31].totalSize + 3) < pLVar7) { if (f != NULL) { io::File_Close(f); } io::File_SetLoadCallback(Loader_FileLoadCallback,NULL); return; } } while( true ); } void __cdecl lego::front::Loader_Shutdown(char *filename) { File *f; uint uVar1; LoaderSection *pLVar2; if (filename == NULL) { f = NULL; } else { f = io::File_Open(filename,"w"); } pLVar2 = globs::loaderGlobs.sectionList; do { if (pLVar2->name != NULL) { uVar1 = pLVar2->currentSize; if (uVar1 == 0) { uVar1 = pLVar2->totalSize; } if (f != NULL) { io::File_PrintF(f,"%s%s%i\n",pLVar2->name,"=",uVar1); } io::Mem_Free(pLVar2->name); } pLVar2 = pLVar2 + 1; } while (pLVar2 < (LoaderSection *)&globs::loaderGlobs.current); if (f != NULL) { io::File_Close(f); } lego::image::Image_Remove(globs::loaderGlobs.LoadScreen); if (globs::loaderGlobs.ShutdownScreen != NULL) { lego::image::Image_Remove(globs::loaderGlobs.ShutdownScreen); } return; } // Pass NULL to disable progress bar // Section is either "Game Data" or "Levels::*". // But this is not hardcoded by the Loader module. void __cdecl lego::front::Loader_display_loading_bar(char *section) { char cVar1; int iVar2; undefined4 *puVar3; uint uVar4; uint uVar5; LoaderSection *pLVar6; LoaderSection *pLVar7; LoaderSection *pLVar8; undefined4 *puVar9; int iVar10; char *pcVar11; if (section == NULL) { // &= ~LOADER_FLAG_ENABLED; (~0x1) globs::loaderGlobs.flags = globs::loaderGlobs.flags & 0xfffffffe; return; } iVar10 = 0; pLVar8 = globs::loaderGlobs.sectionList; pLVar6 = NULL; do { pLVar7 = pLVar8; if ((pLVar8->name != NULL) && (iVar2 = std::_stricmp(pLVar8->name,section), pLVar7 = pLVar6, iVar2 == 0)) { globs::loaderGlobs.current = globs::loaderGlobs.sectionList + iVar10; globs::loaderGlobs.sectionList[iVar10].currentSize = 0; break; } pLVar8 = pLVar8 + 1; iVar10 += 1; pLVar6 = pLVar7; } while (pLVar8 < (LoaderSection *)&globs::loaderGlobs.current); if ((iVar10 == 50) && (pLVar7 != NULL)) { uVar4 = 0xffffffff; pcVar11 = section; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar11; pcVar11 = pcVar11 + 1; } while (cVar1 != '\0'); puVar3 = (undefined4 *)io::Mem_Alloc(~uVar4); uVar4 = 0xffffffff; pLVar7->name = (char *)puVar3; do { pcVar11 = section; if (uVar4 == 0) break; uVar4 -= 1; pcVar11 = section + 1; cVar1 = *section; section = pcVar11; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar9 = (undefined4 *)(pcVar11 + -uVar4); for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar3 = *puVar9; puVar9 = puVar9 + 1; puVar3 = puVar3 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar3 = *(undefined *)puVar9; puVar9 = (undefined4 *)((int)puVar9 + 1); puVar3 = (undefined4 *)((int)puVar3 + 1); } pLVar7->currentSize = 0; pLVar7->totalSize = 0; globs::loaderGlobs.current = pLVar7; } globs::loaderGlobs.flags |= LOADER_GLOB_FLAG_ENABLED; globs::loaderGlobs.progressLast = -1.0; Loader_FileLoadCallback(NULL,0,NULL); return; } void __cdecl lego::front::Loader_FileLoadCallback(char *filename,uint fileSize,void *data) { float fVar1; int y; longlong lVar2; char *msg; char *pcVar3; Size2F barSize; Point2F barPosition; if (((byte)globs::loaderGlobs.flags & LOADER_GLOB_FLAG_ENABLED) != 0) { if (((globs::loaderGlobs.current == NULL) || ((globs::loaderGlobs.current)->currentSize = (globs::loaderGlobs.current)->currentSize + fileSize, globs::loaderGlobs.current == NULL)) || ((globs::loaderGlobs.current)->totalSize == 0)) { fileSize = 0; } else { fileSize = (uint)((float)(ulonglong)(globs::loaderGlobs.current)->currentSize / (float)(globs::loaderGlobs.current)->totalSize); } // // minimum increase since last update of progress bar // if (floatVal > (loaderGlobs.progressLast - 0.002f)) if ((ushort)((ushort)((float)fileSize < globs::loaderGlobs.progressLast - -0.002) << 8 | (ushort)((float)fileSize == globs::loaderGlobs.progressLast - -0.002) << 0xe) == 0) { barPosition.y = globs::loaderGlobs.ProgressWindow.y; barPosition.x = globs::loaderGlobs.ProgressWindow.x; barSize.width = globs::loaderGlobs.ProgressWindow.width; barSize.height = globs::loaderGlobs.ProgressWindow.height; lego::image::Image_DisplayScaled(globs::loaderGlobs.LoadScreen,NULL,NULL,NULL); // if (floatVal > 1.0f) floatVal = 1.0f; if ((ushort)((ushort)((float)fileSize < 1.0) << 8 | (ushort)((float)fileSize == 1.0) << 0xe) == 0) { // 1.0f fileSize = 0x3f800000; } switch(globs::loaderGlobs.ProgressDirection) { case DIRECTION_UP: fVar1 = barSize.height + barPosition.y; barPosition.y = fVar1 - barSize.height * (float)fileSize; barSize.height = fVar1 - barPosition.y; break; case DIRECTION_RIGHT: barSize.width = barSize.width * (float)fileSize; break; case DIRECTION_DOWN: barSize.height = barSize.height * (float)fileSize; break; case DIRECTION_LEFT: fVar1 = barSize.width + barPosition.x; barPosition.x = fVar1 - barSize.width * (float)fileSize; barSize.width = fVar1 - barPosition.x; } if (globs::loaderGlobs.ProgressBar != NULL) { lego::image::Image_DisplayScaled(globs::loaderGlobs.ProgressBar,NULL,&barPosition,&barSize); } if (globs::loaderGlobs.LoadingText != NULL) { msg = "%s"; pcVar3 = globs::loaderGlobs.LoadingText; lVar2 = __ftol((float10)globs::loaderGlobs.ProgressWindow.y); y = (int)lVar2 + -1; lVar2 = __ftol((float10)globs::loaderGlobs.ProgressWindow.width * (float10)0.5 + (float10)globs::loaderGlobs.ProgressWindow.x); lego::image::Font_PrintF (globs::loaderGlobs.font,(int)lVar2 - (globs::loaderGlobs.LoadingWidth >> 1),y,msg ,pcVar3); } main::Main_LoopUpdate(0); globs::loaderGlobs.progressLast = (float)fileSize; } } return; } void __cdecl lego::front::Loader_display_shutdown(void) { if (globs::loaderGlobs.ShutdownScreen != NULL) { lego::image::Image_DisplayScaled(globs::loaderGlobs.ShutdownScreen,NULL,NULL,NULL); ddraw::DirectDraw_Flip(); return; } return; } Map3D * __cdecl lego::map::Map3D_Create(Container *root,char *filename,float blockSize,float roughLevel) { Point2F *pPVar1; Map3D_Block *pMVar2; ushort heightValue; MapFileInfo *mapFileInfo; Map3D *map; IDirect3DRMMaterial2 *material; Map3D_TransitionBlock *transBlocks; Container *transMesh; Container *mesh; Map3D_Block *blocks3D; D3DRMGroupIndex group; uint diffxy00_11; int iVar3; int i; uint uVar4; uint uVar5; undefined4 *puVar6; Map3D_TransitionBlock *pMVar7; BOOL *pBVar8; uint bx; uint diffxy10_01; float10 fVar9; float10 fVar10; uint faceData [6]; uint blockHeight; Map3D_Block *block3Dy0; Map3D_Block *block3Dy1; uint *pGridWidth; uVar5 = 0; mapFileInfo = (MapFileInfo *)io::File_LoadBinary(filename,NULL); if (mapFileInfo != NULL) { map = (Map3D *)io::Mem_Alloc(0x73d4); if (map != NULL) { pGridWidth = &map->gridWidth; map->blockSize = blockSize; map->roughLevel = roughLevel; Map3D_MapFileGetSpecs(mapFileInfo,pGridWidth,&map->gridHeight); blockHeight = map->gridHeight - 1; map->blockWidth = *pGridWidth - 1; map->blockHeight = blockHeight; (map->worldDimensions_fnegx).width = -((float)(ulonglong)(*pGridWidth - 1) * blockSize * 0.5); map->textureSet = NULL; (map->worldDimensions_fnegx).height = (float)(ulonglong)blockHeight * blockSize * 0.5; puVar6 = (undefined4 *)map->texsNum; // std::memset(surfMap->texsNum, 0, 0x80); for (iVar3 = 0x20; iVar3 != 0; iVar3 += -1) { *puVar6 = 0; puVar6 = puVar6 + 1; } map->flagsMap = MAP3D_FLAG_NONE; map->visibleBlocksNum = 0; map->uvBlocksNum = 0; map->float_20 = 0.0; // THIS MATERIAL IS NEVER USED, AND IS NEVER RELEASED!!! material = gfx::Material_Create(1.0,1.0,1.0,0.0,0.0,0.0,0.0); transBlocks = map->transBlocks; map->material = material; pMVar7 = transBlocks; // std::memset(surfMap->transBlocks, 0, 0x230); for (iVar3 = 0x8c; iVar3 != 0; iVar3 += -1) { pMVar7->groupID = D3DRMGROUP_0; pMVar7 = (Map3D_TransitionBlock *)&pMVar7->timer; } pBVar8 = map->texsNoFade; // std::memset(surfMap->flag_40b4, 0, 0x200); for (iVar3 = 0x80; iVar3 != 0; iVar3 += -1) { *pBVar8 = 0; pBVar8 = pBVar8 + 1; } // for (i = 0; i < 10; i++) { // transBlocks[i]->groupID = -1; (not created yet) // } i = 10; do { transBlocks->groupID = D3DRMGROUP_ALLGROUPS; transBlocks = transBlocks + 1; i += -1; } while (i != 0); transMesh = gfx::Container_MakeMesh2(root,Container_MeshType_Transparent); map->transMesh = transMesh; mesh = gfx::Container_MakeMesh2(root,Container_MeshType_Immediate); map->mesh = mesh; if (mesh != NULL) { blocks3D = (Map3D_Block *)io::Mem_Alloc(*pGridWidth * map->gridHeight * 0x28); map->blocks3D = blocks3D; if (blocks3D != NULL) { faceData[0] = 0; faceData[1] = 1; faceData[2] = 3; faceData[3] = 1; faceData[4] = 2; faceData[5] = 3; if (map->blockWidth * map->blockHeight != 0) { do { group = gfx::Container_Mesh_AddGroup(map->mesh,4,2,3,faceData); gfx::Container_Mesh_HideGroup(map->mesh,group,TRUE); gfx::Container_Mesh_SetQuality(map->mesh,group,Gouraud); uVar5 += 1; } while (uVar5 < map->blockWidth * map->blockHeight); } uVar5 = 0; if (map->gridHeight != 0) { do { uVar4 = *pGridWidth; bx = 0; if (uVar4 != 0) { do { map->blocks3D[uVar5 * uVar4 + bx].flags3D = MAP3DBLOCK_FLAG_UNK_20|MAP3DBLOCK_FLAG_UNK_40; map->blocks3D[uVar5 * *pGridWidth + bx].texture = TEXTURE_FLOOR_STD; uVar4 = *pGridWidth; pMVar2 = map->blocks3D; heightValue = Map3D_MapFileBlockValue(mapFileInfo,bx,uVar5,uVar4); pMVar2[uVar5 * uVar4 + bx].heightValue = (byte)heightValue; pPVar1 = &map->blocks3D[uVar5 * *pGridWidth + bx].uvCoord; fVar9 = math::Maths_RandRange(0.0,1.0); pPVar1->x = (float)fVar9; fVar9 = math::Maths_RandRange(0.0,1.0); fVar10 = (float10)1.0 / SQRT((float10)pPVar1->x * (float10)pPVar1->x + fVar9 * fVar9); pPVar1->x = (float)(fVar10 * (float10)pPVar1->x); pPVar1->y = (float)(fVar10 * fVar9); iVar3 = uVar5 * *pGridWidth + bx; pPVar1 = &map->blocks3D[iVar3].uvCoord; pPVar1->x = map->blocks3D[iVar3].uvCoord.x * 0.3; pPVar1->y = pPVar1->y * 0.3; iVar3 = uVar5 * *pGridWidth + bx; bx += 1; map->blocks3D[iVar3].highlight = 0; uVar4 = *pGridWidth; } while (bx < uVar4); } uVar5 += 1; } while (uVar5 < map->gridHeight); } Map3D_InitRoughness(map); // y = 0; filename = NULL; if (map->blockHeight != 0) { do { // x = 0; blockSize = 0.0; if (map->blockWidth != 0) { do { // Compare crossed height differences. // Condition is true when abs(x0y0 - x1y1) < diff(x1y0 - x0y1). block3Dy0 = map->blocks3D + (int)filename * *pGridWidth + (int)blockSize; block3Dy1 = map->blocks3D + (int)(filename + 1) * *pGridWidth + (int)blockSize; diffxy00_11 = (uint)block3Dy0->heightValue - (uint)block3Dy1[1].heightValue; diffxy10_01 = (uint)block3Dy0[1].heightValue - (uint)block3Dy1->heightValue; // diffxy00_11 = (blocks3D[y][x].heightValue - blocks3D[y+1][x+1].heightValue) // diffxy10_01 = (blocks3D[y][x+1].heightValue - blocks3D[y+1][x].heightValue) // if (abs(diffxy00_11) < abs(diffxy10_01)) if ((diffxy00_11 ^ (int)diffxy00_11 >> 0x1f) - ((int)diffxy00_11 >> 0x1f) < (diffxy10_01 ^ (int)diffxy10_01 >> 0x1f) - ((int)diffxy10_01 >> 0x1f)) { // (surfMap, x, y, TRUE); Map3D_SetBlockRotated(map,(uint)blockSize,(uint)filename,TRUE); } else { // (surfMap, x, y); Map3D_GenerateBlockPlaneNormals(map,(uint)blockSize,(uint)filename); } // while (++x < surfMap->blockWidth); blockSize = (float)((int)blockSize + 1); } while ((uint)blockSize < map->blockWidth); } // while (++y < surfMap->blockHeight); filename = filename + 1; } while (filename < (char *)map->blockHeight); } io::Mem_Free(mapFileInfo); return map; } gfx::Container_Remove(map->mesh); } io::Mem_Free(map); } io::Mem_Free(mapFileInfo); } return NULL; } void __cdecl lego::map::Map3D_InitRoughness(Map3D *map) { float fVar1; float fVar2; float fVar3; float fVar4; float fVar5; uint uVar6; Point2F *pOffset; float *pVertPosY; float10 fVar7; float10 extraout_ST0; longlong lVar8; longlong lVar9; uint y; uint x; int i; Point2F OFFSETS [4]; Vertex vertices [4]; OFFSETS[0].x = 0.0; fVar5 = map->roughLevel; OFFSETS[0].y = 0.0; OFFSETS[1].x = 1.0; OFFSETS[1].y = 0.0; OFFSETS[2].x = 1.0; OFFSETS[2].y = 1.0; OFFSETS[3].x = 0.0; OFFSETS[3].y = 1.0; y = 0; if (map->blockHeight != 0) { do { x = 0; if (map->blockWidth != 0) { do { pOffset = OFFSETS; fVar7 = (float10)(ulonglong)x; pVertPosY = &vertices[0].position.y; i = 4; do { fVar1 = pOffset->y; fVar2 = map->blockSize; fVar3 = pOffset->y; fVar4 = (map->worldDimensions_fnegx).height; pVertPosY[-1] = (float)((fVar7 + (float10)pOffset->x) * (float10)map->blockSize + (float10)(map->worldDimensions_fnegx).width); *pVertPosY = fVar4 - (fVar1 + (float)(ulonglong)y) * fVar2; lVar8 = __ftol((float10)fVar3); uVar6 = map->gridWidth; lVar9 = __ftol((float10)pOffset->x); fVar2 = -((float)(uint)map->blocks3D[(y + (int)lVar8) * uVar6 + x + (int)lVar9]. heightValue * fVar5); fVar1 = map->float_20; pVertPosY[1] = fVar2; if (fVar2 < fVar1) { map->float_20 = fVar2; } pOffset = pOffset + 1; pVertPosY = pVertPosY + 9; i += -1; fVar7 = extraout_ST0; } while (i != 0); gfx::Container_Mesh_SetVertices(map->mesh,y * map->blockWidth + x,0,4,vertices); x += 1; } while (x < map->blockWidth); } y += 1; } while (y < map->blockHeight); } return; } void __cdecl lego::map::Map3D_Remove(Map3D *map) { gfx::Container_Remove(map->mesh); gfx::Container_Remove(map->transMesh); io::Mem_Free(map->blocks3D); io::Mem_Free(map); return; } // Initialisation function only. // States a textureNo. cannot use fade transitions. void __cdecl lego::map::Map3D_SetTextureNoFade(Map3D *map,SurfaceTexture texture) { map->texsNoFade[texture] = TRUE; return; } void __cdecl lego::map::Map3D_SetBlockFadeInTexture (Map3D *map,int bx,int by,SurfaceTexture newTexture,byte direction) { uint i; D3DRMGroupIndex groupID; float *pVertV; Container_Texture *ref_itext; float *pTransV; int j; Map3D_TransitionBlock *transBlock; uint faceData [6]; Vertex vertices [4]; uint transFlags; SurfaceTexture oldTexture; uint width; faceData[1] = 1; faceData[3] = 1; width = map->blockWidth; faceData[0] = 0; faceData[2] = 3; faceData[4] = 2; faceData[5] = 3; oldTexture = map->blocks3D[by * map->gridWidth + bx].texture; if ((oldTexture != newTexture) && (map->texsNoFade[oldTexture] == 0)) { i = 0; transBlock = map->transBlocks; do { if ((transBlock->flags & 1) == 0) { if (transBlock->groupID == D3DRMGROUP_ALLGROUPS) { // First-time creation for transBlock Mesh Group groupID = gfx::Container_Mesh_AddGroup(map->transMesh,4,2,3,faceData); transBlock->groupID = groupID; } else { // Otherwise, unhide Mesh group gfx::Container_Mesh_HideGroup(map->transMesh,transBlock->groupID,FALSE); } gfx::Container_Mesh_GetVertices(map->mesh,by * width + bx,0,4,vertices); pTransV = &transBlock->uvCoords[0].y; j = 4; pVertV = &vertices[0].tv; do { pTransV[-1] = pVertV[-1]; *pTransV = *pVertV; pTransV = pTransV + 2; j += -1; pVertV = pVertV + 9; } while (j != 0); ref_itext = Detail_GetTexture(map->textureSet, map->blocks3D[by * map->gridWidth + bx].texture); gfx::Container_Mesh_SetTexture(map->transMesh,transBlock->groupID,ref_itext); transFlags = *(uint *)&transBlock->flags; (transBlock->blockPos).x = bx; (transBlock->blockPos).y = by; transBlock->timer = 0.05; *(uint *)&transBlock->flags = transFlags | 1; break; } i += 1; transBlock = transBlock + 1; } while (i < 10); } Map3D_SetBlockTexture(map,bx,by,newTexture,direction); return; } BOOL __cdecl lego::map::Map3D_IsBlockMeshHidden(Map3D *map,int bx,int by) { BOOL hidden; hidden = gfx::Container_Mesh_IsGroupHidden(map->mesh,map->blockWidth * by + bx); return hidden; } void __cdecl lego::map::Map3D_UpdateAllBlockNormals(Map3D *map) { uint vy; uint vx; vy = 0; if (map->gridHeight != 0) { do { vx = 0; if (map->gridWidth != 0) { do { Map3D_UpdateBlockNormals(map,vx,vy); vx += 1; } while (vx < map->gridWidth); } vy += 1; } while (vy < map->gridHeight); } return; } BOOL __cdecl lego::map::Map3D_CheckBuildingTolerance (Map3D *map,Point2I *shapePoints,uint shapeCount,float buildTolerance, float buildMaxVariation) { int *pVertIndexY; Point2I *pDir; Point2I *pPoint; uint j; float *pVertPosZ; float maxZ; float minZ; int k; uint i; Point2I DIRECTIONS [4]; Point2I VERT_INDICES [6]; Vector3F vertPoses [4]; bool bCheckMinMax; VERT_INDICES[2].y = 3; VERT_INDICES[4].y = 3; VERT_INDICES[5].y = 3; DIRECTIONS[0].x = 0; DIRECTIONS[0].y = 0; DIRECTIONS[1].x = 1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 1; DIRECTIONS[2].y = 1; DIRECTIONS[3].x = 0; DIRECTIONS[3].y = 1; VERT_INDICES[0].x = 0; VERT_INDICES[0].y = 1; VERT_INDICES[1].x = 0; VERT_INDICES[1].y = 2; VERT_INDICES[2].x = 0; VERT_INDICES[3].x = 1; VERT_INDICES[3].y = 2; VERT_INDICES[4].x = 1; VERT_INDICES[5].x = 2; bCheckMinMax = false; minZ = 10000.0; maxZ = -10000.0; i = 0; if (shapeCount != 0) { pPoint = shapePoints + 1; do { if (((i == shapeCount - 1) || (shapePoints->x != pPoint->x)) || (shapePoints->y != pPoint->y)) { Map3D_GetBlockVertexPositions(map,shapePoints->x,shapePoints->y,vertPoses); j = 0; pVertIndexY = &VERT_INDICES[0].y; do { if (buildMaxVariation < ABS(vertPoses[pVertIndexY[-1]].z - vertPoses[*pVertIndexY].z)) { return 0; } j += 1; pVertIndexY = pVertIndexY + 2; } while (j < 6); pVertPosZ = &vertPoses[0].z; pDir = DIRECTIONS; k = 4; do { if ((map->blocks3D[(pDir->y + shapePoints->y) * map->gridWidth + pDir->x + shapePoints->x] .flags3D & MAP3DBLOCK_FLAG_VERTEXLEVELED) != MAP3DBLOCK_FLAG_NONE) { if (*pVertPosZ < minZ) { minZ = *pVertPosZ; } if ((ushort)((ushort)(*pVertPosZ < maxZ) << 8 | (ushort)(*pVertPosZ == maxZ) << 0xe) == 0) { maxZ = *pVertPosZ; } bCheckMinMax = true; } pDir = pDir + 1; pVertPosZ = pVertPosZ + 3; k += -1; } while (k != 0); } else { i += 1; pPoint = pPoint + 1; shapePoints = shapePoints + 1; } i += 1; pPoint = pPoint + 1; shapePoints = shapePoints + 1; } while (i < shapeCount); } // if (bCheckMinMax && ((maxZ - minZ) > buildTolerance)) if ((bCheckMinMax) && ((ushort)((ushort)(maxZ - minZ < buildTolerance) << 8 | (ushort)(maxZ - minZ == buildTolerance) << 0xe) == 0)) { return FALSE; } return TRUE; } void __cdecl lego::map::Map3D_FlattenShapeVertices (Map3D *map,Point2I *shapePoints,uint shapeCount,float mult_4_0) { int *piVar1; float *pfVar2; uint by; int iVar3; float fVar4; int iVar5; Point2I *pPVar6; Point2I *pShape_1; uint j1; Point2I *pPVar7; float totalZ; Point2I *local_22c; uint bCheckMinMax; uint numVertTotal; uint addCount; uint i; float minZ; Vector3F (*local_210) [4]; Point2I local_200 [4]; Vector3F local_1e0 [10] [4]; float range; range = mult_4_0 * 0.5; local_200[1].x = 1; local_200[2].x = 1; local_200[2].y = 1; local_200[3].y = 1; numVertTotal = 0; bCheckMinMax = 0; totalZ = 0.0; local_200[0].x = 0; local_200[0].y = 0; local_200[1].y = 0; local_200[3].x = 0; minZ = 10000.0; local_22c = (Point2I *)0xc61c4000; addCount = 0; i = 0; if (shapeCount != 0) { local_210 = local_1e0; pShape_1 = shapePoints + 1; pPVar7 = globs::s_SurfaceMap_Points10; do { if (((i == shapeCount - 1) || (shapePoints->x != pShape_1->x)) || (shapePoints->y != pShape_1->y)) { pPVar7->x = shapePoints->x; by = shapePoints->y; pPVar7->y = by; Map3D_GetBlockVertexPositions(map,pPVar7->x,by,(Vector3F *)local_210); j1 = 0; pPVar6 = local_200; do { if ((map->blocks3D[(pPVar6->y + pPVar7->y) * map->gridWidth + pPVar7->x + pPVar6->x]. flags3D & MAP3DBLOCK_FLAG_VERTEXLEVELED) == MAP3DBLOCK_FLAG_NONE) { totalZ = local_1e0[addCount][j1].z + totalZ; numVertTotal += 1; } else { pfVar2 = &local_1e0[addCount][j1].z; if (local_1e0[addCount][j1].z < minZ) { minZ = *pfVar2; } if ((ushort)((ushort)(*pfVar2 < (float)local_22c) << 8 | (ushort)(*pfVar2 == (float)local_22c) << 0xe) == 0) { local_22c = (Point2I *)*pfVar2; } bCheckMinMax += 1; } j1 += 1; pPVar6 = pPVar6 + 1; } while (j1 < 4); addCount += 1; local_210 = local_210[1]; pPVar7 = pPVar7 + 1; } else { i += 1; pShape_1 = pShape_1 + 1; shapePoints = shapePoints + 1; } i += 1; pShape_1 = pShape_1 + 1; shapePoints = shapePoints + 1; } while (i < shapeCount); } totalZ = totalZ / (float)(ulonglong)numVertTotal; if (bCheckMinMax != 0) { if ((ushort)((ushort)(range + totalZ < (float)local_22c) << 8 | (ushort)(range + totalZ == (float)local_22c) << 0xe) == 0) { totalZ = (float)local_22c - range; } if (totalZ - range < minZ) { totalZ = range + minZ; } } i = 0; if (addCount != 0) { local_22c = globs::s_SurfaceMap_Points10; do { bCheckMinMax = 0; piVar1 = &local_22c->y; pShape_1 = local_200; do { iVar3 = pShape_1->y; iVar5 = pShape_1->x; if ((map->blocks3D[(iVar3 + *piVar1) * map->gridWidth + local_22c->x + iVar5].flags3D & MAP3DBLOCK_FLAG_VERTEXLEVELED) == MAP3DBLOCK_FLAG_NONE) { fVar4 = local_1e0[i][bCheckMinMax].z - totalZ; if (range < ABS(fVar4)) { Map3D_MoveBlockVertices (map,local_22c->x + iVar5,*piVar1 + iVar3, ((fVar4 / fVar4) * range + totalZ) - local_1e0[i][bCheckMinMax].z); } iVar5 = (*piVar1 + iVar3) * map->gridWidth + local_22c->x + iVar5; map->blocks3D[iVar5].flags3D = map->blocks3D[iVar5].flags3D | MAP3DBLOCK_FLAG_VERTEXLEVELED; } bCheckMinMax += 1; pShape_1 = pShape_1 + 1; } while (bCheckMinMax < 4); i += 1; local_22c = local_22c + 1; } while (i < addCount); } return; } // This seems to be used when the height difference of diagonal vertex points differs. // // diffxy00_11 = (blocks3D[y][x].heightValue - blocks3D[y+1][x+1].heightValue) // diffxy10_01 = (blocks3D[y][x+1].heightValue - blocks3D[y+1][x].heightValue) // rotated = (abs(diffxy00_11) < std::abs(diffxy10_01)); void __cdecl lego::map::Map3D_SetBlockRotated(Map3D *map,uint bx,uint by,BOOL on) { Map3D_BlockFlags *pMVar1; int iVar2; D3DRMGroupIndex groupID; Vertex *pVVar3; Vertex *pVVar4; Vertex vertices [4]; Vertex vertexSwap; Map3D_BlockFlags bVar2; // if ((on!=0) != Map3D_IsBlockRotated(surfMap, bx, by)) if (((on != 0) && ((map->blocks3D[by * map->gridWidth + bx].flags3D & MAP3DBLOCK_FLAG_ROTATED) == MAP3DBLOCK_FLAG_NONE)) || ((on == 0 && ((map->blocks3D[by * map->gridWidth + bx].flags3D & MAP3DBLOCK_FLAG_ROTATED) != MAP3DBLOCK_FLAG_NONE)))) { groupID = map->blockWidth * by + bx; gfx::Container_Mesh_GetVertices(map->mesh,groupID,0,4,vertices); iVar2 = by * map->gridWidth + bx; bVar2 = map->blocks3D[iVar2].flags3D; pMVar1 = &map->blocks3D[iVar2].flags3D; if ((bVar2 & MAP3DBLOCK_FLAG_ROTATED) == MAP3DBLOCK_FLAG_NONE) { // Shift vertices up one // // memcpy(&vertexSwap, &vertices[3], sizeof(D3DRMVertex)); // memcpy(&vertices[3], &vertices[2], sizeof(D3DRMVertex)); // memcpy(&vertices[2], &vertices[1], sizeof(D3DRMVertex)); // memcpy(&vertices[1], &vertices[0], sizeof(D3DRMVertex)); // memcpy(&vertices[0], &vertexSwap, sizeof(D3DRMVertex)); *pMVar1 = bVar2 | MAP3DBLOCK_FLAG_ROTATED; pVVar3 = vertices + 3; pVVar4 = &vertexSwap; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar4->position).x = (pVVar3->position).x; pVVar3 = (Vertex *)&(pVVar3->position).y; pVVar4 = (Vertex *)&(pVVar4->position).y; } pVVar3 = vertices + 2; pVVar4 = vertices + 3; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar4->position).x = (pVVar3->position).x; pVVar3 = (Vertex *)&(pVVar3->position).y; pVVar4 = (Vertex *)&(pVVar4->position).y; } pVVar3 = vertices + 1; pVVar4 = vertices + 2; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar4->position).x = (pVVar3->position).x; pVVar3 = (Vertex *)&(pVVar3->position).y; pVVar4 = (Vertex *)&(pVVar4->position).y; } pVVar3 = vertices; pVVar4 = vertices + 1; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar4->position).x = (pVVar3->position).x; pVVar3 = (Vertex *)&(pVVar3->position).y; pVVar4 = (Vertex *)&(pVVar4->position).y; } pVVar3 = vertices; } else { // Shift vertices down one // // memcpy(&vertexSwap, &vertices[0], sizeof(D3DRMVertex)); // memcpy(&vertices[0], &vertices[1], sizeof(D3DRMVertex)); // memcpy(&vertices[1], &vertices[2], sizeof(D3DRMVertex)); // memcpy(&vertices[2], &vertices[3], sizeof(D3DRMVertex)); // memcpy(&vertices[3], &vertexSwap, sizeof(D3DRMVertex)); *pMVar1 = bVar2 & ~MAP3DBLOCK_FLAG_ROTATED; pVVar3 = vertices; pVVar4 = &vertexSwap; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar4->position).x = (pVVar3->position).x; pVVar3 = (Vertex *)&(pVVar3->position).y; pVVar4 = (Vertex *)&(pVVar4->position).y; } pVVar3 = vertices + 1; pVVar4 = vertices; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar4->position).x = (pVVar3->position).x; pVVar3 = (Vertex *)&(pVVar3->position).y; pVVar4 = (Vertex *)&(pVVar4->position).y; } pVVar3 = vertices + 2; pVVar4 = vertices + 1; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar4->position).x = (pVVar3->position).x; pVVar3 = (Vertex *)&(pVVar3->position).y; pVVar4 = (Vertex *)&(pVVar4->position).y; } pVVar3 = vertices + 3; pVVar4 = vertices + 2; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar4->position).x = (pVVar3->position).x; pVVar3 = (Vertex *)&(pVVar3->position).y; pVVar4 = (Vertex *)&(pVVar4->position).y; } pVVar3 = vertices + 3; } pVVar4 = &vertexSwap; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { (pVVar3->position).x = (pVVar4->position).x; pVVar4 = (Vertex *)&(pVVar4->position).y; pVVar3 = (Vertex *)&(pVVar3->position).y; } gfx::Container_Mesh_SetVertices(map->mesh,groupID,0,4,vertices); Map3D_GenerateBlockPlaneNormals(map,bx,by); // Perform action in a square: { { 0, 0 }, { 1, 0 }, // { 0, 1 }, { 1, 1 } } Map3D_SetBlockVertexModified(map,bx,by); Map3D_SetBlockVertexModified(map,bx + 1,by); Map3D_SetBlockVertexModified(map,bx + 1,by + 1); Map3D_SetBlockVertexModified(map,bx,by + 1); } return; } void __cdecl lego::map::Map3D_SetBlockVertexModified(Map3D *map,uint vx,uint vy) { Map3D_BlockFlags *flags3D; flags3D = &map->blocks3D[map->gridWidth * vy + vx].flags3D; *flags3D = *flags3D | MAP3DBLOCK_FLAG_VERTEXMODIFIED; map->flagsMap = map->flagsMap | MAP3D_FLAG_VERTEXMODIFIED; return; } void __cdecl lego::map::Map3D_Update(Map3D *map,float elapsedGame) { int idx; uint width; uint by; uint bx; // 0x2 = needs some UpdateBlockTextureAndVertices(?) if ((*(byte *)&map->flagsMap & MAP3D_FLAG_VERTEXMODIFIED) != 0) { by = 0; if (map->gridHeight != 0) { do { width = map->gridWidth; bx = 0; if (width != 0) { do { // 0x4 = needs UpdateBlockTextureAndVertices if ((map->blocks3D[by * width + bx].flags3D & MAP3DBLOCK_FLAG_VERTEXMODIFIED) != MAP3DBLOCK_FLAG_NONE) { Map3D_UpdateBlockNormals(map,bx,by); idx = by * map->gridWidth + bx; // ~0x4 map->blocks3D[idx].flags3D = map->blocks3D[idx].flags3D & ~MAP3DBLOCK_FLAG_VERTEXMODIFIED; } width = map->gridWidth; bx += 1; } while (bx < width); } by += 1; } while (by < map->gridHeight); } map->flagsMap = map->flagsMap & ~MAP3D_FLAG_VERTEXMODIFIED; } Map3D_UpdateTextureUVs(map,elapsedGame); Map3D_UpdateFadeInTransitions(map,elapsedGame); return; } void __cdecl lego::map::Map3D_UpdateFadeInTransitions(Map3D *map,float elapsedGame) { float *pVertTexV; int j; int i; float *pTrans_0xc; Vertex vertices [4]; float *pTransUV_m1; float timer; i = 10; // (Map3D_TransBlock+0xc) pTrans_0xc = (float *)&map->transBlocks[0].blockPos.y; do { // if (transBlocks[idx].flags & MAP3DTRANS_FLAG_USED) if ((*(byte *)(pTrans_0xc + 10) & 1) != 0) { // map->blockWidth * transBlocks[idx].blockPos.y + transBlocks[idx].blockPos.x gfx::Container_Mesh_GetVertices (map->mesh,map->blockWidth * (int)*pTrans_0xc + (int)pTrans_0xc[-1],0,4,vertices); pVertTexV = &vertices[0].tv; j = 4; pTransUV_m1 = pTrans_0xc; do { // vertices[j].tu = transBlocks[idx].uvCoords[j].x; // vertices[j].tv = transBlocks[idx].uvCoords[j].y; pVertTexV[-1] = pTransUV_m1[1]; *pVertTexV = pTransUV_m1[2]; pVertTexV = pVertTexV + 9; j += -1; pTransUV_m1 = pTransUV_m1 + 2; } while (j != 0); // transBlocks[idx].groupID gfx::Container_Mesh_SetVertices(map->transMesh,(D3DRMGroupIndex)pTrans_0xc[-3],0,4,vertices); gfx::Container_Mesh_SetColourAlpha (map->transMesh,(D3DRMGroupIndex)pTrans_0xc[-3],1.0,1.0,1.0,1.0 - pTrans_0xc[-2]); // transBlocks[idx].timer -= elapsedGame * -0.04f; timer = pTrans_0xc[-2] - elapsedGame * -0.04; pTrans_0xc[-2] = timer; // if (timer > 1.0f) if ((ushort)((ushort)(timer < 1.0) << 8 | (ushort)(timer == 1.0) << 0xe) == 0) { gfx::Container_Mesh_HideGroup(map->transMesh,(D3DRMGroupIndex)pTrans_0xc[-3],TRUE); // transBlocks[idx].flags &= ~MAP3DTRANS_FLAG_USED; pTrans_0xc[10] = (float)((uint)pTrans_0xc[10] & 0xfffffffe); } } // transBlocks idx++; pTrans_0xc = pTrans_0xc + 0xe; i += -1; } while (i != 0); return; } void __cdecl lego::map::Map3D_AddTextureMapping(Map3D *map,SurfaceTexture texA,SurfaceTexture texB) { uint texANum; uint i; uint texB_; uint texA_; texA_ = (uint)texA; i = 0; texANum = (uint)map->texsNum[texA_]; // check if mapping has already been created. If so, end operation if (texANum != 0) { do { // mapping already exists at index? if (map->texsGrid[texA_][i] == texB) { return; } i += 1; } while (i < texANum); } // mapping not found, add texB to end of texA[] list map->texsGrid[texA_][texANum] = texB; map->texsNum[texA_] = map->texsNum[texA_] + 1; // now create the reverse mapping, add texA to end of texB[] list texB_ = (uint)texB; map->texsGrid[texB_][map->texsNum[texB_]] = texA; map->texsNum[texB_] = map->texsNum[texB_] + 1; return; } void __cdecl lego::map::Map3D_SetTextureSet(Map3D *map,Detail_TextureSet *tset) { map->textureSet = tset; return; } void __cdecl lego::map::Map3D_SetBlockTexture (Map3D *map,uint bx,uint by,SurfaceTexture newTexture,byte direction) { byte bVar1; Container_Texture *ref_itext; uint i; D3DRMGroupIndex groupID; float *pVertV; byte DIRECTIONS_UNK [4]; Vertex vertices [4]; _direction = (uint)direction; if ((bx < map->blockWidth) && (by < map->blockHeight)) { groupID = by * map->blockWidth + bx; DIRECTIONS_UNK[0] = 1; DIRECTIONS_UNK[1] = 3; DIRECTIONS_UNK[2] = 2; DIRECTIONS_UNK[3] = 0; ref_itext = Detail_GetTexture(map->textureSet,newTexture); map->blocks3D[by * map->gridWidth + bx].texture = newTexture; if ((map->blocks3D[by * map->gridWidth + bx].flags3D & MAP3DBLOCK_FLAG_ROTATED) != MAP3DBLOCK_FLAG_NONE) { _direction = (uint)(byte)(direction + 1); } gfx::Container_Mesh_SetTexture(map->mesh,groupID,ref_itext); if ((map->blocks3D[by * map->gridWidth + bx].flags3D & MAP3DBLOCK_FLAG_UVWOBBLES) == MAP3DBLOCK_FLAG_NONE) { gfx::Container_Mesh_GetVertices(map->mesh,groupID,0,4,vertices); i = 0; pVertV = &vertices[0].tv; do { bVar1 = DIRECTIONS_UNK[i - _direction & 3]; i += 1; pVertV[-1] = (float)(uint)(bVar1 >> 1); *pVertV = (float)(uint)(bVar1 & 1); pVertV = pVertV + 9; } while (i < 4); gfx::Container_Mesh_SetVertices(map->mesh,groupID,0,4,vertices); } } return; } void __cdecl lego::map::Map3D_MoveBlockVertices(Map3D *map,uint bx,uint by,float zDist) { float *pOffsetM1Y; uint by_00; int i; Direction DVar1; Point2F *pOffsetM1; longlong lVar2; Direction direction; Vector3F vertDists [1]; Point2F OFFSETS_M1 [4]; uint y; uint x; Vector3F *pVertDist; DVar1 = DIRECTION_UP; vertDists[0].z = zDist; OFFSETS_M1[0].x = 0.0; OFFSETS_M1[0].y = 0.0; OFFSETS_M1[1].x = -1.0; OFFSETS_M1[1].y = 0.0; OFFSETS_M1[2].x = -1.0; OFFSETS_M1[2].y = -1.0; OFFSETS_M1[3].x = 0.0; OFFSETS_M1[3].y = -1.0; vertDists[0].x = 0.0; vertDists[0].y = 0.0; // for (uint i = 0; i < 4; i++) // OFFSETS_M1[i].x += (float)bx, OFFSETS_M1[i].y += (float)by; i = 4; pOffsetM1Y = &OFFSETS_M1[0].y; do { i += -1; pOffsetM1Y[-1] = (float)(ulonglong)bx + pOffsetM1Y[-1]; *pOffsetM1Y = *pOffsetM1Y + (float)(ulonglong)by; pOffsetM1Y = pOffsetM1Y + 2; } while (i != 0); // for (uint vertIdx = 0; vertIdx < 4; vertIdx++) // SurfaceMap_Block_SetIndexVertexPosition(surfMap, // OFFSETS_M1[i].x, OFFSETS_M1[i].y, vertIdx, vertPoses); pOffsetM1 = OFFSETS_M1; do { pVertDist = vertDists; direction = DVar1; lVar2 = __ftol((float10)pOffsetM1->y); by_00 = (uint)lVar2; lVar2 = __ftol((float10)pOffsetM1->x); Map3D_MoveBlockDirectionVertex(map,(uint)lVar2,by_00,direction,pVertDist); DVar1 += DIRECTION_RIGHT; pOffsetM1 = pOffsetM1 + 1; } while (DVar1 < DIRECTION__COUNT); for (y = by - 1; y <= by; y += 1) { for (x = bx - 1; x <= bx; x += 1) { Map3D_GenerateBlockPlaneNormals(map,x,y); } } return; } void __cdecl lego::map::Map3D_SetPerspectiveCorrectionAll(Map3D *map,BOOL on) { uint width; uint by; uint bx; by = 0; if (map->blockHeight != 0) { do { width = map->blockWidth; bx = 0; if (width != 0) { do { gfx::Container_Mesh_SetPerspectiveCorrection(map->mesh,by * width + bx,on); width = map->blockWidth; bx += 1; } while (bx < width); } by += 1; } while (by < map->blockHeight); } return; } WallHighlightType __cdecl lego::map::Map3D_SetBlockHighlight(Map3D *map,int bx,int by,WallHighlightType highlightType) { int idx; byte oldHighlight; idx = map->gridWidth * by + bx; oldHighlight = map->blocks3D[idx].highlight; map->blocks3D[idx].highlight = (byte)highlightType; Map3D_Block_SetColour (map,bx,by,TRUE,globs::constant::c_wallHighlightColours[highlightType].red, globs::constant::c_wallHighlightColours[highlightType].green, globs::constant::c_wallHighlightColours[highlightType].blue); return (uint)oldHighlight; } WallHighlightType __cdecl lego::map::Map3D_GetBlockHighlight(Map3D *map,int bx,int by) { return (uint)map->blocks3D[map->gridWidth * by + bx].highlight; } void __cdecl lego::map::Map3D_ClearBlockHighlight(Map3D *map,int bx,int by) { // clear block colour Map3D_Block_SetColour(map,bx,by,FALSE,1.0,1.0,1.0); map->blocks3D[map->gridWidth * by + bx].highlight = WALLHIGHLIGHT_NONE; return; } void __cdecl lego::map::Map3D_Block_SetColour(Map3D *map,int bx,int by,BOOL setColour,float r,float g,float b) { D3DRMGroupIndex groupID; groupID = map->blockWidth * by + bx; if (setColour != 0) { gfx::Container_Mesh_SetColourAlpha(map->mesh,groupID,r,g,b,1.0); return; } gfx::Container_Mesh_SetColourAlpha(map->mesh,groupID,1.0,1.0,1.0,1.0); map->blocks3D[map->gridWidth * by + bx].highlight = WALLHIGHLIGHT_NONE; return; } BOOL __cdecl lego::map::Map3D_BlockToWorldPos(Map3D *map,uint bx,uint by,float *out_x,float *out_y) { if ((bx < map->blockWidth) && (by < map->blockHeight)) { *out_x = map->blockSize * 0.5 + (float)(ulonglong)bx * map->blockSize + (map->worldDimensions_fnegx).width; *out_y = (map->worldDimensions_fnegx).height - (map->blockSize * 0.5 + (float)(ulonglong)by * map->blockSize); return TRUE; } return FALSE; } BOOL __cdecl lego::map::Map3D_WorldToBlockPos_NoZ(Map3D *map,float in_x,float in_y,int *out_bx,int *out_by) { BOOL BVar1; // The final argument here ((float *)&out_y) is a dummy argument that won't output the // pointed-to value BVar1 = Map3D_WorldToBlockPos(map,in_x,in_y,out_bx,out_by,(float *)&out_by); return BVar1; } BOOL __cdecl lego::map::Map3D_WorldToBlockPos (Map3D *map,float in_x,float in_y,int *out_bx,int *out_by,float *out_unk_z) { float fVar1; int iVar2; int iVar3; longlong lVar4; lVar4 = __ftol(((float10)in_x - (float10)(map->worldDimensions_fnegx).width) / (float10)map->blockSize); iVar2 = (int)lVar4; lVar4 = __ftol(((float10)(map->worldDimensions_fnegx).height - (float10)in_y) / (float10)map->blockSize); iVar3 = (int)lVar4; if (out_bx != NULL) { *out_bx = iVar2; } if (out_by != NULL) { *out_by = iVar3; } if ((((-1 < iVar2) && (iVar2 < (int)map->blockWidth)) && (-1 < iVar3)) && (iVar3 < (int)map->blockHeight)) { if (out_unk_z != NULL) { fVar1 = map->blockSize * 0.5; in_x = (in_x - ((float)iVar2 * map->blockSize + (map->worldDimensions_fnegx).width)) / fVar1; fVar1 = -((in_y - ((map->worldDimensions_fnegx).height - (float)iVar3 * map->blockSize)) / fVar1); if ((ushort)((ushort)(in_x < 1.0) << 8 | (ushort)(in_x == 1.0) << 0xe) == 0) { in_x = 2.0 - in_x; } if ((ushort)((ushort)(fVar1 < 1.0) << 8 | (ushort)(fVar1 == 1.0) << 0xe) == 0) { fVar1 = 2.0 - fVar1; } if (in_x < fVar1) { fVar1 = in_x; } *out_unk_z = fVar1; } return TRUE; } return 0; } void __cdecl lego::map::Map3D_FUN_0044fad0(Map3D *map,float in_x,float in_y,int *out_x,int *out_y) { int iVar1; int iVar2; longlong lVar3; lVar3 = __ftol(((float10)in_x - (float10)(map->worldDimensions_fnegx).width) / (float10)map->blockSize); iVar2 = (int)lVar3; lVar3 = __ftol(((float10)(map->worldDimensions_fnegx).height - (float10)in_y) / (float10)map->blockSize); iVar1 = (int)lVar3; if (iVar2 < 0) { iVar2 = 0; } if ((int)map->blockWidth <= iVar2) { iVar2 = map->blockWidth - 1; } if (iVar1 < 0) { iVar1 = 0; } if ((int)map->blockHeight <= iVar1) { iVar1 = map->blockHeight - 1; } if (out_x != NULL) { *out_x = iVar2; } if (out_y != NULL) { *out_y = iVar1; } return; } // Always returns false. BOOL __cdecl lego::map::Map3D_FUN_0044fb30 (Map3D *map,Point2F *wPos2D,Point2F *optout_blockPosf,Point2F *optout_centerDir) { float fVar1; BOOL BVar2; Point2F *local_8; float fStack4; Map3D *map_00; Point2F *optin_param_4_00; Point2F *param_2_00; param_2_00 = wPos2D; map_00 = map; BVar2 = Map3D_WorldToBlockPos_NoZ(map,wPos2D->x,wPos2D->y,(int *)&map,(int *)&wPos2D); optin_param_4_00 = optout_centerDir; if (BVar2 != 0) { if (optout_blockPosf != NULL) { local_8 = wPos2D; fStack4 = 0.0; optout_blockPosf->x = (float)ZEXT48(map); optout_blockPosf->y = (float)ZEXT48(wPos2D); } if (optout_centerDir != NULL) { Map3D_BlockToWorldPos(map_00,(uint)map,(uint)wPos2D,(float *)&local_8,&fStack4); optin_param_4_00->x = param_2_00->x - (float)local_8; optin_param_4_00->y = param_2_00->y - fStack4; fVar1 = 1.0 / map_00->blockSize; optin_param_4_00->x = fVar1 * optin_param_4_00->x - -0.5; optin_param_4_00->y = fVar1 * optin_param_4_00->y - -0.5; } } return 0; } float10 __cdecl lego::map::Map3D_GetWorldZ(Map3D *map,float xPos,float yPos) { BOOL BVar1; float10 fVar2; uint local_38; float local_34; Vector3F local_30; float local_24; float local_20; float local_1c; float local_18; float local_10; float local_c; float local_8; float local_4; Map3D *map_00; map_00 = map; local_34 = 0.0; BVar1 = Map3D_WorldToBlockPos_NoZ(map,xPos,yPos,(int *)&local_38,(int *)&map); if (BVar1 != 0) { BVar1 = Map3D_GetBlockVertexPositions(map_00,local_38,(uint)map,&local_30); if (BVar1 == 0) { if (map_00->blockSize <= (xPos - local_30.x) + (local_30.y - yPos)) { local_30.z = (local_4 - local_10) + (local_1c - local_10) + local_10; } else { local_10 = (local_4 - local_30.z) + (local_1c - local_30.z) + local_30.z; } } else { if (map_00->blockSize <= (local_24 - xPos) + (local_20 - yPos)) { local_1c = (local_10 - local_4) + (local_30.z - local_4) + local_4; } else { local_4 = (local_10 - local_1c) + (local_30.z - local_1c) + local_1c; } } fVar2 = ((float10)local_10 - (float10)local_4) * (((float10)local_18 - (float10)local_c) / ((float10)xPos - (float10)local_c)) + (float10)local_4; return (((float10)local_30.y - (float10)local_8) / ((float10)yPos - (float10)local_8)) * ((((float10)local_1c - (float10)local_30.z) * (((float10)xPos - (float10)local_30.x) / ((float10)local_24 - (float10)local_30.x)) + (float10)local_30.z) - fVar2) + fVar2; } return (float10)local_34; } void __cdecl lego::map::Map3D_FUN_0044fd70(Map3D *map,float in_x,float in_y,Vector3F *out_vector) { BOOL BVar1; uint uVar2; Map3D_Block *pMVar3; uint local_34; Vector3F local_30; float local_24; float local_20; Map3D *map_00; map_00 = map; BVar1 = Map3D_WorldToBlockPos_NoZ(map,in_x,in_y,(int *)&local_34,(int *)&map); if (BVar1 == 0) { return; } BVar1 = Map3D_GetBlockVertexPositions(map_00,local_34,(uint)map,&local_30); if (BVar1 == 0) { uVar2 = map_00->gridWidth; if ((local_30.y - in_y) + (in_x - local_30.x) < map_00->blockSize) { LAB_0044fe14: pMVar3 = map_00->blocks3D + uVar2 * (int)map + local_34; goto LAB_0044fe28; } } else { uVar2 = map_00->gridWidth; if (map_00->blockSize <= (local_20 - in_y) + (local_24 - in_x)) goto LAB_0044fe14; } pMVar3 = (Map3D_Block *)&map_00->blocks3D[uVar2 * (int)map + local_34].normalB; LAB_0044fe28: out_vector->x = (pMVar3->normalA).x; out_vector->y = (pMVar3->normalA).y; out_vector->z = (pMVar3->normalA).z; return; } BOOL __cdecl lego::map::Map3D_FUN_0044fe50 (Map3D *map,float xPos,float yPos,BOOL diagonal,float unkMultiplier,float *out_xOut, float *out_yOut) { Vector3F *pVVar1; float fVar2; float fVar3; BOOL BVar4; Map3D_Block *pMVar5; int iVar6; int iVar7; uint local_68; Point2F local_64; Point2F local_5c; Point2F local_54; Point2F local_4c; Point2F local_44; float local_3c; float local_38; float local_34; Vector3F local_30; float local_24 [9]; Map3D *map_00; map_00 = map; BVar4 = Map3D_WorldToBlockPos_NoZ(map,xPos,yPos,(int *)&local_68,(int *)&map); if (BVar4 == 0) { return FALSE; } BVar4 = Map3D_GetBlockVertexPositions(map_00,local_68,(uint)map,&local_30); if (BVar4 == 0) { if ((xPos - local_30.x) + (local_30.y - yPos) < map_00->blockSize) { pMVar5 = map_00->blocks3D + map_00->gridWidth * (int)map + local_68; local_3c = (pMVar5->normalA).x; local_38 = (pMVar5->normalA).y; local_34 = (pMVar5->normalA).z; goto LAB_0044ff78; } pMVar5 = (Map3D_Block *)&map_00->blocks3D[map_00->gridWidth * (int)map + local_68].normalB; } else { if ((local_24[0] - xPos) + (local_24[1] - yPos) < map_00->blockSize) { pVVar1 = &map_00->blocks3D[map_00->gridWidth * (int)map + local_68].normalB; local_3c = pVVar1->x; local_38 = pVVar1->y; local_34 = pVVar1->z; goto LAB_0044ff78; } pMVar5 = map_00->blocks3D + map_00->gridWidth * (int)map + local_68; } local_3c = (pMVar5->normalA).x; local_38 = (pMVar5->normalA).y; local_34 = (pMVar5->normalA).z; LAB_0044ff78: if (diagonal == 0) { if (ABS(local_3c) <= ABS(local_38)) { if (0.0 <= local_38) { iVar6 = 0; iVar7 = 1; } else { iVar6 = 2; iVar7 = 3; } } else { if (0.0 <= local_3c) { iVar6 = 1; iVar7 = 2; } else { iVar6 = 0; iVar7 = 3; } } } else { if (BVar4 == 0) { iVar6 = 1; iVar7 = 3; } else { iVar6 = 0; iVar7 = 2; } } local_54.x = local_24[iVar6 * 3 + -3]; local_54.y = local_24[iVar6 * 3 + -2]; local_4c.x = xPos; local_5c.x = local_24[iVar7 * 3 + -3] - local_54.x; local_5c.y = local_24[iVar7 * 3 + -2] - local_54.y; local_4c.y = yPos; local_64.x = local_3c; local_64.y = local_38; math::Maths_Vector2DIntersection(&local_44,&local_54,&local_5c,&local_4c,&local_64); fVar3 = unkMultiplier * map_00->blockSize; fVar2 = 1.0 / SQRT(local_64.y * local_64.y + local_64.x * local_64.x); *out_xOut = local_44.x - fVar2 * local_64.x * fVar3; *out_yOut = local_44.y - fVar2 * local_64.y * fVar3; return TRUE; } float10 __cdecl lego::map::Map3D_UnkCameraXYFunc_RetZunk(Map3D *map,float xPos,float yPos) { Map3D *pMVar1; BOOL BVar2; Point2F *pPVar3; float *pfVar4; int iVar5; float10 fVar6; float10 extraout_ST0; longlong lVar7; uint local_68; int local_64; float local_60; undefined4 uStack92; float local_58; undefined4 uStack84; Point2F OFFSETS [4]; Vector3F local_30 [4]; pMVar1 = map; local_58 = 0.0; BVar2 = Map3D_WorldToBlockPos_NoZ(map,xPos,yPos,(int *)&local_68,(int *)&map); if (BVar2 != 0) { uStack92 = 0; local_58 = (float)local_68; fVar6 = (float10)ZEXT48(map); uStack84 = 0; local_60 = (float)(ulonglong)local_68; OFFSETS[0].x = 0.0; OFFSETS[0].y = 0.0; OFFSETS[1].x = 1.0; OFFSETS[1].y = 0.0; OFFSETS[2].x = 1.0; OFFSETS[2].y = 1.0; OFFSETS[3].x = 0.0; OFFSETS[3].y = 1.0; pPVar3 = OFFSETS; local_64 = 4; pfVar4 = &local_30[0].y; do { pfVar4[-1] = (pPVar3->x + local_60) * pMVar1->blockSize + (pMVar1->worldDimensions_fnegx).width; *pfVar4 = (float)((float10)(pMVar1->worldDimensions_fnegx).height - ((float10)pPVar3->y + fVar6) * (float10)pMVar1->blockSize); lVar7 = __ftol((float10)pPVar3->y); iVar5 = (int)(map->texsGrid[-1] + (int)lVar7 + 0x4c) * pMVar1->gridWidth + local_68; lVar7 = __ftol((float10)pPVar3->x); pPVar3 = pPVar3 + 1; local_58 = (float)(uint)pMVar1->blocks3D[iVar5 + (int)lVar7].heightValue; local_64 += -1; pfVar4[1] = -((float)(int)local_58 * pMVar1->roughLevel); pfVar4 = pfVar4 + 3; fVar6 = extraout_ST0; } while (local_64 != 0); if (pMVar1->blockSize <= (local_30[1].x - xPos) + (local_30[1].y - yPos)) { fVar6 = (float10)local_30[3].z; local_30[1].z = (float)(((float10)local_30[2].z - fVar6) + ((float10)local_30[0].z - fVar6) + fVar6); } else { fVar6 = ((float10)local_30[2].z - (float10)local_30[1].z) + ((float10)local_30[0].z - (float10)local_30[1].z) + (float10)local_30[1].z; } fVar6 = ((float10)local_30[2].z - fVar6) * (((float10)local_30[2].x - (float10)local_30[3].x) / ((float10)xPos - (float10)local_30[3].x)) + fVar6; return (((float10)local_30[0].y - (float10)local_30[3].y) / ((float10)yPos - (float10)local_30[3].y)) * ((((float10)local_30[1].z - (float10)local_30[0].z) * (((float10)xPos - (float10)local_30[0].x) / ((float10)local_30[1].x - (float10)local_30[0].x)) + (float10)local_30[0].z) - fVar6) + fVar6; } return (float10)local_58; } void __cdecl lego::map::Map3D_GetBlockFirstVertexPosition(Map3D *map,int vx,int vy,Vector3F *out_vector) { Vertex vertex; gfx::Container_Mesh_GetVertices (map->mesh,vy * map->blockWidth + vx, map->blocks3D[map->gridWidth * vy + vx].flags3D & MAP3DBLOCK_FLAG_ROTATED,1,&vertex); out_vector->x = vertex.position.x; out_vector->y = vertex.position.y; out_vector->z = vertex.position.z; return; } // Returns TRUE if vertexes are shiftded down once, // or FALSE if in original position. BOOL __cdecl lego::map::Map3D_GetBlockVertexPositions(Map3D *map,uint bx,uint by,Vector3F *out_vertPoses) { uint width; Vertex vertices [4]; width = map->blockWidth; if ((bx < width) && (by < map->blockHeight)) { gfx::Container_Mesh_GetVertices(map->mesh,by * width + bx,0,4,vertices); if ((map->blocks3D[map->gridWidth * by + bx].flags3D & MAP3DBLOCK_FLAG_ROTATED) != MAP3DBLOCK_FLAG_NONE) { // Return vertices shifted down once. out_vertPoses->x = vertices[1].position.x; out_vertPoses->y = vertices[1].position.y; out_vertPoses->z = vertices[1].position.z; out_vertPoses[1].x = vertices[2].position.x; out_vertPoses[1].y = vertices[2].position.y; out_vertPoses[1].z = vertices[2].position.z; out_vertPoses[2].x = vertices[3].position.x; out_vertPoses[2].y = vertices[3].position.y; out_vertPoses[2].z = vertices[3].position.z; out_vertPoses[3].x = vertices[0].position.x; out_vertPoses[3].y = vertices[0].position.y; out_vertPoses[3].z = vertices[0].position.z; return TRUE; } // Return vertices in original position. out_vertPoses->x = vertices[0].position.x; out_vertPoses->y = vertices[0].position.y; out_vertPoses->z = vertices[0].position.z; out_vertPoses[1].x = vertices[1].position.x; out_vertPoses[1].y = vertices[1].position.y; out_vertPoses[1].z = vertices[1].position.z; out_vertPoses[2].x = vertices[2].position.x; out_vertPoses[2].y = vertices[2].position.y; out_vertPoses[2].z = vertices[2].position.z; out_vertPoses[3].x = vertices[3].position.x; out_vertPoses[3].y = vertices[3].position.y; out_vertPoses[3].z = vertices[3].position.z; // result = FALSE; width = 0; } // return result; return width; } void __cdecl lego::map::Map3D_GetBlockVertexPositions_NoRot(Map3D *map,uint bx,uint by,Vector3F *out_vertPoses) { Vertex vertices [4]; gfx::Container_Mesh_GetVertices(map->mesh,by * map->blockWidth + bx,0,4,vertices); out_vertPoses->x = vertices[0].position.x; out_vertPoses->y = vertices[0].position.y; out_vertPoses->z = vertices[0].position.z; out_vertPoses[1].x = vertices[1].position.x; out_vertPoses[1].y = vertices[1].position.y; out_vertPoses[1].z = vertices[1].position.z; out_vertPoses[2].x = vertices[2].position.x; out_vertPoses[2].y = vertices[2].position.y; out_vertPoses[2].z = vertices[2].position.z; out_vertPoses[3].x = vertices[3].position.x; out_vertPoses[3].y = vertices[3].position.y; out_vertPoses[3].z = vertices[3].position.z; return; } BOOL __cdecl lego::map::Map3D_IsInsideDimensions(Map3D *map,uint bx,uint by) { if (map->blockWidth <= bx) { return 0; } return (uint)(by < map->blockHeight); } BOOL __cdecl lego::map::Map3D_GetIntersections (Map3D *map,Viewport *view,uint mouseX,uint mouseY,uint *out_bx,uint *out_by, Vector3F *out_vector) { float fVar1; float fVar2; float fVar3; float fVar4; BOOL BVar5; int iVar6; float *pfVar7; Vector3F *vector; Point2I blockPos; Point2I loopOffset; Point2F mousePos; Vector3F xformVecZ1; Vector3F xformVecZ0; Vector4F xformPoly; Vector4F xformMouseZ0; Vector4F xformMouseZ1; Point2F polyPoints [5]; Vector3F vertPoses [4]; mousePos.x = (float)(ulonglong)mouseX; blockPos.x = mouseY; blockPos.y = 0; mousePos.y = (float)(ulonglong)mouseY; // xformMouseZ0 = Vector4F{mouseX, mouseY, 0.0, 1.0}; // xformMouseZ1 = Vector4F{mouseX, mouseY, 1.0, 1.0}; xformMouseZ0.z = 0.0; xformMouseZ0.w = 1.0; xformMouseZ1.z = 1.0; xformMouseZ1.w = 1.0; xformMouseZ0.x = mousePos.x; xformMouseZ0.y = mousePos.y; xformMouseZ1.x = mousePos.x; xformMouseZ1.y = mousePos.y; lego::view::Viewport_InverseTransform(view,&xformVecZ0,&xformMouseZ0); lego::view::Viewport_InverseTransform(view,&xformVecZ1,&xformMouseZ1); fVar2 = xformVecZ1.x - xformVecZ0.x; fVar1 = xformVecZ1.y - xformVecZ0.y; fVar3 = xformVecZ1.z - xformVecZ0.z; fVar4 = 1.0 / SQRT(fVar3 * fVar3 + fVar1 * fVar1 + fVar2 * fVar2); xformVecZ1.x = fVar4 * fVar2; xformVecZ1.y = fVar4 * fVar1; xformVecZ1.z = fVar4 * fVar3; BVar5 = Map3D_Intersections_Sub1_FUN_00450820 (map,&xformVecZ0,&xformVecZ1,out_vector,&blockPos,0x14); if (BVar5 == 0) { return FALSE; } // Do a 2D loop in range: (-2,-2) -> (2,2) loopOffset.y = -2; do { loopOffset.x = -2; do { if (((uint)(loopOffset.x + blockPos.x) < map->blockWidth) && ((uint)(blockPos.y + loopOffset.y) < map->blockHeight)) { Map3D_GetBlockVertexPositions (map,loopOffset.x + blockPos.x,blockPos.y + loopOffset.y,vertPoses); vector = vertPoses; iVar6 = 4; pfVar7 = &polyPoints[0].y; do { lego::view::Viewport_Transform(view,&xformPoly,vector); vector = vector + 1; iVar6 += -1; pfVar7[-1] = xformPoly.x / xformPoly.w; *pfVar7 = xformPoly.y / xformPoly.w; pfVar7 = pfVar7 + 2; } while (iVar6 != 0); polyPoints[4].x = polyPoints[0].x; polyPoints[4].y = polyPoints[0].y; BVar5 = math::Maths_PointInsidePoly(&mousePos,polyPoints,polyPoints + 1,4); if (BVar5 != 0) { *out_bx = loopOffset.x + blockPos.x; *out_by = blockPos.y + loopOffset.y; Map3D_Intersections_Sub2_FUN_004518a0 (map,*out_bx,blockPos.y + loopOffset.y,&xformVecZ0,&xformVecZ1,out_vector); return TRUE; } } loopOffset.x += 1; } while (loopOffset.x < 3); loopOffset.y += 1; if (2 < loopOffset.y) { return FALSE; } } while( true ); } BOOL __cdecl lego::map::Map3D_Intersections_Sub1_FUN_00450820 (Map3D *map,Vector3F *rayOrigin,Vector3F *ray,Vector3F *out_endPoint,Point2I *out_blockPos ,int unkCount) { BOOL BVar1; float10 fVar2; Vector3F planePoint; Vector3F planeNormal; planePoint.x = 0.0; planePoint.y = 0.0; planePoint.z = -50.0; planeNormal.x = 0.0; planeNormal.y = 0.0; planeNormal.z = -1.0; if (unkCount != 0) { do { math::Maths_RayPlaneIntersection(out_endPoint,rayOrigin,ray,&planePoint,&planeNormal); fVar2 = Map3D_GetWorldZ(map,out_endPoint->x,out_endPoint->y); planePoint.z = (float)fVar2; unkCount += -1; } while (unkCount != 0); } BVar1 = Map3D_WorldToBlockPos_NoZ (map,out_endPoint->x,out_endPoint->y,&out_blockPos->x,&out_blockPos->y); return BVar1; } void __cdecl lego::map::Map3D_AddVisibleBlocksInRadius_AndDoCallbacks (Map3D *map,int bx,int by,int radius,XYCallback opt_callback) { int rel_y; int abs_x; int abs_y; int neg_radius; int rel_x; neg_radius = -radius; if (-radius == radius || SBORROW4(neg_radius,radius) != radius * -2 < 0) { abs_y = neg_radius + by; rel_y = neg_radius; do { if (neg_radius <= radius) { abs_x = neg_radius + bx; rel_x = neg_radius; do { if ((((rel_x * rel_x + rel_y * rel_y <= radius * radius) && (-1 < abs_x)) && (abs_x < (int)map->blockWidth)) && ((-1 < abs_y && (abs_y < (int)map->blockHeight)))) { Map3D_HideBlock(map,abs_x,abs_y,FALSE); if (opt_callback != NULL) { (*opt_callback)(abs_x,abs_y); } map->visibleBlocksTable[map->visibleBlocksNum].x = (short)rel_x + (short)bx; map->visibleBlocksTable[map->visibleBlocksNum].y = (short)rel_y + (short)by; map->visibleBlocksNum = map->visibleBlocksNum + 1; } rel_x += 1; abs_x += 1; } while (rel_x <= radius); } rel_y += 1; abs_y += 1; } while (rel_y <= radius); } return; } void __cdecl lego::map::Map3D_HideBlock(Map3D *map,int bx,int by,BOOL hide) { gfx::Container_Mesh_HideGroup(map->mesh,by * map->blockWidth + bx,hide); return; } void __cdecl lego::map::Map3D_AddVisibleBlock(Map3D *map,int bx,int by) { Map3D_HideBlock(map,bx,by,FALSE); map->visibleBlocksTable[map->visibleBlocksNum].x = (ushort)bx; map->visibleBlocksTable[map->visibleBlocksNum].y = (ushort)by; map->visibleBlocksNum = map->visibleBlocksNum + 1; return; } void __cdecl lego::map::Map3D_HideVisibleBlocksList(Map3D *map) { uint i; Coord2U *coord; i = 0; if (map->visibleBlocksNum != 0) { coord = map->visibleBlocksTable; do { Map3D_HideBlock(map,(uint)coord->x,(uint)coord->y,TRUE); i += 1; coord = coord + 1; } while (i < map->visibleBlocksNum); } map->visibleBlocksNum = 0; return; } void __cdecl lego::map::Map3D_BlockVertexToWorldPos (Map3D *map,uint bx,uint by,float *out_xPos,float *out_yPos,float *out_zPos) { uint uVar1; uint index; Vertex vertices [1]; if (map->gridWidth <= bx) { return; } if (map->gridHeight <= by) { return; } uVar1 = map->blockWidth; index = 0; if (bx == uVar1) { if (by == map->blockHeight) { bx -= 1; by -= 1; index = 2; goto LAB_00450ae4; } if (bx == uVar1) { bx -= 1; index = 1; goto LAB_00450ae4; } } if (by == map->blockHeight) { by -= 1; index = 0xffffffff; } LAB_00450ae4: if ((map->blocks3D[by * map->gridWidth + bx].flags3D & MAP3DBLOCK_FLAG_ROTATED) != MAP3DBLOCK_FLAG_NONE) { index += 1; } if (index == 0xffffffff) { index = 3; } gfx::Container_Mesh_GetVertices(map->mesh,by * uVar1 + bx,index,1,vertices); *out_xPos = vertices[0].position.x; *out_yPos = vertices[0].position.y; *out_zPos = vertices[0].position.z; return; } float10 __cdecl lego::map::Map3D_BlockSize(Map3D *map) { return (float10)map->blockSize; } int __cdecl lego::map::Map3D_CheckRoutingComparison_FUN_00450b60 (int param_1,int param_2,int param_3,int param_4) { int iVar1; int iVar2; iVar2 = -1; if (param_1 == param_3) { if (param_2 + -1 == param_4) { return 0; } if (param_2 + 1 == param_4) { return 2; } } else { iVar1 = param_1 + 1; if (param_2 == param_4) { if (iVar1 == param_3) { return 1; } if (param_1 + -1 == param_3) { return 3; } } else { if (iVar1 == param_3) { if (param_2 + -1 == param_4) { return 4; } if ((iVar1 == param_3) && (param_2 + 1 == param_4)) { return 5; } } if (param_1 + -1 == param_3) { if (param_2 + 1 == param_4) { return 6; } if ((param_1 + -1 == param_3) && (param_2 + -1 == param_4)) { iVar2 = 7; } } } } return iVar2; } // used by water or lava to move uv's void __cdecl lego::map::Map3D_SetBlockUVWobbles(Map3D *map,uint bx,uint by,BOOL on) { int idx; uint i; ushort *pBlockPosY; uint count; if (on == 0) { if ((map->blocks3D[by * map->gridWidth + bx].flags3D & MAP3DBLOCK_FLAG_UVWOBBLES) != MAP3DBLOCK_FLAG_NONE) { // Find block in table, and remove if found count = map->uvBlocksNum; i = 0; if (count != 0) { pBlockPosY = &map->uvBlocksTable[0].y; while ((pBlockPosY[-1] != bx || (*pBlockPosY != by))) { i += 1; pBlockPosY = pBlockPosY + 2; if (count <= i) { return; } } map->uvBlocksNum = count - 1; // We need to swap out this block position with the last one in the list, // to avoid performing memmov. map->uvBlocksTable[i].x = map->uvBlocksTable[count - 1].x; map->uvBlocksTable[i].y = map->uvBlocksTable[map->uvBlocksNum].y; idx = by * map->gridWidth + bx; map->blocks3D[idx].flags3D = map->blocks3D[idx].flags3D & ~MAP3DBLOCK_FLAG_UVWOBBLES; } } } else { if ((map->blocks3D[by * map->gridWidth + bx].flags3D & MAP3DBLOCK_FLAG_UVWOBBLES) == MAP3DBLOCK_FLAG_NONE) { map->uvBlocksTable[map->uvBlocksNum].x = (ushort)bx; map->uvBlocksTable[map->uvBlocksNum].y = (ushort)by; idx = by * map->gridWidth + bx; map->uvBlocksNum = map->uvBlocksNum + 1; map->blocks3D[idx].flags3D = map->blocks3D[idx].flags3D | MAP3DBLOCK_FLAG_UVWOBBLES; return; } } return; } void __cdecl lego::map::Map3D_SetEmissive(Map3D *map,BOOL on) { uint i; Coord2U *pBlockPos; // Only turned on in FP view if ((on != 0) && ((*(byte *)&map->flagsMap & MAP3D_FLAG_EMISSIVE_4) == 0)) { i = 0; if (map->uvBlocksNum != 0) { pBlockPos = map->uvBlocksTable; do { gfx::Container_Mesh_SetEmissive (map->mesh,(uint)pBlockPos->y * map->blockWidth + (uint)pBlockPos->x,0.3,0.3,0.3); i += 1; pBlockPos = pBlockPos + 1; } while (i < map->uvBlocksNum); } map->flagsMap = map->flagsMap | MAP3D_FLAG_EMISSIVE_4; return; } if ((on == 0) && ((*(byte *)&map->flagsMap & MAP3D_FLAG_EMISSIVE_4) != 0)) { i = 0; if (map->uvBlocksNum != 0) { pBlockPos = map->uvBlocksTable; do { gfx::Container_Mesh_SetEmissive (map->mesh,(uint)pBlockPos->y * map->blockWidth + (uint)pBlockPos->x,0.0,0.0,0.0); i += 1; pBlockPos = pBlockPos + 1; } while (i < map->uvBlocksNum); } map->flagsMap = map->flagsMap & ~MAP3D_FLAG_EMISSIVE_4; } return; } void __cdecl lego::map::Map3D_UpdateTextureUVs(Map3D *map,float elapsedGame) { Point2F *pPVar1; Map3D_BlockFlags MVar2; float fVar3; float fVar4; float fVar5; float fVar6; float fVar7; ushort *pCoordY; int sxOff; D3DRMGroupIndex groupID; uint dirOff; uint sx; uint sy; int syOff; float10 fVar8; float10 fVar9; float10 fVar10; uint local_11c; Point2F baseUV; Point2F randUV; Point2F *pOffset_F; Point2I *pOffset_I; uint dirIndex; uint tableIndex; Point2F OFFSETS_F [4]; Point2I OFFSETS_I [4]; Vertex vertices [4]; int sxDiff; // if (elapsedGame > 0.001f) if ((ushort)((ushort)(elapsedGame < 0.001) << 8 | (ushort)(elapsedGame == 0.001) << 0xe) == 0) { OFFSETS_I[1].x = 1; OFFSETS_I[2].x = 1; OFFSETS_I[2].y = 1; OFFSETS_I[3].y = 1; OFFSETS_F[0].x = 0.0; OFFSETS_F[0].y = 1.0; OFFSETS_F[1].x = 1.0; OFFSETS_F[1].y = 1.0; OFFSETS_F[2].x = 1.0; OFFSETS_F[2].y = 0.0; OFFSETS_F[3].x = 0.0; OFFSETS_F[3].y = 0.0; OFFSETS_I[0].x = 0; OFFSETS_I[0].y = 0; OFFSETS_I[1].y = 0; OFFSETS_I[3].x = 0; tableIndex = 0; if (map->uvBlocksNum != 0) { fVar5 = 50.0 / elapsedGame; pCoordY = &map->uvBlocksTable[0].y; fVar6 = 1.0 / (fVar5 - -1.0); do { sy = (uint)*pCoordY; sx = (uint)pCoordY[-1]; groupID = map->blockWidth * sy + sx; MVar2 = map->blocks3D[sy * map->gridWidth + sx].flags3D; gfx::Container_Mesh_GetVertices(map->mesh,groupID,0,4,vertices); pOffset_F = OFFSETS_F; pOffset_I = OFFSETS_I; dirIndex = 0; local_11c = 0; do { dirOff = dirIndex; if ((MVar2 & MAP3DBLOCK_FLAG_ROTATED) != MAP3DBLOCK_FLAG_NONE) { dirOff = dirIndex + 1 & 3; } syOff = sy + *(int *)((int)&OFFSETS_I[0].y + local_11c); sxDiff = pOffset_I->x; sxOff = syOff * map->gridWidth + sx + sxDiff; fVar3 = vertices[dirOff].tu; randUV.x = map->blocks3D[sxOff].uvCoord.x + pOffset_F->x; fVar4 = vertices[dirOff].tv; randUV.y = map->blocks3D[sxOff].uvCoord.y + *(float *)((int)&OFFSETS_F[0].y + local_11c); fVar7 = SQRT((fVar4 - randUV.y) * (fVar4 - randUV.y) + (fVar3 - randUV.x) * (fVar3 - randUV.x)); baseUV.x = randUV.x; baseUV.y = randUV.y; if (((ushort)((ushort)(fVar7 < 0.36) << 8 | (ushort)(fVar7 == 0.36) << 0xe) != 0) && (baseUV.x = fVar3, baseUV.y = fVar4, fVar7 < 0.05)) { fVar8 = math::Maths_RandRange(0.0,1.0); fVar3 = (float)fVar8; fVar8 = math::Maths_RandRange(0.0,1.0); pPVar1 = &map->blocks3D[syOff * map->gridWidth + sx + sxDiff].uvCoord; fVar9 = (float10)1.0 / SQRT(fVar8 * (float10)(float)fVar8 + (float10)fVar3 * (float10)fVar3); fVar10 = ((float10)pPVar1->x + fVar9 * (float10)fVar3) * (float10)0.3; fVar3 = (pPVar1->y + (float)(fVar9 * (float10)(float)fVar8)) * 0.3; randUV.y = fVar3 + *(float *)((int)&OFFSETS_F[0].y + local_11c); randUV.x = (float)(fVar10 + (float10)pOffset_F->x); pPVar1->x = (float)fVar10; pPVar1->y = fVar3; } local_11c += 8; pOffset_I = pOffset_I + 1; pOffset_F = pOffset_F + 1; vertices[dirOff].tu = fVar6 * (fVar5 * baseUV.x + randUV.x); dirIndex += 1; vertices[dirOff].tv = fVar6 * (fVar5 * baseUV.y + randUV.y); } while (local_11c < 0x20); gfx::Container_Mesh_SetVertices(map->mesh,groupID,0,4,vertices); tableIndex += 1; pCoordY = pCoordY + 2; } while (tableIndex < map->uvBlocksNum); } } return; } // WARNING: Unable to use type for symbol vertDirection void __cdecl lego::map::Map3D_UpdateBlockNormals(Map3D *map,uint bx,uint by) { float fVar1; float fVar2; uint uVar3; BOOL BVar4; int i; float *pNormInZ; Vector3F *pVertNormalsOut; Direction idxGetIn; uint idxSetOut; Point2F *pBlockOffsets2; longlong lVar5; longlong lVar6; longlong lVar7; Direction direction; int idxOut; int idxIn; Point2F blockOffsets [4]; Vector3F vertNormalsOut [4]; Vector3F vertNormalsIn [4]; Vector3F *pVertNormOut; Vector3F *pVertNormalsIn; float *pBlockOffsetsIn; Vector3F *pVertNormIn; Direction vertDirection; Point2F *pBlockOffsets1; float *pNormOutZ; idxGetIn = DIRECTION_UP; blockOffsets[0].x = 0.0; blockOffsets[0].y = 0.0; blockOffsets[1].x = -1.0; blockOffsets[1].y = 0.0; blockOffsets[2].x = -1.0; blockOffsets[2].y = -1.0; blockOffsets[3].x = 0.0; blockOffsets[3].y = -1.0; vertNormalsOut[0].x = 0.0; vertNormalsOut[0].y = 0.0; vertNormalsOut[0].z = 0.0; vertNormalsOut[1].x = 0.0; vertNormalsOut[1].y = 0.0; vertNormalsOut[1].z = 0.0; vertNormalsOut[2].x = 0.0; vertNormalsOut[2].y = 0.0; vertNormalsOut[2].z = 0.0; vertNormalsOut[3].x = 0.0; vertNormalsOut[3].y = 0.0; vertNormalsOut[3].z = 0.0; i = 4; pBlockOffsetsIn = &blockOffsets[0].y; do { i += -1; pBlockOffsetsIn[-1] = pBlockOffsetsIn[-1] + (float)(ulonglong)bx; *pBlockOffsetsIn = (float)(ulonglong)by + *pBlockOffsetsIn; pBlockOffsetsIn = pBlockOffsetsIn + 2; } while (i != 0); pBlockOffsets1 = blockOffsets; pVertNormalsIn = vertNormalsIn; do { direction = idxGetIn; pVertNormIn = pVertNormalsIn; lVar5 = __ftol((float10)pBlockOffsets1->y); uVar3 = (uint)lVar5; lVar5 = __ftol((float10)pBlockOffsets1->x); Map3D_GetBlockDirectionNormal(map,(uint)lVar5,uVar3,direction,pVertNormIn); idxGetIn += DIRECTION_RIGHT; pVertNormalsIn = pVertNormalsIn + 1; pBlockOffsets1 = pBlockOffsets1 + 1; } while (idxGetIn < DIRECTION__COUNT); pBlockOffsets1 = blockOffsets; idxOut = 4; pNormOutZ = &vertNormalsOut[0].z; do { lVar5 = __ftol((float10)pBlockOffsets1->y); lVar6 = __ftol((float10)pBlockOffsets1->x); pBlockOffsets2 = blockOffsets; pNormInZ = &vertNormalsIn[0].z; idxIn = 4; do { lVar7 = __ftol((float10)pBlockOffsets2->y); uVar3 = (uint)lVar7; lVar7 = __ftol((float10)pBlockOffsets2->x); BVar4 = Map3D_BlockPairHasTextureMatch(map,(uint)lVar6,(uint)lVar5,(uint)lVar7,uVar3); if (BVar4 == 0) { fVar1 = pNormInZ[-1]; fVar2 = *pNormInZ; pNormOutZ[-2] = pNormInZ[-2] + pNormOutZ[-2]; pNormOutZ[-1] = fVar1 + pNormOutZ[-1]; *pNormOutZ = fVar2 + *pNormOutZ; } pBlockOffsets2 = pBlockOffsets2 + 1; pNormInZ = pNormInZ + 3; idxIn += -1; } while (idxIn != 0); pBlockOffsets1 = pBlockOffsets1 + 1; idxOut += -1; fVar1 = 1.0 / SQRT(pNormOutZ[-2] * pNormOutZ[-2] + *pNormOutZ * *pNormOutZ + pNormOutZ[-1] * pNormOutZ[-1]); *pNormOutZ = fVar1 * *pNormOutZ; pNormOutZ[-2] = fVar1 * pNormOutZ[-2]; pNormOutZ[-1] = fVar1 * pNormOutZ[-1]; pNormOutZ = pNormOutZ + 3; } while (idxOut != 0); idxSetOut = 0; pBlockOffsets1 = blockOffsets; pVertNormalsOut = vertNormalsOut; do { vertDirection = idxSetOut; pVertNormOut = pVertNormalsOut; lVar5 = __ftol((float10)pBlockOffsets1->y); uVar3 = (uint)lVar5; lVar5 = __ftol((float10)pBlockOffsets1->x); Map3D_SetBlockDirectionNormal(map,(uint)lVar5,uVar3,vertDirection,pVertNormOut); idxSetOut += DIRECTION_RIGHT; pVertNormalsOut = pVertNormalsOut + 1; pBlockOffsets1 = pBlockOffsets1 + 1; } while (idxSetOut < DIRECTION__COUNT); return; } BOOL __cdecl lego::map::Map3D_BlockPairHasTextureMatch(Map3D *map,uint bx1,uint by1,uint bx2,uint by2) { uint i; SurfaceTexture tex1; SurfaceTexture tex2; if (((((by1 != by2) || (bx1 != bx2)) && (bx1 < map->blockWidth)) && ((by1 < map->blockHeight && (bx2 < map->blockWidth)))) && (by2 < map->blockHeight)) { tex1 = map->blocks3D[by1 * map->gridWidth + bx1].texture; tex2 = map->blocks3D[by2 * map->gridWidth + bx2].texture; // Find a texture coord match for the 2 block positions by1 = (uint)tex1; if ((tex1 != TEXTURE__INVALID) && (tex2 != TEXTURE__INVALID)) { i = 0; // if (surfMap->texsNum[tex1] != 0) if (map->texsNum[by1] != 0) { do { // if (surfMap->texsGrid[tex1][i] == tex2) if (map->texsGrid[by1][i] == tex2) { return TRUE; } i += 1; } while (i < map->texsNum[by1]); return FALSE; } } } return FALSE; } void __cdecl lego::map::Map3D_SetBlockDirectionNormal (Map3D *map,uint bx,uint by,Direction direction,Vector3F *normal) { D3DRMGroupIndex groupID; Vertex vertices [1]; groupID = by * map->blockWidth + bx; if ((bx < map->blockWidth) && (by < map->blockHeight)) { if ((map->blocks3D[map->gridWidth * by + bx].flags3D & MAP3DBLOCK_FLAG_ROTATED) != MAP3DBLOCK_FLAG_NONE) { direction = direction + DIRECTION_RIGHT & DIRECTION_LEFT; } gfx::Container_Mesh_GetVertices(map->mesh,groupID,direction,1,vertices); vertices[0].normal.x = normal->x; vertices[0].normal.y = normal->y; vertices[0].normal.z = normal->z; gfx::Container_Mesh_SetVertices(map->mesh,groupID,direction,1,vertices); } return; } BOOL __cdecl lego::map::Map3D_GetBlockDirectionNormal (Map3D *map,uint bx,uint by,Direction direction,Vector3F *out_normal) { int idx; float m; float add_z; Map3D_Block *block3D; Vector3F *pNormalB; if ((bx < map->blockWidth) && (by < map->blockHeight)) { block3D = map->blocks3D + by * map->gridWidth + bx; if ((block3D->flags3D & MAP3DBLOCK_FLAG_ROTATED) != MAP3DBLOCK_FLAG_NONE) { // direction = (direction + 1) % DIRECTION_COUNT; direction = direction + DIRECTION_RIGHT & DIRECTION_LEFT; } if (direction == DIRECTION_UP) { // *out_normal = block3D->normalA; out_normal->x = (block3D->normalA).x; out_normal->y = (block3D->normalA).y; out_normal->z = (block3D->normalA).z; } if (direction == DIRECTION_DOWN) { // *out_normal = block3D->normalB; pNormalB = &map->blocks3D[by * map->gridWidth + bx].normalB; out_normal->x = pNormalB->x; out_normal->y = pNormalB->y; out_normal->z = pNormalB->z; } if ((direction == DIRECTION_RIGHT) || (direction == DIRECTION_LEFT)) { // Maths_Vector3DAdd(out_normal, block3D->normalB, block3D->normalA); // Maths_Vector3DNormalize(out_normal); block3D = map->blocks3D + by * map->gridWidth + bx; out_normal->x = (block3D->normalA).x; out_normal->y = (block3D->normalA).y; out_normal->z = (block3D->normalA).z; idx = by * map->gridWidth + bx; pNormalB = &map->blocks3D[idx].normalB; out_normal->x = map->blocks3D[idx].normalB.x + out_normal->x; out_normal->y = pNormalB->y + out_normal->y; add_z = pNormalB->z + out_normal->z; out_normal->z = add_z; m = 1.0 / SQRT(out_normal->x * out_normal->x + add_z * add_z + out_normal->y * out_normal->y); out_normal->x = m * out_normal->x; out_normal->y = m * out_normal->y; out_normal->z = m * out_normal->z; } return TRUE; } out_normal->z = 0.0; out_normal->y = 0.0; out_normal->x = 0.0; return FALSE; } void __cdecl lego::map::Map3D_MoveBlockDirectionVertex (Map3D *map,uint bx,uint by,Direction direction,Vector3F *vertDist) { D3DRMGroupIndex groupID; Vertex vertices [1]; uint width; width = map->blockWidth; groupID = by * width + bx; if ((bx < width) && (by < map->blockHeight)) { if ((map->blocks3D[map->gridWidth * by + bx].flags3D & MAP3DBLOCK_FLAG_ROTATED) != MAP3DBLOCK_FLAG_NONE) { direction = direction + DIRECTION_RIGHT & DIRECTION_LEFT; } gfx::Container_Mesh_GetVertices(map->mesh,groupID,direction,1,vertices); vertices[0].position.x = vertDist->x + vertices[0].position.x; vertices[0].position.y = vertDist->y + vertices[0].position.y; vertices[0].position.z = vertDist->z + vertices[0].position.z; gfx::Container_Mesh_SetVertices(map->mesh,groupID,direction,1,vertices); } return; } void __cdecl lego::map::Map3D_GenerateBlockPlaneNormals(Map3D *map,uint bx,uint by) { Vertex vertices [4]; uint width; width = map->blockWidth; if ((bx < width) && (by < map->blockHeight)) { gfx::Container_Mesh_GetVertices(map->mesh,by * width + bx,0,4,vertices); // (&surfMap->blocks3D[by * surfMap->gridWidth + bx].vector_0, // &vertices[0].position, &vertices[1].position, &vertices[2].position) math::Maths_PlaneNormal (&map->blocks3D[by * map->gridWidth + bx].normalA,&vertices[0].position, &vertices[1].position,&vertices[3].position); // (&surfMap->blocks3D[by * surfMap-gridWidth + bx].vector_c, // &vertices[1].position, &vertices[2].position, &vertices[3].position) // // NOTE: index is shifted one after the previous call math::Maths_PlaneNormal (&map->blocks3D[by * map->gridWidth + bx].normalB,&vertices[1].position, &vertices[2].position,&vertices[3].position); } return; } void __cdecl lego::map::Map3D_MapFileGetSpecs(MapFileInfo *mapFileInfo,uint *out_width,uint *out_height) { *out_width = (mapFileInfo->dimensions).width; *out_height = (mapFileInfo->dimensions).height; return; } ushort __cdecl lego::map::Map3D_MapFileBlockValue(MapFileInfo *mapFile,uint bx,uint by,uint gridWidth) { return mapFile->blocks[gridWidth * by + bx]; } BOOL __cdecl lego::map::Map3D_Intersections_Sub2_FUN_004518a0 (Map3D *map,uint bx,uint by,Vector3F *rayOrigin,Vector3F *ray,Vector3F *out_vector) { Map3D_Block *pMVar1; Vector3F *pVVar2; float fVar3; float fVar4; float fVar5; float fVar6; float fVar7; float fVar8; bool bVar9; int iVar10; BOOL BVar11; Point2F local_88; Vector3F local_7c; Point2F local_70; Point2F local_68; float local_60; float local_5c; float local_58; float local_54; Vector3F local_50; Vector3F local_44; int local_38; BOOL local_34; Vector3F local_30; float local_24; float local_20; Vector3F local_18; float local_c; float local_8; local_34 = Map3D_GetBlockVertexPositions(map,bx,by,&local_30); bVar9 = false; local_38 = 0; iVar10 = by * map->gridWidth + bx; pMVar1 = map->blocks3D + iVar10; local_7c.x = map->blocks3D[iVar10].normalA.x; local_7c.y = (pMVar1->normalA).y; local_7c.z = (pMVar1->normalA).z; BVar11 = math::Maths_RayPlaneIntersection(&local_50,rayOrigin,ray,&local_30,&local_7c); if (BVar11 != 0) { if (local_34 == 0) { local_68.x = local_24; local_68.y = local_20; } else { local_68.x = local_18.x; local_68.y = local_18.y; } local_88.x = local_50.x; local_88.y = local_50.y; BVar11 = math::Maths_PointInsidePoly(&local_88,&local_70,&local_68,3); if (BVar11 != 0) { bVar9 = true; } } iVar10 = by * map->gridWidth + bx; pVVar2 = &map->blocks3D[iVar10].normalB; local_7c.x = map->blocks3D[iVar10].normalB.x; local_7c.y = pVVar2->y; local_7c.z = pVVar2->z; BVar11 = math::Maths_RayPlaneIntersection(&local_44,rayOrigin,ray,&local_18,&local_7c); if (BVar11 != 0) { if (local_34 == 0) { local_68.x = local_18.x; local_68.y = local_18.y; local_60 = local_c; local_5c = local_8; local_58 = local_24; local_54 = local_20; } else { local_68.x = local_24; local_68.y = local_20; local_60 = local_18.x; local_5c = local_18.y; local_58 = local_30.x; local_54 = local_30.y; } local_88.x = local_44.x; local_88.y = local_44.y; local_70.x = local_58; local_70.y = local_54; BVar11 = math::Maths_PointInsidePoly(&local_88,&local_70,&local_68,3); if (BVar11 != 0) { local_38 = 1; } } if (!bVar9) { if (local_38 == 0) { return FALSE; } if (true) goto LAB_00451c3e; } if (local_38 == 0) { if (bVar9) { out_vector->x = local_50.x; out_vector->y = local_50.y; out_vector->z = local_50.z; return TRUE; } } else { fVar3 = local_50.x - rayOrigin->x; fVar4 = local_44.x - rayOrigin->x; fVar8 = local_50.y - rayOrigin->y; fVar5 = local_44.y - rayOrigin->y; fVar7 = local_50.z - rayOrigin->z; fVar6 = local_44.z - rayOrigin->z; fVar3 = SQRT(fVar7 * fVar7 + fVar8 * fVar8 + fVar3 * fVar3); fVar4 = SQRT(fVar6 * fVar6 + fVar5 * fVar5 + fVar4 * fVar4); if ((ushort)((ushort)(fVar4 < fVar3) << 8 | (ushort)(fVar4 == fVar3) << 0xe) == 0) { out_vector->x = local_50.x; out_vector->y = local_50.y; out_vector->z = local_50.z; return TRUE; } } LAB_00451c3e: out_vector->x = local_44.x; out_vector->y = local_44.y; out_vector->z = local_44.z; return TRUE; } MeshLOD * __cdecl lego::gfx::MeshLOD_Create (MeshLOD *opt_prevMeshLOD,char *partName,char *dirname,char *meshName,uint setID) { char cVar1; Container *cont; MeshLOD *newMeshLOD; undefined4 *puVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; char fname [256]; std::sprintf(fname,"%s\\%s",dirname,meshName); cont = Container_Load(NULL,fname,"LWO",TRUE); if (cont == NULL) { cont = Container_Load(NULL,fname,"MESH",TRUE); if (cont == NULL) { return NULL; } } newMeshLOD = (MeshLOD *)io::Mem_Alloc(0x18); newMeshLOD->flags = MESHLOD_FLAG_MEMBLOCK; if (opt_prevMeshLOD != NULL) { opt_prevMeshLOD->next = newMeshLOD; } newMeshLOD->contMeshOrigin = cont; uVar3 = 0xffffffff; newMeshLOD->next = NULL; newMeshLOD->setID = setID; pcVar6 = partName; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); puVar2 = (undefined4 *)io::Mem_Alloc(~uVar3); uVar3 = 0xffffffff; newMeshLOD->partName = (char *)puVar2; do { pcVar6 = partName; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = partName + 1; cVar1 = *partName; partName = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar2 = *puVar5; puVar5 = puVar5 + 1; puVar2 = puVar2 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar2 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar2 = (undefined4 *)((int)puVar2 + 1); } newMeshLOD->contMeshTarget = NULL; return newMeshLOD; } // Creates a MeshLOD struct pointing to a non-existant Mesh. // AKA, when a part is configured as NULL in the .ae file. MeshLOD * __cdecl lego::gfx::MeshLOD_CreateEmpty(MeshLOD *opt_prevMeshLOD,char *partName,uint setID) { char cVar1; MeshLOD *newMeshLOD; undefined4 *puVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; newMeshLOD = (MeshLOD *)io::Mem_Alloc(0x18); newMeshLOD->flags = MESHLOD_FLAG_MEMBLOCK; if (opt_prevMeshLOD != NULL) { opt_prevMeshLOD->next = newMeshLOD; } newMeshLOD->setID = setID; uVar3 = 0xffffffff; newMeshLOD->next = NULL; newMeshLOD->contMeshOrigin = NULL; pcVar6 = partName; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); puVar2 = (undefined4 *)io::Mem_Alloc(~uVar3); uVar3 = 0xffffffff; newMeshLOD->partName = (char *)puVar2; do { pcVar6 = partName; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = partName + 1; cVar1 = *partName; partName = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar2 = *puVar5; puVar5 = puVar5 + 1; puVar2 = puVar2 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar2 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar2 = (undefined4 *)((int)puVar2 + 1); } newMeshLOD->contMeshTarget = NULL; return newMeshLOD; } MeshLOD * __cdecl lego::gfx::MeshLOD_Clone(MeshLOD *srcMeshLOD) { MeshLOD *clonedMeshLOD; int i; int count; int iVar1; MeshLODFlags *pMVar2; MeshLOD *pMVar3; Container **ppCVar4; count = 0; clonedMeshLOD = srcMeshLOD; if (srcMeshLOD != NULL) { do { clonedMeshLOD = clonedMeshLOD->next; count += 1; } while (clonedMeshLOD != NULL); } if (count == 0) { return NULL; } clonedMeshLOD = (MeshLOD *)io::Mem_Alloc(count * 0x18); i = 0; if (srcMeshLOD != NULL) { pMVar2 = &clonedMeshLOD->flags; do { pMVar3 = srcMeshLOD; ppCVar4 = (Container **)(pMVar2 + -4); for (iVar1 = 6; iVar1 != 0; iVar1 += -1) { *ppCVar4 = pMVar3->contMeshOrigin; pMVar3 = (MeshLOD *)&pMVar3->contMeshTarget; ppCVar4 = ppCVar4 + 1; } pMVar2[-3] = MESHLOD_FLAG_NONE; i += 1; *pMVar2 = *pMVar2 & ~MESHLOD_FLAG_MEMBLOCK | MESHLOD_FLAG_CLONED; pMVar2[1] = (MeshLODFlags)(pMVar2 + 2); srcMeshLOD = srcMeshLOD->next; pMVar2 = pMVar2 + 6; } while (srcMeshLOD != NULL); } clonedMeshLOD->flags = clonedMeshLOD->flags | MESHLOD_FLAG_MEMBLOCK; clonedMeshLOD[i + -1].next = NULL; return clonedMeshLOD; } void __cdecl lego::gfx::MeshLOD_SwapTarget(MeshLOD *meshLOD,Container *contActTarget,BOOL restore,uint setID) { char *name; Container *part; if (meshLOD != NULL) { do { if (setID == meshLOD->setID) { if (meshLOD->contMeshTarget == NULL) { name = Container_FormatPartName(contActTarget,meshLOD->partName,NULL); part = Container_SearchTree(contActTarget,name,Container_SearchMode_FirstMatch,NULL); meshLOD->contMeshTarget = part; } if (meshLOD->contMeshTarget != NULL) { Container_Mesh_Swap(meshLOD->contMeshTarget,meshLOD->contMeshOrigin,restore); } } meshLOD = meshLOD->next; } while (meshLOD != NULL); } return; } void __cdecl lego::gfx::MeshLOD_RemoveTargets(MeshLOD *meshLOD) { if (meshLOD != NULL) { do { meshLOD->contMeshTarget = NULL; meshLOD = meshLOD->next; } while (meshLOD != NULL); } return; } void __cdecl lego::gfx::MeshLOD_Free(MeshLOD *meshLOD) { MeshLOD *item; MeshLOD *lastMemItem_; MeshLOD *lastMemItem; MeshLOD **pItemNext; lastMemItem_ = NULL; item = meshLOD; lastMemItem = lastMemItem_; if (meshLOD != NULL) { do { // if (!(m->flags & MESHLOD_FLAG_CLONED)) if ((*(byte *)&item->flags & 1) == 0) { if (item->partName != NULL) { io::Mem_Free(item->partName); } if (item->contMeshOrigin != NULL) { Container_Remove(item->contMeshOrigin); } } lastMemItem_ = item; // if (!(m->flags & MESHLOD_FLAG_MEMBLOCK) && ... if (((*(byte *)&item->flags & 2) == 0) && (lastMemItem_ = lastMemItem, lastMemItem != NULL)) { // Splice out items that are not the start of a contiguous memory block. lastMemItem->next = item->next; } pItemNext = &item->next; item = *pItemNext; lastMemItem = lastMemItem_; } while (*pItemNext != NULL); } if ((lastMemItem_ != NULL) && (meshLOD != NULL)) { do { item = meshLOD->next; io::Mem_Free(meshLOD); meshLOD = item; } while (item != NULL); } return; } void __cdecl lego::game::Message_Initialise(void) { globs::messageGlobs.messageName[0] = "Message_Null"; globs::messageGlobs.messageName[1] = "Message_Select"; globs::messageGlobs.messageName[2] = "Message_Selected"; globs::messageGlobs.messageName[3] = "Message_ClearSelection"; globs::messageGlobs.messageName[4] = "Message_Deselect"; globs::messageGlobs.messageName[5] = "Message_Goto"; globs::messageGlobs.messageName[6] = "Message_RockMonsterGoto"; globs::messageGlobs.messageName[7] = "Message_RockMonsterGotoComplete"; globs::messageGlobs.messageName[8] = "Message_UserGoto"; globs::messageGlobs.messageName[9] = "Message_FirstPerson"; globs::messageGlobs.messageName[10] = "Message_TrackObject"; globs::messageGlobs.messageName[11] = "Message_TopView"; globs::messageGlobs.messageName[12] = "Message_PlaySample"; globs::messageGlobs.messageName[13] = "Message_Dig"; globs::messageGlobs.messageName[14] = "Message_DigComplete"; globs::messageGlobs.messageName[15] = "Message_Repair"; globs::messageGlobs.messageName[16] = "Message_RepairComplete"; globs::messageGlobs.messageName[17] = "Message_Reinforce"; globs::messageGlobs.messageName[18] = "Message_ReinforceComplete"; globs::messageGlobs.messageName[19] = "Message_RockFall"; globs::messageGlobs.messageName[20] = "Message_RockFallComplete"; globs::messageGlobs.messageName[21] = "Message_GenerateCrystal"; globs::messageGlobs.messageName[22] = "Message_GenerateCrystalComplete"; globs::messageGlobs.messageName[23] = "Message_CollectCrystal"; globs::messageGlobs.messageName[24] = "Message_CollectCrystalComplete"; globs::messageGlobs.messageName[25] = "Message_CrystalToRefinery"; globs::messageGlobs.messageName[26] = "Message_CrystalToRefineryComplete"; globs::messageGlobs.messageName[27] = "Message_GenerateOre"; globs::messageGlobs.messageName[28] = "Message_GenerateOreComplete"; globs::messageGlobs.messageName[29] = "Message_CollectOre"; globs::messageGlobs.messageName[30] = "Message_CollectOreComplete"; globs::messageGlobs.messageName[31] = "Message_GenerateRockMonster"; globs::messageGlobs.messageName[32] = "Message_GenerateRockMonsterComplete"; globs::messageGlobs.messageName[33] = "Message_GatherRock"; globs::messageGlobs.messageName[34] = "Message_GatherRockComplete"; globs::messageGlobs.messageName[35] = "Message_PickRandomFloor"; globs::messageGlobs.messageName[36] = "Message_PickRandomFloorComplete"; globs::messageGlobs.messageName[37] = "Message_AttackBuilding"; globs::messageGlobs.messageName[38] = "Message_AttackBuildingComplete"; globs::messageGlobs.messageName[39] = "Message_Clear"; globs::messageGlobs.messageName[40] = "Message_ClearComplete"; globs::messageGlobs.messageName[41] = "Message_GetIn"; globs::messageGlobs.messageName[42] = "Message_ManSelectedAndMonsterClicked"; globs::messageGlobs.messageName[43] = "Message_FollowAttack"; globs::messageGlobs.messageName[44] = "Message_CollectTool"; globs::messageGlobs.messageName[45] = "Message_ReduceSelection"; globs::messageGlobs.messageName[46] = "Message_ClearFallIn"; globs::messageGlobs.messageName[47] = "Message_ClearFallInComplete"; globs::messageGlobs.messageName[48] = "Message_BuildPath"; globs::messageGlobs.messageName[49] = "Message_BuildPathComplete"; globs::messageGlobs.messageName[50] = "Message_Train"; globs::messageGlobs.messageName[51] = "Message_TrainComplete"; globs::messageGlobs.messageName[52] = "Message_GenerateCrystalAndOre"; globs::messageGlobs.messageName[53] = "Message_GenerateCrystalAndOreComplete"; globs::messageGlobs.messageName[54] = "Message_GenerateFromCryOre"; globs::messageGlobs.messageName[55] = "Message_GenerateFromCryOreComplete"; globs::messageGlobs.messageName[56] = "Message_Upgrade"; globs::messageGlobs.messageName[57] = "Message_UpgradeComplete"; globs::messageGlobs.messageName[58] = "Message_ClearBuilding"; globs::messageGlobs.messageName[59] = "Message_ClearBuildingComplete"; globs::messageGlobs.messageName[60] = "Message_ClearInitial"; globs::messageGlobs.messageName[61] = "Message_ClearInitialComplete"; globs::messageGlobs.messageName[62] = "Message_ClearRemovePath"; globs::messageGlobs.messageName[63] = "Message_ClearRemovePathComplete"; globs::messageGlobs.messageName[64] = "Message_Debug_DestroyAll"; return; } void __cdecl lego::game::Message_RemoveEventsWithObject(LegoObject *liveObj) { int iVar1; uint count; uint newCount; uint i; Message_Event *pMVar2; Message_Event *pMVar3; i = 0; count = globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB]; if (count != 0) { do { newCount = count; if (liveObj == globs::messageGlobs.eventLists[globs::messageGlobs.eventAB][i].argumentObj) { newCount = count - 1; pMVar2 = globs::messageGlobs.eventLists[globs::messageGlobs.eventAB + -1] + count + 0x7ff; pMVar3 = globs::messageGlobs.eventLists[globs::messageGlobs.eventAB] + i; for (iVar1 = 5; iVar1 != 0; iVar1 += -1) { pMVar3->type = pMVar2->type; pMVar2 = (Message_Event *)&pMVar2->argumentObj; pMVar3 = (Message_Event *)&pMVar3->argumentObj; } globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB] = newCount; } i += 1; count = newCount; } while (i < newCount); } return; } Message_Type __cdecl lego::game::Message_ParsePTLName(char *ptlName) { Message_Type cmpResult; char **ppcVar1; Message_Type index; index = Message_Null; ppcVar1 = globs::messageGlobs.messageName; do { cmpResult = std::_stricmp(*ppcVar1 + 8,ptlName); if (cmpResult == Message_Null) { return index; } ppcVar1 = ppcVar1 + 1; index += Message_Select; } while (ppcVar1 < &globs::messageGlobs.reserved1); return cmpResult; } void __cdecl lego::game::Message_RegisterHotKeyEvent (Keys8 key,Message_Type messageType,LegoObject *argument1Obj,undefined4 argument2, Point2I *opt_blockPos) { uint index; globs::messageGlobs.hotKeyKeyList[globs::messageGlobs.hotKeyCount] = key; index = globs::messageGlobs.hotKeyCount; globs::messageGlobs.hotKeyEventList[globs::messageGlobs.hotKeyCount].type = messageType; globs::messageGlobs.hotKeyEventList[index].argument2 = argument2; globs::messageGlobs.hotKeyEventList[index].argumentObj = argument1Obj; if (opt_blockPos != NULL) { globs::messageGlobs.hotKeyEventList[index].blockPos.x = opt_blockPos->x; globs::messageGlobs.hotKeyEventList[index].blockPos.y = opt_blockPos->y; } globs::messageGlobs.hotKeyCount += 1; return; } void __cdecl lego::game::Message_PostEvent (Message_Type messageType,LegoObject *argument1Obj,undefined4 argument2, Point2I *opt_blockPos) { BOOL bx2; uint index; Message_Event *message; bx2 = globs::messageGlobs.eventAB; index = globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB]; if (index < 0x800) { globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB] = index + 1; message = globs::messageGlobs.eventLists[bx2] + index; message->type = Message_Null; globs::messageGlobs.eventLists[bx2][index].argumentObj = NULL; globs::messageGlobs.eventLists[bx2][index].argument2 = 0; globs::messageGlobs.eventLists[bx2][index].blockPos.x = 0; globs::messageGlobs.eventLists[bx2][index].blockPos.y = 0; message->type = messageType; globs::messageGlobs.eventLists[bx2][index].argumentObj = argument1Obj; globs::messageGlobs.eventLists[bx2][index].argument2 = argument2; if (opt_blockPos != NULL) { globs::messageGlobs.eventLists[bx2][index].blockPos.x = opt_blockPos->x; globs::messageGlobs.eventLists[bx2][index].blockPos.y = opt_blockPos->y; } } return; } void __cdecl lego::game::Message_Update(void) { BOOL BVar1; undefined4 *puVar2; LegoObject **ppLVar3; uint i; if (((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) == GAME1_NONE) && (i = 0, globs::messageGlobs.hotKeyCount != 0)) { puVar2 = &globs::messageGlobs.hotKeyEventList[0].argument2; do { if (globs::INPUT.Key_Map[globs::messageGlobs.hotKeyKeyList[i]] != false) { Message_PostEvent(puVar2[-2],puVar2[-1],*puVar2,(Point2I *)(puVar2 + 1)); } i += 1; puVar2 = puVar2 + 5; } while (i < globs::messageGlobs.hotKeyCount); } i = 0; if (globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB] != 0) { do { PTL_TranslateEvent(globs::messageGlobs.eventLists[globs::messageGlobs.eventAB] + i); i += 1; } while (i < globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB]); } BVar1 = globs::messageGlobs.eventAB; i = globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB]; globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB] = 0; globs::messageGlobs.eventAB = ZEXT14(globs::messageGlobs.eventAB == 0); globs::messageGlobs.eventCounts[globs::messageGlobs.eventAB] = 0; if (i != 0) { ppLVar3 = (LegoObject **)&globs::messageGlobs.eventLists[BVar1][0].argument2; do { if (true) { switch(ppLVar3[-2]) { case (LegoObject *)0x1: Message_SelectObject(ppLVar3[-1],(BOOL)*ppLVar3); break; case (LegoObject *)0x3: Message_ClearSelectedUnits(); break; case (LegoObject *)0x4: Message_DeselectObject(ppLVar3[-1]); break; case (LegoObject *)0x5: case (LegoObject *)0x6: ai::AITask_Game_PTL_GotoOrRMGoto(ppLVar3[-1],(Point2I *)(ppLVar3 + 1),(AITask *)*ppLVar3); break; case (LegoObject *)0x8: ai::AITask_QueueGotoBlock_Group (globs::messageGlobs.selectedUnitList,globs::messageGlobs.selectedUnitCount, (Point2I *)(ppLVar3 + 1),(BOOL)*ppLVar3); break; case (LegoObject *)0x9: Message_EnterFirstPersonView((uint)*ppLVar3); break; case (LegoObject *)0xa: if (globs::messageGlobs.selectedUnitCount != 0) { lrr::Lego_TrackObjectInRadar(globs::messageGlobs.selectedUnitList[0]); } break; case (LegoObject *)0xb: lrr::Lego_SetViewMode(ViewMode_Top,NULL,0); break; case (LegoObject *)0xc: snd::SFX_Random_PlaySoundNormal((SFX_ID)*ppLVar3,FALSE); break; case (LegoObject *)0x13: Lego_PTL_RockFall((uint)ppLVar3[1],(uint)ppLVar3[2],(uint)*ppLVar3 & 0xffff, (uint)*ppLVar3 >> 0x10); break; case (LegoObject *)0x15: Level_GenerateCrystal((Point2I *)(ppLVar3 + 1),0,NULL,TRUE); break; case (LegoObject *)0x17: ai::AITask_DoCollect(ppLVar3[-1],0.0); break; case (LegoObject *)0x19: ai::AITask_QueueDepositInObject(ppLVar3[-1],*ppLVar3); break; case (LegoObject *)0x1b: Level_GenerateOre((Point2I *)(ppLVar3 + 1),0,NULL,TRUE); break; case (LegoObject *)0x1d: ai::AITask_DoCollect(ppLVar3[-1],0.0); break; case (LegoObject *)0x1f: LegoObject_TryGenerateRMonsterAtRandomBlock(); break; case (LegoObject *)0x21: LegoObject_PTL_GatherRock(ppLVar3[-1]); break; case (LegoObject *)0x23: Message_PickRandomFloorBlock(ppLVar3[-1]); break; case (LegoObject *)0x25: LegoObject_PTL_AttackBuilding(ppLVar3[-1],*ppLVar3); break; case (LegoObject *)0x2b: ai::AITask_Game_PTL_FollowAttack(ppLVar3[-1],*ppLVar3); break; case (LegoObject *)0x2d: Message_ReduceSelectedUnits(); break; case (LegoObject *)0x34: LegoObject_PTL_GenerateCrystalsAndOre((Point2I *)(ppLVar3 + 1),0); break; case (LegoObject *)0x36: LegoObject_PTL_GenerateFromCryOre((Point2I *)(ppLVar3 + 1)); break; case (LegoObject *)0x40: Message_Debug_DestroySelectedUnits(); } } ppLVar3 = ppLVar3 + 5; i -= 1; } while (i != 0); } return; } void __cdecl lego::game::Message_PickRandomFloorBlock(LegoObject *liveObj) { short rng; Map3D *map; BOOL BVar1; uint i; Point2I blockPos; uint height; bool success; uint width; map = lrr::Lego_GetMap(); width = map->blockWidth; map = lrr::Lego_GetMap(); height = map->blockHeight; success = false; i = 0; do { rng = math::Maths_Rand(); blockPos.x = (int)rng % (int)width; rng = math::Maths_Rand(); blockPos.y = (int)rng % (int)height; BVar1 = Level_Block_IsGround(blockPos.x,blockPos.y); if (BVar1 != 0) { success = true; break; } i += 1; } while (i < 1000); if (success) { Message_PostEvent(Message_PickRandomFloorComplete,liveObj,0,&blockPos); } return; } // Remove object from selection. // Cancel first-person view if this is the objectFP. // And clear the camera tracker reference to this object. void __cdecl lego::game::Message_RemoveObjectReference(LegoObject *liveObj) { Message_RemoveEventsWithObject(liveObj); Message_DeselectObject(liveObj); if (globs::legoGlobs.objectFP == liveObj) { lrr::Lego_SetViewMode(ViewMode_Top,NULL,0); globs::legoGlobs.objectFP = NULL; } if ((globs::legoGlobs.cameraTrack)->trackObj == liveObj) { (globs::legoGlobs.cameraTrack)->trackObj = NULL; LegoObject_GetPosition(liveObj,&globs::legoGlobs.radarCenter.x,&globs::legoGlobs.radarCenter.y); // Signal lost flag? globs::legoGlobs.flags1 |= GAME1_RADAR_TRACKOBJECTLOST; } return; } // Allocates and outputs a copied list of all currently selected units. BOOL __cdecl lego::game::Message_CopySelectedUnits(LegoObject ***out_unitsList,uint *out_unitsCount) { LegoObject **ppLVar1; uint uVar2; int iVar3; LegoObject **ppLVar4; if (globs::messageGlobs.selectedUnitCount != 0) { *out_unitsCount = globs::messageGlobs.selectedUnitCount; ppLVar1 = (LegoObject **)io::Mem_Alloc(globs::messageGlobs.selectedUnitCount * 4); *out_unitsList = ppLVar1; ppLVar4 = globs::messageGlobs.selectedUnitList; for (uVar2 = *out_unitsCount & 0x3fffffff; uVar2 != 0; uVar2 -= 1) { *ppLVar1 = *ppLVar4; ppLVar4 = ppLVar4 + 1; ppLVar1 = ppLVar1 + 1; } for (iVar3 = 0; iVar3 != 0; iVar3 += -1) { *(undefined *)ppLVar1 = *(undefined *)ppLVar4; ppLVar4 = (LegoObject **)((int)ppLVar4 + 1); ppLVar1 = (LegoObject **)((int)ppLVar1 + 1); } return TRUE; } return FALSE; } // Returns the table of selected units, and can return the number of units in the table with // out_count LegoObject ** __cdecl lego::game::Message_GetSelectedUnits2(uint *out_count) { if (globs::messageGlobs.selectedUnitCount != 0) { if (out_count != NULL) { *out_count = globs::messageGlobs.selectedUnitCount; } return globs::messageGlobs.selectedUnitList; } if (out_count != NULL) { *out_count = 0; } return NULL; } BOOL __cdecl lego::game::Message_AnyUnitSelected(void) { return (uint)(globs::messageGlobs.selectedUnitCount != 0); } LegoObject * __cdecl lego::game::Message_GetPrimarySelectedUnit(void) { // Return the first-selected Object if count is non-zero (otherwise address is masked // against 0x0) return (LegoObject *) (-(uint)(globs::messageGlobs.selectedUnitCount != 0) & (uint)globs::messageGlobs.selectedUnitList[0]); } LegoObject ** __cdecl lego::game::Message_GetSelectedUnits(void) { return globs::messageGlobs.selectedUnitList; } uint __cdecl lego::game::Message_GetNumSelectedUnits(void) { return globs::messageGlobs.selectedUnitCount; } // Should only be used during Level_Free, because normally extra logic is needed when deselecting an // object (i.e. unsetting flags). void __cdecl lego::game::Message_CleanupSelectedUnitsCount(void) { globs::messageGlobs.selectedUnitCount = 0; return; } BOOL __cdecl lego::game::Message_IsUnitSelected(LegoObject *liveObj,uint *optout_index) { LiveFlags3 LVar1; if (optout_index != NULL) { LVar1 = Message_FindIndexOfObject (globs::messageGlobs.selectedUnitList,globs::messageGlobs.selectedUnitCount, liveObj,optout_index); return LVar1; } return liveObj->flags3 & LIVEOBJ3_SELECTED; } BOOL __cdecl lego::game::Message_FindIndexOfObject (LegoObject **objsTable,uint objsCount,LegoObject *thisObj,uint *optout_index) { uint i; i = 0; if (objsCount == 0) { return FALSE; } do { if (*objsTable == thisObj) { if (optout_index != NULL) { *optout_index = i; } return TRUE; } i += 1; objsTable = objsTable + 1; } while (i < objsCount); return FALSE; } // Used to check for double-selection of unit to enter laser tracker mode. BOOL __cdecl lego::game::Message_IsObjectDoubleSelectable(LegoObject *liveObj) { BOOL BVar1; BVar1 = Message_IsUnitSelected(liveObj,NULL); if ((BVar1 == 0) && ((*(byte *)&liveObj->flags4 & LIVEOBJ4_DOUBLESELECTREADY) == 0)) { return FALSE; } return TRUE; } BOOL __cdecl lego::game::Message_SelectObject(LegoObject *liveObj,BOOL noDoubleSelect) { BOOL BVar1; BVar1 = Message_SelectObject2(liveObj,noDoubleSelect,TRUE); return BVar1; } // When noDoubleSelect is false, it's possible to double-click and enter laser tracker mode. BOOL __cdecl lego::game::Message_SelectObject2(LegoObject *liveObj,BOOL noDoubleSelect,BOOL interrupt) { BOOL BVar1; StatsFlags1 sflags1; Container *cont; Point2F local_14; Vector3F local_c; if (liveObj->carryingThisObject != NULL) { liveObj = liveObj->carryingThisObject; } BVar1 = Message_IsObjectSelectable(liveObj); if (BVar1 != 0) { if (noDoubleSelect == 0) { BVar1 = Message_IsObjectDoubleSelectable(liveObj); if (BVar1 != 0) { LegoObject_TryEnterLaserTrackerMode(liveObj); return FALSE; } } BVar1 = Message_IsUnitSelected(liveObj,NULL); if ((BVar1 == 0) && (globs::messageGlobs.selectedUnitCount < 100)) { LegoObject_RunThroughListsSkipUpgradeParts(LegoObject_Callback_ExitLaserTrackerMode,NULL); globs::messageGlobs.selectedUnitList[globs::messageGlobs.selectedUnitCount] = liveObj; globs::messageGlobs.selectedUnitCount += 1; liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_SELECTED; if ((liveObj->type != LegoObject_Building) && (((liveObj->flags1 & (LIVEOBJ1_STORING|LIVEOBJ1_SLIPPING|LIVEOBJ1_RESTING)) == LIVEOBJ1_NONE && ((liveObj->flags2 & LIVEOBJ2_UNK_100) == LIVEOBJ2_NONE)))) { LegoObject_Route_End(liveObj,FALSE); ai::AITask_VariousGatherTasks_FUN_00403a90(liveObj); if ((liveObj->type == LegoObject_MiniFigure) && (interrupt != 0)) { gfx::Container_GetOrientation((globs::legoGlobs.cameraMain)->cont4,NULL,&local_c,NULL); local_14.x = -local_c.x; local_14.y = -local_c.y; LegoObject_Interrupt(liveObj,FALSE,FALSE); LegoObject_FaceTowardsCamera(liveObj,&local_14); } } if ((*(byte *)&liveObj->flags3 & LIVEOBJ3_CANYESSIR) != 0) { sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if (((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) || (liveObj->driveObject != NULL)) { cont = LegoObject_GetActivityContainer(liveObj); snd::SFX_Random_PlaySound3DOnContainer(cont,SFX_YesSir,FALSE,TRUE,NULL); return TRUE; } } } } return FALSE; } BOOL __cdecl lego::game::Message_IsObjectSelectable(LegoObject *liveObj) { BOOL BVar1; if ((liveObj->flags3 & LIVEOBJ3_CANSELECT) != LIVEOBJ3_NONE) { BVar1 = LegoObject_IsActive(liveObj,TRUE); // not flags (LIVEOBJ2_THROWN|LIVEOBJ2_DRIVING) if ((((BVar1 != 0) && ((*(byte *)&liveObj->flags2 & 10) == 0)) && ((liveObj->flags1 & (LIVEOBJ1_SLIPPING|LIVEOBJ1_RESTING)) == LIVEOBJ1_NONE)) && ((liveObj->type != LegoObject_Vehicle || ((liveObj->flags1 & LIVEOBJ1_CLEARING) == LIVEOBJ1_NONE)))) { return TRUE; } } return FALSE; } void __cdecl lego::game::Message_ReduceSelectedUnits(void) { int iVar1; StatsFlags1 sflags1; LegoObject **pUnits; uint i; Interface_MenuType menuType; BOOL loc_hasElectricFence; BOOL loc_hasBuilding; BOOL loc_hasWaterVehicle; BOOL loc_hasUnmannedVehicle; BOOL loc_hasLandVehicle; BOOL loc_hasMain; LegoObject *driveObj; bool hasBuilding; bool hasElectricFence; bool hasLandVehicle; bool hasMain; bool hasMiniFigure; bool hasUnmannedVehicle; bool hasWaterVehicle; LegoObject_Type objType; bool reduce; LegoObject *unit; i = 0; hasMiniFigure = false; hasLandVehicle = false; hasUnmannedVehicle = false; hasWaterVehicle = false; hasBuilding = false; hasElectricFence = false; hasMain = false; if (globs::messageGlobs.selectedUnitCount != 0) { pUnits = globs::messageGlobs.selectedUnitList; do { unit = *pUnits; if ((unit->type == LegoObject_MiniFigure) && (unit->driveObject == NULL)) { hasMiniFigure = true; break; } sflags1 = stats::StatsObject_GetStatsFlags1(unit); if ((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) { objType = unit->type; if (objType == LegoObject_Vehicle) { sflags1 = stats::StatsObject_GetStatsFlags1(unit); if (((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && ((*(byte *)&unit->flags4 & 0x40) == 0)) { hasWaterVehicle = true; } else { hasLandVehicle = true; } } else { if (objType == LegoObject_Building) { hasBuilding = true; } else { if ((objType == LegoObject_ElectricFence) && ((unit->flags2 & LIVEOBJ2_ACTIVEELECTRICFENCE) != LIVEOBJ2_NONE)) { hasElectricFence = true; } } } } else { if (unit->driveObject == NULL) { hasUnmannedVehicle = true; } else { sflags1 = stats::StatsObject_GetStatsFlags1(unit); if (((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && ((*(byte *)&unit->flags4 & 0x40) == 0)) { hasWaterVehicle = true; } else { hasLandVehicle = true; } } } i += 1; pUnits = pUnits + 1; } while (i < globs::messageGlobs.selectedUnitCount); } i = 0; if (hasMiniFigure) { front::Interface_OpenMenu(Interface_Menu_LegoMan,NULL); hasWaterVehicle = false; hasLandVehicle = false; hasUnmannedVehicle = false; hasBuilding = false; hasElectricFence = false; } else { if (hasLandVehicle) { front::Interface_OpenMenu(Interface_Menu_LandVehicle,NULL); hasWaterVehicle = false; hasUnmannedVehicle = false; hasBuilding = false; hasElectricFence = false; } else { if (hasWaterVehicle) { front::Interface_OpenMenu(Interface_Menu_WaterVehicle,NULL); hasUnmannedVehicle = false; hasBuilding = false; hasElectricFence = false; } else { if (hasUnmannedVehicle) { front::Interface_OpenMenu(Interface_Menu_UnmannedVehicle,NULL); hasBuilding = false; hasElectricFence = false; } else { if (hasBuilding) { front::Interface_OpenMenu(Interface_Menu_Building,NULL); hasElectricFence = false; } else { hasMain = !hasElectricFence; if (hasMain) { menuType = Interface_Menu_Main; } else { menuType = Interface_Menu_ElectricFence; } front::Interface_OpenMenu(menuType,NULL); } } } } } if (globs::messageGlobs.selectedUnitCount != 0) { pUnits = globs::messageGlobs.selectedUnitList; do { unit = *pUnits; reduce = false; if ((hasMiniFigure) && ((unit->type != LegoObject_MiniFigure || (unit->driveObject != NULL)))) goto LAB_00452e44; if (hasLandVehicle) { sflags1 = stats::StatsObject_GetStatsFlags1(unit); if ((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) { LAB_00452df3: if (unit->type != LegoObject_Vehicle) goto LAB_00452e44; } else { sflags1 = stats::StatsObject_GetStatsFlags1(unit); if (((sflags1 & STATS1_CROSSLAND) == STATS1_NONE) && ((*(byte *)&unit->flags4 & 0x40) == 0)) { LAB_00452de2: reduce = true; } LAB_00452de7: driveObj = unit->driveObject; joined_r0x00452e42: if (driveObj == NULL) goto LAB_00452e44; } } else { if (hasWaterVehicle) { sflags1 = stats::StatsObject_GetStatsFlags1(unit); if ((sflags1 & STATS1_CANBEDRIVEN) == STATS1_NONE) goto LAB_00452df3; sflags1 = stats::StatsObject_GetStatsFlags1(unit); if (((sflags1 & STATS1_CROSSLAND) != STATS1_NONE) || ((*(byte *)&unit->flags4 & 0x40) != 0)) goto LAB_00452de2; goto LAB_00452de7; } if (hasUnmannedVehicle) { sflags1 = stats::StatsObject_GetStatsFlags1(unit); if ((sflags1 & STATS1_CANBEDRIVEN) != STATS1_NONE) { // THE DECOMPILER LOGIC HERE IS WRONG!!! // Rather, only if driveObj is NON-ZERO is reduce set to true. driveObj = unit->driveObject; goto joined_r0x00452e42; } } else { if ((!hasBuilding) || (unit->type == LegoObject_Building)) { if (!hasElectricFence) goto LAB_00452e49; if (unit->type == LegoObject_ElectricFence) { driveObj = (LegoObject *)(unit->flags2 & LIVEOBJ2_ACTIVEELECTRICFENCE); goto joined_r0x00452e42; } } } LAB_00452e44: reduce = true; } LAB_00452e49: if ((reduce) || (hasMain)) { // Replace this reduced object with the object at the end of the list. iVar1 = globs::messageGlobs.selectedUnitCount - 1; globs::messageGlobs.selectedUnitCount = globs::messageGlobs.selectedUnitCount - 1; *pUnits = globs::messageGlobs.selectedUnitList[iVar1]; i -= 1; unit->flags3 = unit->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP| LIVEOBJ3_CANYESSIR|LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400| LIVEOBJ3_UNUSED_800|LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000| LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE|LIVEOBJ3_UNK_10000| LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING| LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); pUnits = pUnits + -1; } i += 1; pUnits = pUnits + 1; } while (i < globs::messageGlobs.selectedUnitCount); } return; } void __cdecl lego::game::Message_ClearSelectedUnits(void) { LegoObject **pUnit; uint i; LiveFlags4 *pFlags4; i = 0; if (globs::messageGlobs.selectedUnitCount != 0) { pUnit = globs::messageGlobs.selectedUnitList; do { if (((*pUnit)->flags3 & LIVEOBJ3_SELECTED) != LIVEOBJ3_NONE) { pFlags4 = &(*pUnit)->flags4; *pFlags4 = *pFlags4 | LIVEOBJ4_DOUBLESELECTREADY; } (*pUnit)->flags3 = (*pUnit)->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING| LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); (*pUnit)->flags4 = (*pUnit)->flags4 & ~LIVEOBJ4_LASERTRACKERMODE; i += 1; pUnit = pUnit + 1; } while (i < globs::messageGlobs.selectedUnitCount); } globs::messageGlobs.selectedUnitCount = 0; return; } BOOL __cdecl lego::game::Message_DeselectObject(LegoObject *liveObj) { int iVar1; BOOL isSelected; LegoObject *liveObj_; liveObj_ = liveObj; if (globs::messageGlobs.selectedUnitCount != 0) { isSelected = Message_IsUnitSelected(liveObj,(uint *)&liveObj); if (isSelected != 0) { if (liveObj == NULL) { front::Interface_OpenMenu(Interface_Menu_Main,NULL); } // param_1 is no longer liveObject, transformed by first function call of this function iVar1 = globs::messageGlobs.selectedUnitCount - 1; globs::messageGlobs.selectedUnitCount = globs::messageGlobs.selectedUnitCount - 1; globs::messageGlobs.selectedUnitList[(int)liveObj] = globs::messageGlobs.selectedUnitList[iVar1]; liveObj_->flags3 = liveObj_->flags3 & (LIVEOBJ3_UNK_1|LIVEOBJ3_CANDIG|LIVEOBJ3_CANREINFORCE|LIVEOBJ3_CANTURN| LIVEOBJ3_CANFIRSTPERSON|LIVEOBJ3_CANCARRY|LIVEOBJ3_CANPICKUP|LIVEOBJ3_CANYESSIR| LIVEOBJ3_CANSELECT|LIVEOBJ3_UNK_200|LIVEOBJ3_UNK_400|LIVEOBJ3_UNUSED_800| LIVEOBJ3_CENTERBLOCKIDLE|LIVEOBJ3_UNK_2000|LIVEOBJ3_UNK_4000|LIVEOBJ3_CANDYNAMITE| LIVEOBJ3_UNK_10000|LIVEOBJ3_SIMPLEOBJECT|LIVEOBJ3_CANDAMAGE|LIVEOBJ3_UPGRADEPART| LIVEOBJ3_ALLOWCULLING_UNK|LIVEOBJ3_AITASK_UNK_400000|LIVEOBJ3_REMOVING| LIVEOBJ3_UNK_1000000|LIVEOBJ3_UNK_2000000|LIVEOBJ3_CANGATHER| LIVEOBJ3_MONSTER_UNK_8000000|LIVEOBJ3_CANROUTERUBBLE|LIVEOBJ3_HASPOWER| LIVEOBJ3_UNK_40000000|LIVEOBJ3_POWEROFF); return TRUE; } } return 0; } uint __cdecl lego::game::Message_Debug_DestroySelectedUnits(void) { StatsFlags1 sflags1; uint index; LegoObject *driveObj; index = globs::messageGlobs.selectedUnitCount; if (globs::messageGlobs.selectedUnitCount != 0) { do { sflags1 = stats::StatsObject_GetStatsFlags1(globs::messageGlobs.selectedUnitList[0]); if (((sflags1 & STATS1_CANBEDRIVEN) != STATS1_NONE) && (driveObj = globs::messageGlobs.selectedUnitList[0]->driveObject, driveObj != NULL)) { // unit->driveObject->flags2 &= LIVEOBJ2_DRIVING; // Why can't you just be normal?? driveObj->flags2 = driveObj->flags2 & (LIVEOBJ2_THROWING|LIVEOBJ2_THROWN|LIVEOBJ2_UNK_4|LIVEOBJ2_UNK_10|LIVEOBJ2_UNK_20| LIVEOBJ2_UNK_40|LIVEOBJ2_UNK_80|LIVEOBJ2_UNK_100|LIVEOBJ2_BUILDPATH|LIVEOBJ2_TRAINING| LIVEOBJ2_UNK_800|LIVEOBJ2_DAMAGE_UNK_1000|LIVEOBJ2_SHOWDAMAGENUMBERS|LIVEOBJ2_PUSHED| LIVEOBJ2_UPGRADING|LIVEOBJ2_TRIGGERFRAMECALLBACK|LIVEOBJ2_UNK_20000|LIVEOBJ2_UNK_40000 |LIVEOBJ2_UNK_80000|LIVEOBJ2_UNK_100000|LIVEOBJ2_UNK_200000|LIVEOBJ2_FIRINGLASER| LIVEOBJ2_FIRINGPUSHER|LIVEOBJ2_FIRINGFREEZER|LIVEOBJ2_ACTIVEELECTRICFENCE| LIVEOBJ2_UNK_4000000|LIVEOBJ2_FROZEN|LIVEOBJ2_RECHARGING|LIVEOBJ2_UNK_20000000| LIVEOBJ2_DAMAGESHAKING|LIVEOBJ2_UNK_80000000); globs::messageGlobs.selectedUnitList[0]->driveObject->driveObject = NULL; } if (globs::messageGlobs.selectedUnitList[0]->type == LegoObject_Building) { Construction_RemoveBuildingObject(globs::messageGlobs.selectedUnitList[0]); } else { if (globs::messageGlobs.selectedUnitList[0]->type == LegoObject_ElectricFence) { ElectricFence_RemoveFence(globs::messageGlobs.selectedUnitList[0]); } LegoObject_Remove(globs::messageGlobs.selectedUnitList[0]); } index -= 1; } while (index != 0); } return globs::messageGlobs.selectedUnitCount; } BOOL __cdecl lego::game::Message_EnterFirstPersonView(uint cameraFrame) { LegoObject *unit; LegoObject **pUnit; uint i; if (((globs::legoGlobs.objectFP != NULL) && ((*(byte *)&(globs::legoGlobs.objectFP)->flags3 & LIVEOBJ3_CANFIRSTPERSON) != 0)) && ((unit = globs::legoGlobs.objectFP, (globs::legoGlobs.objectFP)->type == LegoObject_MiniFigure || ((globs::legoGlobs.objectFP)->driveObject != NULL)))) { LAB_00453096: lrr::Lego_SetViewMode(ViewMode_FP,unit,cameraFrame); return TRUE; } i = 0; if (globs::messageGlobs.selectedUnitCount != 0) { pUnit = globs::messageGlobs.selectedUnitList; do { unit = *pUnit; if ((unit->type == LegoObject_MiniFigure) && (unit->driveObject != NULL)) { unit = unit->driveObject; } if (((*(byte *)&unit->flags3 & LIVEOBJ3_CANFIRSTPERSON) != 0) && ((unit->type == LegoObject_MiniFigure || (unit->driveObject != NULL)))) goto LAB_00453096; i += 1; pUnit = pUnit + 1; } while (i < globs::messageGlobs.selectedUnitCount); } return 0; } BOOL __cdecl lego::nerps::NERPsFile_LoadScriptFile(char *filename) { int iVar1; NERPsFile_Globs *pNVar2; NERPsRuntime_Globs *pNVar3; int local_4; pNVar2 = &globs::nerpsfileGlobs; for (iVar1 = 0x2d; iVar1 != 0; iVar1 += -1) { pNVar2->camIsLockedOn = 0; pNVar2 = (NERPsFile_Globs *)&pNVar2->camLockOnRecord; } local_4 = TRUE; front::Text_Clear(); globs::nerpsfileGlobs.scriptSize = 0; pNVar3 = &globs::nerpsruntimeGlobs; for (iVar1 = 0xb; iVar1 != 0; iVar1 += -1) { pNVar3->registers[0] = 0; pNVar3 = (NERPsRuntime_Globs *)(pNVar3->registers + 1); } globs::nerpsfileGlobs.instructions = NULL; globs::nerpsruntimeGlobs.messagePermit = TRUE; funcs::NERPFunc__SetMessagePermit(&local_4); globs::nerpsfileGlobs.instructions = (NERPsInstruction *)io::File_LoadBinary(filename,&globs::nerpsfileGlobs.scriptSize); return (uint)(globs::nerpsfileGlobs.instructions != NULL); } // WARNING: Function: _alloca4k replaced with injection: alloca_probe BOOL __cdecl lego::nerps::NERPsFile_LoadMessageFile(char *filename) { NERPMessageImage *pNVar1; NERPMessageSound *pNVar2; char cVar3; byte bVar4; char *s; int iVar5; Image *image; NERPMessageImage *newImageList; uint uVar6; int sound3DHandle; NERPMessageSound *newSoundList; char **newLineList; char **ppcVar7; uint uVar8; byte *imageKey; byte *soundKey; char *pcVar9; uint lineCount; uint fileSize; char **lineList; int lineListOffset; char acStack8448 [128]; char acStack8320 [128]; char acStack8192 [4096]; char local_1000 [4092]; undefined4 uStack4; bool newLine; uStack4 = 0x45313a; newLine = true; lineCount = 0; s = (char *)io::File_LoadBinary(filename,&fileSize); if (s == NULL) { globs::nerpsfileGlobs.messageBuffer = s; globs::nerpsfileGlobs.lineIndexArray_7c[0] = globs::nerpsfileGlobs.soundCount; return FALSE; } globs::nerpsfileGlobs.messageBuffer = s; if (fileSize != 0) { lineListOffset = 0; do { if (*s == '_') { *s = ' '; } if ((byte)*s < 0x20) { *s = 0; newLine = true; } else { if (newLine) { if (*s == ':') { imageKey = (byte *)s + 1; iVar5 = std::sscanf((char *)imageKey,"%s",acStack8320); s = (char *)imageKey; if (iVar5 != 0) { uVar8 = 0xffffffff; pcVar9 = acStack8320; do { if (uVar8 == 0) break; uVar8 -= 1; cVar3 = *pcVar9; pcVar9 = pcVar9 + 1; } while (cVar3 != '\0'); newLine = false; s = (char *)(imageKey + (~uVar8 - 1)); bVar4 = *s; for (; (bVar4 < 0x21 && ((uint)((int)s - (int)globs::nerpsfileGlobs.messageBuffer) < fileSize)); s = (char *)((byte *)s + 1)) { if (bVar4 == '\r') { newLine = true; } *s = 0; bVar4 = ((byte *)s)[1]; } iVar5 = std::sscanf(s,"%s",acStack8448); if ((iVar5 != 0) && (!newLine)) { uVar8 = 0xffffffff; pcVar9 = acStack8448; do { if (uVar8 == 0) break; uVar8 -= 1; cVar3 = *pcVar9; pcVar9 = pcVar9 + 1; } while (cVar3 != '\0'); s = (char *)((byte *)s + (~uVar8 - 1)); image = lego::image::Image_LoadBMPScaled(acStack8448,0,0); if (image != NULL) { newImageList = (NERPMessageImage *) io::Mem_Alloc(globs::nerpsfileGlobs.imageCount * 8 + 8); newLine = globs::nerpsfileGlobs.imageCount == 0; uVar8 = 0; if (!newLine) { do { pNVar1 = globs::nerpsfileGlobs.imageList + uVar8; uVar6 = uVar8 + 1; newImageList[uVar8].key = pNVar1->key; newImageList[uVar8].image = pNVar1->image; uVar8 = uVar6; } while (uVar6 < globs::nerpsfileGlobs.imageCount); newLine = globs::nerpsfileGlobs.imageCount == 0; } if (!newLine) { io::Mem_Free(globs::nerpsfileGlobs.imageList); } newImageList[globs::nerpsfileGlobs.imageCount].key = (char *)imageKey; newImageList[globs::nerpsfileGlobs.imageCount].image = image; globs::nerpsfileGlobs.imageCount += 1; globs::nerpsfileGlobs.imageList = newImageList; } } } } iVar5 = lineListOffset; if (*s == '$') { soundKey = (byte *)s + 1; iVar5 = std::sscanf((char *)soundKey,"%s",local_1000); s = (char *)soundKey; if (iVar5 != 0) { uVar8 = 0xffffffff; pcVar9 = local_1000; do { if (uVar8 == 0) break; uVar8 -= 1; cVar3 = *pcVar9; pcVar9 = pcVar9 + 1; } while (cVar3 != '\0'); newLine = false; // buffer = (char*)pbVar15 + std::strlen(local_1000); s = (char *)(soundKey + (~uVar8 - 1)); bVar4 = *s; for (; (bVar4 < 0x21 && ((uint)((int)s - (int)globs::nerpsfileGlobs.messageBuffer) < fileSize)); s = (char *)((byte *)s + 1)) { if (bVar4 == '\r') { newLine = true; } *s = 0; bVar4 = ((byte *)s)[1]; } iVar5 = std::sscanf(s,"%s",acStack8192); if ((iVar5 != 0) && (!newLine)) { uVar8 = 0xffffffff; pcVar9 = acStack8192; do { if (uVar8 == 0) break; uVar8 -= 1; cVar3 = *pcVar9; pcVar9 = pcVar9 + 1; } while (cVar3 != '\0'); s = (char *)((byte *)s + (~uVar8 - 1)); sound3DHandle = snd::Sound3D_Load(acStack8192,TRUE,0,0); if (sound3DHandle != 0) { newSoundList = (NERPMessageSound *) io::Mem_Alloc(globs::nerpsfileGlobs.soundCount * 8 + 8); newLine = globs::nerpsfileGlobs.soundCount == 0; uVar8 = 0; if (!newLine) { do { pNVar2 = globs::nerpsfileGlobs.soundList + uVar8; uVar6 = uVar8 + 1; newSoundList[uVar8].key = pNVar2->key; newSoundList[uVar8].sound3DHandle = pNVar2->sound3DHandle; uVar8 = uVar6; } while (uVar6 < globs::nerpsfileGlobs.soundCount); newLine = globs::nerpsfileGlobs.soundCount == 0; } if (!newLine) { io::Mem_Free(globs::nerpsfileGlobs.soundList); } newSoundList[globs::nerpsfileGlobs.soundCount].key = (char *)soundKey; newSoundList[globs::nerpsfileGlobs.soundCount].sound3DHandle = sound3DHandle; globs::nerpsfileGlobs.soundCount += 1; globs::nerpsfileGlobs.soundList = newSoundList; globs::nerpsfileGlobs.lineIndexArray_7c[0] = globs::nerpsfileGlobs.soundCount; } } } } else { // This block may look like its riddled with holes, but its actually sane, // because iVar5 (iStack8452) is always 0 the first time this block is reached, // after first reaching the block, ppcStack8456 has actually been assigned once, // and is safe to read. newLineList = (char **)io::Mem_Alloc(lineListOffset + 4); if (iVar5 != 0) { ppcVar7 = newLineList; uVar8 = lineCount; do { *ppcVar7 = *(char **)(((int)lineList - (int)newLineList) + (int)ppcVar7); ppcVar7 = ppcVar7 + 1; uVar8 -= 1; } while (uVar8 != 0); } if (iVar5 != 0) { io::Mem_Free(lineList); } *(char **)((int)newLineList + iVar5) = s; lineCount += 1; lineListOffset = iVar5 + 4; lineList = newLineList; } } newLine = false; } s = (char *)((byte *)s + 1); } while ((uint)((int)s - (int)globs::nerpsfileGlobs.messageBuffer) < fileSize); } globs::nerpsfileGlobs.lineCount = lineCount; globs::nerpsfileGlobs.lineList = lineList; return TRUE; } char * __cdecl lego::nerps::NERPsFile_GetMessageLine(uint lineIndex) { if (lineIndex < globs::nerpsfileGlobs.lineCount) { return globs::nerpsfileGlobs.lineList[lineIndex]; } return NULL; } BOOL __cdecl lego::nerps::NERPsFile_Free(void) { int iVar1; uint uVar2; NERPsFile_Globs *pNVar3; if (globs::nerpsfileGlobs.scriptSize != 0) { io::Mem_Free(globs::nerpsfileGlobs.instructions); } if (globs::nerpsfileGlobs.messageBuffer != NULL) { io::Mem_Free(globs::nerpsfileGlobs.messageBuffer); if (globs::nerpsfileGlobs.lineList != NULL) { io::Mem_Free(globs::nerpsfileGlobs.lineList); } } uVar2 = 0; globs::nerpsfileGlobs.messageBuffer = NULL; globs::nerpsfileGlobs.lineList = NULL; globs::nerpsfileGlobs.lineCount = 0; globs::nerpsfileGlobs.scriptSize = 0; if (globs::nerpsfileGlobs.soundCount != 0) { do { snd::Sound3D_Remove(globs::nerpsfileGlobs.soundList[uVar2].sound3DHandle); uVar2 += 1; } while (uVar2 < globs::nerpsfileGlobs.soundCount); if (globs::nerpsfileGlobs.soundCount != 0) { if (globs::nerpsfileGlobs.soundList != NULL) { io::Mem_Free(globs::nerpsfileGlobs.soundList); globs::nerpsfileGlobs.soundList = NULL; } globs::nerpsfileGlobs.soundCount = 0; } } pNVar3 = &globs::nerpsfileGlobs; for (iVar1 = 0x2d; iVar1 != 0; iVar1 += -1) { pNVar3->camIsLockedOn = 0; pNVar3 = (NERPsFile_Globs *)&pNVar3->camLockOnRecord; } front::Text_Clear(); return TRUE; } // Helper function that converts an instruction for a call with zero arguments into its literal // return value. void __cdecl lego::nerps::NERPsRuntime_LoadLiteral(NERPsInstruction *ref_instruction) { NERPsInstruction NVar1; NVar1 = *ref_instruction; // if (ref_instruction->opcode == OP_CALL && // c_nerpsFunctions[ref_instruction->value].arguments == NERPS_ARGS_0) if ((((uint)NVar1 & 0xffff0000) == 0x20000) && (globs::constant::c_nerpsFunctions[(uint)NVar1 & 0xffff].arguments == NERPS_ARGS_0)) { // *(uint32*)ref_instruction = // c_nerpsFunctions[ref_instruction->value].function(nullptr); NVar1 = (NERPsInstruction) (*globs::constant::c_nerpsFunctions[(uint)NVar1 & 0xffff].function)(NULL); } *ref_instruction = NVar1; return; } void __cdecl lego::nerps::NERPsRuntime_Execute(float elapsedAbs) { uint uVar1; uint funcId; uint regB; uint opId; uint uVar2; int numInstrArgs; uint currCmp; uint nextCmp; uint regA; uint instrIdx; uint lastRegB; NERPsInstruction argsStack [3]; char logBuff [512]; NERPsInstruction instr; NERPsInstruction *instructions; NERPsFunctionArgs nargs; uint ret; instructions = globs::nerpsfileGlobs.instructions; ret = 0; if (globs::nerpsfileGlobs.instructions != NULL) { uVar1 = globs::nerpsfileGlobs.scriptSize >> 2; instrIdx = 0; regA = 0; currCmp = 0; regB = lastRegB; if (uVar1 != 0) { do { numInstrArgs = 0; instr = instructions[instrIdx]; if (((uint)instr & 0x20000) == 0) { if (((uint)instr & 0x10000) == 0) { if (((uint)instr & 0x40000) == 0) { if (((uint)instr & 0x80000) == 0) { regB = SEXT24(instructions[instrIdx].value); if (ret != 0) { regB = (uint)(regB == 0); } ret = regB; lastRegB = regB; if (currCmp != 0) { if (currCmp == 1) { if ((regA == 0) || (ret = currCmp, regB == 0)) { LAB_00453acb: ret = 0; } } else { if (currCmp == 2) { if ((regA == 0) && (regB == 0)) goto LAB_00453acb; ret = 1; } else { if (currCmp == 3) { ret = (uint)(regB < regA); } else { if (currCmp == 4) { ret = (uint)(regA < regB); } else { if (currCmp == 5) { ret = (uint)(regA == regB); } else { if (currCmp == 6) { ret = (uint)(regB <= regA); } else { if (currCmp != 7) goto joined_r0x00453b1b; ret = (uint)(regA <= regB); } } } } } } } goto LAB_00453b28; } if (regA != 0) { instrIdx = (uint)instr & 0xffff; } LAB_00453a74: regA = 0; ret = 0; nextCmp = 0; } else { regA = 0; ret = 0; nextCmp = 0; } } else { uVar2 = 0; opId = (uint)instr & 0xffff; ret = regA; if (opId == 0) goto LAB_00453b28; ret = uVar2; nextCmp = opId; if ((opId != 2) && (ret = opId, nextCmp = currCmp, opId != 1)) { if (opId == 5) { ret = uVar2; nextCmp = 3; } else { if (opId == 6) { ret = uVar2; nextCmp = 4; } else { if (opId == 7) { ret = uVar2; nextCmp = 5; } else { if (opId == 8) { ret = uVar2; nextCmp = 6; } else { if (opId == 9) { ret = uVar2; nextCmp = 7; } else { ret = uVar2; if (opId == 10) { nextCmp = 8; } } } } } } } } } else { funcId = (uint)instr & 0xffff; if ((funcId == 0) && ((regA != 0 || (currCmp == 0)))) break; nargs = globs::constant::c_nerpsFunctions[funcId].arguments; if (nargs == NERPS_ARGS_0) { LAB_0045383f: regB = (*globs::constant::c_nerpsFunctions[funcId].function)(NULL); lastRegB = regB; } else { if ((nargs != NERPS_ARGS_1) && (nargs != NERPS_ARGS_2)) { if (nargs == NERPS_ARGS_0_NORETURN) { if (regA == 0) goto LAB_00453a74; if (globs::nerpsruntimeGlobs.logFuncCalls != 0) { std::sprintf(logBuff,"Func Call %s",globs::constant::c_nerpsFunctions[funcId].name ); } (*globs::constant::c_nerpsFunctions[(uint)instructions[instrIdx] & 0xffff].function) (NULL); regA = 0; regB = lastRegB; ret = 0; nextCmp = 0; } else { if (nargs == NERPS_ARGS_1_NORETURN) { if (regA != 0) { if (globs::nerpsruntimeGlobs.logFuncCalls != 0) { std::sprintf(logBuff,"Func Call %s", globs::constant::c_nerpsFunctions[funcId].name); } argsStack[0] = instructions[instrIdx + 1]; NERPsRuntime_LoadLiteral(argsStack); (*globs::constant::c_nerpsFunctions[(uint)instructions[instrIdx] & 0xffff]. function)((int *)argsStack); regB = lastRegB; } instrIdx += 1; } else { if (nargs == NERPS_ARGS_2_NORETURN) { if (regA != 0) { argsStack[0] = instructions[instrIdx + 1]; argsStack[1] = instructions[instrIdx + 2]; NERPsRuntime_LoadLiteral(argsStack); NERPsRuntime_LoadLiteral(argsStack + 1); (*globs::constant::c_nerpsFunctions[(uint)instructions[instrIdx] & 0xffff]. function)((int *)argsStack); regB = lastRegB; } instrIdx += 2; } else { nextCmp = currCmp; if (nargs != NERPS_ARGS_3_NORETURN) goto LAB_00453b2d; if (regA != 0) { argsStack[0] = instructions[instrIdx + 1]; argsStack[1] = instructions[instrIdx + 2]; argsStack[2] = instructions[instrIdx + 3]; NERPsRuntime_LoadLiteral(argsStack); NERPsRuntime_LoadLiteral(argsStack + 1); NERPsRuntime_LoadLiteral(argsStack + 2); (*globs::constant::c_nerpsFunctions[(uint)instructions[instrIdx] & 0xffff]. function)((int *)argsStack); regB = lastRegB; } instrIdx += 3; } } regA = 0; ret = 0; nextCmp = 0; } goto LAB_00453b2d; } if (nargs == NERPS_ARGS_0) goto LAB_0045383f; if (nargs == NERPS_ARGS_1) { argsStack[0] = instructions[instrIdx + 1]; NERPsRuntime_LoadLiteral(argsStack); regB = (*globs::constant::c_nerpsFunctions[(uint)instructions[instrIdx] & 0xffff]. function)((int *)argsStack); numInstrArgs = 1; lastRegB = regB; } else { if (nargs == NERPS_ARGS_2) { argsStack[0] = instructions[instrIdx + 1]; argsStack[1] = instructions[instrIdx + 2]; NERPsRuntime_LoadLiteral(argsStack); NERPsRuntime_LoadLiteral(argsStack + 1); regB = (*globs::constant::c_nerpsFunctions[(uint)instructions[instrIdx] & 0xffff]. function)((int *)argsStack); numInstrArgs = 2; lastRegB = regB; } } } instrIdx += numInstrArgs; if (ret != 0) { regB = (uint)(regB == 0); lastRegB = regB; } ret = regB; if (currCmp != 0) { if (currCmp == 1) { if ((regA == 0) || (ret = currCmp, regB == 0)) { LAB_00453947: ret = 0; } } else { if (currCmp == 2) { if ((regA == 0) && (regB == 0)) goto LAB_00453947; ret = 1; } else { if (currCmp == 3) { ret = (uint)(regB < regA); } else { if (currCmp == 4) { ret = (uint)(regA < regB); } else { if (currCmp == 5) { ret = (uint)(regA == regB); } else { if (currCmp == 6) { ret = (uint)(regB <= regA); } else { if (currCmp == 7) { ret = (uint)(regA <= regB); } else { joined_r0x00453b1b: ret = regA; if (currCmp == 8) { ret = (uint)(regA != regB); } } } } } } } } } LAB_00453b28: regA = ret; ret = 0; nextCmp = 1; } LAB_00453b2d: instrIdx += 1; currCmp = nextCmp; } while (instrIdx < uVar1); } NERPsRuntime_EndExecute(elapsedAbs); } return; } int __cdecl lego::nerps::funcs::NERPFunc__SetGameSpeed(int *stack) { Lego_Level *level; if ((*stack == 0) && (level = lrr::Lego_GetLevel(), level->status != LEVELSTATUS_INCOMPLETE)) { return 0; } lrr::Lego_LockGameSpeed(stack[1]); lrr::Lego_SetGameSpeed((float)(ulonglong)(uint)*stack * 0.01); lrr::Lego_LockGameSpeed(stack[1]); return 0; } void __cdecl lego::nerps::NERPs_SetHasNextButton(BOOL hasNextButton) { globs::nerps::nerpsHasNextButton = hasNextButton; return; } void __cdecl lego::nerps::NERPsRuntime_RepeatMessage(void) { if (globs::nerps::nerpsHasNextButton != 0) { NERPs_RestartMessageSample(); return; } return; } void __cdecl lego::nerps::NERPsRuntime_AdvanceMessage(void) { char *text; TutorialFlags TVar1; int gameSpeedStack [2]; // gameSpeedStack[0] = 100; // game speed at 100% // gameSpeedStack[1] = FALSE; // don't lock game speed gameSpeedStack[0] = 100; gameSpeedStack[1] = FALSE; lrr::Lego_SetPointerSFX(PointerSFX_Okay); if (globs::nerpsfileGlobs.int_a4 != 0) { globs::nerpsfileGlobs.int_a4 += -1; if (3 < globs::nerpsfileGlobs.int_a4) { globs::nerpsfileGlobs.int_a4 = 3; } if ((int)globs::nerpsfileGlobs.uint_a0 < globs::nerpsfileGlobs.int_a4) { globs::nerpsfileGlobs.int_a4 = globs::nerpsfileGlobs.uint_a0; } text = NERPsFile_GetMessageLine (*(uint *)((int)&globs::nerpsfileGlobs + (globs::nerpsfileGlobs.uint_a0 - globs::nerpsfileGlobs.int_a4) * 4 + 0x7c)); front::Text_SetNERPsMessage(text,FALSE); if (globs::nerpsfileGlobs.int_a4 == 0) { lrr::Lego_SetFlags2_40_And_2_unkCamera(FALSE,TRUE); TVar1 = funcs::NERPFunc__GetTutorialFlags(NULL); if (TVar1 != TUTORIAL_NONE) { funcs::NERPFunc__SetGameSpeed(gameSpeedStack); } } lrr::Lego_SetFlags2_80(TRUE); return; } if (globs::nerps::nerpsBOOL_004a7740 != 0) { globs::nerpsfileGlobs.uint_a8 += 1; } globs::nerps::nerpsBOOL_004a7740 = FALSE; return; } int __cdecl lego::nerps::funcs::NERPFunc__GetMessagesAreUpToDate(int *stack) { return (uint)(globs::nerpsfileGlobs.lineCount <= globs::nerpsfileGlobs.uint_a8); } int __cdecl lego::nerps::funcs::NERPFunc__SupressArrow(int *stack) { globs::nerpsruntimeGlobs.supressArrow = *stack; if (globs::nerpsfileGlobs.int_a4 == 0) { lrr::Lego_SetFlags2_40_And_2_unkCamera((uint)(globs::nerpsruntimeGlobs.supressArrow == 0),TRUE); return 0; } lrr::Lego_SetFlags2_40_And_2_unkCamera(TRUE,TRUE); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__AdvanceMessage(int *stack) { if (1 < globs::nerpsfileGlobs.int_a4) { globs::nerpsfileGlobs.int_a4 = 1; } NERPsRuntime_AdvanceMessage(); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__AllowCameraMovement(int *stack) { globs::nerpsruntimeGlobs.allowCameraMovement = *stack << 0xc; return 0; } int __cdecl lego::nerps::funcs::NERPFunc__ClickOnlyObjects(int *stack) { int local_4; local_4 = 0x1ff3 - globs::nerpsruntimeGlobs.allowCameraMovement; NERPFunc__SetTutorialFlags(&local_4); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__ClickOnlyMap(int *stack) { int local_4; local_4 = 0x1ffb - globs::nerpsruntimeGlobs.allowCameraMovement; NERPFunc__SetTutorialFlags(&local_4); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__ClickOnlyIcon(int *stack) { int local_4; local_4 = 0x1ffe - globs::nerpsruntimeGlobs.allowCameraMovement; NERPFunc__SetTutorialFlags(&local_4); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__ClickOnlyCalltoarms(int *stack) { int local_4; local_4 = 0x1f7f - globs::nerpsruntimeGlobs.allowCameraMovement; NERPFunc__SetTutorialFlags(&local_4); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__DisallowAll(int *stack) { int local_4; local_4 = 0x1fff - globs::nerpsruntimeGlobs.allowCameraMovement; NERPFunc__SetTutorialFlags(&local_4); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__FlashCallToArmsIcon(int *stack) { if (*stack != 0) { front::Panel_SetCurrentAdvisorFromButton(Panel_TopPanel,2,TRUE); return 0; } front::Advisor_End(); return 0; } void __cdecl lego::nerps::NERPsRuntime_UpdateTimers(float elapsed) { float fVar1; float *pfVar2; float *pfVar3; // Standard units to milliseconds. fVar1 = elapsed * 1000.0 * 0.04; pfVar2 = globs::nerpsruntimeGlobs.timers; do { pfVar3 = pfVar2 + 1; *pfVar2 = *pfVar2 + fVar1; pfVar2 = pfVar3; } while (pfVar3 < &globs::nerpsruntimeGlobs.supressArrow); if (globs::nerpsruntimeGlobs.messageTimer == 0.0) { return; } if (0.0 <= globs::nerpsruntimeGlobs.messageTimer) { if ((globs::nerps::nerpsHasNextButton == 0) || (globs::nerpsruntimeGlobs.nextArrowDisabled != 0) ) { globs::nerpsruntimeGlobs.messageTimer = globs::nerpsruntimeGlobs.messageTimer - fVar1; if ((ushort)((ushort)(globs::nerpsruntimeGlobs.messageTimer < 0.0) << 8 | (ushort)(globs::nerpsruntimeGlobs.messageTimer == 0.0) << 0xe) == 0) goto LAB_00453f3e; } else { if ((globs::nerpsruntimeGlobs.timerbool_2c != 0) && (((0 < globs::nerpsfileGlobs.int_a4 && (globs::nerpsruntimeGlobs.supressArrow != 0)) || (globs::nerpsruntimeGlobs.supressArrow == 0)))) { lrr::Lego_SetFlags2_40_And_2_unkCamera(globs::nerps::nerpsBOOL_004a7740,TRUE); } globs::nerpsruntimeGlobs.timerbool_2c = globs::nerps::nerpsBOOL_004a7740; if (globs::nerps::nerpsBOOL_004a7740 != 0) goto LAB_00453f3e; } } globs::nerpsruntimeGlobs.messageTimer = 0.0; LAB_00453f3e: if ((globs::nerpsfileGlobs.AdvisorTalkingMode != 0) && (globs::nerpsruntimeGlobs.messageTimer < 1000.0)) { front::Advisor_End(); return; } return; } int __cdecl lego::nerps::funcs::NERPFunc__GetTimer0(int *stack) { longlong lVar1; lVar1 = __ftol((float10)globs::nerpsruntimeGlobs.timers[0]); return (int)lVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTimer1(int *stack) { longlong lVar1; lVar1 = __ftol((float10)globs::nerpsruntimeGlobs.timers[1]); return (int)lVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTimer2(int *stack) { longlong lVar1; lVar1 = __ftol((float10)globs::nerpsruntimeGlobs.timers[2]); return (int)lVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTimer3(int *stack) { longlong lVar1; lVar1 = __ftol((float10)globs::nerpsruntimeGlobs.timers[3]); return (int)lVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTimer0(int *stack) { globs::nerpsruntimeGlobs.timers[0] = (float)(ulonglong)(uint)*stack; return 1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTimer1(int *stack) { globs::nerpsruntimeGlobs.timers[1] = (float)(ulonglong)(uint)*stack; return 1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTimer2(int *stack) { globs::nerpsruntimeGlobs.timers[2] = (float)(ulonglong)(uint)*stack; return 1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTimer3(int *stack) { globs::nerpsruntimeGlobs.timers[3] = (float)(ulonglong)(uint)*stack; return 1; } void __cdecl lego::nerps::NERPsRuntime_EndExecute(float elapsedAbs) { float fVar1; BOOL BVar2; Lego_Level *pLVar3; float10 fVar4; LegoObject *local_10; undefined4 local_c; int local_8; int local_4; if (globs::nerpsfileGlobs.camIsLockedOn == 0) goto LAB_00454114; if (globs::nerpsfileGlobs.camLockOnObject == NULL) { if (9 < globs::nerpsfileGlobs.camLockOnRecord) goto LAB_00454114; BVar2 = lrr::Lego_GetRecordObject(globs::nerpsfileGlobs.camLockOnRecord,&local_10); if (BVar2 == 0) { globs::nerpsfileGlobs.camIsLockedOn = 0; goto LAB_00454114; } game::LegoObject_GetBlockPos(local_10,&local_8,&local_4); game::LegoObject_GetPosition (local_10,&globs::nerpsfileGlobs.camLockOnPos.x,&globs::nerpsfileGlobs.camLockOnPos.y) ; } else { game::LegoObject_GetBlockPos(globs::nerpsfileGlobs.camLockOnObject,&local_8,&local_4); game::LegoObject_GetPosition (globs::nerpsfileGlobs.camLockOnObject,&globs::nerpsfileGlobs.camLockOnPos.x, &globs::nerpsfileGlobs.camLockOnPos.y); local_10 = globs::nerpsfileGlobs.camLockOnObject; } lrr::Lego_Goto(local_10,NULL,1); LAB_00454114: if (globs::nerpsfileGlobs.camIsZooming != 0) { fVar1 = globs::nerpsfileGlobs.camZoomTotal / (elapsedAbs * 25.0); globs::nerpsfileGlobs.camZoomMoved = fVar1 + globs::nerpsfileGlobs.camZoomMoved; if (((ushort)((ushort)(globs::nerpsfileGlobs.camZoomMoved < globs::nerpsfileGlobs.camZoomTotal - 5.0) << 8 | (ushort)(globs::nerpsfileGlobs.camZoomMoved == globs::nerpsfileGlobs.camZoomTotal - 5.0) << 0xe) == 0) && ((ushort)((ushort)(globs::nerpsfileGlobs.camZoomTotal - -5.0 < globs::nerpsfileGlobs.camZoomMoved) << 8 | (ushort)(globs::nerpsfileGlobs.camZoomTotal - -5.0 == globs::nerpsfileGlobs.camZoomMoved) << 0xe) == 0)) { globs::nerpsfileGlobs.camIsZooming = 0; globs::nerpsfileGlobs.camZoomMoved = 0.0; } lego::view::Camera_AddZoom(globs::legoGlobs.cameraMain,fVar1); } if (globs::nerpsfileGlobs.camIsRotating != 0) { if ((ushort)((ushort)(globs::nerpsfileGlobs.camRotTotal < 0.0) << 8 | (ushort)(globs::nerpsfileGlobs.camRotTotal == 0.0) << 0xe) == 0) { fVar1 = globs::nerpsfileGlobs.camRotTotal - globs::nerpsfileGlobs.camRotMoved; } else { fVar1 = globs::nerpsfileGlobs.camRotTotal + globs::nerpsfileGlobs.camRotMoved; } fVar4 = lrr::Lego_GetElapsedAbs(); fVar4 = fVar4 * (float10)(fVar1 * 0.1666667) * (float10)0.3333333; globs::nerpsfileGlobs.camRotMoved = (float)(fVar4 + (float10)globs::nerpsfileGlobs.camRotMoved); if ((((ushort)((ushort)(globs::nerpsfileGlobs.camRotTotal < 0.0) << 8 | (ushort)(globs::nerpsfileGlobs.camRotTotal == 0.0) << 0xe) == 0) && ((ushort)((ushort)(globs::nerpsfileGlobs.camRotMoved < globs::nerpsfileGlobs.camRotTotal - 1.0) << 8 | (ushort)(globs::nerpsfileGlobs.camRotMoved == globs::nerpsfileGlobs.camRotTotal - 1.0) << 0xe) == 0)) || ((globs::nerpsfileGlobs.camRotTotal < 0.0 && (globs::nerpsfileGlobs.camRotMoved < globs::nerpsfileGlobs.camRotTotal - -1.0)))) { globs::nerpsfileGlobs.camIsRotating = 0; globs::nerpsfileGlobs.camRotMoved = 0.0; } lego::view::Camera_AddRotation(globs::legoGlobs.cameraMain,(float)(fVar4 * (float10)0.01745329)) ; } pLVar3 = lrr::Lego_GetLevel(); if (pLVar3->status != LEVELSTATUS_INCOMPLETE) { local_10 = (LegoObject *)100; local_c = 0; funcs::NERPFunc__SetGameSpeed((int *)&local_10); } return; } int __cdecl lego::nerps::funcs::NERPFunc__CameraLockOnMonster(int *stack) { if (*stack != 0) { game::LegoObject_RunThroughListsSkipUpgradeParts (NERPsRuntime_LiveObject_GetIfRockMonsterAnd_FUN_004542e0, &globs::nerpsfileGlobs.camLockOnObject); globs::nerpsfileGlobs.camIsLockedOn = TRUE; return 0; } globs::nerpsfileGlobs.camIsLockedOn = 0; globs::nerpsfileGlobs.camLockOnObject = NULL; return 0; } BOOL __cdecl lego::nerps::NERPsRuntime_LiveObject_GetIfRockMonsterAnd_FUN_004542e0 (LegoObject *liveObj,LegoObject **out_liveObj) { BOOL BVar1; if (liveObj != NULL) { BVar1 = game::LegoObject_IsRockMonsterCanGather(liveObj); if (BVar1 != 0) { *out_liveObj = liveObj; return TRUE; } } return 0; } int __cdecl lego::nerps::funcs::NERPFunc__CameraLockOnObject(int *stack) { if (*stack != 0) { globs::nerpsfileGlobs.camLockOnRecord = *stack - 1; globs::nerpsfileGlobs.camIsLockedOn = TRUE; } return 0; } int __cdecl lego::nerps::funcs::NERPFunc__CameraUnlock(int *stack) { globs::nerpsfileGlobs.camIsLockedOn = 0; globs::nerpsfileGlobs.camLockOnRecord = 0xffffffff; globs::nerpsfileGlobs.camLockOnObject = NULL; return 0; } int __cdecl lego::nerps::funcs::NERPFunc__CameraZoomIn(int *stack) { if (globs::nerpsfileGlobs.camZoomMoved != 0.0) { lego::view::Camera_AddZoom (globs::legoGlobs.cameraMain, globs::nerpsfileGlobs.camZoomTotal - globs::nerpsfileGlobs.camZoomMoved); globs::nerpsfileGlobs.camZoomMoved = 0.0; } if (-(float)(ulonglong)(uint)*stack != 0.0) { globs::nerpsfileGlobs.camIsZooming = TRUE; } globs::nerpsfileGlobs.camZoomTotal = -(float)(ulonglong)(uint)*stack; return 0; } int __cdecl lego::nerps::funcs::NERPFunc__CameraZoomOut(int *stack) { if (globs::nerpsfileGlobs.camZoomMoved != 0.0) { lego::view::Camera_AddZoom (globs::legoGlobs.cameraMain, globs::nerpsfileGlobs.camZoomTotal - globs::nerpsfileGlobs.camZoomMoved); } if ((float)(ulonglong)(uint)*stack != 0.0) { globs::nerpsfileGlobs.camIsZooming = TRUE; } globs::nerpsfileGlobs.camZoomTotal = (float)(ulonglong)(uint)*stack; return 0; } int __cdecl lego::nerps::funcs::NERPFunc__CameraRotate(int *stack) { if (globs::nerpsfileGlobs.camRotMoved != 0.0) { lego::view::Camera_AddRotation (globs::legoGlobs.cameraMain, (globs::nerpsfileGlobs.camRotTotal - globs::nerpsfileGlobs.camRotMoved) * 0.01745329) ; globs::nerpsfileGlobs.camRotMoved = 0.0; } globs::nerpsfileGlobs.camRotTotal = (float)(ulonglong)(uint)*stack; if ((ushort)((ushort)(globs::nerpsfileGlobs.camRotTotal < 180.0) << 8 | (ushort)(globs::nerpsfileGlobs.camRotTotal == 180.0) << 0xe) == 0) { globs::nerpsfileGlobs.camRotTotal = globs::nerpsfileGlobs.camRotTotal - 360.0; } if (globs::nerpsfileGlobs.camRotTotal != 0.0) { globs::nerpsfileGlobs.camIsRotating = TRUE; } return 0; } int __cdecl lego::nerps::funcs::NERPFunc__GetSelectedRecordObject(int *stack) { BOOL BVar1; uint recordObjPtr; LegoObject *recordObj; recordObjPtr = 0; do { recordObj = NULL; BVar1 = lrr::Lego_GetRecordObject(recordObjPtr,&recordObj); if (BVar1 != 0) { BVar1 = game::Message_IsUnitSelected(recordObj,NULL); if (BVar1 != 0) { return recordObjPtr + 1; } } recordObjPtr += 1; } while (recordObjPtr < 10); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetCrystalPriority(int *stack) { ai::AITask_Game_SetPriorityOff(AI_Priority_Crystal,(uint)(*stack == 0)); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetMonsterAttackPowerstation(int *stack) { SearchNERPsSetMonsterAttack search; if (*stack == TRUE) { search.sflags2Exclude = STATS2_GENERATEPOWER; search.sflags2Include = 0xffffffff; search.stopAttacking = TRUE; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LegoObject_Callback_SetMonsterAttack,&search); return 0; } search.sflags2Exclude = 0; search.sflags2Include = 0xffffffff; search.stopAttacking = FALSE; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LegoObject_Callback_SetMonsterAttack,&search); return 0; } BOOL __cdecl lego::nerps::NERPs_LegoObject_Callback_SetMonsterAttack (LegoObject *liveObj,SearchNERPsSetMonsterAttack *search) { BOOL BVar1; StatsFlags2 sflags2; uint bx; uint by; if (liveObj != NULL) { game::LegoObject_GetBlockPos(liveObj,(int *)&bx,(int *)&by); BVar1 = game::Level_Block_IsSolidBuilding(bx,by,TRUE); if (BVar1 != 0) { // if ( (A & sflags2) && (A != -1)) FAIL // if (!(B & sflags2) && (B != -1)) FAIL // It's impossible for A to conflict with B, despite what it looks like. sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); // != 0xffffffff if (((search->sflags2Exclude & sflags2) != STATS2_NONE) || (search->sflags2Include != 0xffffffff)) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((search->sflags2Include & sflags2) == STATS2_NONE) { return 0; } // != 0xffffffff if (search->sflags2Exclude != 0xffffffff) { return 0; } } if (search->stopAttacking == FALSE) { ai::AITask_DoRepair(liveObj); } else { if (search->stopAttacking == TRUE) { ai::AITask_StopRepairForObject(liveObj); return 0; } } } } return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetMonsterAttackNowt(int *stack) { SearchNERPsSetMonsterAttack search; if (*stack == TRUE) { search.sflags2Exclude = 0; search.sflags2Include = 0xffffffff; search.stopAttacking = TRUE; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LegoObject_Callback_SetMonsterAttack,&search); return 0; } search.sflags2Exclude = 0; search.sflags2Include = 0xffffffff; search.stopAttacking = FALSE; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LegoObject_Callback_SetMonsterAttack,&search); return 0; } void __cdecl lego::nerps::NERPs_SetObjectsLevel(char *objName,uint objLevel) { SearchSetObjectsLevel_8c search; std::sprintf(search.objName,"%s",objName); search.objLevel = objLevel; lrr::Lego_GetObjectByName(objName,&search.objType,&search.objID,NULL); game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_Callback_SetLevelOfObjects,&search); return; } BOOL __cdecl lego::nerps::NERPs_LiveObject_Callback_SetLevelOfObjects (LegoObject *liveObj,SearchSetObjectsLevel_8c *search) { if (((liveObj != NULL) && (liveObj->type == search->objType)) && (liveObj->id == search->objID)) { stats::StatsObject_SetObjectLevel(liveObj,search->objLevel); } return 0; } BOOL __cdecl lego::nerps::NERPs_LiveObject_Callback_CountRecordObjectsAtBlock (BlockPointer *blockPointer,int bx,int by,SearchNERPsCountRecordObjects *search) { Lego_Level *level; Point2I blockPos; Point2F worldPos; level = lrr::Lego_GetLevel(); game::LegoObject_GetPosition(search->liveObj,&worldPos.x,&worldPos.y); lego::map::Map3D_WorldToBlockPos_NoZ(level->map,worldPos.x,worldPos.y,&blockPos.x,&blockPos.y); if ((bx == blockPos.x) && (by == blockPos.y)) { search->count = search->count + 1; } return TRUE; } int __cdecl lego::nerps::funcs::NERPFunc__GetRecordObjectAtTutorial(int *stack) { BOOL BVar1; uint recordObjPtr; SearchNERPsCountRecordObjects search; int *pStack; pStack = stack; recordObjPtr = 0; do { stack = NULL; BVar1 = lrr::Lego_GetRecordObject(recordObjPtr,(LegoObject **)&stack); if (BVar1 != 0) { search.liveObj = (LegoObject *)stack; search.count = 0; NERPsRuntime_EnumerateBlockPointers (*pStack,NERPs_LiveObject_Callback_CountRecordObjectsAtBlock,&search); if (search.count != 0) { return recordObjPtr + 1; } } recordObjPtr += 1; } while (recordObjPtr < 10); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__GetRecordObjectAmountAtTutorial(int *stack) { BOOL BVar1; uint recordObjPtr; SearchNERPsCountRecordObjects search; int *pStack; pStack = stack; search.count = 0; recordObjPtr = 0; do { stack = NULL; BVar1 = lrr::Lego_GetRecordObject(recordObjPtr,(LegoObject **)&stack); if (BVar1 != 0) { search.liveObj = (LegoObject *)stack; NERPsRuntime_EnumerateBlockPointers (*pStack,NERPs_LiveObject_Callback_CountRecordObjectsAtBlock,&search); } recordObjPtr += 1; } while (recordObjPtr < 10); return search.count; } void __cdecl lego::nerps::NERPsRuntime_DrawTutorialIcon (Lego_Level *level,Viewport *viewMain,float elapsedGame,float elapsedAbs) { BOOL BVar1; float10 fVar2; float10 fVar3; Point2F local_14; Vector3F local_c; fVar2 = (float10)fsin((float10)globs::nerpsruntimeGlobs.tutorialIconTimer); globs::nerpsruntimeGlobs.tutorialIconTimer = globs::nerpsruntimeGlobs.tutorialIconTimer - elapsedAbs * 25.0 * -0.01333333; if (globs::nerpsfileGlobs.RecordObjectPointer != 0) { BVar1 = lrr::Lego_GetRecordObject (globs::nerpsfileGlobs.RecordObjectPointer - 1,(LegoObject **)&elapsedAbs); if (BVar1 != 0) { *(BOOL *)((int)elapsedAbs + 0x3f8) = TRUE; game::LegoObject_GetPosition((LegoObject *)elapsedAbs,&local_c.x,&local_c.y); fVar3 = lego::map::Map3D_GetWorldZ(level->map,local_c.x,local_c.y); local_c.z = (float)fVar3; lego::view::Viewport_WorldToScreen(viewMain,&local_14,&local_c); local_14.x = local_14.x - (float)((int)(globs::legoGlobs.TutorialIcon)->width / 2); local_14.y = local_14.y - ((float)fVar2 * 20.0 + (float)((globs::legoGlobs.TutorialIcon)->height << 1)); lego::image::Image_DisplayScaled(globs::legoGlobs.TutorialIcon,NULL,&local_14,NULL); } } return; } int __cdecl lego::nerps::funcs::NERPFunc__SetRecordObjectPointer(int *stack) { globs::nerpsfileGlobs.RecordObjectPointer = *stack; return *stack; } int __cdecl lego::nerps::NERPs_GetIconClicked(Interface_MenuItemType *pMenuIcon) { int iVar1; iVar1 = front::Interface_GetIconClicked(*pMenuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetOxygenLevel(int *stack) { BOOL BVar1; longlong lVar2; float oxygen; oxygen = (globs::legoGlobs.currLevel)->oxygenLevel; if (oxygen < 1.0) { oxygen = 0.0; } if (oxygen == 0.0) { BVar1 = unk::Teleporter_ServiceAll (TELEPORT_SERVIVE_VEHICLE|TELEPORT_SERVIVE_MINIFIGURE| TELEPORT_SERVIVE_BUILDING|TELEPORT_SERVIVE_ELECTRICFENCE); if (BVar1 == 0) { oxygen = 1.0; } } if (oxygen < 1.0) { oxygen = 1.0; } lVar2 = __ftol((float10)oxygen); return (int)lVar2; } int __cdecl lego::nerps::funcs::NERPFunc__GenerateSlug(int *stack) { LegoObject_ID objID; Container *objModel; LegoObject_Type objType; lrr::Lego_GetObjectByName("Slug",&objType,&objID,&objModel); game::LegoObject_TryGenerateSlug(NULL,objID); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetAttackDefer(int *stack) { lrr::Lego_SetAttackDefer(*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetCallToArms(int *stack) { lrr::Lego_SetCallToArmsOn(*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__GetCallToArmsButtonClicked(int *stack) { return globs::legoGlobs.flags2 & GAME2_CALLTOARMS; } int __cdecl lego::nerps::funcs::NERPFunc__SetRockMonster(int *stack) { LegoObject_ID objID; objID = lrr::Lego_GetEmergeCreatureID(); game::LegoObject_TryGenerateRMonster (globs::legoGlobs.rockMonsterData + objID,LegoObject_RockMonster,objID,*stack - 1, stack[1] - 1); return 1; } int __cdecl lego::nerps::funcs::NERPFunc__GetRockMonstersDestroyed(int *stack) { // table[REWARDTYPE_ROCKMONSTERS] return globs::rewardGlobs.current.items[6].numDestroyed; } void __cdecl lego::nerps::NERPsRuntime_IncHiddenObjectsFound(LegoObject_Type unused_objType) { globs::nerpsruntimeGlobs.hiddenObjectsFound += 1; return; } void __cdecl lego::nerps::NERPsRuntime_ClearHiddenObjectsFound(void) { globs::nerpsruntimeGlobs.hiddenObjectsFound = 0; return; } int __cdecl lego::nerps::funcs::NERPFunc__GetHiddenObjectsFound(int *stack) { return globs::nerpsruntimeGlobs.hiddenObjectsFound; } int __cdecl lego::nerps::funcs::NERPFunc__SetHiddenObjectsFound(int *stack) { globs::nerpsruntimeGlobs.hiddenObjectsFound = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetUpgradeBuildingIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_UpgradeBuilding,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetUpgradeBuildingIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_UpgradeBuilding; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashUpgradeBuildingIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_UpgradeBuilding,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetGoBackIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_Back,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGoBackIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_Back; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashGoBackIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_Back,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetRockMonsterRunningAway(int *stack) { SearchNERPsSetObjectHealthPain search; // enum value 0 (does not require assigning local_4 (field_8) search.type = 0; search.runningAwayCount = 0; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_Callback_SetRockMonsterHealthType,&search); return search.runningAwayCount; } BOOL __cdecl lego::nerps::NERPs_LiveObject_Callback_SetRockMonsterHealthType (LegoObject *liveObj,SearchNERPsSetObjectHealthPain *search) { uint healthType; healthType = search->type; if ((((healthType == 0) || (healthType == 1)) || (healthType == 2)) && (liveObj->type == LegoObject_RockMonster)) { if (healthType == 0) { // type 0: Running away if (((ushort)((ushort)(liveObj->health < 0.0) << 8 | (ushort)(liveObj->health == 0.0) << 0xe) == 0) && (liveObj->health < liveObj->stats->PainThreshold - liveObj->stats->PainThreshold * 0.01 * 20.0)) { game::LegoObject_Route_End(liveObj,FALSE); search->runningAwayCount = search->runningAwayCount + 1; } } else { if (healthType == 1) { // type 1: PainThreshold liveObj->stats->PainThreshold = search->painHealthValue; return 0; } if (healthType == 2) { // type 2: Health liveObj->health = search->painHealthValue; return 0; } } } return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetRockMonsterPainThreshold(int *stack) { SearchNERPsSetObjectHealthPain search; search.type = 1; search.painHealthValue = (float)(ulonglong)(uint)*stack; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_Callback_SetRockMonsterHealthType,&search); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetRockMonsterHealth(int *stack) { SearchNERPsSetObjectHealthPain search; search.type = 2; search.painHealthValue = (float)(ulonglong)(uint)*stack; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_Callback_SetRockMonsterHealthType,&search); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetPauseGame(int *stack) { lrr::Lego_SetPaused(FALSE,*stack); return 1; } int __cdecl lego::nerps::funcs::NERPFunc__GetAnyKeyPressed(int *stack) { uint uVar1; uVar1 = input::Input_AnyKeyPressed(); return uVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetIconPos(int *stack) { globs::nerps::nerpsIconPos.x = (float)(ulonglong)(uint)*stack; globs::nerps::nerpsIconPos.y = (float)(ulonglong)(uint)stack[1]; return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetIconSpace(int *stack) { globs::nerps::nerpsIconSpace = *stack; return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetIconWidth(int *stack) { globs::nerps::nerpsIconWidth = *stack; return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetLevelCompleted(int *stack) { game::Objective_SetStatus(LEVELSTATUS_COMPLETE); return 1; } int __cdecl lego::nerps::funcs::NERPFunc__SetLevelFail(int *stack) { if ((globs::legoGlobs.flags1 & GAME1_LEVELENDING) == GAME1_NONE) { game::Objective_SetStatus(LEVELSTATUS_FAILED); } return 1; } int __cdecl lego::nerps::funcs::NERPFunc__SetGameFail(int *stack) { game::Objective_SetStatus(LEVELSTATUS_FAILED); return 1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTutorialPointer(int *stack) { NERPsRuntime_SetTutorialPointer(*stack,stack[1]); return 1; } int __cdecl lego::nerps::NERPsRuntime_SetSubmenuIconClicked(char *itemName,int clickedCount) { int iVar1; LegoObject_Type objType; lrr::Lego_GetObjectByName(itemName,&objType,(LegoObject_ID *)&itemName,NULL); iVar1 = front::Interface_SetSubmenuIconClicked(objType,(LegoObject_ID)itemName,clickedCount); return iVar1; } int __cdecl lego::nerps::NERPsRuntime_FlashSubmenuIcon(char *objName,BOOL flash) { int objIndex; lrr::Lego_GetObjectByName(objName,(LegoObject_Type *)&objName,(LegoObject_ID *)&objIndex,NULL); front::Interface_SetSubmenuIconFlash((LegoObject_Type)objName,objIndex,flash); return (int)objName; } BOOL __cdecl lego::nerps::NERPsRuntime_Enumerate_SetTutorialBlockClicks (BlockPointer *blockPointer,uint bx,uint by,int *pClickCount) { Lego_Level *level; level = lrr::Lego_GetLevel(); level->blocks[level->width * by + bx].clickCount = *pClickCount; return TRUE; } // NERPS: void SetTutorialBlockClicks(blockPointer, clickCount) int __cdecl lego::nerps::funcs::NERPFunc__SetTutorialBlockClicks(int *stack) { NERPsRuntime_EnumerateBlockPointers (*stack,NERPsRuntime_Enumerate_SetTutorialBlockClicks,stack + 1); return 1; } BOOL __cdecl lego::nerps::NERPsRuntime_Enumerate_SetTutorialCrystals (BlockPointer *blockPointer,uint bx,uint by,int *pCrystalCount) { Lego_Level *level; int i; Point2I blockPos; level = lrr::Lego_GetLevel(); blockPos.x = bx; blockPos.y = by; i = 0; level->blocks[level->width * by + bx].generateCrystals = *pCrystalCount; if (0 < *pCrystalCount) { do { game::Level_GenerateCrystal(&blockPos,0,NULL,TRUE); i += 1; } while (i < *pCrystalCount); } return TRUE; } // NERPS: void SetTutorialCrystals(blockPointer, crystalCount) int __cdecl lego::nerps::funcs::NERPFunc__SetTutorialCrystals(int *stack) { NERPsRuntime_EnumerateBlockPointers(*stack,NERPsRuntime_Enumerate_SetTutorialCrystals,stack + 1); return 1; } BOOL __cdecl lego::nerps::NERPs_SetOreAtBlock(BlockPointer *blockPointer,uint bx,uint by,int *pGenerateOre) { Lego_Level *level; Point2I blockPos; level = lrr::Lego_GetLevel(); blockPos.x = bx; blockPos.y = by; level->blocks[level->width * by + bx].generateOre = *pGenerateOre; game::Level_GenerateOre(&blockPos,0,NULL,FALSE); return 1; } int __cdecl lego::nerps::funcs::NERPFunc__SetOreAtIconPositions(int *stack) { NERPsRuntime_EnumerateBlockPointers(*stack,NERPs_SetOreAtBlock,stack + 1); return 1; } int __cdecl lego::nerps::NERPsRuntime_CountSelectedUnits_ByObjectName(char *objName) { LegoObject **pUnit; uint numSelected; int count; uint i; LegoObject_ID local_4; count = 0; lrr::Lego_GetObjectByName(objName,(LegoObject_Type *)&objName,&local_4,NULL); pUnit = game::Message_GetSelectedUnits(); i = 0; numSelected = game::Message_GetNumSelectedUnits(); if (numSelected != 0) { do { if (((char *)(*pUnit)->type == objName) && ((*pUnit)->id == local_4)) { count += 1; } i += 1; pUnit = pUnit + 1; numSelected = game::Message_GetNumSelectedUnits(); } while (i < numSelected); } return count; } int __cdecl lego::nerps::funcs::NERPFunc__GetMiniFigureSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("Pilot"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetSmallTruckSelected(int *stack) { LegoObject *unit; LegoObject_ID objID; LegoObject_Type objType; unit = front::Interface_GetPrimarySelectedUnit(); if (unit == NULL) { return 0; } lrr::Lego_GetObjectByName("SmallTruck",&objType,&objID,NULL); if (unit->id != objID) { return 0; } return (uint)(unit->type == objType); } int __cdecl lego::nerps::funcs::NERPFunc__GetSmallDiggerSelected(int *stack) { LegoObject *unit; LegoObject_ID objID; LegoObject_Type objType; unit = front::Interface_GetPrimarySelectedUnit(); if (unit == NULL) { return 0; } lrr::Lego_GetObjectByName("SmallDigger",&objType,&objID,NULL); if (unit->id != objID) { return 0; } return (uint)(unit->type == objType); } int __cdecl lego::nerps::funcs::NERPFunc__GetRapidRiderSelected(int *stack) { LegoObject *unit; LegoObject_ID objID; LegoObject_Type objType; unit = front::Interface_GetPrimarySelectedUnit(); if (unit == NULL) { return 0; } lrr::Lego_GetObjectByName("SmallCat",&objType,&objID,NULL); if (unit->id != objID) { return 0; } return (uint)(unit->type == objType); } int __cdecl lego::nerps::funcs::NERPFunc__GetSmallHelicopterSelected(int *stack) { LegoObject *unit; LegoObject_ID objID; LegoObject_Type objType; unit = front::Interface_GetPrimarySelectedUnit(); if (unit == NULL) { return 0; } lrr::Lego_GetObjectByName("SmallHeli",&objType,&objID,NULL); if (unit->id != objID) { return 0; } return (uint)(unit->type == objType); } int __cdecl lego::nerps::funcs::NERPFunc__GetGraniteGrinderSelected(int *stack) { LegoObject *unit; LegoObject_ID objID; LegoObject_Type objType; unit = front::Interface_GetPrimarySelectedUnit(); if (unit == NULL) { return 0; } lrr::Lego_GetObjectByName("WalkerDigger",&objType,&objID,NULL); if (unit->id != objID) { return 0; } return (uint)(unit->type == objType); } int __cdecl lego::nerps::funcs::NERPFunc__GetChromeCrusherSelected(int *stack) { LegoObject *unit; LegoObject_ID objID; LegoObject_Type objType; unit = front::Interface_GetPrimarySelectedUnit(); if (unit == NULL) { return 0; } lrr::Lego_GetObjectByName("LargeDigger",&objType,&objID,NULL); if (unit->id != objID) { return 0; } return (uint)(unit->type == objType); } BOOL __cdecl lego::nerps::NERPs_Game_DoCallbacks_ByObjectName(char *objName) { LegoObject_Type local_c; LegoObject_ID local_8; BOOL local_4; lrr::Lego_GetObjectByName(objName,&local_c,&local_8,NULL); local_4 = 0; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_Callback_ByObjectTypeIndex_IsDriving,&local_c); return local_4; } BOOL __cdecl lego::nerps::NERPs_LiveObject_Callback_ByObjectTypeIndex_IsDriving (LegoObject *liveObj1,LegoObject *liveObj_template) { if (((liveObj1->type == liveObj_template->type) && (liveObj1->id == liveObj_template->id)) && (liveObj1->driveObject != NULL)) { liveObj_template->customName = liveObj_template->customName + 1; } return 0; } int __cdecl lego::nerps::funcs::NERPFunc__AddPoweredCrystals(int *stack) { uint uVar1; uVar1 = 0; if (*stack != 0) { do { game::Level_IncCrystalsStored(); uVar1 += 1; } while (uVar1 < (uint)*stack); } game::LegoObject_RequestPowerGridUpdate(); return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__AddStoredOre(int *stack) { uint uVar1; uVar1 = 0; if (*stack != 0) { do { game::Level_IncOreStored(0); uVar1 += 1; } while (uVar1 < (uint)*stack); } return *stack; } BOOL __cdecl lego::nerps::NERPsRuntime_Callback_GetTutorialCrystals (BlockPointer *blockPointer,uint bx,uint by,int *out_tutorialCrystals) { Lego_Level *level; level = lrr::Lego_GetLevel(); *out_tutorialCrystals = *out_tutorialCrystals + level->blocks[level->width * by + bx].generateCrystals; return TRUE; } int __cdecl lego::nerps::funcs::NERPFunc__GetTutorialCrystals(int *stack) { int crystals; crystals = 0; NERPsRuntime_EnumerateBlockPointers(*stack,NERPsRuntime_Callback_GetTutorialCrystals,&crystals); return crystals; } BOOL __cdecl lego::nerps::NERPsRuntime_Callback_GetTutorialBlockClicks (BlockPointer *blockPointer,uint bx,uint by,int *out_clicks) { Lego_Level *level; level = lrr::Lego_GetLevel(); *out_clicks = *out_clicks + level->blocks[level->width * by + bx].clickCount; return TRUE; } int __cdecl lego::nerps::funcs::NERPFunc__GetTutorialBlockClicks(int *stack) { int clicks; clicks = 0; NERPsRuntime_EnumerateBlockPointers(*stack,NERPsRuntime_Callback_GetTutorialBlockClicks,&clicks); return clicks; } // Special arguments: // objLevel: -1 = all levels // objLevel: -2 = powered objects (ignoring levels?) int __cdecl lego::nerps::NERPsRuntime_GetLevelObjectsBuilt(char *objName,int objLevel) { int iVar1; uint levels; uint totalCount; uint i; LegoObject_Type objType; SearchObjectTypeCount_c searchCounts; lrr::Lego_GetObjectByName(objName,&objType,(LegoObject_ID *)&objName,NULL); iVar1 = objLevel; if (objLevel < 0) { totalCount = 0; i = 0; levels = stats::Stats_GetLevels(objType,(LegoObject_ID)objName); if (levels != 0) { do { if (iVar1 == -1) { levels = game::LegoObject_GetLevelObjectsBuilt(objType,(LegoObject_ID)objName,i,TRUE); totalCount += levels; } if (iVar1 == -2) { searchCounts.objType = objType; searchCounts.objIndex = (int)objName; searchCounts.count = 0; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPsRuntime_LiveObjectCallback_GetPoweredObjectsBuilt,&searchCounts); totalCount += searchCounts.count; } i += 1; levels = stats::Stats_GetLevels(objType,(LegoObject_ID)objName); } while (i < levels); } return totalCount; } levels = game::LegoObject_GetLevelObjectsBuilt(objType,(LegoObject_ID)objName,objLevel,TRUE); return levels; } BOOL __cdecl lego::nerps::NERPsRuntime_LiveObjectCallback_GetPoweredObjectsBuilt (LegoObject *liveObj,SearchObjectTypeCount_c *search) { if ((liveObj->type == search->objType) && (liveObj->id == search->objIndex)) { if ((liveObj->flags3 & LIVEOBJ3_HASPOWER) != LIVEOBJ3_NONE) { search->count = search->count + 1; return 0; } search->count = 0; } return 0; } uint __cdecl lego::nerps::NERPsRuntime_GetPreviousLevelObjectsBuilt(char *objName,int objLevel) { uint count; LegoObject_Type objType; lrr::Lego_GetObjectByName(objName,&objType,(LegoObject_ID *)&objName,NULL); count = game::LegoObject_GetPreviousLevelObjectsBuilt(objType,(LegoObject_ID)objName,objLevel); return count; } int __cdecl lego::nerps::NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName(char *objName) { int iVar1; LegoObject_Type local_4; lrr::Lego_GetObjectByName(objName,&local_4,(LegoObject_ID *)&objName,NULL); iVar1 = front::Interface_GetSubmenuIconClicked(local_4,(LegoObject_ID)objName); return iVar1; } BOOL __cdecl lego::nerps::NERPsRuntime_FlashIcon(Interface_MenuItemType menuIcon,BOOL flash) { BOOL BVar1; if (flash == TRUE) { BVar1 = front::Interface_SetAdvisorPointToFashingIcon(menuIcon,TRUE); if (BVar1 != 0) { front::Interface_SetIconFlash(menuIcon,TRUE); return TRUE; } } else { front::Advisor_End(); front::Interface_SetIconFlash(menuIcon,FALSE); } return 0; } int __cdecl lego::nerps::funcs::NERPFunc__GetMiniFigureinGraniteGrinder(int *stack) { BOOL BVar1; BVar1 = NERPs_Game_DoCallbacks_ByObjectName("Walkerdigger"); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetMiniFigureinChromeCrusher(int *stack) { BOOL BVar1; BVar1 = NERPs_Game_DoCallbacks_ByObjectName("LargeDigger"); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetMiniFigureinSmallDigger(int *stack) { BOOL BVar1; BVar1 = NERPs_Game_DoCallbacks_ByObjectName("SmallDigger"); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetMiniFigureinRapidRider(int *stack) { BOOL BVar1; BVar1 = NERPs_Game_DoCallbacks_ByObjectName("SmallCat"); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetMiniFigureinSmallTruck(int *stack) { BOOL BVar1; BVar1 = NERPs_Game_DoCallbacks_ByObjectName("SmallTruck"); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetMiniFigureinSmallHelicopter(int *stack) { BOOL BVar1; BVar1 = NERPs_Game_DoCallbacks_ByObjectName("SmallHeli"); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetBarracksLevel(int *stack) { NERPs_SetObjectsLevel("Barracks",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetDocksLevel(int *stack) { NERPs_SetObjectsLevel("Docks",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetGeoDomeLevel(int *stack) { NERPs_SetObjectsLevel("Geo-dome",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetPowerstationLevel(int *stack) { NERPs_SetObjectsLevel("Powerstation",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetToolStoreLevel(int *stack) { NERPs_SetObjectsLevel("Toolstation",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetGunstationLevel(int *stack) { NERPs_SetObjectsLevel("Gunstation",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetTeleportPadLevel(int *stack) { NERPs_SetObjectsLevel("TeleportPad",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetSuperTeleportLevel(int *stack) { NERPs_SetObjectsLevel("TeleportBIG",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetUpgradeStationLevel(int *stack) { NERPs_SetObjectsLevel("Upgrade",*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__GetBarracksSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("Barracks"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetDocksSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("Docks"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGeoDomeSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("Geo-Dome"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPowerstationSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("Powerstation"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetToolStoreSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("Toolstation"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGunstationSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("Gunstation"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTeleportPadSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("TeleportPad"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetSuperTeleportSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("TeleportBIG"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetUpgradeStationSelected(int *stack) { int iVar1; iVar1 = NERPsRuntime_CountSelectedUnits_ByObjectName("Upgrade"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredBarracksBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Barracks",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredDocksBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Docks",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredGeodomeBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Geo-dome",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredPowerstationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Powerstation",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredToolStoresBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Toolstation",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredGunstationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("GunStation",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredTeleportsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("TeleportPad",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredVehicleTeleportsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("TeleportBIG",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPoweredUpgradeStationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Upgrade",-2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetBarracksBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Barracks",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetDocksBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Docks",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGeodomeBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Geo-dome",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPowerstationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Powerstation",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetToolStoresBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Toolstation",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGunstationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("GunStation",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTeleportsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("TeleportPad",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetVehicleTeleportsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("TeleportBIG",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetUpgradeStationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Upgrade",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1BarracksBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Barracks",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1DocksBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Docks",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1GeodomeBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Geo-dome",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1PowerstationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Powerstation",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1ToolStoresBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Toolstation",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1GunstationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("GunStation",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1TeleportsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("TeleportPad",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1VehicleTeleportsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("TeleportBIG",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel1UpgradeStationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Upgrade",1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2BarracksBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Barracks",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2DocksBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Docks",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2GeodomeBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Geo-dome",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2PowerstationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Powerstation",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2ToolStoresBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Toolstation",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2GunstationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("GunStation",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2TeleportsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("TeleportPad",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2VehicleTeleportsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("TeleportBIG",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLevel2UpgradeStationsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Upgrade",2); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetBarracksIconClicked(int *stack) { int iVar1; iVar1 = NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName("Barracks"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGeodomeIconClicked(int *stack) { int iVar1; iVar1 = NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName("Geo-dome"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPowerstationIconClicked(int *stack) { int iVar1; iVar1 = NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName("Powerstation"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetToolStoreIconClicked(int *stack) { int iVar1; iVar1 = NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName("Toolstation"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGunstationIconClicked(int *stack) { int iVar1; iVar1 = NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName("Gunstation"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTeleportPadIconClicked(int *stack) { int iVar1; iVar1 = NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName("TeleportPad"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetVehicleTransportIconClicked(int *stack) { int iVar1; iVar1 = NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName("TeleportBIG"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetUpgradeStationIconClicked(int *stack) { int iVar1; iVar1 = NERPs_SubMenu_GetBuildingVehicleIcon_ByObjectName("Upgrade"); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetBarracksIconClicked(int *stack) { int iVar1; iVar1 = NERPsRuntime_SetSubmenuIconClicked("Barracks",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetGeodomeIconClicked(int *stack) { int iVar1; iVar1 = NERPsRuntime_SetSubmenuIconClicked("Geo-dome",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetPowerstationIconClicked(int *stack) { int iVar1; iVar1 = NERPsRuntime_SetSubmenuIconClicked("Powerstation",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetToolStoreIconClicked(int *stack) { int iVar1; iVar1 = NERPsRuntime_SetSubmenuIconClicked("Toolstation",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetGunstationIconClicked(int *stack) { int iVar1; iVar1 = NERPsRuntime_SetSubmenuIconClicked("Gunstation",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTeleportPadIconClicked(int *stack) { int iVar1; iVar1 = NERPsRuntime_SetSubmenuIconClicked("TeleportPad",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetVehicleTransportIconClicked(int *stack) { int iVar1; iVar1 = NERPsRuntime_SetSubmenuIconClicked("TeleportBIG",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetUpgradeStationIconClicked(int *stack) { int iVar1; iVar1 = NERPsRuntime_SetSubmenuIconClicked("Upgrade",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashBarracksIcon(int *stack) { int iVar1; iVar1 = NERPsRuntime_FlashSubmenuIcon("Barracks",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashGeodomeIcon(int *stack) { int iVar1; iVar1 = NERPsRuntime_FlashSubmenuIcon("Geo-dome",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashPowerStationIcon(int *stack) { int iVar1; iVar1 = NERPsRuntime_FlashSubmenuIcon("Powerstation",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashToolStoreIcon(int *stack) { int iVar1; iVar1 = NERPsRuntime_FlashSubmenuIcon("Toolstation",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashGunstationIcon(int *stack) { int iVar1; iVar1 = NERPsRuntime_FlashSubmenuIcon("Gunstation",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashTeleportPadIcon(int *stack) { int iVar1; iVar1 = NERPsRuntime_FlashSubmenuIcon("TeleportPad",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashVehicleTransportIcon(int *stack) { int iVar1; iVar1 = NERPsRuntime_FlashSubmenuIcon("TeleportBIG",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashUpgradeStationIcon(int *stack) { int iVar1; iVar1 = NERPsRuntime_FlashSubmenuIcon("Upgrade",*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPathsBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Path",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetStudCount(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("ProcessedOre",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetSmallHelicoptersOnLevel(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("SmallHeli",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGraniteGrindersOnLevel(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("WalkerDigger",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetRapidRidersOnLevel(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("SmallCat",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetSmallDiggersOnLevel(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("SmallDigger",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetSlugsOnLevel(int *stack) { int slugs; slugs = NERPsRuntime_GetLevelObjectsBuilt("Slug",-1); return slugs; } int __cdecl lego::nerps::funcs::NERPFunc__GetMiniFiguresOnLevel(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Pilot",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetOreRefineriesBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("Refinery",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetCrystalRefineriesBuilt(int *stack) { int iVar1; iVar1 = NERPsRuntime_GetLevelObjectsBuilt("CrystalRefinery",-1); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTeleportIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_TeleportMan; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetDynamiteClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_Dynamite; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetMountIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_GetIn; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTrainIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_TrainSkill; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetDropSonicBlasterIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_DropBirdScarer; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGetToolIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_GetTool; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGetPusherIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_GetPusherGun; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGetSonicBlasterIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_GetBirdScarer; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTrainSailorIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_TrainSailor; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTrainPilotIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_TrainPilot; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetTrainDriverIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_TrainDriver; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetGetLaserIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_GetLaser; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetDismountIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_GetOut; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetDigIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_Dig; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetBuildIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_BuildBuilding; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetLayPathIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_LayPath; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetPlaceFenceIconClicked(int *stack) { int iVar1; Interface_MenuItemType menuIcon; menuIcon = Interface_MenuItem_PlaceFence; iVar1 = NERPs_GetIconClicked(&menuIcon); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTeleportIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_TeleportMan,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetDynamiteClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_Dynamite,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTrainIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_TrainSkill,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTrainDriverIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_TrainDriver,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTrainSailorIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_TrainSailor,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetGetToolIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_GetTool,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetDropSonicBlasterIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_DropBirdScarer,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetGetLaserIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_GetLaser,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetGetPusherIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_GetPusherGun,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetGetSonicBlasterIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_GetBirdScarer,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetDismountIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_GetOut,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetTrainPilotIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_TrainPilot,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetMountIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_GetIn,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetDigIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_Dig,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetBuildIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_BuildBuilding,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetLayPathIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_LayPath,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetPlaceFenceIconClicked(int *stack) { int iVar1; iVar1 = front::Interface_SetIconClicked(Interface_MenuItem_PlaceFence,*stack); return iVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashTeleportIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_TeleportMan,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashDynamiteIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_Dynamite,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashMountIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_GetIn,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashTrainIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_TrainSkill,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashTrainDriverIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_TrainDriver,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashTrainPilotIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_TrainPilot,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashTrainSailorIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_TrainSailor,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashDismountIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_GetOut,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashGetToolIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_GetTool,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashDropSonicBlasterIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_DropBirdScarer,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashGetLaserIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_GetLaser,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashGetPusherIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_GetPusherGun,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashGetSonicBlasterIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_GetBirdScarer,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashDigIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_Dig,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashBuildIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_BuildBuilding,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashLayPathIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_LayPath,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__FlashPlaceFenceIcon(int *stack) { BOOL BVar1; BVar1 = NERPsRuntime_FlashIcon(Interface_MenuItem_PlaceFence,*stack); return BVar1; } int __cdecl lego::nerps::funcs::NERPFunc__GetRandom(int *stack) { ushort uVar1; uVar1 = math::Maths_Rand(); return uVar1 & 0xfff; } int __cdecl lego::nerps::funcs::NERPFunc__GetRandomTrueFalse(int *stack) { ushort uVar1; uVar1 = math::Maths_Rand(); return uVar1 & 1; } int __cdecl lego::nerps::funcs::NERPFunc__GetRandom10(int *stack) { short sVar1; sVar1 = math::Maths_Rand(); return (int)sVar1 % 10; } int __cdecl lego::nerps::funcs::NERPFunc__GetRandom100(int *stack) { short sVar1; sVar1 = math::Maths_Rand(); return (int)sVar1 % 100; } int __cdecl lego::nerps::funcs::NERPFunc__GetCrystalsPickedUp(int *stack) { return (globs::legoGlobs.currLevel)->crystalsPickedUp; } int __cdecl lego::nerps::funcs::NERPFunc__GetCrystalsCurrentlyStored(int *stack) { int numCrystals; // `TRUE` to return crystals as total count. numCrystals = game::Level_GetCrystalCount(TRUE); return numCrystals; } int __cdecl lego::nerps::funcs::NERPFunc__False(int *stack) { return 0; } int __cdecl lego::nerps::funcs::NERPFunc__GetOrePickedUp(int *stack) { return (globs::legoGlobs.currLevel)->orePickedUp; } int __cdecl lego::nerps::funcs::NERPFunc__GetOreCurrentlyStored(int *stack) { return (globs::legoGlobs.currLevel)->ore; } // NOTE: For the sake of Ghidra auto-completion, the return type // will be `TutorialFlags`, rather than the required `int` type. TutorialFlags __cdecl lego::nerps::funcs::NERPFunc__GetTutorialFlags(int *stack) { return globs::nerpsruntimeGlobs.tutorialFlags; } int __cdecl lego::nerps::funcs::NERPFunc__GetR0(int *stack) { return globs::nerpsruntimeGlobs.registers[0]; } int __cdecl lego::nerps::funcs::NERPFunc__GetR1(int *stack) { return globs::nerpsruntimeGlobs.registers[1]; } int __cdecl lego::nerps::funcs::NERPFunc__GetR2(int *stack) { return globs::nerpsruntimeGlobs.registers[2]; } int __cdecl lego::nerps::funcs::NERPFunc__GetR3(int *stack) { return globs::nerpsruntimeGlobs.registers[3]; } int __cdecl lego::nerps::funcs::NERPFunc__GetR4(int *stack) { return globs::nerpsruntimeGlobs.registers[4]; } int __cdecl lego::nerps::funcs::NERPFunc__GetR5(int *stack) { return globs::nerpsruntimeGlobs.registers[5]; } int __cdecl lego::nerps::funcs::NERPFunc__GetR6(int *stack) { return globs::nerpsruntimeGlobs.registers[6]; } int __cdecl lego::nerps::funcs::NERPFunc__GetR7(int *stack) { return globs::nerpsruntimeGlobs.registers[7]; } int __cdecl lego::nerps::funcs::NERPFunc__AddR0(int *stack) { globs::nerpsruntimeGlobs.registers[0] += *stack; return globs::nerpsruntimeGlobs.registers[0]; } int __cdecl lego::nerps::funcs::NERPFunc__AddR1(int *stack) { globs::nerpsruntimeGlobs.registers[1] += *stack; return globs::nerpsruntimeGlobs.registers[1]; } int __cdecl lego::nerps::funcs::NERPFunc__AddR2(int *stack) { globs::nerpsruntimeGlobs.registers[2] += *stack; return globs::nerpsruntimeGlobs.registers[2]; } int __cdecl lego::nerps::funcs::NERPFunc__AddR3(int *stack) { globs::nerpsruntimeGlobs.registers[3] += *stack; return globs::nerpsruntimeGlobs.registers[3]; } int __cdecl lego::nerps::funcs::NERPFunc__AddR4(int *stack) { globs::nerpsruntimeGlobs.registers[4] += *stack; return globs::nerpsruntimeGlobs.registers[4]; } int __cdecl lego::nerps::funcs::NERPFunc__AddR5(int *stack) { globs::nerpsruntimeGlobs.registers[5] += *stack; return globs::nerpsruntimeGlobs.registers[5]; } int __cdecl lego::nerps::funcs::NERPFunc__AddR6(int *stack) { globs::nerpsruntimeGlobs.registers[6] += *stack; return globs::nerpsruntimeGlobs.registers[6]; } int __cdecl lego::nerps::funcs::NERPFunc__AddR7(int *stack) { globs::nerpsruntimeGlobs.registers[7] += *stack; return globs::nerpsruntimeGlobs.registers[7]; } int __cdecl lego::nerps::funcs::NERPFunc__SubR0(int *stack) { globs::nerpsruntimeGlobs.registers[0] -= *stack; return globs::nerpsruntimeGlobs.registers[0]; } int __cdecl lego::nerps::funcs::NERPFunc__SubR1(int *stack) { globs::nerpsruntimeGlobs.registers[1] -= *stack; return globs::nerpsruntimeGlobs.registers[1]; } int __cdecl lego::nerps::funcs::NERPFunc__SubR2(int *stack) { globs::nerpsruntimeGlobs.registers[2] -= *stack; return globs::nerpsruntimeGlobs.registers[2]; } int __cdecl lego::nerps::funcs::NERPFunc__SubR3(int *stack) { globs::nerpsruntimeGlobs.registers[3] -= *stack; return globs::nerpsruntimeGlobs.registers[3]; } int __cdecl lego::nerps::funcs::NERPFunc__SubR4(int *stack) { globs::nerpsruntimeGlobs.registers[4] -= *stack; return globs::nerpsruntimeGlobs.registers[4]; } int __cdecl lego::nerps::funcs::NERPFunc__SubR5(int *stack) { globs::nerpsruntimeGlobs.registers[5] -= *stack; return globs::nerpsruntimeGlobs.registers[5]; } int __cdecl lego::nerps::funcs::NERPFunc__SubR6(int *stack) { globs::nerpsruntimeGlobs.registers[6] -= *stack; return globs::nerpsruntimeGlobs.registers[6]; } int __cdecl lego::nerps::funcs::NERPFunc__SubR7(int *stack) { globs::nerpsruntimeGlobs.registers[7] -= *stack; return globs::nerpsruntimeGlobs.registers[7]; } int __cdecl lego::nerps::funcs::NERPFunc__SetR0(int *stack) { globs::nerpsruntimeGlobs.registers[0] = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetR1(int *stack) { globs::nerpsruntimeGlobs.registers[1] = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetR2(int *stack) { globs::nerpsruntimeGlobs.registers[2] = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetR3(int *stack) { globs::nerpsruntimeGlobs.registers[3] = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetR4(int *stack) { globs::nerpsruntimeGlobs.registers[4] = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetR5(int *stack) { globs::nerpsruntimeGlobs.registers[5] = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetR6(int *stack) { globs::nerpsruntimeGlobs.registers[6] = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetR7(int *stack) { globs::nerpsruntimeGlobs.registers[7] = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetTutorialFlags(int *stack) { globs::nerpsruntimeGlobs.tutorialFlags = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__GetTrainFlags(int *stack) { return globs::objectGlobs.NERPs_TrainFlags; } int __cdecl lego::nerps::funcs::NERPFunc__SetTrainFlags(int *stack) { globs::objectGlobs.NERPs_TrainFlags = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__GetMonstersOnLevel(int *stack) { int lavaMons; int rockMons; int iceMons; lavaMons = NERPsRuntime_GetLevelObjectsBuilt("LavaMonster",0); rockMons = NERPsRuntime_GetLevelObjectsBuilt("RockMonster",0); iceMons = NERPsRuntime_GetLevelObjectsBuilt("IceMonster",0); return iceMons + lavaMons + rockMons; } int __cdecl lego::nerps::funcs::NERPFunc__GetBuildingsTeleported(int *stack) { return globs::objectGlobs.BuildingsTeleported; } int __cdecl lego::nerps::funcs::NERPFunc__SetBuildingsTeleported(int *stack) { game::LegoObject_SetNumBuildingsTeleported(*stack); return 0; } int __cdecl lego::nerps::funcs::NERPFunc__SetMessagePermit(int *stack) { globs::nerpsruntimeGlobs.messagePermit = *stack; if (*stack == TRUE) { lrr::Lego_SetFlags2_40_And_2_unkCamera(FALSE,TRUE); lrr::Lego_SetFlags2_80(FALSE); } globs::textGlobs.jankCounter = 0; globs::textGlobs.currText = NULL; return *stack; } // May actually be related to message capabilities. BOOL __cdecl lego::nerps::NERPsRuntime_IsMessagePermit(void) { return globs::nerpsruntimeGlobs.messagePermit; } BOOL __cdecl lego::nerps::NERPsRuntime_GetMessageWait(void) { return globs::nerpsruntimeGlobs.messageWait; } int __cdecl lego::nerps::funcs::NERPFunc__SetMessageWait(int *stack) { globs::nerpsruntimeGlobs.messageWait = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetMessageTimerValues(int *stack) { globs::nerps::nerpsMessageTimerValues[0] = (float)(ulonglong)(uint)*stack; globs::nerps::nerpsMessageTimerValues[1] = (float)(ulonglong)(uint)stack[1]; globs::nerps::nerpsMessageTimerValues[2] = (float)(ulonglong)(uint)stack[2]; return 1; } int __cdecl lego::nerps::funcs::NERPFunc__GetMessageTimer(int *stack) { longlong lVar1; lVar1 = __ftol((float10)globs::nerpsruntimeGlobs.messageTimer); return (int)lVar1; } int __cdecl lego::nerps::funcs::NERPFunc__SetMessage(int *stack) { BOOL BVar1; char *text; uint lineIndex; BVar1 = NERPsRuntime_IsMessagePermit(); if (BVar1 != 0) { return 0; } lineIndex = *stack; if (lineIndex != 0) { lineIndex -= 1; } text = NERPsFile_GetMessageLine(lineIndex); if (lineIndex != globs::nerpsfileGlobs.lineIndexArray_7c[globs::nerpsfileGlobs.uint_a0]) { if (globs::nerpsfileGlobs.uint_a0 == 8) { globs::nerpsfileGlobs.lineIndexArray_7c[1] = globs::nerpsfileGlobs.lineIndexArray_7c[5]; globs::nerpsfileGlobs.lineIndexArray_7c[2] = globs::nerpsfileGlobs.lineIndexArray_7c[6]; globs::nerpsfileGlobs.lineIndexArray_7c[4] = globs::nerpsfileGlobs.lineIndexArray_7c[8]; globs::nerpsfileGlobs.lineIndexArray_7c[3] = globs::nerpsfileGlobs.lineIndexArray_7c[7]; globs::nerpsfileGlobs.uint_a0 = 4; } globs::nerpsfileGlobs.lineIndexArray_7c[globs::nerpsfileGlobs.uint_a0 + 1] = lineIndex; globs::nerpsfileGlobs.uint_a0 += 1; if (globs::nerpsfileGlobs.uint_a0 != 0) { lrr::Lego_SetFlags2_80(TRUE); } if (globs::nerpsfileGlobs.int_a4 != 0) { globs::nerpsfileGlobs.int_a4 += 1; } } front::Text_SetNERPsMessage(text,stack[1]); globs::nerpsruntimeGlobs.nextArrowDisabled = stack[1]; globs::nerps::nerpsBOOL_004a7740 = TRUE; BVar1 = NERPsRuntime_GetMessageWait(); if (BVar1 != 0) { // Ensure the screen has rendered before going into the endless wait loop. ddraw::DirectDraw_Flip(); // IsKeyUp(KEY_RETURN) || IsKeyUnchanged(KEY_RETURN) (28) // // ...What is going on here? An infinite loop until the user presses enter?? // ...This is really bad. while ((globs::INPUT.Key_Map[28] == false || (globs::INPUT.prevKey_Map[28] == globs::INPUT.Key_Map[28]))) { input::Input_ReadKeys(); } } return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__SetObjectiveSwitch(int *stack) { globs::nerpsruntimeGlobs.objectiveSwitch = *stack; return *stack; } int __cdecl lego::nerps::funcs::NERPFunc__GetObjectiveSwitch(int *stack) { if (globs::nerpsruntimeGlobs.objectiveSwitch != 0) { globs::nerpsruntimeGlobs.objectiveSwitch = 0; return TRUE; } return FALSE; } int __cdecl lego::nerps::funcs::NERPFunc__GetObjectiveShowing(int *stack) { BOOL BVar1; BVar1 = game::Objective_IsShowing(); return (uint)(BVar1 != 0); } void __cdecl lego::nerps::NERPs_RestartMessageSample(void) { if (globs::nerps::nerpsUnkSampleIndex != -1) { snd::Sound3D_Play2(Sound3DPlay_Normal,NULL,globs::nerps::nerpsUnkSampleIndex,FALSE,NULL); } return; } // WARNING: Could not reconcile some variable overlaps // text is the raw input line (which usually has `#soundName#` and `` etc.) // out_buffer is the stripped output line without the `#soundName#` or `` markers. void __cdecl lego::nerps::NERPs_Level_NERPMessage_Parse(char *text,char *out_buffer,BOOL updateTimer) { char cVar1; bool bVar2; byte bVar3; BOOL BVar4; TutorialFlags tflags; int iVar5; uint uVar6; uint uVar7; undefined4 *puVar8; char *pcVar9; Image **ppIVar10; float10 fVar11; Point2F local_164; uint local_15c; undefined4 uStack344; float newTimerValue; Image *images [20]; char keyBuff [256]; int sound3DHandle; ppIVar10 = images; images[0] = NULL; local_15c &= 0xffffff00; for (iVar5 = 0x13; ppIVar10 = ppIVar10 + 1, iVar5 != 0; iVar5 += -1) { *ppIVar10 = NULL; } newTimerValue = globs::nerps::nerpsMessageTimerValues[2]; if (((globs::nerpsfileGlobs.imageCount == 0) && (globs::nerpsfileGlobs.soundCount == 0)) && (out_buffer != NULL)) { uVar6 = 0xffffffff; do { pcVar9 = text; if (uVar6 == 0) break; uVar6 -= 1; pcVar9 = text + 1; cVar1 = *text; text = pcVar9; } while (cVar1 != '\0'); uVar6 = ~uVar6; puVar8 = (undefined4 *)(pcVar9 + -uVar6); for (uVar7 = uVar6 >> 2; uVar7 != 0; uVar7 -= 1) { *(undefined4 *)out_buffer = *puVar8; puVar8 = puVar8 + 1; out_buffer = (char *)((int)out_buffer + 4); } for (uVar6 &= 3; uVar6 != 0; uVar6 -= 1) { *out_buffer = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); out_buffer = (char *)((int)out_buffer + 1); } } else { cVar1 = *text; local_164.x = (float)out_buffer; while (cVar1 != '\0') { cVar1 = *text; if (cVar1 == '<') { cVar1 = text[1]; text = text + 1; bVar2 = false; pcVar9 = keyBuff; while ((cVar1 != '\0' && (!bVar2))) { if (cVar1 == '>') { *pcVar9 = '\0'; bVar3 = 0; if (globs::nerpsfileGlobs.imageCount != 0) { uVar6 = 0; do { iVar5 = std::_stricmp(globs::nerpsfileGlobs.imageList[uVar6].key,keyBuff); if (iVar5 == 0) { bVar2 = true; images[local_15c & 0xff] = globs::nerpsfileGlobs.imageList[bVar3].image; local_15c = local_15c & 0xffffff00 | (uint)(byte)((char)local_15c + 1); break; } bVar3 += 1; uVar6 = (uint)bVar3; } while (uVar6 < globs::nerpsfileGlobs.imageCount); } } else { *pcVar9 = cVar1; } pcVar9 = pcVar9 + 1; text = text + 1; cVar1 = *text; } } else { if (cVar1 == '#') { cVar1 = text[1]; text = text + 1; bVar2 = false; pcVar9 = keyBuff; while ((cVar1 != '\0' && (!bVar2))) { if (cVar1 == '#') { *pcVar9 = '\0'; bVar3 = 0; if (globs::nerpsfileGlobs.soundCount != 0) { uVar6 = 0; do { iVar5 = std::_stricmp(globs::nerpsfileGlobs.soundList[uVar6].key,keyBuff); if (iVar5 == 0) { uVar6 = (uint)bVar3; sound3DHandle = globs::nerpsfileGlobs.soundList[uVar6].sound3DHandle; if (globs::nerpsfileGlobs.lineIndexArray_7c[0] != uVar6) { globs::nerpsfileGlobs.lineIndexArray_7c[0] = uVar6; fVar11 = snd::Sound3D_GetSamplePlayTime(sound3DHandle); newTimerValue = (float)(fVar11 * (float10)globs::nerps::nerpsMessageTimerValues[0] + (float10)globs::nerps::nerpsMessageTimerValues[1]); BVar4 = snd::SFX_IsSoundOn(); if (BVar4 != 0) { snd::SFX_StopGlobalSample(); fVar11 = snd::Sound3D_GetSamplePlayTime(sound3DHandle); snd::SFX_SetGlobalSampleDurationIfLE0_AndNullifyHandle ((float)(fVar11 * (float10)25.0)); snd::Sound3D_Play2(Sound3DPlay_Normal,NULL,sound3DHandle,FALSE,NULL); globs::nerps::nerpsUnkSampleIndex = sound3DHandle; tflags = funcs::NERPFunc__GetTutorialFlags(NULL); if (tflags == TUTORIAL_NONE) { front::Advisor_Start(Advisor_TalkInGame,TRUE); globs::nerpsfileGlobs.AdvisorTalkingMode = TRUE; } } } break; } bVar3 += 1; uVar6 = (uint)bVar3; } while (uVar6 < globs::nerpsfileGlobs.soundCount); } bVar2 = true; } else { *pcVar9 = cVar1; } pcVar9 = pcVar9 + 1; text = text + 1; cVar1 = *text; } } else { if (out_buffer != NULL) { *(char *)local_164.x = cVar1; local_164.x = (float)((int)local_164.x + 1); } text = text + 1; } } cVar1 = *text; } if (out_buffer != NULL) { *(char *)local_164.x = '\0'; } if ((char)local_15c != '\0') { ppIVar10 = images; uVar7 = local_15c & 0xff; iVar5 = 0; uVar6 = uVar7; do { local_15c = globs::nerps::nerpsIconWidth * uVar7; local_164.y = globs::nerps::nerpsIconPos.y; uStack344 = 0; local_164.x = (float)(ulonglong)(uint)(globs::nerps::nerpsIconSpace * iVar5) + (globs::nerps::nerpsIconPos.x - (float)(ulonglong)local_15c); lego::image::Image_DisplayScaled(*ppIVar10,NULL,&local_164,NULL); iVar5 += 1; ppIVar10 = ppIVar10 + 1; uVar6 -= 1; } while (uVar6 != 0); } } if (updateTimer != 0) { globs::nerpsruntimeGlobs.messageTimer = newTimerValue; } return; } void __cdecl lego::nerps::NERPs_InitBlockPointersTable(Lego_Level *level) { BlockPointer *blockPointer; int iVar1; uint blockPointerID; uint x; BlockPointer **ppBVar2; uint y; x = 0; ppBVar2 = level->blockPointers; for (iVar1 = 0x37; iVar1 != 0; iVar1 += -1) { *ppBVar2 = NULL; ppBVar2 = ppBVar2 + 1; } if (level->width != 0) { do { y = 0; if (level->height != 0) { do { if (level->blocks[y * level->width + x].blockpointer != 0) { blockPointer = (BlockPointer *)io::Mem_Alloc(0xc); blockPointerID = (uint)level->blocks[y * level->width + x].blockpointer; (blockPointer->blockPos).x = x; (blockPointer->blockPos).y = y; blockPointer->next = level->blockPointers[blockPointerID]; level->blockPointers[blockPointerID] = blockPointer; level->blocks[y * level->width + x].blockpointer = 0; } y += 1; } while (y < level->height); } x += 1; } while (x < level->width); } return; } BlockPointer * __cdecl lego::nerps::NERPs_GetBlockPointer(Lego_Level *level,int blockPointerID) { if (((-1 < blockPointerID) && (blockPointerID < 0x37)) && (level->blockPointers[blockPointerID] != NULL)) { return level->blockPointers[blockPointerID]; } return NULL; } void __cdecl lego::nerps::NERPs_FreeBlockPointers(void) { BlockPointer *pBVar1; Lego_Level *level; BlockPointer *blockPointer; BlockPointer **pBlockPointer; int blockPointerID; level = lrr::Lego_GetLevel(); blockPointerID = 0; pBlockPointer = level->blockPointers; do { blockPointer = NERPs_GetBlockPointer(level,blockPointerID); while (blockPointer != NULL) { pBVar1 = blockPointer->next; io::Mem_Free(blockPointer); blockPointer = pBVar1; } *pBlockPointer = NULL; blockPointerID += 1; pBlockPointer = pBlockPointer + 1; } while (blockPointerID < 0x37); return; } void __cdecl lego::nerps::NERPsRuntime_EnumerateBlockPointers (int blockPointerID,NERPsBlockPointerCallback callback,void *data) { Lego_Level *level; BlockPointer *blockPointer; BOOL BVar1; level = lrr::Lego_GetLevel(); blockPointer = NERPs_GetBlockPointer(level,blockPointerID); while ((blockPointer != NULL && (BVar1 = (*callback)(blockPointer,(blockPointer->blockPos).x,(blockPointer->blockPos).y, data), BVar1 != 0))) { blockPointer = blockPointer->next; } return; } BOOL __cdecl lego::nerps::NERPsRuntime_TutorialActionCallback (BlockPointer *unused,uint bx,uint by,SearchNERPsTutorialAction *search) { Lego_Level *level; BOOL BVar1; LegoObject_ID objID; LegoObject *pLVar2; int iVar3; SearchNERPsTutorialAction *pSVar4; Point2I blockPos; Point2I camBlockPos; Vector3F local_38; SearchNERPsTutorialAction search2; level = lrr::Lego_GetLevel(); blockPos.x = bx; blockPos.y = by; switch(search->action) { case NERPS_TUTORIAL_GETBLOCKISGROUND: search->result = search->result + (level->blocks[level->width * by + bx].flags1 & BLOCK1_FLOOR); return TRUE; case NERPS_TUTORIAL_SETBLOCKISGROUND: BVar1 = 0; level = lrr::Lego_GetLevel(); game::Level_DestroyWall(level,bx,by,BVar1); return TRUE; case NERPS_TUTORIAL_GETBLOCKISPATH: BVar1 = game::Level_Block_IsPath(&blockPos); search->result = search->result + BVar1; return TRUE; case NERPS_TUTORIAL_SETBLOCKISPATH: iVar3 = level->width * by + bx; level->blocks[iVar3].flags1 = level->blocks[iVar3].flags1 & ~BLOCK1_RUBBLE_FULL; game::Level_Block_ClearRubbleLayer(&blockPos); game::Level_Block_SetPath(&blockPos); return TRUE; case NERPS_TUTORIAL_SETCAMERAGOTOTUTORIAL: lrr::Lego_Goto(NULL,&blockPos,TRUE); return TRUE; case NERPS_TUTORIAL_GETCAMERAATTUTORIAL: gfx::Container_GetPosition((globs::legoGlobs.cameraMain)->cont3,NULL,&local_38); lego::map::Map3D_WorldToBlockPos_NoZ (level->map,local_38.x,local_38.y,&camBlockPos.x,&camBlockPos.y); if ((blockPos.x == camBlockPos.x) && (blockPos.y == camBlockPos.y)) { search->result = 1; return TRUE; } break; case NERPS_TUTORIAL_SETROCKMONSTERATTUTORIAL: objID = lrr::Lego_GetEmergeCreatureID(); pLVar2 = game::LegoObject_TryGenerateRMonster (globs::legoGlobs.rockMonsterData + objID,LegoObject_RockMonster,objID, blockPos.x,blockPos.y); if (pLVar2 != NULL) { pLVar2->stats->PainThreshold = 60.0; return TRUE; } break; case NERPS_TUTORIAL_SETCONGREGATIONATTUTORIAL_START: ai::AITask_DoGoto_Congregate(&blockPos); return TRUE; case NERPS_TUTORIAL_SETCONGREGATIONATTUTORIAL_STOP: ai::AITask_StopGoto_Congregate(&blockPos); return TRUE; case NERPS_TUTORIAL_GETUNITATBLOCK: pSVar4 = &search2; for (iVar3 = 0xb; iVar3 != 0; iVar3 += -1) { pSVar4->action = NERPS_TUTORIAL_NONE; pSVar4 = (SearchNERPsTutorialAction *)&pSVar4->blockPointerIdx; } search2.blockPos.x = bx; search2.blockPos.y = by; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_CallbackCheck_FUN_00457320,&search2); search->result = search->result + search2.result; return TRUE; case NERPS_TUTORIAL_SETTUTORIALPOINTER_UNK: pSVar4 = &search2; for (iVar3 = 0xb; iVar3 != 0; iVar3 += -1) { pSVar4->action = NERPS_TUTORIAL_NONE; pSVar4 = (SearchNERPsTutorialAction *)&pSVar4->blockPointerIdx; } search2.blockPos.x = bx; search2.blockPos.y = by; search2.fieldBool_1c = TRUE; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_Callback_SetBool3f8IfAtBlockPos_FUN_00457390,&search2); return TRUE; case NERPS_TUTORIAL_MAKESOMEONEPICKUP: pSVar4 = &search2; for (iVar3 = 0xb; iVar3 != 0; iVar3 += -1) { pSVar4->action = NERPS_TUTORIAL_NONE; pSVar4 = (SearchNERPsTutorialAction *)&pSVar4->blockPointerIdx; } search2.blockPos.x = bx; search2.blockPos.y = by; search2.fieldBool_20 = 1; search2.int_28 = 2; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_CallbackCheck_FUN_00457320,&search2); pLVar2 = search2.object_24; if (search2.result != 0) { search2.int_28 = 6; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_CallbackCheck_FUN_00457320,&search2); if (search2.result != 0) { game::LegoObject_TryCollectObject(pLVar2,search2.object_24); return TRUE; } } break; case NERPS_TUTORIAL_GETMONSTERATTUTORIAL: pSVar4 = &search2; for (iVar3 = 0xb; iVar3 != 0; iVar3 += -1) { pSVar4->action = NERPS_TUTORIAL_NONE; pSVar4 = (SearchNERPsTutorialAction *)&pSVar4->blockPointerIdx; } search2.blockPos.x = bx; search2.blockPos.y = by; game::LegoObject_RunThroughListsSkipUpgradeParts (NERPs_LiveObject_CallbackCheck_FUN_00457320,&search2); search->result = search->result + search2.result; } return TRUE; } BOOL __cdecl lego::nerps::NERPs_LiveObject_CallbackCheck_FUN_00457320 (LegoObject *liveObj,SearchNERPsTutorialAction *search) { int bx; int by; if (liveObj != NULL) { game::LegoObject_GetBlockPos(liveObj,&bx,&by); if ((bx == (search->blockPos).x) && (by == (search->blockPos).y)) { if ((search->fieldBool_20 != 0) && (liveObj->type == search->int_28)) { search->object_24 = liveObj; search->result = TRUE; return TRUE; } search->result = search->result + 1; } } return 0; } BOOL __cdecl lego::nerps::NERPs_LiveObject_Callback_SetBool3f8IfAtBlockPos_FUN_00457390 (LegoObject *liveObj,SearchNERPsTutorialAction *search) { int bx; int by; if (liveObj != NULL) { game::LegoObject_GetBlockPos(liveObj,&bx,&by); if ((bx == (search->blockPos).x) && (by == (search->blockPos).y)) { liveObj->bool_3f8 = TRUE; return 0; } liveObj->bool_3f8 = FALSE; } return 0; } int __cdecl lego::nerps::funcs::NERPFunc__MakeSomeoneOnThisBlockPickUpSomethingOnThisBlock(int *stack) { SearchNERPsTutorialAction search; search.result = 0; search.blockPointerIdx = *stack; search.action = NERPS_TUTORIAL_MAKESOMEONEPICKUP; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } void __cdecl lego::nerps::NERPsRuntime_SetTutorialPointer(int blockPointerIdx,int unkMode0_1) { Lego_Level *level; BlockPointer *blockPointer; BOOL BVar1; int bx; int by; SearchNERPsTutorialAction search; level = lrr::Lego_GetLevel(); for (blockPointer = NERPs_GetBlockPointer(level,blockPointerIdx); blockPointer != NULL; blockPointer = blockPointer->next) { if ((LegoObject *)unkMode0_1 == (LegoObject *)0x1) { level->blocks[level->width * (blockPointer->blockPos).y + (blockPointer->blockPos).x]. blockpointer = (byte)blockPointerIdx; search.blockPointerIdx = blockPointerIdx; search.result = 0; search.action = NERPS_TUTORIAL_SETTUTORIALPOINTER_UNK; NERPsRuntime_EnumerateBlockPointers (blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); } if ((LegoObject *)unkMode0_1 == NULL) { level->blocks[level->width * (blockPointer->blockPos).y + (blockPointer->blockPos).x]. blockpointer = 0; } } if ((globs::nerpsfileGlobs.RecordObjectPointer != 0) && (BVar1 = lrr::Lego_GetRecordObject (globs::nerpsfileGlobs.RecordObjectPointer - 1,(LegoObject **)&unkMode0_1), BVar1 != 0)) { game::LegoObject_GetBlockPos((LegoObject *)unkMode0_1,&bx,&by); search.blockPos.x = bx; search.blockPos.y = by; NERPs_LiveObject_Callback_SetBool3f8IfAtBlockPos_FUN_00457390((LegoObject *)unkMode0_1,&search); } return; } int __cdecl lego::nerps::funcs::NERPFunc__SetCongregationAtTutorial(int *stack) { SearchNERPsTutorialAction search; search.result = 0; search.blockPointerIdx = *stack; search.action = NERPS_TUTORIAL_SETCONGREGATIONATTUTORIAL_STOP - (stack[1] != 0); NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__SetRockMonsterAtTutorial(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_SETROCKMONSTERATTUTORIAL; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__SetCameraGotoTutorial(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_SETCAMERAGOTOTUTORIAL; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__GetCameraAtTutorial(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_GETCAMERAATTUTORIAL; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__GetTutorialBlockIsGround(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_GETBLOCKISGROUND; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__GetTutorialBlockIsPath(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_GETBLOCKISPATH; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__SetTutorialBlockIsGround(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_SETBLOCKISGROUND; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__SetTutorialBlockIsPath(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_SETBLOCKISPATH; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__GetUnitAtBlock(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_GETUNITATBLOCK; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } int __cdecl lego::nerps::funcs::NERPFunc__GetMonsterAtTutorial(int *stack) { SearchNERPsTutorialAction search; search.action = NERPS_TUTORIAL_GETMONSTERATTUTORIAL; search.blockPointerIdx = *stack; search.result = 0; NERPsRuntime_EnumerateBlockPointers (search.blockPointerIdx,globs::constant::c_NERPsRuntime_TutorialActionCallback,&search); return search.result; } void __cdecl lego::game::Objective_LoadObjectiveText (Config *config,char *gameName,char *levelName,Lego_Level *level,char *filename) { char cVar1; TextWindow *textWnd; uint uVar2; char *pcVar3; uint uVar4; char *pcVar5; int iVar6; int iVar7; char **ppcVar8; undefined4 *puVar9; TextWindow **ppTVar10; undefined4 *puVar11; char *pcVar12; bool bVar13; longlong lVar14; size_t _MaxCount; size_t local_cc8; int local_cc0; Area2F local_cbc; int local_cac; int local_ca8; Area2F local_ca4; char *local_c94; Area2F local_c90; char local_c80 [126]; char acStack3074 [1026]; undefined4 local_800 [256]; char local_400 [1024]; local_ca4.x = (level->objective).panelImagePosition.x - -60.0; local_c90.y = (level->objective).panelImagePosition.y - -220.0; local_ca4.y = (level->objective).panelImagePosition.y - -60.0; local_cbc.x = (level->objective).panelImagePosition.x - -40.0; local_cbc.y = (level->objective).panelImagePosition.y - -34.0; local_c90.width = 320.0; local_c90.height = 20.0; local_ca4.width = 390.0; local_cac = 0; local_ca4.height = 180.0; local_cbc.width = 422.0; local_cbc.height = 21.0; local_cc0 = 0; iVar6 = 0; local_ca8 = 0; local_c90.x = local_ca4.x; std::sprintf(globs::objectiveGlobs.filename,"%s",filename); if (globs::objectiveGlobs.textWindows[0] != NULL) { front::TextWindow_Remove(globs::objectiveGlobs.textWindows[0]); } if (globs::objectiveGlobs.pageTextWindows[0] != NULL) { front::TextWindow_Remove(globs::objectiveGlobs.pageTextWindows[0]); } if (globs::objectiveGlobs.pageTextWindows[1] != NULL) { front::TextWindow_Remove(globs::objectiveGlobs.pageTextWindows[1]); } if (globs::objectiveGlobs.pageTextWindows[2] != NULL) { front::TextWindow_Remove(globs::objectiveGlobs.pageTextWindows[2]); } if (globs::objectiveGlobs.beginTextWindow != NULL) { front::TextWindow_Remove(globs::objectiveGlobs.beginTextWindow); } ppTVar10 = globs::objectiveGlobs.textWindows; do { textWnd = front::TextWindow_Create(globs::legoGlobs.fontBriefingLo,&local_ca4,0x400); *ppTVar10 = textWnd; front::TextWindow_EnableCentering(textWnd,FALSE); ppTVar10 = ppTVar10 + 1; } while (ppTVar10 < globs::objectiveGlobs.pageTextWindows); globs::objectiveGlobs.beginTextWindow = front::TextWindow_Create(globs::legoGlobs.fontBriefingHi,&local_c90,0x400); globs::objectiveGlobs.hasBeginText = 0; globs::objectiveGlobs.file = io::File_Open(globs::objectiveGlobs.filename,"r"); ppcVar8 = globs::objectiveGlobs.messages; do { if (*ppcVar8 != NULL) { io::Mem_Free(*ppcVar8); *ppcVar8 = NULL; } ppcVar8[0x6c] = NULL; ppcVar8[0x68] = NULL; ppcVar8[100] = NULL; ppcVar8 = ppcVar8 + 1; } while (ppcVar8 < globs::objectiveGlobs.reserved1); if (globs::objectiveGlobs.file != NULL) { io::File_Seek(globs::objectiveGlobs.file,0,0); uVar4 = 0xffffffff; pcVar3 = levelName; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar1 != '\0'); uVar2 = 0; if (~uVar4 != 1) { do { if (iVar6 == 2) { local_c94 = levelName + uVar2; local_ca8 = 1; break; } if (levelName[uVar2] == ':') { iVar6 += 1; } uVar2 += 1; } while (uVar2 < ~uVar4 - 1); } pcVar3 = io::File_GetS(acStack3074 + 2,0x400,globs::objectiveGlobs.file); while (pcVar3 != NULL) { if (local_ca8 != 0) { uVar4 = 0xffffffff; pcVar3 = local_c94; do { pcVar5 = pcVar3; if (uVar4 == 0) break; uVar4 -= 1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar9 = (undefined4 *)(pcVar5 + -uVar4); puVar11 = local_800; for (uVar2 = uVar4 >> 2; uVar2 != 0; uVar2 -= 1) { *puVar11 = *puVar9; puVar9 = puVar9 + 1; puVar11 = puVar11 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar9; puVar9 = (undefined4 *)((int)puVar9 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } local_cc8 = std::sprintf(local_400,"[%s]",local_800); if (acStack3074[2] == '[') { local_cac = 0; local_cc0 = 0; } if (local_cac != 0) { uVar4 = 0xffffffff; uVar2 = 10; pcVar3 = acStack3074 + 2; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar1 != '\0'); _MaxCount = 10; iVar7 = 4; acStack3074[~uVar4] = '\0'; iVar6 = std::_strnicmp(acStack3074 + 2,"Objective:",_MaxCount); if (iVar6 == 0) { iVar7 = 0; } else { uVar2 = 0xb; iVar6 = std::_strnicmp(acStack3074 + 2,"Completion:",0xb); if (iVar6 == 0) { iVar7 = 1; } else { uVar2 = 8; iVar6 = std::_strnicmp(acStack3074 + 2,"Failure:",8); if (iVar6 == 0) { iVar7 = 2; } else { uVar2 = 0xf; iVar6 = std::_strnicmp(acStack3074 + 2,"CrystalFailure:",0xf); if (iVar6 == 0) { iVar7 = 3; } } } } if (iVar7 != 4) { uVar4 = 0xffffffff; pcVar3 = acStack3074 + 2; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar1 != '\0'); if (uVar2 < ~uVar4 - 1) { do { if ((acStack3074[uVar2 + 2] != ' ') && (acStack3074[uVar2 + 2] != '\t')) break; uVar4 = 0xffffffff; uVar2 += 1; pcVar3 = acStack3074 + 2; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar1 != '\0'); } while (uVar2 < ~uVar4 - 1); } bVar13 = false; pcVar3 = acStack3074 + 2; cVar1 = acStack3074[2]; while (cVar1 != '\0') { if ((bVar13) && ((*pcVar3 == 'a' || (*pcVar3 == 'n')))) { pcVar3[-1] = ' '; if (*pcVar3 == 'a') { uVar4 = globs::objectiveGlobs.pageCounts[iVar7]; *pcVar3 = '\a'; globs::objectiveGlobs.pageCounts[iVar7] = uVar4 + 1; bVar13 = false; } else { *pcVar3 = '\n'; bVar13 = false; } } else { bVar13 = *pcVar3 == '\\'; } pcVar5 = pcVar3 + 1; pcVar3 = pcVar3 + 1; cVar1 = *pcVar5; } front::TextWindow_PrintF (globs::objectiveGlobs.textWindows[iVar7],"%s",acStack3074 + uVar2 + 2); pcVar3 = util::Util_StrCpy(acStack3074 + uVar2 + 2); globs::objectiveGlobs.messages[iVar7] = pcVar3; } } if (local_cc0 != 0) { uVar4 = 0xffffffff; pcVar3 = acStack3074 + 2; pcVar5 = acStack3074 + 2; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); acStack3074[~uVar4] = '\0'; front::TextWindow_PrintF(globs::objectiveGlobs.beginTextWindow,"%s",pcVar3); local_cc0 = 0; globs::objectiveGlobs.hasBeginText = TRUE; } iVar6 = std::_strnicmp(local_400,acStack3074 + 2,local_cc8); if (iVar6 == 0) { local_cac = 1; } iVar6 = std::_strnicmp(acStack3074 + 2,"[BEGIN]",7); if (iVar6 == 0) { local_cc0 = 1; } } pcVar3 = io::File_GetS(acStack3074 + 2,0x400,globs::objectiveGlobs.file); } io::File_Close(globs::objectiveGlobs.file); } pcVar3 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MissionBriefingText",0); pcVar3 = cfg::Config_GetTempStringValue(config,pcVar3); if (pcVar3 != NULL) { uVar4 = lego::image::Font_GetStringWidth(globs::legoGlobs.fontBriefingHi,pcVar3); local_cbc.x = (local_cbc.width * 0.5 - (float)(uVar4 >> 1)) + local_cbc.x; local_cbc.width = (float)(ulonglong)uVar4; globs::objectiveGlobs.pageTextWindows[0] = front::TextWindow_Create(globs::legoGlobs.fontBriefingHi,&local_cbc,0x400); if (globs::objectiveGlobs.pageTextWindows[0] != NULL) { iVar6 = -1; uVar4 = 0; pcVar5 = pcVar3; do { if (iVar6 == 0) break; iVar6 += -1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); if (iVar6 != -1) { pcVar5 = pcVar3; do { cVar1 = *pcVar5; if (cVar1 == '_') { cVar1 = ' '; } pcVar5[(int)(local_c80 + -(int)pcVar3)] = cVar1; uVar4 += 1; uVar2 = 0xffffffff; pcVar5 = pcVar5 + 1; pcVar12 = pcVar3; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar12; pcVar12 = pcVar12 + 1; } while (cVar1 != '\0'); } while (uVar4 < ~uVar2); } front::TextWindow_Clear(globs::objectiveGlobs.pageTextWindows[0]); front::TextWindow_PrintF(globs::objectiveGlobs.pageTextWindows[0],"%s",local_c80); } } pcVar3 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MissionCompletedText",0); pcVar3 = cfg::Config_GetTempStringValue(config,pcVar3); if (pcVar3 != NULL) { uVar4 = lego::image::Font_GetStringWidth(globs::legoGlobs.fontBriefingHi,pcVar3); local_cbc.x = (local_cbc.width * 0.5 - (float)(uVar4 >> 1)) + local_cbc.x; local_cbc.width = (float)(ulonglong)uVar4; globs::objectiveGlobs.pageTextWindows[1] = front::TextWindow_Create(globs::legoGlobs.fontBriefingHi,&local_cbc,0x400); if (globs::objectiveGlobs.pageTextWindows[1] != NULL) { iVar6 = -1; uVar4 = 0; pcVar5 = pcVar3; do { if (iVar6 == 0) break; iVar6 += -1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); if (iVar6 != -1) { pcVar5 = pcVar3; do { cVar1 = *pcVar5; if (cVar1 == '_') { cVar1 = ' '; } pcVar5[(int)(local_c80 + -(int)pcVar3)] = cVar1; uVar4 += 1; uVar2 = 0xffffffff; pcVar5 = pcVar5 + 1; pcVar12 = pcVar3; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar12; pcVar12 = pcVar12 + 1; } while (cVar1 != '\0'); } while (uVar4 < ~uVar2); } front::TextWindow_Clear(globs::objectiveGlobs.pageTextWindows[1]); front::TextWindow_PrintF(globs::objectiveGlobs.pageTextWindows[1],"%s",local_c80); } } pcVar3 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,"Main","MissionFailedText",0); pcVar3 = cfg::Config_GetTempStringValue(config,pcVar3); if (pcVar3 != NULL) { uVar4 = lego::image::Font_GetStringWidth(globs::legoGlobs.fontBriefingHi,pcVar3); local_cbc.x = (local_cbc.width * 0.5 - (float)(uVar4 >> 1)) + local_cbc.x; local_cbc.width = (float)(ulonglong)uVar4; globs::objectiveGlobs.pageTextWindows[2] = front::TextWindow_Create(globs::legoGlobs.fontBriefingHi,&local_cbc,0x400); if (globs::objectiveGlobs.pageTextWindows[2] != NULL) { iVar6 = -1; uVar4 = 0; pcVar5 = pcVar3; do { if (iVar6 == 0) break; iVar6 += -1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); if (iVar6 != -1) { pcVar5 = pcVar3; do { cVar1 = *pcVar5; if (cVar1 == '_') { cVar1 = ' '; } pcVar5[(int)(local_c80 + -(int)pcVar3)] = cVar1; uVar4 += 1; uVar2 = 0xffffffff; pcVar5 = pcVar5 + 1; pcVar12 = pcVar3; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar12; pcVar12 = pcVar12 + 1; } while (cVar1 != '\0'); } while (uVar4 < ~uVar2); } front::TextWindow_Clear(globs::objectiveGlobs.pageTextWindows[2]); front::TextWindow_PrintF(globs::objectiveGlobs.pageTextWindows[2],"%s",local_c80); } } if (globs::objectiveGlobs.hasBeginText == 0) { local_ca4.height = local_ca4.height + local_c90.height; ppTVar10 = globs::objectiveGlobs.textWindows; do { lVar14 = __ftol((float10)local_ca4.height); uVar4 = (uint)lVar14; lVar14 = __ftol((float10)local_ca4.width); front::TextWindow_ChangeSize(*ppTVar10,(uint)lVar14,uVar4); ppTVar10 = ppTVar10 + 1; } while (ppTVar10 < globs::objectiveGlobs.textWindows + 3); } return; } void __cdecl lego::game::Objective_LoadLevel (Config *config,char *gameName,char *levelName,Lego_Level *level,uint screenWidth, uint screenHeight) { ObjectiveData *pOVar1; char *pcVar2; BoolTri BVar3; Image *pIVar4; int iVar5; uint uVar6; uint uVar7; uint uVar8; char *pcVar9; BOOL BVar10; int iVar11; ObjectiveData *pOVar12; LegoObject_ID local_500; LegoObject_Type local_4fc; Point2I blockPos; char *stringParts [60]; char buff [1024]; pOVar1 = &level->objective; pOVar12 = pOVar1; for (iVar11 = 0x15; iVar11 != 0; iVar11 += -1) { pOVar12->panelImage = NULL; pOVar12 = (ObjectiveData *)&pOVar12->panelImagePosition; } globs::objectiveGlobs.flags = OBJECTIVE_GLOB_FLAG_NONE; globs::objectiveGlobs.objectiveSwitch = TRUE; pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"DontShowObjectiveAdvisor",0); BVar3 = cfg::Config_GetBoolValue(config,pcVar2); if (BVar3 != BOOL3_TRUE) { globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_SHOWBRIEFINGADVISOR; } pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"DontShowObjectiveAcheiveAdvisor",0); BVar3 = cfg::Config_GetBoolValue(config,pcVar2); if (BVar3 != BOOL3_TRUE) { globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_SHOWACHIEVEDADVISOR; } pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"DontShowObjectiveFailedAdvisor",0); BVar3 = cfg::Config_GetBoolValue(config,pcVar2); if (BVar3 != BOOL3_TRUE) { globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_SHOWFAILEDADVISOR; } std::sprintf(buff,"ObjectiveImage%ix%i",screenWidth,screenHeight); pcVar2 = cfg::Config_BuildStringID(gameName,levelName,buff,0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 != NULL) { pcVar2 = util::Util_StrCpy(pcVar2); iVar11 = util::Util_Tokenise(pcVar2,stringParts,","); if (pOVar1->panelImage != NULL) { lego::image::Image_Remove(pOVar1->panelImage); } pIVar4 = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); pOVar1->panelImage = pIVar4; if (pIVar4 != NULL) { lego::image::Image_SetPenZeroTrans(pIVar4); } iVar5 = std::atoi(stringParts[1]); (level->objective).panelImagePosition.x = (float)iVar5; iVar5 = std::atoi(stringParts[2]); (level->objective).panelImagePosition.y = (float)iVar5; if ((iVar11 == 6) && (pOVar1->panelImage != NULL)) { // Optional string parts: "filename,x,y[,r,g,b]" uVar6 = std::atoi(stringParts[3]); uVar7 = std::atoi(stringParts[4]); uVar8 = std::atoi(stringParts[5]); lego::image::Image_SetupTrans (pOVar1->panelImage,(float)(ulonglong)(uVar6 / 0xff), (float)(ulonglong)(uVar7 / 0xff),(float)(ulonglong)(uVar8 / 0xff), (float)(ulonglong)(uVar6 / 0xff),(float)(ulonglong)(uVar7 / 0xff), (float)(ulonglong)(uVar8 / 0xff)); } io::Mem_Free(pcVar2); } std::sprintf(buff,"ObjectiveAcheivedImage%ix%i",screenWidth,screenHeight); pcVar2 = cfg::Config_BuildStringID(gameName,levelName,buff,0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 != NULL) { pcVar2 = util::Util_StrCpy(pcVar2); iVar11 = util::Util_Tokenise(pcVar2,stringParts,","); pIVar4 = (level->objective).achievedImage; if (pIVar4 != NULL) { lego::image::Image_Remove(pIVar4); } pIVar4 = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); (level->objective).achievedImage = pIVar4; if (pIVar4 != NULL) { lego::image::Image_SetPenZeroTrans(pIVar4); } iVar5 = std::atoi(stringParts[1]); (level->objective).achievedImagePosition.x = (float)iVar5; iVar5 = std::atoi(stringParts[2]); (level->objective).achievedImagePosition.y = (float)iVar5; if ((iVar11 == 6) && ((level->objective).achievedImage != NULL)) { uVar6 = std::atoi(stringParts[3]); uVar7 = std::atoi(stringParts[4]); uVar8 = std::atoi(stringParts[5]); lego::image::Image_SetupTrans (pOVar1->panelImage,(float)(ulonglong)(uVar6 / 0xff), (float)(ulonglong)(uVar7 / 0xff),(float)(ulonglong)(uVar8 / 0xff), (float)(ulonglong)(uVar6 / 0xff),(float)(ulonglong)(uVar7 / 0xff), (float)(ulonglong)(uVar8 / 0xff)); } io::Mem_Free(pcVar2); } pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"ObjectiveAcheivedAVI",0); pcVar2 = cfg::Config_GetStringValue(config,pcVar2); if (pcVar2 != NULL) { iVar11 = util::Util_Tokenise(pcVar2,stringParts,","); pcVar9 = util::Util_StrCpy(stringParts[0]); (level->objective).achievedVideoName = pcVar9; if (iVar11 == 3) { // Optional string parts: "filename[,x,y]" iVar11 = std::atoi(stringParts[1]); (level->objective).achievedVideoPosition.x = (float)iVar11; iVar11 = std::atoi(stringParts[2]); (level->objective).achievedVideoPosition.y = (float)iVar11; io::Mem_Free(pcVar2); } else { (level->objective).noAchievedVideo = TRUE; io::Mem_Free(pcVar2); } } std::sprintf(buff,"ObjectiveFailedImage%ix%i",screenWidth,screenHeight); pcVar2 = cfg::Config_BuildStringID(gameName,levelName,buff,0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 != NULL) { pcVar2 = util::Util_StrCpy(pcVar2); util::Util_Tokenise(pcVar2,stringParts,","); pIVar4 = (level->objective).failedImage; if (pIVar4 != NULL) { lego::image::Image_Remove(pIVar4); } pIVar4 = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); (level->objective).failedImage = pIVar4; if (pIVar4 != NULL) { lego::image::Image_SetPenZeroTrans(pIVar4); } iVar11 = std::atoi(stringParts[1]); (level->objective).failedImagePosition.x = (float)iVar11; iVar11 = std::atoi(stringParts[2]); (level->objective).failedImagePosition.y = (float)iVar11; io::Mem_Free(pcVar2); } pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"CrystalObjective",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"CrystalObjective",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); } uVar6 = std::atoi(pcVar2); pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"OreObjective",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"OreObjective",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); } uVar7 = std::atoi(pcVar2); Objective_SetCryOreObjectives(level,uVar6,uVar7); pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"TimerObjective",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 != NULL) { pcVar2 = util::Util_StrCpy(pcVar2); util::Util_Tokenise(pcVar2,stringParts,":"); iVar11 = std::atoi(stringParts[0]); iVar5 = std::_stricmp(stringParts[1],"HitTimeFailObjective"); Objective_SetTimerObjective(level,(float)iVar11 * 25.0,(uint)(iVar5 == 0)); io::Mem_Free(pcVar2); } pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"ConstructionObjective",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if ((pcVar2 != NULL) && (BVar10 = lrr::Lego_GetObjectByName(pcVar2,&local_4fc,&local_500,NULL), BVar10 != 0)) { Objective_SetConstructionObjective(level,local_4fc,local_500); } pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"BlockObjective",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 != NULL) { pcVar2 = util::Util_StrCpy(pcVar2); util::Util_Tokenise(pcVar2,stringParts,","); blockPos.x = std::atoi(stringParts[0]); blockPos.y = std::atoi(stringParts[1]); Objective_SetBlockObjective(level,&blockPos); io::Mem_Free(pcVar2); } pcVar2 = cfg::Config_BuildStringID(gameName,levelName,"ObjectiveText",0); pcVar2 = cfg::Config_GetTempStringValue(config,pcVar2); if (pcVar2 != NULL) { Objective_LoadObjectiveText(config,gameName,levelName,level,pcVar2); } if (globs::objectiveGlobs.flags == OBJECTIVE_GLOB_FLAG_NONE) { globs::objectiveGlobs.flags = OBJECTIVE_GLOB_FLAG_SHOWBRIEFINGADVISOR; } return; } void __cdecl lego::game::Objective_SetCryOreObjectives(Lego_Level *level,uint crystals,uint ore) { if (crystals != 0) { globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_CRYSTAL; (level->objective).crystals = crystals; } if (ore != 0) { globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_ORE; (level->objective).ore = ore; } return; } void __cdecl lego::game::Objective_SetBlockObjective(Lego_Level *level,Point2I *blockPos) { globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_BLOCK; (level->objective).blockPos.x = blockPos->x; (level->objective).blockPos.y = blockPos->y; return; } void __cdecl lego::game::Objective_SetTimerObjective(Lego_Level *level,float timer,BOOL hitTimeFail) { globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_TIMER; (level->objective).timer = timer; if (hitTimeFail != 0) { // This has to be a bug, or a lazy workaround for bugs with the original flag. globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_SHOWACHIEVEDADVISOR; } return; } void __cdecl lego::game::Objective_SetConstructionObjective (Lego_Level *level,LegoObject_Type objType,LegoObject_ID objID) { globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_CONSTRUCTION; (level->objective).constructionType = objType; (level->objective).constructionID = objID; return; } BOOL __cdecl lego::game::Objective_IsObjectiveAchieved(void) { return globs::objectiveGlobs.achieved; } void __cdecl lego::game::Objective_SetEndTeleportEnabled(BOOL on) { globs::objectiveGlobs.endTeleportEnabled = on; return; } void __cdecl lego::game::Objective_SetStatus(LevelStatus status) { Lego_Level *level; TutorialFlags tutFlags; char *sfxUnderscore; char *sfxLevelName; uint teleFlags; char *sfxTypeName; char buff [256]; bool levelEnding; bool levelSpecificSFX; level = lrr::Lego_GetLevel(); sfxTypeName = NULL; levelEnding = true; levelSpecificSFX = true; tutFlags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (tutFlags == TUTORIAL_NONE) { globs::legoGlobs.flags2 |= GAME2_INMENU; } globs::objectiveGlobs.currentPages[0] = 0; globs::objectiveGlobs.currentPages[1] = 0; globs::objectiveGlobs.currentPages[2] = 0; globs::objectiveGlobs.currentPages[3] = 0; if ((globs::objectiveGlobs.flags & (OBJECTIVE_GLOB_FLAG_BRIEFING|OBJECTIVE_GLOB_FLAG_COMPLETED|OBJECTIVE_GLOB_FLAG_FAILED)) != OBJECTIVE_GLOB_FLAG_NONE) { globs::objectiveGlobs.currentPages[0] = 0; globs::objectiveGlobs.currentPages[1] = 0; globs::objectiveGlobs.currentPages[2] = 0; globs::objectiveGlobs.currentPages[3] = 0; return; } if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_CRYSTAL) != OBJECTIVE_GLOB_FLAG_NONE) { globs::objectiveGlobs.currentPages[0] = 0; globs::objectiveGlobs.currentPages[1] = 0; globs::objectiveGlobs.currentPages[2] = 0; globs::objectiveGlobs.currentPages[3] = 0; return; } while ((((globs::INPUT.mslb != 0 || (globs::INPUT.msrb != 0)) || (globs::INPUT.mslbheld != 0)) || (globs::INPUT.lClicked != 0))) { globs::INPUT.lClicked = FALSE; main::Main_LoopUpdate(TRUE); } if (status == LEVELSTATUS_INCOMPLETE) { sfxTypeName = ____EMPTYSTR__; globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_BRIEFING; levelEnding = false; level->status = LEVELSTATUS_INCOMPLETE; } else { if (status == LEVELSTATUS_COMPLETE) { globs::objectiveGlobs.achieved = TRUE; globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_COMPLETED; level->status = LEVELSTATUS_COMPLETE; sfxTypeName = "Acheived"; lego::image::Image_GetScreenshot (&globs::rewardGlobs.current.saveCaptureImage, globs::frontGlobs.saveImageBigSize.width,globs::frontGlobs.saveImageBigSize.height) ; globs::rewardGlobs.current.saveHasCapture = TRUE; } else { if (status == LEVELSTATUS_FAILED) { globs::objectiveGlobs.achieved = FALSE; globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_FAILED; sfxTypeName = "Failed"; level->status = LEVELSTATUS_FAILED; } else { if (status != LEVELSTATUS_FAILED_CRYSTALS) goto LAB_00458a9a; globs::objectiveGlobs.achieved = FALSE; globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_FAILED|OBJECTIVE_GLOB_FLAG_CRYSTAL; sfxTypeName = "FailedCrystals"; level->status = LEVELSTATUS_FAILED; levelSpecificSFX = false; } } lrr::Lego_UnkObjective_CompleteSub_FUN_004262f0(); reward::RewardQuota_CountUnits(); } LAB_00458a9a: globs::objectiveGlobs.flags |= OBJECTIVE_GLOB_FLAG_STATUSREADY; if (levelEnding) { // (globals::g_IsEndTeleportEnabled ? 2 : 4) teleFlags = (-(uint)(globs::objectiveGlobs.endTeleportEnabled != 0) & 0xfffffffe) + 4; unk::Teleporter_Start(TELEPORT_SERVIVE_VEHICLE,2,teleFlags); unk::Teleporter_Start(TELEPORT_SERVIVE_MINIFIGURE,2,teleFlags); unk::Teleporter_Start(TELEPORT_SERVIVE_BUILDING,2,teleFlags); unk::Teleporter_Start(TELEPORT_SERVIVE_ELECTRICFENCE,2,teleFlags); Construction_DisableCryOreDrop(TRUE); LegoObject_SetLevelEnding(TRUE); } if ((sfxTypeName != NULL) && (((byte)globs::legoGlobs.flags1 & GAME1_USESFX) != 0)) { if (levelSpecificSFX) { sfxLevelName = level->name; } else { sfxLevelName = ____EMPTYSTR__; } sfxUnderscore = "_"; if (!levelSpecificSFX) { sfxUnderscore = ____EMPTYSTR__; } std::sprintf(buff,"Stream_Objective%s%s%s",sfxTypeName,sfxUnderscore,sfxLevelName); if (globs::objectiveGlobs.soundName != NULL) { io::Mem_Free(globs::objectiveGlobs.soundName); } globs::objectiveGlobs.soundName = util::Util_StrCpy(buff); globs::objectiveGlobs.soundHandle = -1; globs::objectiveGlobs.showing = 0; return; } globs::objectiveGlobs.soundName = NULL; return; } void __cdecl lego::game::Objective_StopShowing(void) { TutorialFlags tflags; if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_BRIEFING) == OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_COMPLETED) == OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_FAILED) != OBJECTIVE_GLOB_FLAG_NONE) { globs::objectiveGlobs.flags &= ~(OBJECTIVE_GLOB_FLAG_FAILED|OBJECTIVE_GLOB_FLAG_CRYSTAL); } } else { globs::objectiveGlobs.flags &= ~OBJECTIVE_GLOB_FLAG_COMPLETED; } } else { nerps::funcs::NERPFunc__SetObjectiveSwitch(&globs::objectiveGlobs.objectiveSwitch); globs::objectiveGlobs.flags &= ~OBJECTIVE_GLOB_FLAG_BRIEFING; globs::objectiveGlobs.objectiveSwitch = FALSE; if ((globs::legoGlobs.flags2 & GAME2_MUSICREADY) != GAME2_NONE) { lrr::Lego_SetMusicPlaying(TRUE); globs::legoGlobs.flags2 &= ~GAME2_MUSICREADY; } } front::Advisor_End(); if (globs::objectiveGlobs.soundHandle != -1) { snd::Sound3D_Stream_Stop(FALSE); globs::objectiveGlobs.soundHandle = -1; } lrr::Lego_SetPaused(FALSE,FALSE); snd::SFX_SetQueueMode_AndFlush(FALSE); tflags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (tflags == TUTORIAL_NONE) { globs::legoGlobs.flags2 &= ~GAME2_INMENU; } return; } // Returns true if the mission briefing or failure/complete window is show. BOOL __cdecl lego::game::Objective_IsShowing(void) { // (OBJECTIVE_GLOB_FLAG_BRIEFING|OBJECTIVE_GLOB_FLAG_COMPLETED|OBJECTIVE_GLOB_FLAG_FAILED) // (0x1|0x2|0x4) if (((byte)globs::objectiveGlobs.flags & 7) == 0) { return 0; } return TRUE; } BOOL __cdecl lego::game::Objective_HandleKeys(BOOL nextKeyPressed,BOOL leftButtonReleased,BOOL *out_exitGame) { BOOL BVar1; LevelStatus status; status = LEVELSTATUS_FAILED_OTHER; if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_BRIEFING) == OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_COMPLETED) == OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_FAILED) != OBJECTIVE_GLOB_FLAG_NONE) { status = (LevelStatus)((byte)(globs::objectiveGlobs.flags >> 8) & 1 | 2); } } else { status = LEVELSTATUS_COMPLETE; } } else { status = LEVELSTATUS_INCOMPLETE; } *out_exitGame = FALSE; if (((nextKeyPressed != 0) || (leftButtonReleased != 0)) && (globs::objectiveGlobs.currentPages[status] == globs::objectiveGlobs.pageCounts[status])) { if (((globs::INPUT.msx < 130) || ((int)((globs::legoGlobs.RepeatButtonImage)->width + 130) <= globs::INPUT.msx)) || ((globs::INPUT.msy < 315 || ((int)((globs::legoGlobs.RepeatButtonImage)->height + 315) <= globs::INPUT.msy)))) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_BRIEFING) == OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & (OBJECTIVE_GLOB_FLAG_COMPLETED|OBJECTIVE_GLOB_FLAG_FAILED)) != OBJECTIVE_GLOB_FLAG_NONE) { BVar1 = unk::Teleporter_ServiceAll (TELEPORT_SERVIVE_VEHICLE|TELEPORT_SERVIVE_MINIFIGURE| TELEPORT_SERVIVE_BUILDING|TELEPORT_SERVIVE_ELECTRICFENCE); if (BVar1 != 0) { Objective_StopShowing(); BVar1 = lrr::Lego_EndLevel(); *out_exitGame = (uint)(BVar1 == 0); } } } else { Objective_StopShowing(); lrr::Lego_SetMenuNextPosition(NULL); lrr::Lego_SetMenuPreviousPosition(NULL); lrr::Lego_SetPaused(FALSE,FALSE); input::Input_SetCursorPos ((int)globs::mainGlobs.appWidth / 2,(int)globs::mainGlobs.appHeight / 2); BVar1 = front::Bubble_GetObjectUIsAlwaysVisible(); if (BVar1 != 0) { front::Bubble_ToggleObjectUIsAlwaysVisible(); } } } } if (status == LEVELSTATUS_FAILED_OTHER) goto LAB_00458e8c; if (globs::objectiveGlobs.currentPages[status] < globs::objectiveGlobs.pageCounts[status]) { if (((globs::INPUT.msx < 470) || ((int)((globs::legoGlobs.NextButtonImage)->width + 470) <= globs::INPUT.msx)) || ((globs::INPUT.msy < 315 || ((int)((globs::legoGlobs.NextButtonImage)->height + 315) <= globs::INPUT.msy)))) { LAB_00458e07: if (nextKeyPressed == 0) goto LAB_00458e20; if (leftButtonReleased != 0) goto LAB_00458e0f; } else { front::ToolTip_Activate(ToolTip_More); if (leftButtonReleased == 0) goto LAB_00458e07; LAB_00458e0f: lrr::Lego_SetPointerSFX(PointerSFX_Okay); } globs::objectiveGlobs.currentPages[status] = globs::objectiveGlobs.currentPages[status] + 1; } LAB_00458e20: if ((((globs::objectiveGlobs.currentPages[status] != 0) && (129 < globs::INPUT.msx)) && (globs::INPUT.msx < (int)((globs::legoGlobs.RepeatButtonImage)->width + 130))) && ((314 < globs::INPUT.msy && (globs::INPUT.msy < (int)((globs::legoGlobs.RepeatButtonImage)->height + 315))))) { front::ToolTip_Activate(ToolTip_Back); if (leftButtonReleased != 0) { lrr::Lego_SetPointerSFX(PointerSFX_Okay); globs::objectiveGlobs.currentPages[status] = globs::objectiveGlobs.currentPages[status] - 1; } } LAB_00458e8c: BVar1 = Objective_IsShowing(); return BVar1; } void __cdecl lego::game::Objective_Update (TextWindow *textWnd,Lego_Level *level,float elapsedGame,float elapsedAbs) { Image *image; bool bVar1; bool bVar2; BOOL BVar3; BOOL BVar4; float10 fVar5; Point2F *pPVar6; int local_10; Point2F local_c; int local_4; TextWindow *textWnd_00; bVar1 = false; bVar2 = false; BVar4 = 0; local_c.x = 0.0; if (PROGRAMMER_MODE_3 < globs::mainGlobs.programmerLevel) { Objective_StopShowing(); } if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_BRIEFING) == OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_COMPLETED) == OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_FAILED) == OBJECTIVE_GLOB_FLAG_NONE) { BVar3 = Objective_CheckCompleted(level,&local_4,elapsedGame); if (BVar3 == 0) { reward::RewardQuota_UpdateTimers(elapsedGame); } else { if (local_4 == 0) { Objective_SetStatus(LEVELSTATUS_FAILED); } else { Objective_SetStatus(LEVELSTATUS_COMPLETE); } } } else { BVar3 = unk::Teleporter_ServiceAll (TELEPORT_SERVIVE_VEHICLE|TELEPORT_SERVIVE_MINIFIGURE| TELEPORT_SERVIVE_BUILDING|TELEPORT_SERVIVE_ELECTRICFENCE); if (BVar3 != 0) { local_10 = 2; save::ObjectRecall_Save_CreateNewObjectRecall(); if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_CRYSTAL) != OBJECTIVE_GLOB_FLAG_NONE) { local_10 = 3; } lrr::Lego_SetPaused(FALSE,TRUE); bVar2 = true; if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_STATUSREADY) != OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_SHOWFAILEDADVISOR) != OBJECTIVE_GLOB_FLAG_NONE) { front::Advisor_Start(Advisor_Objective,TRUE); } globs::objectiveGlobs.flags &= ~OBJECTIVE_GLOB_FLAG_STATUSREADY; } front::Text_DisplayMessage(Text_SpaceToContinue,FALSE,FALSE); BVar4 = 1; bVar1 = true; } } } else { BVar3 = unk::Teleporter_ServiceAll (TELEPORT_SERVIVE_VEHICLE|TELEPORT_SERVIVE_MINIFIGURE| TELEPORT_SERVIVE_BUILDING|TELEPORT_SERVIVE_ELECTRICFENCE); if (BVar3 != 0) { bVar1 = true; lrr::Lego_SetPaused(FALSE,TRUE); save::ObjectRecall_Save_CopyToNewObjectRecallData(); if ((level->objective).achievedVideoPlayed == 0) { if ((level->objective).noAchievedVideo == 0) { pPVar6 = &(level->objective).achievedVideoPosition; } else { pPVar6 = NULL; } lrr::Lego_PlayMovie_old((level->objective).achievedVideoName,pPVar6); (level->objective).achievedVideoPlayed = TRUE; } local_10 = TRUE; bVar2 = true; front::Text_DisplayMessage(Text_SpaceToContinue,FALSE,FALSE); if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_STATUSREADY) != OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_SHOWACHIEVEDADVISOR) != OBJECTIVE_GLOB_FLAG_NONE) { front::Advisor_Start(Advisor_Objective,TRUE); } globs::objectiveGlobs.flags &= ~OBJECTIVE_GLOB_FLAG_STATUSREADY; } BVar4 = TRUE; } } } else { BVar4 = TRUE; lrr::Lego_SetPaused(FALSE,TRUE); local_10 = 0; bVar2 = true; if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_STATUSREADY) != OBJECTIVE_GLOB_FLAG_NONE) { if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_SHOWBRIEFINGADVISOR) != OBJECTIVE_GLOB_FLAG_NONE) { front::Advisor_Start(Advisor_Objective,TRUE); } globs::objectiveGlobs.flags &= ~OBJECTIVE_GLOB_FLAG_STATUSREADY; } // set to TRUE when (objectiveGlobs.flags & OBJECTIVE_FLAG_BRIEFING) local_c.x = 1.401298e-45; front::Text_DisplayMessage(Text_SpaceToContinue,FALSE,FALSE); } if ((globs::objectiveGlobs.soundHandle != -1) && (globs::objectiveGlobs.soundTimer = globs::objectiveGlobs.soundTimer - elapsedAbs, (ushort)((ushort)(globs::objectiveGlobs.soundTimer < 0.0) << 8 | (ushort)(globs::objectiveGlobs.soundTimer == 0.0) << 0xe) != 0)) { front::Advisor_End(); globs::objectiveGlobs.soundHandle = -1; } if (((bVar1) && ((globs::legoGlobs.flags2 & GAME2_MUSICREADY) == GAME2_NONE)) && (((byte)globs::legoGlobs.flags1 & GAME1_MUSICPLAYING) != 0)) { globs::legoGlobs.flags2 |= GAME2_MUSICREADY; lrr::Lego_SetMusicPlaying(FALSE); } if ((globs::objectiveGlobs.showing != 0) && (globs::objectiveGlobs.soundName != NULL)) { BVar3 = snd::SFX_GetType(globs::objectiveGlobs.soundName,(SFX_ID *)&elapsedAbs); if (BVar3 != 0) { snd::SFX_IsQueueMode(); snd::SFX_SetQueueMode(FALSE,FALSE); globs::objectiveGlobs.soundHandle = snd::SFX_Random_PlaySoundNormal((SFX_ID)elapsedAbs,FALSE); fVar5 = snd::SFX_Random_GetSamplePlayTime((SFX_ID)elapsedAbs); globs::objectiveGlobs.soundTimer = (float)((fVar5 - (float10)1.5) * (float10)25.0); snd::SFX_SetQueueMode_AndFlush(TRUE); } io::Mem_Free(globs::objectiveGlobs.soundName); globs::objectiveGlobs.soundName = NULL; } globs::objectiveGlobs.showing = BVar4; if (local_c.x != 0.0) { snd::SFX_SetQueueMode_AndFlush(TRUE); } if (bVar2) { if (globs::objectiveGlobs.currentPages[local_10] < globs::objectiveGlobs.pageCounts[local_10]) { pPVar6 = &local_c; local_c.x = 470.0; local_c.y = 315.0; } else { pPVar6 = NULL; } lrr::Lego_SetMenuNextPosition(pPVar6); if (globs::objectiveGlobs.currentPages[local_10] == 0) { pPVar6 = NULL; } else { pPVar6 = &local_c; local_c.x = 130.0; local_c.y = 315.0; } lrr::Lego_SetMenuPreviousPosition(pPVar6); if (globs::objectiveGlobs.currentPages[local_10] != globs::objectiveGlobs.currentPageStates[local_10]) { front::TextWindow_Clear(globs::objectiveGlobs.textWindows[local_10]); front::TextWindow_PagePrintF (globs::objectiveGlobs.textWindows[local_10], globs::objectiveGlobs.currentPages[local_10],"%s", globs::objectiveGlobs.messages[local_10]); globs::objectiveGlobs.currentPageStates[local_10] = globs::objectiveGlobs.currentPages[local_10]; } image = (level->objective).panelImage; if (image != NULL) { lego::image::Image_DisplayScaled(image,NULL,&(level->objective).panelImagePosition,NULL); } textWnd_00 = globs::objectiveGlobs.pageTextWindows[1]; if ((level->status != LEVELSTATUS_COMPLETE) && (textWnd_00 = globs::objectiveGlobs.pageTextWindows[2], level->status != LEVELSTATUS_FAILED)) { textWnd_00 = globs::objectiveGlobs.pageTextWindows[0]; } if (textWnd_00 != NULL) { front::TextWindow_Update(textWnd_00,0,elapsedGame,NULL); } if (globs::objectiveGlobs.textWindows[local_10] != NULL) { front::TextWindow_Update(globs::objectiveGlobs.textWindows[local_10],0,elapsedGame,NULL); } if (globs::objectiveGlobs.beginTextWindow != NULL) { front::TextWindow_Update(globs::objectiveGlobs.beginTextWindow,0,elapsedGame,NULL); } } return; } // out_timerStillRunning is set to false when time has run out. BOOL __cdecl lego::game::Objective_CheckCompleted(Lego_Level *level,BOOL *out_timerStillRunning,float elapsed) { float fVar1; BOOL BVar2; if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_SHOWBRIEFINGADVISOR) != OBJECTIVE_GLOB_FLAG_NONE) { return 0; } *out_timerStillRunning = TRUE; if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_TIMER) != OBJECTIVE_GLOB_FLAG_NONE) { fVar1 = (level->objective).timer - elapsed; (level->objective).timer = fVar1; if ((ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) != 0) { // Note that this flag serves two purposes, whether its intentional is unclear. if ((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_SHOWACHIEVEDADVISOR) != OBJECTIVE_GLOB_FLAG_NONE) { *out_timerStillRunning = FALSE; } return TRUE; } } if (((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_CRYSTAL) != OBJECTIVE_GLOB_FLAG_NONE) && ((uint)level->crystals < (level->objective).crystals)) { return 0; } if (((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_ORE) != OBJECTIVE_GLOB_FLAG_NONE) && ((uint)level->ore < (level->objective).ore)) { return 0; } BVar2 = LegoObject_RunThroughListsSkipUpgradeParts (Objective_Callback_CheckCompletedObject,&level->objective); return (uint)(BVar2 != 0); } BOOL __cdecl lego::game::Objective_Callback_CheckCompletedObject(LegoObject *liveObj,ObjectiveData *objective) { int bx; int by; if (((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_BLOCK) != OBJECTIVE_GLOB_FLAG_NONE) && ((liveObj->type == LegoObject_MiniFigure || (liveObj->type == LegoObject_Vehicle)))) { LegoObject_GetBlockPos(liveObj,&bx,&by); if ((bx == (objective->blockPos).x) && (by == (objective->blockPos).y)) { return TRUE; } } if ((((globs::objectiveGlobs.flags & OBJECTIVE_GLOB_FLAG_CONSTRUCTION) != OBJECTIVE_GLOB_FLAG_NONE ) && (objective->constructionType == liveObj->type)) && (objective->constructionID == liveObj->id)) { return TRUE; } return FALSE; } void __cdecl lego::game::ObjectRecall_StoreMiniFigure(LegoObject *liveObj) { ObjectRecallEntry *recall; if ((liveObj->type == LegoObject_MiniFigure) && (((liveObj->abilityFlags != ABILITY_FLAG_NONE || (liveObj->objLevel != 0)) || (liveObj->customName != NULL)))) { if (globs::objectRecallGlobs.recallUsed == globs::objectRecallGlobs.recallCapacity) { // More space is needed, allocate 10 extra slots globs::objectRecallGlobs.recallCapacity += 10; globs::objectRecallGlobs.recallList = (ObjectRecallEntry *) io::Mem_ReAlloc(globs::objectRecallGlobs.recallList, globs::objectRecallGlobs.recallCapacity * 0x14); } recall = globs::objectRecallGlobs.recallList + globs::objectRecallGlobs.recallUsed; globs::objectRecallGlobs.recallUsed = globs::objectRecallGlobs.recallUsed + 1; recall->abilityFlags = liveObj->abilityFlags; recall->level = liveObj->objLevel; // std::memset(recall->customName, 0, 0xc); *(undefined4 *)recall->customName = 0; *(undefined4 *)(recall->customName + 4) = 0; *(undefined4 *)(recall->customName + 8) = 0; if (liveObj->customName != NULL) { std::strncpy(recall->customName,liveObj->customName,0xb); } } return; } BOOL __cdecl lego::game::ObjectRecall_RecallMiniFigure(LegoObject *liveObj) { ObjectRecallEntry *recall; if ((liveObj->type == LegoObject_MiniFigure) && (globs::objectRecallGlobs.recallUsed != 0)) { globs::objectRecallGlobs.recallUsed -= 1; recall = globs::objectRecallGlobs.recallList + globs::objectRecallGlobs.recallUsed; // Trained ability flags liveObj->abilityFlags = globs::objectRecallGlobs.recallList[globs::objectRecallGlobs.recallUsed].abilityFlags; stats::StatsObject_SetObjectLevel(liveObj,recall->level); LegoObject_SetCustomName(liveObj,recall->customName); return TRUE; } return 0; } void __cdecl lego::save::ObjectRecall_Save_FreeObjectRecall(void) { globs::objectRecallGlobs.recallUsed = 0; globs::objectRecallGlobs.recallCapacity = 0; if (globs::objectRecallGlobs.recallList != NULL) { io::Mem_Free(globs::objectRecallGlobs.recallList); } globs::objectRecallGlobs.recallList = NULL; return; } void __cdecl lego::save::ObjectRecall_Save_CopyToNewObjectRecallData(void) { uint uVar1; int iVar2; ObjectRecallEntry *pOVar3; ObjectRecallEntry *pOVar4; if ((globs::objectRecallGlobs.recallUsed != 0) && (globs::objectRecallGlobs.recallList != NULL)) { if (globs::objectRecallGlobs.recallNewList != NULL) { io::Mem_Free(globs::objectRecallGlobs.recallNewList); } globs::objectRecallGlobs.recallNewList = (ObjectRecallEntry *)io::Mem_Alloc(globs::objectRecallGlobs.recallUsed * 0x14); // std::memcpy(recallNewList, recallList, recallUsed * 0x14); pOVar3 = globs::objectRecallGlobs.recallList; pOVar4 = globs::objectRecallGlobs.recallNewList; for (uVar1 = globs::objectRecallGlobs.recallUsed * 5 & 0x3fffffff; uVar1 != 0; uVar1 -= 1) { pOVar4->abilityFlags = pOVar3->abilityFlags; pOVar3 = (ObjectRecallEntry *)&pOVar3->level; pOVar4 = (ObjectRecallEntry *)&pOVar4->level; } for (iVar2 = 0; iVar2 != 0; iVar2 += -1) { *(undefined *)&pOVar4->abilityFlags = *(undefined *)&pOVar3->abilityFlags; pOVar3 = (ObjectRecallEntry *)((int)&pOVar3->abilityFlags + 1); pOVar4 = (ObjectRecallEntry *)((int)&pOVar4->abilityFlags + 1); } globs::objectRecallGlobs.recallNewCount = globs::objectRecallGlobs.recallUsed; globs::objectRecallGlobs.loaded = TRUE; } return; } BOOL __cdecl lego::save::ObjectRecall_Save_CreateNewObjectRecall(void) { uint uVar1; int iVar2; ObjectRecallEntry *pOVar3; ObjectRecallEntry *pOVar4; ObjectRecall_Save_FreeObjectRecall(); if ((globs::objectRecallGlobs.recallNewList != NULL) && (globs::objectRecallGlobs.recallNewCount != 0)) { globs::objectRecallGlobs.recallList = (ObjectRecallEntry *)io::Mem_Alloc(globs::objectRecallGlobs.recallNewCount * 0x14); // std::memcpy(recallList, recallNewList, recallNewCount * 0x14); pOVar3 = globs::objectRecallGlobs.recallNewList; pOVar4 = globs::objectRecallGlobs.recallList; for (uVar1 = globs::objectRecallGlobs.recallNewCount * 5 & 0x3fffffff; uVar1 != 0; uVar1 -= 1) { pOVar4->abilityFlags = pOVar3->abilityFlags; pOVar3 = (ObjectRecallEntry *)&pOVar3->level; pOVar4 = (ObjectRecallEntry *)&pOVar4->level; } for (iVar2 = 0; iVar2 != 0; iVar2 += -1) { *(undefined *)&pOVar4->abilityFlags = *(undefined *)&pOVar3->abilityFlags; pOVar3 = (ObjectRecallEntry *)((int)&pOVar3->abilityFlags + 1); pOVar4 = (ObjectRecallEntry *)((int)&pOVar4->abilityFlags + 1); } globs::objectRecallGlobs.recallUsed = globs::objectRecallGlobs.recallNewCount; globs::objectRecallGlobs.recallCapacity = globs::objectRecallGlobs.recallNewCount; return TRUE; } return 0; } BOOL __cdecl lego::save::ObjectRecall_IsLoaded(void) { return globs::objectRecallGlobs.loaded; } BOOL __cdecl lego::save::ObjectRecall_SaveRROSFile(char *filename) { File *f; RROSFileHeader hdr; f = io::File_Open(filename,"wb"); if (f != NULL) { // std::strncpy(hdr.signature, "RROS", 4); hdr.signature = 0x534f5252; hdr.count = globs::objectRecallGlobs.recallUsed; // Write Header: // char[4] "RROS" // uint count io::File_Write(&hdr,4,2,f); // Write Payload: // RROSStruct14[count] data io::File_Write(globs::objectRecallGlobs.recallList,0x14,globs::objectRecallGlobs.recallUsed,f); io::File_Close(f); ObjectRecall_Save_CopyToNewObjectRecallData(); globs::objectRecallGlobs.loaded = FALSE; return TRUE; } return FALSE; } BOOL __cdecl lego::save::ObjectRecall_LoadRROSFile(char *filename) { File *f; int fileSize; BOOL result; RROSFileHeader hdr; result = 0; ObjectRecall_Save_FreeObjectRecall(); f = io::File_Open(filename,"rb"); if (f != NULL) { fileSize = io::File_Length(f); io::File_Read(&hdr,4,2,f); // if (std::strncmp(hdr.signature, "RROS", 4) == 0) if (hdr.signature == L'\x534f5252') { if (fileSize - 8U == hdr.count * 0x14) { globs::objectRecallGlobs.recallUsed = hdr.count; globs::objectRecallGlobs.recallCapacity = hdr.count; globs::objectRecallGlobs.recallList = (ObjectRecallEntry *)io::Mem_Alloc(hdr.count * 0x14); io::File_Read(globs::objectRecallGlobs.recallList,0x14,globs::objectRecallGlobs.recallUsed,f ); ObjectRecall_Save_CopyToNewObjectRecallData(); globs::objectRecallGlobs.loaded = FALSE; } } io::File_Close(f); result = TRUE; } return result; } void __cdecl lego::front::ObjInfo_Initialise(Config *config,char *gameName) { ObjInfo_LoadHealthBar(config,gameName); ObjInfo_LoadHunger(config,gameName); ObjInfo_LoadBubble(config,gameName); return; } BOOL __cdecl lego::front::ObjInfo_LoadHealthBar(Config *config,char *gameName) { char *pcVar1; int iVar2; int x; int y; int width; int height; BOOL BVar3; BoolTri BVar4; float *pfVar5; ColourRGBF *pCVar6; float *pfVar7; float *out_b; char *stringParts [10]; pcVar1 = cfg::Config_BuildStringID(gameName,"ObjInfo","HealthBarPosition",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { return 0; } iVar2 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar2 == 2) { x = std::atoi(stringParts[0]); globs::objinfoGlobs.HealthBarPosition.x = (float)x; y = std::atoi(stringParts[1]); globs::objinfoGlobs.HealthBarPosition.y = (float)y; io::Mem_Free(pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"ObjInfo","HealthBarWidthHeight",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { return 0; } iVar2 = util::Util_Tokenise(pcVar1,stringParts,":"); if (iVar2 == 2) { width = std::atoi(stringParts[0]); globs::objinfoGlobs.HealthBarWidthHeight.width = (float)width; height = std::atoi(stringParts[1]); globs::objinfoGlobs.HealthBarWidthHeight.height = (float)height; io::Mem_Free(pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"ObjInfo","HealthBarBorderSize",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(gameName,"ObjInfo","HealthBarBorderSize",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); } globs::objinfoGlobs.HealthBarBorderSize = std::atoi(pcVar1); out_b = globs::objinfoGlobs.HealthBarBorderRGB_b; pfVar7 = globs::objinfoGlobs.HealthBarBorderRGB_g; pfVar5 = globs::objinfoGlobs.HealthBarBorderRGB_r; pcVar1 = cfg::Config_BuildStringID(gameName,"ObjInfo","HealthBarBorderRGB",0); BVar3 = cfg::Config_GetRGBValue(config,pcVar1,pfVar5,pfVar7,out_b); if (BVar3 == 0) { return 0; } globs::objinfoGlobs.HealthBarBorderRGB_r[1] = globs::objinfoGlobs.HealthBarBorderRGB_r[0] + globs::objinfoGlobs.HealthBarBorderRGB_r[0] * 0.4; globs::objinfoGlobs.HealthBarBorderRGB_r[2] = globs::objinfoGlobs.HealthBarBorderRGB_r[0] - globs::objinfoGlobs.HealthBarBorderRGB_r[0] * 0.4; globs::objinfoGlobs.HealthBarBorderRGB_g[1] = globs::objinfoGlobs.HealthBarBorderRGB_g[0] + globs::objinfoGlobs.HealthBarBorderRGB_g[0] * 0.4; globs::objinfoGlobs.HealthBarBorderRGB_g[2] = globs::objinfoGlobs.HealthBarBorderRGB_g[0] - globs::objinfoGlobs.HealthBarBorderRGB_g[0] * 0.4; globs::objinfoGlobs.HealthBarBorderRGB_b[1] = globs::objinfoGlobs.HealthBarBorderRGB_b[0] + globs::objinfoGlobs.HealthBarBorderRGB_b[0] * 0.4; globs::objinfoGlobs.HealthBarBorderRGB_b[2] = globs::objinfoGlobs.HealthBarBorderRGB_b[0] - globs::objinfoGlobs.HealthBarBorderRGB_b[0] * 0.4; pfVar5 = globs::objinfoGlobs.HealthBarBorderRGB_g; do { if ((ushort)((ushort)(pfVar5[-3] < 1.0) << 8 | (ushort)(pfVar5[-3] == 1.0) << 0xe) == 0) { pfVar5[-3] = 1.0; } if ((ushort)((ushort)(*pfVar5 < 1.0) << 8 | (ushort)(*pfVar5 == 1.0) << 0xe) == 0) { *pfVar5 = 1.0; } if ((ushort)((ushort)(pfVar5[3] < 1.0) << 8 | (ushort)(pfVar5[3] == 1.0) << 0xe) == 0) { pfVar5[3] = 1.0; } if (pfVar5[-3] < 0.0) { pfVar5[-3] = 0.0; } if (*pfVar5 < 0.0) { *pfVar5 = 0.0; } if (pfVar5[3] < 0.0) { pfVar5[3] = 0.0; } pfVar5 = pfVar5 + 1; } while (pfVar5 < globs::objinfoGlobs.HealthBarBorderRGB_b); pfVar7 = &globs::objinfoGlobs.HealthBarBackgroundRGB.blue; pfVar5 = &globs::objinfoGlobs.HealthBarBackgroundRGB.green; pCVar6 = &globs::objinfoGlobs.HealthBarBackgroundRGB; pcVar1 = cfg::Config_BuildStringID(gameName,"ObjInfo","HealthBarBackgroundRGB",0); BVar3 = cfg::Config_GetRGBValue(config,pcVar1,&pCVar6->red,pfVar5,pfVar7); if (BVar3 == 0) { return 0; } pfVar7 = &globs::objinfoGlobs.HealthBarRGB.blue; pfVar5 = &globs::objinfoGlobs.HealthBarRGB.green; pCVar6 = &globs::objinfoGlobs.HealthBarRGB; pcVar1 = cfg::Config_BuildStringID(gameName,"ObjInfo","HealthBarRGB",0); BVar3 = cfg::Config_GetRGBValue(config,pcVar1,&pCVar6->red,pfVar5,pfVar7); if (BVar3 == 0) { return 0; } pcVar1 = cfg::Config_BuildStringID(gameName,"ObjInfo","HealthBarVertical",0); BVar4 = cfg::Config_GetBoolValue(config,pcVar1); if (BVar4 == BOOL3_TRUE) { globs::objinfoGlobs.flags |= OBJINFO_GLOB_FLAG_HEALTHBAR_VERTICAL; } globs::objinfoGlobs.flags = globs::objinfoGlobs.flags | OBJINFO_GLOB_FLAG_HEALTHBAR; return TRUE; } } io::Mem_Free(pcVar1); return FALSE; } BOOL __cdecl lego::front::ObjInfo_LoadHunger(Config *config,char *gameName) { char *str; int numParts; int x; int y; char *stringParts [10]; ObjInfo_LoadHungerImages(config,gameName); str = cfg::Config_BuildStringID(gameName,"ObjInfo","HungerImagesPosition",0); str = cfg::Config_GetStringValue(config,str); if (str != NULL) { numParts = util::Util_Tokenise(str,stringParts,":"); if (numParts == 2) { x = std::atoi(stringParts[0]); globs::objinfoGlobs.HungerPosition.x = (float)x; y = std::atoi(stringParts[1]); globs::objinfoGlobs.HungerPosition.y = (float)y; io::Mem_Free(str); globs::objinfoGlobs.flags = globs::objinfoGlobs.flags | OBJINFO_GLOB_FLAG_HUNGERIMAGES; return TRUE; } io::Mem_Free(str); } return FALSE; } void __cdecl lego::front::ObjInfo_LoadHungerImages(Config *config,char *gameName) { char *str; Image *image; Image **pHungerImage; int i; uint width; uint height; char buff [64]; i = 0; pHungerImage = globs::objinfoGlobs.HungerImages; do { std::sprintf(buff,"HungerImage%i",i); height = 0; width = 0; str = cfg::Config_BuildStringID(gameName,"ObjInfo","HungerImages",buff,0); str = cfg::Config_GetTempStringValue(config,str); image = lego::image::Image_LoadBMPScaled(str,width,height); *pHungerImage = image; if (image != NULL) { lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); } pHungerImage = (Image **)((int)pHungerImage + 4); i += 1; // while (i < 5); } while (pHungerImage < &globs::objinfoGlobs.BubblePosition); return; } BOOL __cdecl lego::front::ObjInfo_LoadBubble(Config *config,char *gameName) { char *str; int iVar1; char *stringParts [10]; str = cfg::Config_BuildStringID(gameName,"ObjInfo","BubbleImagesPosition",0); str = cfg::Config_GetStringValue(config,str); if (str != NULL) { iVar1 = util::Util_Tokenise(str,stringParts,":"); if (iVar1 == 2) { iVar1 = std::atoi(stringParts[0]); globs::objinfoGlobs.BubblePosition.x = (float)iVar1; iVar1 = std::atoi(stringParts[1]); globs::objinfoGlobs.BubblePosition.y = (float)iVar1; io::Mem_Free(str); globs::objinfoGlobs.flags = globs::objinfoGlobs.flags | OBJINFO_GLOB_FLAG_BUBBLEIMAGES; return TRUE; } io::Mem_Free(str); } return FALSE; } void __cdecl lego::front::ObjInfo_DrawHealthBar(LegoObject *liveObj,int screenX,int screenY) { float fVar1; BOOL BVar2; Point2F *ln1From; float rcRed; Point2F *ln2From; float *ln1From_y; float *ln1To_y; uint lineCount; Point2F *ln1To; float *ln2From_y; Area2F fillRect; float *ln2To_y; uint loc_lineCount; Point2F *ln2To; uint i; Point2F ln1ListTo [10]; Point2F ln2ListTo [10]; Point2F ln1ListFrom [10]; Point2F ln2ListFrom [10]; float health; float rcGreen; float rcBlue; float barHeight; float barWidth; float endX; float endY; float startX; float startY; float thickness; lineCount = 0; loc_lineCount = 0; if ((((byte)globs::objinfoGlobs.flags & OBJINFO_GLOB_FLAG_HEALTHBAR) != 0) && (BVar2 = DamageFont_LiveObject_CheckCanShowDamage_Unk(liveObj), BVar2 != 0)) { barWidth = globs::objinfoGlobs.HealthBarWidthHeight.width + (float)(ulonglong)(globs::objinfoGlobs.HealthBarBorderSize * 2); barHeight = globs::objinfoGlobs.HealthBarWidthHeight.height + (float)(ulonglong)(globs::objinfoGlobs.HealthBarBorderSize * 2); fillRect.x = (float)screenX + globs::objinfoGlobs.HealthBarPosition.x; fillRect.y = (float)screenY + globs::objinfoGlobs.HealthBarPosition.y; i = 0; if (globs::objinfoGlobs.HealthBarBorderSize != 0) { ln2To = ln2ListTo; ln2To_y = &ln2ListTo[0].y; ln2From = ln2ListFrom; ln2From_y = &ln2ListFrom[0].y; ln1To_y = &ln1ListTo[0].y; ln1To = ln1ListTo; ln1From_y = &ln1ListFrom[0].y; ln1From = ln1ListFrom; do { thickness = (float)(ulonglong)i; startX = fillRect.x + thickness; startY = fillRect.y + thickness; endY = ((fillRect.y + barHeight) - 1.0) - thickness; endX = ((fillRect.x + barWidth) - 1.0) - thickness; ln1From->x = startX; *ln1From_y = startY; fVar1 = ln1From->x; ln2From->x = startX; *ln1To_y = ((fillRect.y + barHeight) - 2.0) - thickness; *ln2From_y = endY; ln1From[1].x = endX; ln1To->x = fVar1; ln2To->x = ((fillRect.x + barWidth) - 2.0) - thickness; ln1From_y[2] = startY; *ln2To_y = endY; ln2From[1].x = endX; ln1To[1].x = startX - -1.0; ln2From_y[2] = endY; fVar1 = ln2From[1].x; ln1To_y[2] = startY; ln1From = ln1From + 2; ln1From_y = ln1From_y + 4; ln1To = ln1To + 2; ln2From_y = ln2From_y + 4; ln2To_y[2] = startY - -1.0; ln2From = ln2From + 2; ln2To[1].x = fVar1; lineCount = loc_lineCount + 2; ln2To = ln2To + 2; ln1To_y = ln1To_y + 4; ln2To_y = ln2To_y + 4; i += 1; loc_lineCount = lineCount; } while (i < globs::objinfoGlobs.HealthBarBorderSize); } health = liveObj->health; if (0.0 <= health) { if ((ushort)((ushort)(health < 100.0) << 8 | (ushort)(health == 100.0) << 0xe) == 0) { // health = 100.0f; health = (float)&DAT_42c80000; } } else { health = 0.0; } if (((byte)globs::objinfoGlobs.flags & OBJINFO_GLOB_FLAG_HEALTHBAR_VERTICAL) == 0) { fillRect.width = health * barWidth * 0.01; fillRect.height = barHeight; draw::Draw_RectListEx (&fillRect,1,globs::objinfoGlobs.HealthBarRGB.red, globs::objinfoGlobs.HealthBarRGB.green,globs::objinfoGlobs.HealthBarRGB.blue, DrawEffect_None); fillRect.x = fillRect.x + fillRect.width; fillRect.width = barWidth - fillRect.width; rcRed = globs::objinfoGlobs.HealthBarBackgroundRGB.red; rcGreen = globs::objinfoGlobs.HealthBarBackgroundRGB.green; rcBlue = globs::objinfoGlobs.HealthBarBackgroundRGB.blue; } else { fillRect.height = (1.0 - health * 0.01) * barHeight; fillRect.width = barWidth; draw::Draw_RectListEx (&fillRect,1,globs::objinfoGlobs.HealthBarBackgroundRGB.red, globs::objinfoGlobs.HealthBarBackgroundRGB.green, globs::objinfoGlobs.HealthBarBackgroundRGB.blue,DrawEffect_None); fillRect.y = fillRect.y + fillRect.height; fillRect.height = barHeight - fillRect.height; rcRed = globs::objinfoGlobs.HealthBarRGB.red; rcGreen = globs::objinfoGlobs.HealthBarRGB.green; rcBlue = globs::objinfoGlobs.HealthBarRGB.blue; } draw::Draw_RectListEx(&fillRect,1,rcRed,rcGreen,rcBlue,DrawEffect_None); draw::Draw_LineListEx (ln1ListFrom,ln1ListTo,lineCount,globs::objinfoGlobs.HealthBarBorderRGB_r[1], globs::objinfoGlobs.HealthBarBorderRGB_g[1], globs::objinfoGlobs.HealthBarBorderRGB_b[1],DrawEffect_None); draw::Draw_LineListEx (ln2ListFrom,ln2ListTo,lineCount,globs::objinfoGlobs.HealthBarBorderRGB_r[2], globs::objinfoGlobs.HealthBarBorderRGB_g[2], globs::objinfoGlobs.HealthBarBorderRGB_b[2],DrawEffect_None); } return; } void __cdecl lego::front::ObjInfo_DrawHungerImage(LegoObject *liveObj,int screenX,int screenY) { uint index0_4; longlong lVar1; Point2F destPos; if (((byte)globs::objinfoGlobs.flags & OBJINFO_GLOB_FLAG_HUNGERIMAGES) != 0) { lVar1 = __ftol((float10)liveObj->energy * (float10)0.01 * (float10)5.0); index0_4 = (uint)lVar1; if (4 < index0_4) { index0_4 = 4; } if (globs::objinfoGlobs.HungerImages[index0_4] != NULL) { destPos.x = (float)screenX + globs::objinfoGlobs.HungerPosition.x; destPos.y = (float)screenY + globs::objinfoGlobs.HungerPosition.y; lego::image::Image_DisplayScaled (globs::objinfoGlobs.HungerImages[index0_4],NULL,&destPos,NULL); } } return; } void __cdecl lego::front::ObjInfo_DrawBubbleImage(Image *image,int screenX,int screenY) { Point2F destPos; if (((byte)globs::objinfoGlobs.flags & OBJINFO_GLOB_FLAG_BUBBLEIMAGES) != 0) { destPos.x = (float)screenX + globs::objinfoGlobs.BubblePosition.x; destPos.y = (float)screenY + globs::objinfoGlobs.BubblePosition.y; lego::image::Image_DisplayScaled(image,NULL,&destPos,NULL); } return; } void __cdecl lego::front::Panel_Initialise(void) { globs::panelGlobs.panelName[0] = "Panel_Radar"; globs::panelGlobs.panelName[1] = "Panel_RadarFill"; globs::panelGlobs.panelName[2] = "Panel_RadarOverlay"; globs::panelGlobs.panelName[3] = "Panel_Messages"; globs::panelGlobs.panelName[4] = "Panel_MessagesSide"; globs::panelGlobs.panelName[5] = "Panel_CrystalSideBar"; globs::panelGlobs.panelName[6] = "Panel_TopPanel"; globs::panelGlobs.panelName[7] = "Panel_Information"; globs::panelGlobs.panelName[8] = "Panel_PriorityList"; globs::panelGlobs.panelName[9] = "Panel_CameraControl"; globs::panelGlobs.panelName[10] = "Panel_InfoDock"; globs::panelGlobs.panelName[11] = "Panel_Encyclopedia"; globs::panelGlobs.panelButtonName[0][0] = "PanelButton_Radar_Toggle"; globs::panelGlobs.panelButtonName[0][1] = "PanelButton_Radar_TaggedObjectView"; globs::panelGlobs.panelButtonName[0][2] = "PanelButton_Radar_ZoomIn"; globs::panelGlobs.panelButtonName[0][3] = "PanelButton_Radar_ZoomOut"; globs::panelGlobs.panelButtonName[0][4] = "PanelButton_Radar_MapView"; globs::panelGlobs.panelButtonName[5][0] = "PanelButton_CrystalSideBar_Ore"; globs::panelGlobs.panelButtonName[5][1] = "PanelButton_CrystalSideBar_Crystals"; globs::panelGlobs.panelButtonName[6][0] = "PanelButton_TopPanel_Options"; globs::panelGlobs.panelButtonName[6][1] = "PanelButton_TopPanel_Priorities"; globs::panelGlobs.panelButtonName[6][2] = "PanelButton_TopPanel_CallToArms"; globs::panelGlobs.panelButtonName[7][0] = "PanelButton_Information_Toggle"; globs::panelGlobs.panelButtonName[7][1] = "PanelButton_Information_Function"; globs::panelGlobs.panelButtonName[8][0] = "PanelButton_PriorityList_Disable1"; globs::panelGlobs.panelButtonName[8][1] = "PanelButton_PriorityList_Disable2"; globs::panelGlobs.panelButtonName[8][2] = "PanelButton_PriorityList_Disable3"; globs::panelGlobs.panelButtonName[8][3] = "PanelButton_PriorityList_Disable4"; globs::panelGlobs.panelButtonName[8][4] = "PanelButton_PriorityList_Disable5"; globs::panelGlobs.panelButtonName[8][5] = "PanelButton_PriorityList_Disable6"; globs::panelGlobs.panelButtonName[8][6] = "PanelButton_PriorityList_Disable7"; globs::panelGlobs.panelButtonName[8][7] = "PanelButton_PriorityList_Disable8"; globs::panelGlobs.panelButtonName[8][8] = "PanelButton_PriorityList_Disable9"; globs::panelGlobs.panelButtonName[8][9] = "PanelButton_PriorityList_UpOne1"; globs::panelGlobs.panelButtonName[8][10] = "PanelButton_PriorityList_UpOne2"; globs::panelGlobs.panelButtonName[8][11] = "PanelButton_PriorityList_UpOne3"; globs::panelGlobs.panelButtonName[8][12] = "PanelButton_PriorityList_UpOne4"; globs::panelGlobs.panelButtonName[8][13] = "PanelButton_PriorityList_UpOne5"; globs::panelGlobs.panelButtonName[8][14] = "PanelButton_PriorityList_UpOne6"; globs::panelGlobs.panelButtonName[8][15] = "PanelButton_PriorityList_UpOne7"; globs::panelGlobs.panelButtonName[8][16] = "PanelButton_PriorityList_UpOne8"; globs::panelGlobs.panelButtonName[8][17] = "PanelButton_PriorityList_Close"; globs::panelGlobs.panelButtonName[8][18] = "PanelButton_PriorityList_Reset"; globs::panelGlobs.panelButtonName[9][0] = "PanelButton_CameraControl_ZoomIn"; globs::panelGlobs.panelButtonName[9][1] = "PanelButton_CameraControl_ZoomOut"; globs::panelGlobs.panelButtonName[9][2] = "PanelButton_CameraControl_CycleBuildings"; globs::panelGlobs.panelButtonName[9][3] = "PanelButton_CameraControl_Rotate"; globs::panelGlobs.panelButtonName[10][0] = "PanelButton_InfoDock_Goto"; globs::panelGlobs.panelButtonName[10][1] = "PanelButton_InfoDock_Close"; globs::panelGlobs.panelButtonName[11][0] = "PanelButton_Encyclopedia_Close"; globs::panelGlobs.currentPanel = Panel_Type_Count; globs::panelGlobs.currentButton = PANELBUTTON_TYPE_COUNT; return; } void __cdecl lego::front::Panel_LoadInterfaceButtons_ScrollInfo(void) { Panel_ScrollInfo_Initialise(); Panel_Encyclopedia_Initialise(); Panel_Button_SetToggleable(Panel_TopPanel,PanelButton_TopPanel_Priorities,TRUE); Panel_Button_SetToggleable(Panel_TopPanel,PanelButton_TopPanel_CallToArms,TRUE); return; } void __cdecl lego::front::Panel_ResetAll(void) { char *pcVar1; char **ppcVar2; char *pcVar3; int iVar4; ppcVar2 = (char **)&globs::panelGlobs.panelTable[0].flags; do { ppcVar2[-5] = ppcVar2[-7]; pcVar3 = NULL; *ppcVar2 = (char *)((uint)*ppcVar2 & ~(PANEL_FLAG_OPEN|PANEL_FLAG_SLIDING) | PANEL_FLAG_CLOSED); ppcVar2[-4] = ppcVar2[-6]; if (ppcVar2[-1] != NULL) { iVar4 = 0; do { pcVar1 = ppcVar2[-2]; // button->clickCount = 0; *(undefined4 *)(pcVar1 + iVar4 + 0x24) = 0; pcVar1 = pcVar1 + iVar4; iVar4 += 0x2c; pcVar3 = pcVar3 + 1; // button->flags &= ~(PANELBUTTON_FLAG_TOGGLED|PANELBUTTON_FLAG_UNUSED_HOVERFLASH); *(uint *)(pcVar1 + 0x28) = *(uint *)(pcVar1 + 0x28) & 0xffffffb7; } while (pcVar3 < ppcVar2[-1]); } ppcVar2 = ppcVar2 + 0xc; } while (ppcVar2 < globs::panelGlobs.panelButtonName + 0xb); globs::panelGlobs.cryOreMeterValue = 0.0; return; } void __cdecl lego::front::Panel_LoadImage(char *filename,Panel_Type panelType,PanelDataFlags flags) { PanelDataFlags PVar1; Image *image; BOOL BVar2; globs::panelGlobs.panelTable[panelType].buttonCount = 0; globs::panelGlobs.panelTable[panelType].flags = flags; image = lego::image::Image_LoadBMPScaled(filename,0,0); globs::panelGlobs.panelTable[panelType].imageOrFlic = image; if (image != NULL) { globs::panelGlobs.panelTable[panelType].isFlic = 0; lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); globs::panelGlobs.panelTable[panelType].flags = globs::panelGlobs.panelTable[panelType].flags | PANEL_FLAG_HASIMAGE; return; } BVar2 = lego::image::Flic_Setup (filename,(Flic **)(globs::panelGlobs.panelTable + panelType), FLICMEMORY|FLICLOOPINGON); if (BVar2 != 0) { PVar1 = globs::panelGlobs.panelTable[panelType].flags; globs::panelGlobs.panelTable[panelType].isFlic = 1; globs::panelGlobs.panelTable[panelType].flags = PVar1 | PANEL_FLAG_HASIMAGE; } return; } BOOL __cdecl lego::front::Panel_GetPanelType(char *panelName,Panel_Type *out_panelType) { int cmp; Panel_Globs *pName; int i; i = 0; pName = &globs::panelGlobs; do { cmp = std::_stricmp(panelName,(char *)pName->panelName[0]); if (cmp == 0) { *out_panelType = i; return TRUE; } pName = (Panel_Globs *)(pName->panelName + 1); // index++ i += Panel_RadarFill; // index < PANEL__COUNT (12) } while (pName < (Panel_Globs *)globs::panelGlobs.panelTable); return 0; } BOOL __cdecl lego::front::Panel_TestPointInsideImage(Panel_Type panelType,int screenX,int screenY) { Panel_Type PVar1; BOOL BVar2; uint y; PanelData *panel; longlong lVar3; Panel_Type *out_colour; PVar1 = panelType; panel = globs::panelGlobs.panelTable + panelType; if (globs::panelGlobs.panelTable[panelType].isFlic == 0) { out_colour = &panelType; lVar3 = __ftol((float10)globs::panelGlobs.panelTable[panelType].position.y); y = screenY - (int)lVar3; lVar3 = __ftol((float10)globs::panelGlobs.panelTable[PVar1].position.x); BVar2 = lego::image::Image_GetPixel(panel->imageOrFlic,screenX - (int)lVar3,y,out_colour); if (BVar2 != 0) { // return (pixelColour == 0x0); // black, so probably transparent return (uint)(panelType == Panel_Radar); } } return TRUE; } BOOL __cdecl lego::front::Panel_GetButtonType (Panel_Type panelType,char *buttonName,PanelButtonType *out_buttonType) { int cmp; char *(*pName) [24]; PanelButtonType buttonType; pName = globs::panelGlobs.panelButtonName[panelType]; buttonType = 0; do { if ((*pName)[0] != NULL) { cmp = std::_stricmp(buttonName,(*pName)[0]); if (cmp == 0) { *out_buttonType = buttonType; return TRUE; } } buttonType += 1; pName = (char *(*) [24])(*pName + 1); } while (buttonType < PANELBUTTON_TYPE_COUNT); return 0; } uint __cdecl lego::front::Panel_PrintF(Panel_Type panelType,Font *font,int x,int y,BOOL center,char *msg,...) { Font *font_00; int y_00; uint uVar1; float10 fVar2; longlong lVar3; char *msg_00; va_list argptr; Panel_Type panelType_00; font_00 = font; panelType_00 = panelType; if (center != 0) { lego::image::Font_VGetStringInfo(font,&panelType,NULL,msg,&stack0x0000001c); x -= panelType >> 1; } argptr = &stack0x0000001c; msg_00 = msg; fVar2 = std::floor((double)((float)y + globs::panelGlobs.panelTable[panelType_00].position.y)); lVar3 = __ftol(fVar2); y_00 = (int)lVar3; fVar2 = std::floor((double)((float)x + globs::panelGlobs.panelTable[panelType_00].position.x)); lVar3 = __ftol(fVar2); uVar1 = lego::image::Font_VPrintF(font_00,(int)lVar3,y_00,msg_00,argptr); return uVar1; } PanelTextWindow * __cdecl lego::front::Panel_TextWindow_Create(Panel_Type panelType,Font *font,Area2F *rect,uint size) { PanelTextWindow *panelWnd; TextWindow *textWnd; longlong lVar1; Area2F area; area.x = 0.0; area.y = 0.0; area.width = rect->width; area.height = rect->height; panelWnd = (PanelTextWindow *)io::Mem_Alloc(0x10); if (panelWnd != NULL) { panelWnd->textWindow = NULL; (panelWnd->position).x = 0.0; (panelWnd->position).y = 0.0; panelWnd->panel = NULL; textWnd = TextWindow_Create(font,&area,size); panelWnd->textWindow = textWnd; lVar1 = __ftol((float10)rect->x); (panelWnd->position).x = (float)lVar1; lVar1 = __ftol((float10)rect->y); (panelWnd->position).y = (float)lVar1; panelWnd->panel = globs::panelGlobs.panelTable + panelType; } return panelWnd; } void __cdecl lego::front::Panel_TextWindow_PrintF(PanelTextWindow *panelWnd,char *msg,...) { TextWindow_VPrintF(panelWnd->textWindow,0,msg,&stack0x0000000c); return; } void __cdecl lego::front::Panel_TextWindow_Update(PanelTextWindow *textWnd,uint posFromEnd,float elapsed) { int ypos; float10 fVar1; longlong lVar2; fVar1 = std::floor((double)((float)(int)(textWnd->position).y + (textWnd->panel->position).y)); lVar2 = __ftol(fVar1); ypos = (int)lVar2; fVar1 = std::floor((double)((float)(int)(textWnd->position).x + (textWnd->panel->position).x)); lVar2 = __ftol(fVar1); TextWindow_ChangePosition(textWnd->textWindow,(int)lVar2,ypos); TextWindow_Update(textWnd->textWindow,posFromEnd,elapsed,NULL); return; } void __cdecl lego::front::Panel_TextWindow_Clear(PanelTextWindow *panelWnd) { TextWindow_Clear(panelWnd->textWindow); return; } void __cdecl lego::front::Panel_TextWindow_GetInfo (PanelTextWindow *panelWnd,uint *out_linesCount,uint *out_linesCapacity) { TextWindow_GetInfo(panelWnd->textWindow,out_linesCount,out_linesCapacity); return; } void __cdecl lego::front::Panel_SetSlidingPositions (Panel_Type panelType,int xOpen,int yOpen,int xClosed,int yClosed) { byte flags; globs::panelGlobs.panelTable[panelType].openPos.x = (float)xOpen; globs::panelGlobs.panelTable[panelType].closedPos.x = (float)xClosed; flags = *(byte *)&globs::panelGlobs.panelTable[panelType].flags; globs::panelGlobs.panelTable[panelType].openPos.y = (float)yOpen; globs::panelGlobs.panelTable[panelType].closedPos.y = (float)yClosed; globs::panelGlobs.panelTable[panelType].reserved1 = 0; if ((flags & PANEL_FLAG_OPEN) != 0) { globs::panelGlobs.panelTable[panelType].position.x = (float)xOpen; globs::panelGlobs.panelTable[panelType].position.y = (float)yOpen; return; } globs::panelGlobs.panelTable[panelType].position.x = (float)xClosed; globs::panelGlobs.panelTable[panelType].position.y = (float)yClosed; return; } void __cdecl lego::front::Panel_SetPosition(Panel_Type panelType,float x,float y) { globs::panelGlobs.panelTable[panelType].position.x = x; globs::panelGlobs.panelTable[panelType].position.y = y; return; } void __cdecl lego::front::Panel_GetPosition(Panel_Type panelType,float *out_x,float *out_y) { *out_x = globs::panelGlobs.panelTable[panelType].position.x; *out_y = globs::panelGlobs.panelTable[panelType].position.y; return; } void __cdecl lego::front::Panel_Draw(Panel_Type panelType,float elapsedAbs) { int iVar1; float fVar2; uint uVar3; PanelData *pPVar4; float10 fVar5; longlong lVar6; ulonglong uVar7; Point2F finalPos; Point2F destPos; Area2F destArea; pPVar4 = globs::panelGlobs.panelTable + panelType; if ((*(byte *)&globs::panelGlobs.panelTable[panelType].flags & PANEL_FLAG_CLOSED) == 0) { finalPos.x = globs::panelGlobs.panelTable[panelType].openPos.x; finalPos.y = globs::panelGlobs.panelTable[panelType].openPos.y; } else { finalPos.x = globs::panelGlobs.panelTable[panelType].closedPos.x; finalPos.y = globs::panelGlobs.panelTable[panelType].closedPos.y; } if (elapsedAbs != 0.0) { fVar2 = ABS(globs::panelGlobs.panelTable[panelType].position.x - finalPos.x); if ((ushort)((ushort)(fVar2 < 1.0) << 8 | (ushort)(fVar2 == 1.0) << 0xe) == 0) { globs::panelGlobs.panelTable[panelType].position.x = ((4.0 / elapsedAbs) * globs::panelGlobs.panelTable[panelType].position.x + finalPos.x) / (4.0 / elapsedAbs - -1.0); } else { globs::panelGlobs.panelTable[panelType].position.x = finalPos.x; } fVar2 = ABS(globs::panelGlobs.panelTable[panelType].position.y - finalPos.y); if ((ushort)((ushort)(fVar2 < 1.0) << 8 | (ushort)(fVar2 == 1.0) << 0xe) == 0) { globs::panelGlobs.panelTable[panelType].position.y = ((4.0 / elapsedAbs) * globs::panelGlobs.panelTable[panelType].position.y + finalPos.y) / (4.0 / elapsedAbs - -1.0); } else { globs::panelGlobs.panelTable[panelType].position.y = finalPos.y; } } fVar5 = std::floor((double)globs::panelGlobs.panelTable[panelType].position.x); destPos.x = (float)fVar5; destArea.x = (float)fVar5; fVar5 = std::floor((double)globs::panelGlobs.panelTable[panelType].position.y); iVar1 = globs::panelGlobs.panelTable[panelType].isFlic; destPos.y = (float)fVar5; destArea.y = (float)fVar5; if (iVar1 == 0) { lego::image::Image_DisplayScaled(pPVar4->imageOrFlic,NULL,&destPos,NULL); } else { if (iVar1 == 1) { uVar3 = gfx::AnimClone_IsLws__Flic_GetWidth((AnimClone *)pPVar4->imageOrFlic); destArea.width = (float)(ulonglong)uVar3; uVar3 = lego::image::Flic_GetHeight((Flic *)pPVar4->imageOrFlic); destArea.height = (float)(ulonglong)uVar3; uVar7 = CONCAT44(1,~globs::legoGlobs.flags1 >> 0x14) & 0xffffffff00000001; lego::image::Flic_Animate ((Flic *)pPVar4->imageOrFlic,&destArea,(BOOL)uVar7,(BOOL)(uVar7 >> 0x20)); } } if (panelType == Panel_CameraControl) { if ((globs::panelGlobs.flags & PANEL_GLOB_FLAG_ROTATECONTROL_UP) != PANEL_GLOB_FLAG_NONE) { lego::image::Image_DisplayScaled (globs::panelGlobs.rotateUpImage,NULL,&globs::panelGlobs.rotateUpOffset,NULL); globs::panelGlobs.flags &= ~PANEL_GLOB_FLAG_ROTATECONTROL_UP; } if ((globs::panelGlobs.flags & PANEL_GLOB_FLAG_ROTATECONTROL_DOWN) != PANEL_GLOB_FLAG_NONE) { lego::image::Image_DisplayScaled (globs::panelGlobs.rotateDownImage,NULL,&globs::panelGlobs.rotateDownOffset,NULL); globs::panelGlobs.flags &= ~PANEL_GLOB_FLAG_ROTATECONTROL_DOWN; } if ((globs::panelGlobs.flags & PANEL_GLOB_FLAG_ROTATECONTROL_LEFT) != PANEL_GLOB_FLAG_NONE) { lego::image::Image_DisplayScaled (globs::panelGlobs.rotateLeftImage,NULL,&globs::panelGlobs.rotateLeftOffset,NULL); globs::panelGlobs.flags &= ~PANEL_GLOB_FLAG_ROTATECONTROL_LEFT; } if ((globs::panelGlobs.flags & PANEL_GLOB_FLAG_ROTATECONTROL_RIGHT) != PANEL_GLOB_FLAG_NONE) { lego::image::Image_DisplayScaled (globs::panelGlobs.rotateRightImage,NULL,&globs::panelGlobs.rotateRightOffset,NULL); globs::panelGlobs.flags &= ~PANEL_GLOB_FLAG_ROTATECONTROL_RIGHT; } } lVar6 = __ftol((float10)globs::panelGlobs.panelTable[panelType].position.x - (float10)finalPos.x); uVar3 = (int)(uint)lVar6 >> 0x1f; if (((int)(((uint)lVar6 ^ uVar3) - uVar3) < 2) && (lVar6 = __ftol((float10)globs::panelGlobs.panelTable[panelType].position.y - (float10)finalPos.y), uVar3 = (int)(uint)lVar6 >> 0x1f, (int)(((uint)lVar6 ^ uVar3) - uVar3) < 2)) { globs::panelGlobs.panelTable[panelType].flags = globs::panelGlobs.panelTable[panelType].flags & ~PANEL_FLAG_SLIDING; } Panel_DrawButtons(panelType); return; } void __cdecl lego::front::Panel_DrawButtons(Panel_Type panelType) { Image *image; BOOL BVar1; PanelButtonFlags isFlag40; int offset; uint i; PanelButtonData *button; Point2F destPos; PanelButtonFlags flags; i = 0; if (globs::panelGlobs.panelTable[panelType].buttonCount != 0) { offset = 0; do { button = (PanelButtonData *) ((int)&((globs::panelGlobs.panelTable[panelType].buttonList)->rect).left + offset); destPos.x = (button->rect).left + globs::panelGlobs.panelTable[panelType].position.x; destPos.y = (button->rect).top + globs::panelGlobs.panelTable[panelType].position.y; flags = button->flags; if ((flags & PANELBUTTON_FLAG_HIDDEN) == PANELBUTTON_FLAG_NONE) { isFlag40 = flags & PANELBUTTON_FLAG_UNUSED_HOVERFLASH; if (((flags & PANELBUTTON_FLAG_TOGGLED) == PANELBUTTON_FLAG_NONE) && ((flags & PANELBUTTON_FLAG_HOVER) != PANELBUTTON_FLAG_NONE)) { if (isFlag40 == PANELBUTTON_FLAG_NONE) { LAB_0045ad31: image = button->imageHover; } else { BVar1 = Interface_GetFlashingState(); if (BVar1 == 0) goto LAB_0045ad5a; image = button->imageHover; } } else { if (((flags & PANELBUTTON_FLAG_DOWN) == PANELBUTTON_FLAG_NONE) && ((flags & PANELBUTTON_FLAG_TOGGLED) == PANELBUTTON_FLAG_NONE)) { if ((isFlag40 == PANELBUTTON_FLAG_NONE) || (BVar1 = Interface_GetFlashingState(), BVar1 == 0)) { image = button->image; } else { image = button->imageHover; } } else { if ((isFlag40 != PANELBUTTON_FLAG_NONE) && (BVar1 = Interface_GetFlashingState(), BVar1 != 0)) goto LAB_0045ad31; image = button->imagePressed; } } if (image != NULL) { lego::image::Image_DisplayScaled(image,NULL,&destPos,NULL); } } LAB_0045ad5a: i += 1; offset += 0x2c; } while (i < globs::panelGlobs.panelTable[panelType].buttonCount); } return; } void __cdecl lego::front::Panel_Button_Hide(Panel_Type panelType,PanelButtonType buttonType,BOOL hide) { PanelButtonData *buttonList; PanelButtonFlags flags; PanelButtonFlags *pFlags; buttonList = globs::panelGlobs.panelTable[panelType].buttonList; pFlags = &buttonList[buttonType].flags; flags = buttonList[buttonType].flags; if (hide != 0) { *pFlags = flags | PANELBUTTON_FLAG_HIDDEN; return; } *pFlags = flags & ~PANELBUTTON_FLAG_HIDDEN; return; } void __cdecl lego::front::Panel_ToggleOpenClosed(Panel_Type panelType) { PanelDataFlags flags; flags = globs::panelGlobs.panelTable[panelType].flags; if ((flags & PANEL_FLAG_OPEN) != PANEL_FLAG_NONE) { globs::panelGlobs.panelTable[panelType].flags = flags & ~PANEL_FLAG_OPEN | (PANEL_FLAG_CLOSED|PANEL_FLAG_SLIDING); return; } globs::panelGlobs.panelTable[panelType].flags = flags & ~PANEL_FLAG_CLOSED | (PANEL_FLAG_OPEN|PANEL_FLAG_SLIDING); return; } // The panel is in its closed state and is NOT sliding. BOOL __cdecl lego::front::Panel_IsFullyClosed(Panel_Type panelType) { PanelDataFlags flags; flags = globs::panelGlobs.panelTable[panelType].flags; if (((flags & PANEL_FLAG_CLOSED) != PANEL_FLAG_NONE) && ((flags & PANEL_FLAG_SLIDING) == PANEL_FLAG_NONE)) { return TRUE; } return FALSE; } // The panel is in its opened state and is NOT sliding. BOOL __cdecl lego::front::Panel_IsFullyOpen(Panel_Type panelType) { PanelDataFlags flags; flags = globs::panelGlobs.panelTable[panelType].flags; if (((flags & PANEL_FLAG_OPEN) != PANEL_FLAG_NONE) && ((flags & PANEL_FLAG_SLIDING) == PANEL_FLAG_NONE)) { return TRUE; } return FALSE; } BOOL __cdecl lego::front::Panel_IsSliding(Panel_Type panelType) { return globs::panelGlobs.panelTable[panelType].flags & PANEL_FLAG_SLIDING; } void __cdecl lego::front::Panel_Button_SetToggleable (Panel_Type panelType,PanelButtonType buttonType,BOOL toggleable) { PanelButtonData *button; button = globs::panelGlobs.panelTable[panelType].buttonList + buttonType; if (toggleable != 0) { button->flags = button->flags | PANELBUTTON_FLAG_TOGGLEABLE; return; } button->flags = button->flags & ~PANELBUTTON_FLAG_TOGGLEABLE; return; } // Only used for TopPanel buttons Priorities and CallToArms to keep the button indented while // active. void __cdecl lego::front::Panel_Button_SetToggled(Panel_Type panelType,PanelButtonType buttonType,BOOL checked) { PanelButtonData *button; PanelButtonFlags flags; button = globs::panelGlobs.panelTable[panelType].buttonList + buttonType; flags = button->flags; if ((flags & PANELBUTTON_FLAG_TOGGLEABLE) != PANELBUTTON_FLAG_NONE) { if (checked != 0) { button->flags = flags | PANELBUTTON_FLAG_TOGGLED; return; } button->flags = flags & ~(PANELBUTTON_FLAG_DOWN|PANELBUTTON_FLAG_TOGGLED); } return; } void __cdecl lego::front::Panel_CreateButtons (Panel_Type panelType,uint count,PanelButton_Type *buttonTypes,Area2F *areas, char **imageNames,char **imageHoverNames,char **imagePressedNames,ToolTip_Type *toolTips) { PanelButtonData *buttons; Image *image; ToolTip_Type *pToolTip; char **pImageName; float *pArea_y; float area_height; float area_y; char *fileName; if (count != 0) { buttons = (PanelButtonData *)io::Mem_Alloc(count * 0x2c); globs::panelGlobs.panelTable[panelType].buttonList = buttons; globs::panelGlobs.panelTable[panelType].buttonCount = count; if (count != 0) { pArea_y = &areas->y; pImageName = imageNames; // There's a lot of nasty pointer math going on in this function but you can basically // ignore it. It's all done for the sake of not having a dedicated index variable. do { pToolTip = (ToolTip_Type *)(((int)toolTips - (int)imageNames) + (int)pImageName); buttons = globs::panelGlobs.panelTable[panelType].buttonList + *(int *)((int)pToolTip + ((int)buttonTypes - (int)toolTips)); (buttons->rect).left = pArea_y[-1]; (buttons->rect).top = *pArea_y; (buttons->rect).right = pArea_y[1] + pArea_y[-1]; area_height = pArea_y[2]; area_y = *pArea_y; buttons->image = NULL; buttons->imageHover = NULL; buttons->imagePressed = NULL; (buttons->rect).bottom = area_height + area_y; buttons->toolTipType = *pToolTip; if ((imageNames != NULL) && (*pImageName != NULL)) { image = lego::image::Image_LoadBMPScaled(*pImageName,0,0); buttons->image = image; if (image != NULL) { lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); } } if ((imageHoverNames != NULL) && (fileName = *(char **)(((int)imageHoverNames - (int)imageNames) + (int)pImageName), fileName != NULL)) { image = lego::image::Image_LoadBMPScaled(fileName,0,0); buttons->imageHover = image; if (image != NULL) { lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); } } if ((imagePressedNames != NULL) && (fileName = *(char **)(((int)imagePressedNames - (int)imageNames) + (int)pImageName), fileName != NULL)) { image = lego::image::Image_LoadBMPScaled(fileName,0,0); buttons->imagePressed = image; if (image != NULL) { lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); } } pArea_y = pArea_y + 4; pImageName = pImageName + 1; count -= 1; buttons->flags = PANELBUTTON_FLAG_NONE; } while (count != 0); } } return; } BOOL __cdecl lego::front::Panel_CheckCollision (float elapsedAbs,uint mouseX,uint mouseY,BOOL leftButton,BOOL leftButtonLast, BOOL *out_panelCollision) { int *piVar1; uint mouseY_00; BOOL BVar2; BOOL BVar3; TutorialFlags tflags; Lego_Level *level; BOOL BVar4; BVar2 = leftButtonLast; BVar4 = leftButton; mouseY_00 = mouseY; if (leftButton == 0) { globs::panelGlobs.flags &= ~PANEL_GLOB_FLAG_ROTATECONTROL_ACTIVE; } BVar3 = Panel_CheckButtonCollision ((Panel_Type *)&out_panelCollision,(PanelButtonType *)&leftButton,mouseX,mouseY, leftButton,leftButtonLast,&leftButtonLast,out_panelCollision); if (BVar3 == 0) { BVar4 = ScrollInfo_Mouse_FUN_00463b60((int *)&mouseY,mouseX,mouseY_00,BVar4,BVar2); if (BVar4 == 0) { return (BOOL)NULL; } if (mouseY == 0) { Info_UpdateInt6EC_FromScrollInfo(); } if (leftButtonLast == 0) { return (BOOL)(BOOL *)0x1; } } else { globs::legoGlobs.flags1 |= GAME1_MOUSEBUSY; // if (panelType == Panel_Type_Count || panelButton == PanelButton_Type_Count) if ((out_panelCollision == (BOOL *)&DAT_0000000c) || (leftButton == PANELBUTTON_TYPE_COUNT)) { return (BOOL)out_panelCollision; } tflags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (leftButtonLast != 0) { piVar1 = &globs::panelGlobs.panelTable[(int)out_panelCollision].buttonList[leftButton]. clickCount; *piVar1 = *piVar1 + 1; // if (panelType == Panel_Radar) if (((tflags & TUTORIAL_FLAG_NORADAR) != TUTORIAL_NONE) && (out_panelCollision == NULL)) { lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); return (BOOL)(BOOL *)TRUE; } // if (panelType == Panel_TopPanel && panelButton == PanelButton_TopPanel_Options) if ((((tflags & TUTORIAL_FLAG_NOOPTIONS) != TUTORIAL_NONE) && (out_panelCollision == (BOOL *)0x6)) && (leftButton == 0)) { Panel_Button_SetToggled(Panel_TopPanel,0,0); lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); return (BOOL)(BOOL *)TRUE; } // if (panelType == Panel_TopPanel && panelButton == PanelButton_TopPanel_Priorities) if ((((tflags & TUTORIAL_FLAG_NOPRIORITIES) != TUTORIAL_NONE) && (out_panelCollision == (BOOL *)0x6)) && (leftButton == 1)) { Panel_Button_SetToggled(Panel_TopPanel,1,FALSE); lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); return (BOOL)(BOOL *)TRUE; } // if (panelType == Panel_TopPanel && panelButton == PanelButton_TopPanel_CallToArms) if ((((tflags & TUTORIAL_FLAG_NOCALLTOARMS) != TUTORIAL_NONE) && (out_panelCollision == (BOOL *)0x6)) && (leftButton == 2)) { Panel_Button_SetToggled(Panel_TopPanel,2,FALSE); lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); return (BOOL)(BOOL *)TRUE; } // if (panelType == Panel_CameraControl && panelButton == // PanelButton_CameraControl_CycleBuildings) if ((((tflags & TUTORIAL_FLAG_NOCYCLEUNITS) != TUTORIAL_NONE) && (out_panelCollision == (BOOL *)&DAT_00000009)) && (leftButton == 2)) { lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); return (BOOL)(BOOL *)TRUE; } // if (panelType == Panel_CameraControl) if (((tflags & TUTORIAL_FLAG_NOCAMERA) != TUTORIAL_NONE) && (out_panelCollision == (BOOL *)&DAT_00000009)) { // if (panelButton == PanelButton_CameraControl_ZoomIn || panelButton == // PanelButton_CameraControl_ZoomOut) if ((leftButton == 0) || (leftButton == 1)) goto LAB_0045b57a; // if (panelButton == PanelButton_CameraControl_Rotate) if (leftButton == 3) { lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); return (BOOL)(BOOL *)TRUE; } } } if (BVar4 != 0) { if (out_panelCollision == NULL) { if ((globs::legoGlobs.flags1 & GAME1_RADAR_MAPVIEW) != GAME1_NONE) { if (leftButton == PanelButton_Radar_ZoomIn) { if (globs::legoGlobs.radarZoom < 20.0) { globs::legoGlobs.radarZoom = elapsedAbs + globs::legoGlobs.radarZoom; } if ((ushort)((ushort)(globs::legoGlobs.radarZoom < 20.0) << 8 | (ushort)(globs::legoGlobs.radarZoom == 20.0) << 0xe) == 0) { globs::legoGlobs.radarZoom = 20.0; } } else { if (leftButton == PanelButton_Radar_ZoomOut) { if ((ushort)((ushort)(globs::legoGlobs.radarZoom < 10.0) << 8 | (ushort)(globs::legoGlobs.radarZoom == 10.0) << 0xe) == 0) { globs::legoGlobs.radarZoom = globs::legoGlobs.radarZoom - elapsedAbs; } if (globs::legoGlobs.radarZoom < 10.0) { globs::legoGlobs.radarZoom = 10.0; } } } } } else { if (((out_panelCollision == (BOOL *)&DAT_00000009) && (tflags = nerps::funcs::NERPFunc__GetTutorialFlags(NULL), (tflags & TUTORIAL_FLAG_NOCAMERA) == TUTORIAL_NONE)) && (Panel_RotationControl_HandleButtons(leftButton,elapsedAbs), leftButton == PanelButton_CameraControl_Rotate)) { Panel_RotationControl_HandleRotation(mouseX,mouseY_00,elapsedAbs); } } } if (leftButtonLast == 0) { return (BOOL)(BOOL *)0x1; } level = lrr::Lego_GetLevel(); if (level->status == LEVELSTATUS_INCOMPLETE) { lrr::Lego_SetPointerSFX(PointerSFX_Okay); if (false) { return (BOOL)(BOOL *)0x1; } switch(out_panelCollision) { case NULL: // PanelButton_Radar_Toggle if (leftButton == 0) { Panel_ToggleOpenClosed(Panel_Radar); Panel_ToggleOpenClosed(Panel_RadarFill); return (BOOL)(BOOL *)TRUE; } if (leftButton != PanelButton_Radar_TaggedObjectView) { if (leftButton != PanelButton_Radar_MapView) { return (BOOL)(BOOL *)0x1; } // legoGlobs.flags1 &= ~GAME1_RADAR_TRACKOBJECTVIEW; // legoGlobs.flags1 |= GAME1_RADAR_MAPVIEW; globs::legoGlobs.flags1 = globs::legoGlobs.flags1 & ~GAME1_RADAR_TRACKOBJECTVIEW | GAME1_RADAR_MAPVIEW; Panel_Button_Hide(Panel_Radar,PanelButton_Radar_ZoomIn,FALSE); Panel_Button_Hide(Panel_Radar,PanelButton_Radar_ZoomOut,FALSE); return (BOOL)(BOOL *)TRUE; } // legoGlobs.flags1 &= ~GAME1_RADAR_MAPVIEW; // legoGlobs.flags1 |= GAME1_RADAR_TRACKOBJECTVIEW; globs::legoGlobs.flags1 = globs::legoGlobs.flags1 & (GAME1_HIGHFOGCOLOURRGB|GAME1_RADAR_NOTRACKOBJECT|GAME1_VERTEXMODE|GAME1_DYNAMICPM| GAME1_FREEZEINTERFACE|GAME1_CAMERAGOTO|GAME1_ONLYBUILDONPATHS|GAME1_ALWAYSROCKFALL| GAME1_DEBUG_NONERPS|GAME1_PAUSED|GAME1_STREAMNERPSSPEACH|GAME1_LEVELENDING| GAME1_LASERTRACKER|GAME1_DEBUG_SHOWVERTEXMODE|GAME1_DEBUG_NOCLIP_FPS| GAME1_VERTEXLOCKONPOINTER) | (ushort)((ushort)globs::legoGlobs.flags1 | 0x2000) & ~GAME1_RADAR_MAPVIEW; Panel_Button_Hide(Panel_Radar,PanelButton_Radar_ZoomIn,TRUE); Panel_Button_Hide(Panel_Radar,PanelButton_Radar_ZoomOut,TRUE); return (BOOL)(BOOL *)TRUE; default: return (BOOL)(BOOL *)0x1; case (BOOL *)0x6: goto switchD_0045b34e_caseD_6; case (BOOL *)0x8: if (leftButton == PanelButton_PriorityList_Reset) { ai::Priorities_Reset(); return (BOOL)(BOOL *)TRUE; } if (leftButton == PanelButton_PriorityList_Close) { if (((byte)globs::panelGlobs.panelTable[8].flags & 4) != 0) { return (BOOL)(BOOL *)0x1; } Interface_BackToMain(); return (BOOL)(BOOL *)TRUE; } Panel_PriorityList_HandleButton(leftButton); return (BOOL)(BOOL *)TRUE; case (BOOL *)0x9: if (leftButton != PanelButton_CameraControl_CycleBuildings) { return (BOOL)(BOOL *)0x1; } game::LegoObject_CameraCycleUnits(); return (BOOL)(BOOL *)TRUE; case (BOOL *)0xa: if (leftButton == PanelButton_InfoDock_Close) { Info_PopFirstMessage(); return (BOOL)(BOOL *)TRUE; } // PanelButton_InfoDock_Goto if (leftButton != 0) { return (BOOL)(BOOL *)0x1; } Info_UpdateMessage(0); Info_GotoFirst(); return (BOOL)(BOOL *)TRUE; case (BOOL *)0xb: // PanelButton_Encyclopedia_Close if (leftButton != 0) { return (BOOL)(BOOL *)0x1; } if (((byte)globs::panelGlobs.panelTable[11].flags & 4) != 0) { return (BOOL)(BOOL *)0x1; } Interface_BackToMain(); return (BOOL)(BOOL *)TRUE; } } } LAB_0045b57a: lrr::Lego_SetPointerSFX(PointerSFX_NotOkay); return (BOOL)(BOOL *)TRUE; switchD_0045b34e_caseD_6: if ((globs::legoGlobs.viewMode != ViewMode_FP) && (leftButton == PanelButton_TopPanel_Priorities)) { if (((byte)globs::panelGlobs.panelTable[8].flags & 4) == 0) { Interface_BackToMain(); } else { game::Message_PostEvent(Message_ClearSelection,0,0,NULL); Interface_OpenMenu(Interface_Menu_Type_Count,NULL); } } // PanelButton_TopPanel_Options if (leftButton == 0) { lrr::Lego_SetPaused(TRUE,0); globs::legoGlobs.flags2 = globs::legoGlobs.flags2 ^ GAME2_INOPTIONSMENU; return (BOOL)(BOOL *)TRUE; } if (leftButton != PanelButton_TopPanel_CallToArms) { return (BOOL)(BOOL *)0x1; } if ((globs::legoGlobs.flags2 & GAME2_CALLTOARMS) != GAME2_NONE) { lrr::Lego_SetCallToArmsOn(FALSE); return (BOOL)(BOOL *)TRUE; } lrr::Lego_SetCallToArmsOn(TRUE); return (BOOL)(BOOL *)TRUE; } BOOL __cdecl lego::front::Panel_CheckButtonCollision (Panel_Type *out_panelType,PanelButtonType *out_panelButton,int mouseX,int mouseY, BOOL leftButton,BOOL leftButtonLast,BOOL *optout_param_7,BOOL *optout_panelCollision) { BOOL BVar1; int iVar2; PanelButtonFlags PVar3; BOOL isOverButton; PanelButtonType panelButton; ToolTip_Type toolTipType; Panel_Type panelType; PanelButtonData *button; PanelButtonFlags TVar4; PanelButtonFlags TVar5; isOverButton = 0; if (optout_param_7 != NULL) { *optout_param_7 = 0; } // PANEL_BUTTON__COUNT ? *out_panelButton = PANELBUTTON_TYPE_COUNT; *out_panelType = Panel_Type_Count; // Flag must force some behavior for camera control (held down on button?) if (((byte)globs::panelGlobs.flags & 1) != 0) { *out_panelType = Panel_CameraControl; *out_panelButton = PanelButton_CameraControl_Rotate; return TRUE; } panelType = Panel_Radar; do { if ((*(byte *)&globs::panelGlobs.panelTable[panelType].flags & 1) != 0) { if ((((optout_panelCollision != NULL) && (panelType != Panel_RadarFill)) && (panelType != Panel_RadarOverlay)) && (BVar1 = Panel_TestPointInsideImage(panelType,mouseX,mouseY), BVar1 == 0)) { *optout_panelCollision = TRUE; } panelButton = 0; if (globs::panelGlobs.panelTable[panelType].buttonCount != 0) { do { button = globs::panelGlobs.panelTable[panelType].buttonList + panelButton; if (isOverButton == 0) { if ((panelType == Panel_CameraControl) && (panelButton == PanelButton_CameraControl_Rotate)) { iVar2 = Panel_TestPointInsideCircle (mouseX,mouseY,globs::panelGlobs.rotateCenter.x, globs::panelGlobs.rotateCenter.y,globs::panelGlobs.rotateRadius); } else { iVar2 = Panel_TestPointInsideRect (globs::panelGlobs.panelTable + panelType,&button->rect,mouseX, mouseY); } if ((false) || (iVar2 == 0)) goto LAB_0045b7eb; *out_panelType = panelType; if (leftButton == 0) { toolTipType = button->toolTipType; if (((toolTipType == ToolTip_CamControlCycle) && (globs::objectGlobs.cycleBuildingCount == 0)) && (((byte)globs::objectGlobs.flags & 0x40) != 0)) { toolTipType = ToolTip_CamControlCycleMinifigures; } ToolTip_Activate(toolTipType); if (globs::panelGlobs.currentButton != PANELBUTTON_TYPE_COUNT) { if ((panelType == globs::panelGlobs.currentPanel) && (panelButton == globs::panelGlobs.currentButton)) { *out_panelButton = panelButton; TVar4 = (&button->toolTipType)[2]; if ((TVar4 & PANELBUTTON_FLAG_TOGGLEABLE) != PANELBUTTON_FLAG_NONE) { if ((TVar4 & PANELBUTTON_FLAG_TOGGLED) == PANELBUTTON_FLAG_NONE) { PVar3 = TVar4 | PANELBUTTON_FLAG_TOGGLED; } else { PVar3 = TVar4 & ~PANELBUTTON_FLAG_TOGGLED; } (&button->toolTipType)[2] = PVar3; } if (optout_param_7 != NULL) { *optout_param_7 = TRUE; } (&button->toolTipType)[2] = (&button->toolTipType)[2] & 0xfffffffb | 2; } goto LAB_0045b7e4; } isOverButton = TRUE; *out_panelButton = panelButton; (&button->toolTipType)[2] = (&button->toolTipType)[2] & 0xfffffffb | 2; } else { if (globs::panelGlobs.currentButton == PANELBUTTON_TYPE_COUNT) { if (leftButtonLast == 0) { globs::panelGlobs.currentPanel = panelType; isOverButton = TRUE; globs::panelGlobs.currentButton = panelButton; *out_panelButton = panelButton; (&button->toolTipType)[2] = (&button->toolTipType)[2] & 0xfffffffd | 4; } else { LAB_0045b7e4: isOverButton = TRUE; } } else { if ((panelType != globs::panelGlobs.currentPanel) || (panelButton != globs::panelGlobs.currentButton)) goto LAB_0045b7e4; isOverButton = TRUE; *out_panelButton = panelButton; (&button->toolTipType)[2] = (&button->toolTipType)[2] & 0xfffffffd | 4; } } } else { LAB_0045b7eb: TVar5 = (&button->toolTipType)[2]; (&button->toolTipType)[2] = TVar5 & ~PANELBUTTON_FLAG_HOVER; if ((TVar5 & PANELBUTTON_FLAG_TOGGLED) == PANELBUTTON_FLAG_NONE) { PVar3 = TVar5 & ~(PANELBUTTON_FLAG_HOVER|PANELBUTTON_FLAG_DOWN); } else { PVar3 = TVar5 & ~PANELBUTTON_FLAG_HOVER | PANELBUTTON_FLAG_DOWN; } (&button->toolTipType)[2] = PVar3; } panelButton += 1; } while (panelButton < globs::panelGlobs.panelTable[panelType].buttonCount); } } panelType += Panel_RadarFill; if (Panel_Encyclopedia < panelType) { if (leftButton == 0) { globs::panelGlobs.currentPanel = Panel_Type_Count; globs::panelGlobs.currentButton = PANELBUTTON_TYPE_COUNT; } return isOverButton; } } while( true ); } BOOL __cdecl lego::front::Panel_TestPointInsideRect(PanelData *panel,Rect2F *rect,int mouseX,int mouseY) { longlong lVar1; longlong lVar2; float x; float y; lVar1 = __ftol((float10)(panel->position).x); lVar2 = __ftol((float10)(panel->position).y); x = (float)(mouseX - (int)lVar1); if ((((rect->left <= x) && (y = (float)(mouseY - (int)lVar2), y < rect->bottom)) && (rect->top <= y)) && (x < rect->right)) { return TRUE; } return 0; } void __cdecl lego::front::Panel_PriorityList_ResetButtons(void) { globs::panelGlobs.flags = globs::panelGlobs.flags & ~(PANEL_GLOB_FLAG_PRIORITIES_TOP|PANEL_GLOB_FLAG_PRIORITIES_UP); return; } void __cdecl lego::front::Panel_PriorityList_HandleButton(PanelButtonPriorityList buttonType) { switch(buttonType) { case PanelButton_PriorityList_Disable1: ai::Priorities_TurnPriorityOff(0); return; case PanelButton_PriorityList_Disable2: ai::Priorities_TurnPriorityOff(1); return; case PanelButton_PriorityList_Disable3: ai::Priorities_TurnPriorityOff(2); return; case PanelButton_PriorityList_Disable4: ai::Priorities_TurnPriorityOff(3); return; case PanelButton_PriorityList_Disable5: ai::Priorities_TurnPriorityOff(4); return; case PanelButton_PriorityList_Disable6: ai::Priorities_TurnPriorityOff(5); return; case PanelButton_PriorityList_Disable7: ai::Priorities_TurnPriorityOff(6); return; case PanelButton_PriorityList_Disable8: ai::Priorities_TurnPriorityOff(7); return; case PanelButton_PriorityList_Disable9: ai::Priorities_TurnPriorityOff(8); return; case PanelButton_PriorityList_UpOne1: ai::Priorities_MovePriorityUp(1); return; case PanelButton_PriorityList_UpOne2: ai::Priorities_MovePriorityUp(2); return; case PanelButton_PriorityList_UpOne3: ai::Priorities_MovePriorityUp(3); return; case PanelButton_PriorityList_UpOne4: ai::Priorities_MovePriorityUp(4); return; case PanelButton_PriorityList_UpOne5: ai::Priorities_MovePriorityUp(5); return; case PanelButton_PriorityList_UpOne6: ai::Priorities_MovePriorityUp(6); return; case PanelButton_PriorityList_UpOne7: ai::Priorities_MovePriorityUp(7); return; case PanelButton_PriorityList_UpOne8: ai::Priorities_MovePriorityUp(8); } return; } void __cdecl lego::front::Panel_ScrollInfo_Initialise(void) { Area2F rect; ScrollInfo_Initialise("Interface\\InfoPanel\\scrollInfo.bmp",0,0,7,0); ScrollInfo_SetXYOrSize_Unk(0,8,33); rect.x = 0.0; rect.y = 0.0; rect.width = 18.0; rect.height = 11.0; ScrollInfo_AddStruct1C(0,TRUE,&rect,NULL,NULL); rect.x = 0.0; rect.y = 11.0; rect.width = 18.0; rect.height = 11.0; ScrollInfo_AddStruct1C(0,FALSE,&rect,NULL,NULL); rect.x = 0.0; rect.y = 0.0; rect.width = 0.0; rect.height = 0.0; ScrollInfo_AddCreateStruct28(0,&rect,1,0,"Interface\\Buttons\\scrollInfoSld.bmp"); rect.x = 40.0; rect.y = 12.0; rect.width = 180.0; rect.height = 43.0; globs::panelGlobs.infoTextWnd = Panel_TextWindow_Create(Panel_Information,globs::legoGlobs.fontStandard,&rect,0x100); return; } void __cdecl lego::front::Panel_Encyclopedia_Initialise(void) { Area2F rect; rect.x = 21.0; rect.y = 11.0; rect.width = 221.0; rect.height = 227.0; globs::panelGlobs.encyclopediaTextWnd = Panel_TextWindow_Create(Panel_Encyclopedia,globs::legoGlobs.fontStandard,&rect,0x400); return; } BOOL __cdecl lego::front::Panel_TestPointInsideCircle(int x,int y,int centerX,int centerY,int radius) { float dist; dist = SQRT((float)(centerY - y) * (float)(centerY - y) + (float)(centerX - x) * (float)(centerX - x)); if ((ushort)((ushort)((float)radius < dist) << 8 | (ushort)((float)radius == dist) << 0xe) == 0) { return TRUE; } return 0; } void __cdecl lego::front::Panel_RotationControl_NormalizePointRadius (int x,int y,int radius,float *out_x,float *out_y) { *out_x = (float)x / (float)radius; *out_y = (float)y / (float)radius; return; } void __cdecl lego::front::Panel_RotationControl_ClampPointInsideCircle (int *ref_mouseX,int *ref_mouseY,int centerX,int centerY,int radius) { float fVar1; float10 extraout_ST0; float10 extraout_ST1; longlong lVar2; fVar1 = (float)((float10)*ref_mouseX - (float10)centerX); lVar2 = __ftol(((float10)1.0 / SQRT(((float10)*ref_mouseY - (float10)centerY) * (float10)(float)((float10)*ref_mouseY - (float10)centerY) + ((float10)*ref_mouseX - (float10)centerX) * (float10)fVar1)) * (float10)fVar1 * (float10)((float)radius - 1.0) + (float10)centerX); *ref_mouseX = (int)lVar2; lVar2 = __ftol(extraout_ST0 + extraout_ST1); *ref_mouseY = (int)lVar2; return; } void __cdecl lego::front::Panel_RotationControl_Initialise(Config *config,char *gameName) { char *pcVar1; float10 fVar2; char *local_28; char *local_24; char *local_20; pcVar1 = cfg::Config_BuildStringID(gameName,"PanelRotationControl","CenterPositionX",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { globs::panelGlobs.rotateCenter.x = 1; } else { globs::panelGlobs.rotateCenter.x = std::atoi(pcVar1); } pcVar1 = cfg::Config_BuildStringID(gameName,"PanelRotationControl","CenterPositionY",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { globs::panelGlobs.rotateCenter.y = 1; } else { globs::panelGlobs.rotateCenter.y = std::atoi(pcVar1); } pcVar1 = cfg::Config_BuildStringID(gameName,"PanelRotationControl","Radius",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { globs::panelGlobs.rotateRadius = 1; } else { globs::panelGlobs.rotateRadius = std::atoi(pcVar1); } pcVar1 = cfg::Config_BuildStringID(gameName,"PanelRotationControl","LeftImage",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { globs::panelGlobs.rotateLeftImage = NULL; } else { util::Util_Tokenise(pcVar1,&local_28,","); globs::panelGlobs.rotateLeftImage = lego::image::Image_LoadBMPScaled(local_28,0,0); lego::image::Image_SetPenZeroTrans(globs::panelGlobs.rotateLeftImage); fVar2 = std::atof(local_24); globs::panelGlobs.rotateLeftOffset.x = (float)fVar2; fVar2 = std::atof(local_20); globs::panelGlobs.rotateLeftOffset.y = (float)fVar2; io::Mem_Free(pcVar1); } pcVar1 = cfg::Config_BuildStringID(gameName,"PanelRotationControl","RightImage",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { globs::panelGlobs.rotateRightImage = NULL; } else { util::Util_Tokenise(pcVar1,&local_28,","); globs::panelGlobs.rotateRightImage = lego::image::Image_LoadBMPScaled(local_28,0,0); lego::image::Image_SetPenZeroTrans(globs::panelGlobs.rotateRightImage); fVar2 = std::atof(local_24); globs::panelGlobs.rotateRightOffset.x = (float)fVar2; fVar2 = std::atof(local_20); globs::panelGlobs.rotateRightOffset.y = (float)fVar2; io::Mem_Free(pcVar1); } pcVar1 = cfg::Config_BuildStringID(gameName,"PanelRotationControl","UpImage",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 == NULL) { globs::panelGlobs.rotateUpImage = NULL; } else { util::Util_Tokenise(pcVar1,&local_28,","); globs::panelGlobs.rotateUpImage = lego::image::Image_LoadBMPScaled(local_28,0,0); lego::image::Image_SetPenZeroTrans(globs::panelGlobs.rotateUpImage); fVar2 = std::atof(local_24); globs::panelGlobs.rotateUpOffset.x = (float)fVar2; fVar2 = std::atof(local_20); globs::panelGlobs.rotateUpOffset.y = (float)fVar2; io::Mem_Free(pcVar1); } pcVar1 = cfg::Config_BuildStringID(gameName,"PanelRotationControl","DownImage",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 != NULL) { util::Util_Tokenise(pcVar1,&local_28,","); globs::panelGlobs.rotateDownImage = lego::image::Image_LoadBMPScaled(local_28,0,0); lego::image::Image_SetPenZeroTrans(globs::panelGlobs.rotateDownImage); fVar2 = std::atof(local_24); globs::panelGlobs.rotateDownOffset.x = (float)fVar2; fVar2 = std::atof(local_20); globs::panelGlobs.rotateDownOffset.y = (float)fVar2; io::Mem_Free(pcVar1); return; } globs::panelGlobs.rotateDownImage = NULL; return; } BOOL __cdecl lego::front::Panel_RotationControl_HandleRotation(int mouseX,int mouseY,float elapsedAbs) { float yawAmount; BOOL BVar1; float y; float x; BVar1 = Panel_TestPointInsideCircle (mouseX,mouseY,globs::panelGlobs.rotateCenter.x,globs::panelGlobs.rotateCenter.y ,globs::panelGlobs.rotateRadius); if (BVar1 == 0) { if ((globs::panelGlobs.flags & PANEL_GLOB_FLAG_ROTATECONTROL_ACTIVE) == PANEL_GLOB_FLAG_NONE) { return 0; } if (true) { // Clamp mouse inside rotation control, and skip testing deadzone. Panel_RotationControl_ClampPointInsideCircle (&mouseX,&mouseY,globs::panelGlobs.rotateCenter.x,globs::panelGlobs.rotateCenter.y, globs::panelGlobs.rotateRadius); input::Input_SetCursorPos(mouseX,mouseY); goto LAB_0045c031; } } // Test deadzone? BVar1 = Panel_TestPointInsideCircle (mouseX,mouseY,globs::panelGlobs.rotateCenter.x,globs::panelGlobs.rotateCenter.y ,4); if (BVar1 != 0) { return 1; } LAB_0045c031: globs::panelGlobs.flags |= PANEL_GLOB_FLAG_ROTATECONTROL_ACTIVE; Panel_RotationControl_NormalizePointRadius (globs::panelGlobs.rotateCenter.x - mouseX,mouseY - globs::panelGlobs.rotateCenter.y, globs::panelGlobs.rotateRadius,&x,&y); // Test if horizontal arrows are excluded. BVar1 = Panel_TestPointInsideCircle (mouseX,globs::panelGlobs.rotateCenter.y,globs::panelGlobs.rotateCenter.x, globs::panelGlobs.rotateCenter.y,3); if (BVar1 != 0) { // If we're in this block, then the mouse Y is outside the deadzone, and mouse X is // inside the exclusion zone. We can return here. lego::view::Camera_AddTilt(globs::legoGlobs.cameraMain,y * elapsedAbs * 0.04); if (0.0 <= y) { globs::panelGlobs.flags = globs::panelGlobs.flags | PANEL_GLOB_FLAG_ROTATECONTROL_DOWN; return 1; } globs::panelGlobs.flags = globs::panelGlobs.flags | PANEL_GLOB_FLAG_ROTATECONTROL_UP; return 1; } // Test if vertical arrows are excluded. BVar1 = Panel_TestPointInsideCircle (globs::panelGlobs.rotateCenter.x,mouseY,globs::panelGlobs.rotateCenter.x, globs::panelGlobs.rotateCenter.y,3); yawAmount = x * elapsedAbs * 0.04; if (BVar1 == 0) { lego::view::Camera_AddRotation(globs::legoGlobs.cameraMain,yawAmount); lego::view::Camera_AddTilt(globs::legoGlobs.cameraMain,y * elapsedAbs * 0.04); if (0.0 <= y) { globs::panelGlobs.flags |= PANEL_GLOB_FLAG_ROTATECONTROL_DOWN; } else { globs::panelGlobs.flags |= PANEL_GLOB_FLAG_ROTATECONTROL_UP; } if (x < 0.0) { globs::panelGlobs.flags = globs::panelGlobs.flags | PANEL_GLOB_FLAG_ROTATECONTROL_RIGHT; return 1; } } else { // If we're in this block, then the mouse X is outside the deadzone, and mouse Y is // inside the exclusion zone. We can return here. lego::view::Camera_AddRotation(globs::legoGlobs.cameraMain,yawAmount); if (x < 0.0) { globs::panelGlobs.flags = globs::panelGlobs.flags | PANEL_GLOB_FLAG_ROTATECONTROL_RIGHT; return 1; } } globs::panelGlobs.flags = globs::panelGlobs.flags | PANEL_GLOB_FLAG_ROTATECONTROL_LEFT; return 1; } void __cdecl lego::front::Panel_RotationControl_HandleButtons(PanelButton_Type buttonType,float elapsedAbs) { if (buttonType == PanelButton_CameraControl_ZoomIn) { lego::view::Camera_AddZoom(globs::legoGlobs.cameraMain,elapsedAbs * -3.0); return; } if (buttonType == PanelButton_CameraControl_ZoomOut) { lego::view::Camera_AddZoom(globs::legoGlobs.cameraMain,elapsedAbs * 3.0); } return; } void __cdecl lego::front::Panel_Button_GetArea(Panel_Type panelType,PanelButtonType buttonType,Area2F *out_area) { PanelButtonData *button; PanelButtonData *buttonList; buttonList = globs::panelGlobs.panelTable[panelType].buttonList; button = buttonList + buttonType; out_area->x = buttonList[buttonType].rect.left; out_area->y = (button->rect).top; out_area->width = (button->rect).right - (button->rect).left; out_area->height = (button->rect).bottom - (button->rect).top; return; } void __cdecl lego::front::Panel_Crystals_Initialise(char *smallCrystal,char *usedCrystal,char *noSmallCrystal) { globs::panelGlobs.crystalSmallImage = lego::image::Image_LoadBMPScaled(smallCrystal,0,0); if (globs::panelGlobs.crystalSmallImage != NULL) { lego::image::Image_SetupTrans(globs::panelGlobs.crystalSmallImage,0.0,0.0,0.0,0.0,0.0,0.0); } globs::panelGlobs.crystalUsedImage = lego::image::Image_LoadBMPScaled(usedCrystal,0,0); if (globs::panelGlobs.crystalUsedImage != NULL) { lego::image::Image_SetupTrans(globs::panelGlobs.crystalUsedImage,0.0,0.0,0.0,0.0,0.0,0.0); } globs::panelGlobs.crystalNoSmallImage = lego::image::Image_LoadBMPScaled(noSmallCrystal,0,0); if (globs::panelGlobs.crystalNoSmallImage != NULL) { lego::image::Image_SetupTrans(globs::panelGlobs.crystalNoSmallImage,0.0,0.0,0.0,0.0,0.0,0.0); } return; } void __cdecl lego::front::Panel_Crystals_LoadRewardQuota(Config *config,char *gameName,char *levelName) { char *pcVar1; pcVar1 = cfg::Config_BuildStringID(gameName,levelName,"Reward","Quota","Crystals",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(gameName,levelName,"Reward","Quota","Crystals",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); } globs::panelGlobs.crystalQuota = std::atoi(pcVar1); if ((26 < globs::panelGlobs.crystalQuota) || (globs::panelGlobs.crystalQuota == 0)) { // Max that can fit on-screen in the sidebar maybe?? globs::panelGlobs.crystalQuota = 26; } return; } void __cdecl lego::front::Panel_Crystals_Draw(uint crystals,uint usedCrystals,float elapsedGame_unused) { uint (*pauVar1) [6]; uint uVar2; int iVar3; uint *puVar4; uint (*pauVar5) [6]; uint uVar6; CryTuple_8 *pCVar7; uint uVar8; uint uVar9; Image *image; CryTuple_8 *local_70; float local_6c; uint baseCounts [2]; CryTuple_8 tableCounts [12]; // [26] is the hardcoded max displayable crystals in the sidebar tableCounts[0].cryCount = 0; baseCounts[0] = 0; puVar4 = &tableCounts[0].unkCount; for (iVar3 = 0x17; iVar3 != 0; iVar3 += -1) { *puVar4 = 0; puVar4 = puVar4 + 1; } baseCounts[1] = 0; // shift both all/used crystals tables down by one // [0] <- [1] ... [5] <- count pauVar5 = globs::panelGlobs.s_crystalShifts; do { iVar3 = 2; pauVar1 = pauVar5; do { (*pauVar1)[0] = (*pauVar1)[1]; pauVar1 = pauVar1[1]; iVar3 += -1; } while (iVar3 != 0); pauVar5 = (uint (*) [6])(*pauVar5 + 1); } while (pauVar5 < (uint (*) [6])(globs::panelGlobs.s_crystalShifts + 5)); globs::panelGlobs.s_crystalShifts[0][5] = crystals; local_70 = tableCounts; globs::panelGlobs.s_crystalShifts[1][5] = usedCrystals; uVar6 = 0; puVar4 = baseCounts; do { uVar8 = 0; do { uVar9 = *puVar4; uVar2 = 0; if (uVar9 != 0) { pCVar7 = local_70; do { if (pCVar7->cryCount == globs::panelGlobs.s_crystalShifts[uVar8 + uVar6]) { tableCounts[uVar2 + uVar6].unkCount = tableCounts[uVar2 + uVar6].unkCount + 1; break; } uVar2 += 1; pCVar7 = pCVar7 + 1; } while (uVar2 < uVar9); } if (uVar2 == uVar9) { tableCounts[uVar2 + uVar6].cryCount = globs::panelGlobs.s_crystalShifts[uVar8 + uVar6]; tableCounts[uVar2 + uVar6].unkCount = 1; *puVar4 = uVar9 + 1; } uVar8 += 1; } while (uVar8 < 6); uVar6 += 6; local_70 = local_70 + 6; puVar4 = puVar4 + 1; // end of last loop // if (i >= 12) (aka, i >= 2, where i is a multiple of 6) if (0xb < uVar6) { uVar6 = 0; do { uVar8 = baseCounts[uVar6]; uVar9 = 0; if (uVar8 != 0) { pCVar7 = tableCounts; puVar4 = &tableCounts[uVar6 * 6].unkCount; do { uVar2 = *puVar4; if (uVar9 < uVar2) { uVar9 = uVar2; if (uVar6 == 0) { crystals = pCVar7->cryCount; } else { usedCrystals = puVar4[-1]; } } pCVar7 = pCVar7 + 1; puVar4 = puVar4 + 2; uVar8 -= 1; } while (uVar8 != 0); } uVar6 += 1; } while (uVar6 < 2); Panel_PrintF(Panel_CrystalSideBar,globs::legoGlobs.fontToolTip,0x29,0x1d5,1,"%i",crystals); if (globs::panelGlobs.crystalNoSmallImage != NULL) { // More hardcoded screen resolution positions local_70 = (CryTuple_8 *)0x441c0000; local_6c = 429.0; for (uVar6 = globs::panelGlobs.crystalQuota; uVar6 != 0; uVar6 -= 1) { lego::image::Image_DisplayScaled (globs::panelGlobs.crystalNoSmallImage,NULL,(Point2F *)&local_70,NULL); local_6c = local_6c - 17.0; } } if (globs::panelGlobs.crystalSmallImage != NULL) { uVar6 = 0; if (globs::panelGlobs.crystalQuota < crystals) { crystals = globs::panelGlobs.crystalQuota; } if (globs::panelGlobs.crystalQuota < usedCrystals) { usedCrystals = globs::panelGlobs.crystalQuota; } // More hardcoded screen resolution positions local_70 = (CryTuple_8 *)0x441c0000; local_6c = 429.0; image = globs::panelGlobs.crystalSmallImage; uVar8 = usedCrystals; if (globs::panelGlobs.crystalUsedImage != NULL) { for (; image = globs::panelGlobs.crystalUsedImage, globs::panelGlobs.crystalUsedImage = image, uVar8 != 0; uVar8 = uVar8 - 1) { lego::image::Image_DisplayScaled (globs::panelGlobs.crystalSmallImage,NULL,(Point2F *)&local_70,NULL); local_6c = local_6c - 17.0; uVar6 = usedCrystals; } } if (uVar6 < crystals) { iVar3 = crystals - uVar6; do { lego::image::Image_DisplayScaled(image,NULL,(Point2F *)&local_70,NULL); local_6c = local_6c - 17.0; iVar3 += -1; } while (iVar3 != 0); } } return; } } while( true ); } void __cdecl lego::front::Panel_AirMeter_Initialise (char *airJuiceName,uint juiceX,uint juiceY,uint juiceLength,char *noAirName,uint noAirX, uint noAirY) { globs::panelGlobs.airMeterJuiceImage = lego::image::Image_LoadBMPScaled(airJuiceName,0,0); globs::panelGlobs.airMeterJuiceOffset.x = (float)(ulonglong)juiceX; globs::panelGlobs.airMeterJuiceOffset.y = (float)(ulonglong)juiceY; globs::panelGlobs.airMeterJuiceLength = juiceLength; globs::panelGlobs.airMeterNoAirImage = lego::image::Image_LoadBMPScaled(noAirName,0,0); if (globs::panelGlobs.airMeterNoAirImage != NULL) { lego::image::Image_SetupTrans(globs::panelGlobs.airMeterNoAirImage,0.0,0.0,0.0,0.0,0.0,0.0); } globs::panelGlobs.airMeterNoAirOffset.x = (float)(ulonglong)noAirX; globs::panelGlobs.airMeterNoAirOffset.y = (float)(ulonglong)noAirY; return; } void __cdecl lego::front::Panel_AirMeter_DrawJuice(Panel_Type panelType,float oxygen) { Point2F destPos; Size2F destSize; // if (airMeterJuiceImage != nullptr && oxygen > 0.0f) if ((globs::panelGlobs.airMeterJuiceImage != NULL) && ((ushort)((ushort)(oxygen < 0.0) << 8 | (ushort)(oxygen == 0.0) << 0xe) == 0)) { destSize.height = (float)(globs::panelGlobs.airMeterJuiceImage)->height; // if (oxygen > 100.0f) oxygen = 100.0f; if ((ushort)((ushort)(oxygen < 100.0) << 8 | (ushort)(oxygen == 100.0) << 0xe) == 0) { oxygen = (float)&DAT_42c80000; } destSize.width = (float)(ulonglong)globs::panelGlobs.airMeterJuiceLength * 0.01 * oxygen; destPos.x = globs::panelGlobs.panelTable[panelType].position.x + globs::panelGlobs.airMeterJuiceOffset.x; destPos.y = globs::panelGlobs.panelTable[panelType].position.y + globs::panelGlobs.airMeterJuiceOffset.y; lego::image::Image_DisplayScaled(globs::panelGlobs.airMeterJuiceImage,NULL,&destPos,&destSize); } return; } // Tells the AirMeter panel if the Oxygen level is low (10% or less). void __cdecl lego::front::Panel_AirMeter_SetOxygenLow(BOOL o2Low) { globs::panelGlobs.airMeterOxygenLow = o2Low; return; } // This function handles the logic of only drawing when SetOxygenLow is true. void __cdecl lego::front::Panel_AirMeter_DrawOxygenLow(Panel_Type panelType) { Image *image; BOOL BVar1; Point2F destPos; image = globs::panelGlobs.airMeterNoAirImage; if (globs::panelGlobs.airMeterNoAirImage != NULL) { destPos.x = globs::panelGlobs.panelTable[panelType].position.x + globs::panelGlobs.airMeterNoAirOffset.x; destPos.y = globs::panelGlobs.panelTable[panelType].position.y + globs::panelGlobs.airMeterNoAirOffset.y; if (globs::panelGlobs.airMeterOxygenLow != 0) { BVar1 = Interface_GetFlashingState(); if (BVar1 != 0) { lego::image::Image_DisplayScaled(image,NULL,&destPos,NULL); } } } return; } void __cdecl lego::front::Panel_CryOreSideBar_Initialise(char *sidebarName,uint xPos,uint yPos,uint meterOffset) { globs::panelGlobs.cryOreSideBarImage = lego::image::Image_LoadBMPScaled(sidebarName,0,0); globs::panelGlobs.cryOreSideBarOffset.x = (float)(ulonglong)xPos; globs::panelGlobs.cryOreSideBarOffset.y = (float)(ulonglong)yPos; globs::panelGlobs.cryOreMeterOffset = meterOffset; return; } void __cdecl lego::front::Panel_CryOreSideBar_ChangeOreMeter(BOOL increment,uint amount) { if (increment == 0) { if (amount != 0) { do { amount -= 1; globs::panelGlobs.cryOreMeterValue = (globs::panelGlobs.cryOreMeterValue - 0.05) * 20.0 * 0.05263158; } while (amount != 0); } } else { if (amount != 0) { do { amount -= 1; globs::panelGlobs.cryOreMeterValue = globs::panelGlobs.cryOreMeterValue - (1.0 - globs::panelGlobs.cryOreMeterValue) * -0.05 ; } while (amount != 0); } } if (globs::panelGlobs.cryOreMeterValue < 0.0) { globs::panelGlobs.cryOreMeterValue = 0.0; } return; } void __cdecl lego::front::Panel_CryOreSideBar_Draw(void) { Size2F local_10; Point2F local_8; if ((globs::panelGlobs.cryOreSideBarImage != NULL) && ((ushort)((ushort)(globs::panelGlobs.cryOreMeterValue < 0.0) << 8 | (ushort)(globs::panelGlobs.cryOreMeterValue == 0.0) << 0xe) == 0)) { local_10.width = (float)(globs::panelGlobs.cryOreSideBarImage)->width; local_8.x = globs::panelGlobs.cryOreSideBarOffset.x; local_10.height = (float)(ulonglong)globs::panelGlobs.cryOreMeterOffset * globs::panelGlobs.cryOreMeterValue; local_8.y = globs::panelGlobs.cryOreSideBarOffset.y - local_10.height; lego::image::Image_DisplayScaled(globs::panelGlobs.cryOreSideBarImage,NULL,&local_8,&local_10); } return; } BOOL __cdecl lego::front::Panel_SetCurrentAdvisorFromButton (Panel_Type panelType,PanelButtonType buttonType,BOOL setFlag2) { BOOL BVar1; BVar1 = Panel_GetAdvisorTypeFromButton(panelType,buttonType,&buttonType); if (BVar1 != 0) { Advisor_Start(buttonType,setFlag2); return TRUE; } return 0; } BOOL __cdecl lego::front::Panel_GetAdvisorTypeFromButton (Panel_Type panelType,PanelButtonType buttonType,Advisor_Type *out_advisorType) { // max value is used as "invalid" *out_advisorType = Advisor_Type_Count; if (true) { switch(panelType) { case Panel_Radar: // PANELBUTTON_RADAR_TOGGLE (0x0) if (buttonType == 0) { *out_advisorType = Advisor_PanelPoint_RadarToggle; return (uint)(*out_advisorType != Advisor_Type_Count); } // PANELBUTTON_RADAR_TAGGEDOBJECTVIEW (0x1) if (buttonType == 1) { *out_advisorType = Advisor_PanelPoint_RadarTaggedObjectView; return (uint)(*out_advisorType != Advisor_Type_Count); } // PANELBUTTON_RADAR_ZOOMIN (0x2) if (buttonType == 2) { *out_advisorType = Advisor_PanelPoint_RadarZoomIn; return (uint)(*out_advisorType != Advisor_Type_Count); } // PANELBUTTON_RADAR_ZOOMOUT (0x3) if (buttonType == 3) { *out_advisorType = Advisor_PanelPoint_RadarZoomOut; return (uint)(*out_advisorType != Advisor_Type_Count); } // PANELBUTTON_RADAR_MAPVIEW (0x4) if (buttonType == 4) { *out_advisorType = Advisor_PanelPoint_RadarMapView; return (uint)(*out_advisorType != Advisor_Type_Count); } break; case Panel_TopPanel: // PANELBUTTON_TOPPANEL_OPTIONS (0x0) if (buttonType == 0) { *out_advisorType = Advisor_PanelPoint_TopPanelOptions; return (uint)(*out_advisorType != Advisor_Type_Count); } // PANELBUTTON_TOPPANEL_PRIORITIES (0x1) if (buttonType == 1) { *out_advisorType = Advisor_PanelPoint_TopPanelPriorities; return (uint)(*out_advisorType != Advisor_Type_Count); } // PANELBUTTON_TOPPANEL_CALLTOARMS (0x2) if (buttonType == 2) { *out_advisorType = Advisor_PanelPoint_TopPanelCallToArms; return (uint)(*out_advisorType != Advisor_Type_Count); } break; case Panel_CameraControl: if (buttonType == 0) { *out_advisorType = Advisor_PanelPoint_ControlZoomIn; return (uint)(*out_advisorType != Advisor_Type_Count); } if (buttonType == 1) { *out_advisorType = Advisor_PanelPoint_ControlZoomOut; } break; case Panel_InfoDock: if (buttonType == 0) { *out_advisorType = Advisor_PanelPoint_InfoDockGoto; return (uint)(*out_advisorType != Advisor_Type_Count); } if (buttonType == 1) { *out_advisorType = Advisor_PanelPoint_InfoDockClose; return (uint)(*out_advisorType != Advisor_Type_Count); } } } return (uint)(*out_advisorType != Advisor_Type_Count); } void __cdecl lego::front::Pointer_Initialise(void) { globs::pointerGlobs.pointerName[0] = "Pointer_Standard"; globs::pointerGlobs.pointerName[1] = "Pointer_Blank"; globs::pointerGlobs.pointerName[2] = "Pointer_Selected"; globs::pointerGlobs.pointerName[3] = "Pointer_Drill"; globs::pointerGlobs.pointerName[4] = "Pointer_CantDrill"; globs::pointerGlobs.pointerName[5] = "Pointer_Clear"; globs::pointerGlobs.pointerName[6] = "Pointer_Go"; globs::pointerGlobs.pointerName[7] = "Pointer_CantGo"; globs::pointerGlobs.pointerName[8] = "Pointer_Teleport"; globs::pointerGlobs.pointerName[9] = "Pointer_CantTeleport"; globs::pointerGlobs.pointerName[10] = "Pointer_Reinforce"; globs::pointerGlobs.pointerName[11] = "Pointer_CantReinforce"; globs::pointerGlobs.pointerName[12] = "Pointer_RadarPan"; globs::pointerGlobs.pointerName[13] = "Pointer_TrackObject"; globs::pointerGlobs.pointerName[14] = "Pointer_Help"; globs::pointerGlobs.pointerName[15] = "Pointer_CantHelp"; globs::pointerGlobs.pointerName[16] = "Pointer_PutDown"; globs::pointerGlobs.pointerName[17] = "Pointer_GetIn"; globs::pointerGlobs.pointerName[18] = "Pointer_GetOut"; globs::pointerGlobs.pointerName[19] = "Pointer_TutorialBlockInfo"; globs::pointerGlobs.pointerName[20] = "Pointer_Okay"; globs::pointerGlobs.pointerName[21] = "Pointer_NotOkay"; globs::pointerGlobs.pointerName[22] = "Pointer_CanBuild"; globs::pointerGlobs.pointerName[23] = "Pointer_CannotBuild"; globs::pointerGlobs.pointerName[24] = "Pointer_Dynamite"; globs::pointerGlobs.pointerName[25] = "Pointer_CantDynamite"; globs::pointerGlobs.pointerName[26] = "Pointer_PickUp"; globs::pointerGlobs.pointerName[27] = "Pointer_CantPickUp"; globs::pointerGlobs.pointerName[28] = "Pointer_PickUpOre"; globs::pointerGlobs.pointerName[29] = "Pointer_LegoManCantDig"; globs::pointerGlobs.pointerName[30] = "Pointer_VehicleCantDig"; globs::pointerGlobs.pointerName[31] = "Pointer_LegoManDig"; globs::pointerGlobs.pointerName[32] = "Pointer_VehicleDig"; globs::pointerGlobs.pointerName[33] = "Pointer_LegoManCantPickUp"; globs::pointerGlobs.pointerName[34] = "Pointer_VehicleCantPickUp"; globs::pointerGlobs.pointerName[35] = "Pointer_LegoManPickUp"; globs::pointerGlobs.pointerName[36] = "Pointer_VehiclePickUp"; globs::pointerGlobs.pointerName[37] = "Pointer_LegoManCantGo"; globs::pointerGlobs.pointerName[38] = "Pointer_VehicleCantGo"; globs::pointerGlobs.pointerName[39] = "Pointer_LegoManGo"; globs::pointerGlobs.pointerName[40] = "Pointer_VehicleGo"; globs::pointerGlobs.pointerName[41] = "Pointer_LegoManClear"; globs::pointerGlobs.pointerName[42] = "Pointer_VehicleClear"; globs::pointerGlobs.pointerName[43] = "Pointer_SurfaceType_Immovable"; globs::pointerGlobs.pointerName[44] = "Pointer_SurfaceType_Hard"; globs::pointerGlobs.pointerName[45] = "Pointer_SurfaceType_Medium"; globs::pointerGlobs.pointerName[46] = "Pointer_SurfaceType_Loose"; globs::pointerGlobs.pointerName[47] = "Pointer_SurfaceType_Soil"; globs::pointerGlobs.pointerName[48] = "Pointer_SurfaceType_Lava"; globs::pointerGlobs.pointerName[49] = "Pointer_SurfaceType_Water"; globs::pointerGlobs.pointerName[50] = "Pointer_SurfaceType_OreSeam"; globs::pointerGlobs.pointerName[51] = "Pointer_SurfaceType_Lake"; globs::pointerGlobs.pointerName[52] = "Pointer_SurfaceType_CrystalSeam"; globs::pointerGlobs.pointerName[53] = "Pointer_SurfaceType_RechargeSeam"; globs::pointerGlobs.pointerName[54] = "Pointer_CantZoom"; globs::pointerGlobs.pointerName[55] = "Pointer_Zoom"; return; } // Load all Pointers in the CFG block (prop is the first child in the block) // // USAGE: // USAGE: ,, // // NOTE: config is the first item in the array of pointers!! void __cdecl lego::front::Pointer_Load(Config *config) { char cVar1; Pointer_Type PVar2; BOOL BVar3; int numParts; Image *pIVar4; int iVar5; char *pointerName; char *pcVar6; Pointer_Type pointerType; char *stringParts [10]; char buff [1024]; bool reduced; if (config != NULL) { do { pointerName = config->key; reduced = true; if (pointerName != NULL) { iVar5 = -1; pcVar6 = pointerName; do { if (iVar5 == 0) break; iVar5 += -1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); if ((iVar5 != -2) && (*pointerName == '!')) { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEIMAGES) == MAIN_FLAG_NONE) { pointerName = pointerName + 1; } else { reduced = false; } } } if ((reduced) && (BVar3 = Pointer_GetType(pointerName,&pointerType), BVar3 != 0)) { std::sprintf(buff,"%s",config->value); numParts = util::Util_Tokenise(buff,stringParts,","); PVar2 = pointerType; if (numParts == 1) { pIVar4 = lego::image::Image_LoadBMPScaled(stringParts[0],0,0); globs::pointerGlobs.images[PVar2] = pIVar4; globs::pointerGlobs.imageIsFlic[PVar2] = 0; } else { lego::image::Flic_Setup (stringParts[0],(Flic **)(globs::pointerGlobs.images + pointerType), FLICMEMORY|FLICLOOPINGON); globs::pointerGlobs.imageIsFlic[pointerType] = 1; iVar5 = std::atoi(stringParts[1]); globs::pointerGlobs.flicOffsets[pointerType].x = iVar5; iVar5 = std::atoi(stringParts[2]); globs::pointerGlobs.flicOffsets[pointerType].y = iVar5; } if (globs::pointerGlobs.imageIsFlic[pointerType] == 0) { lego::image::Image_SetupTrans (globs::pointerGlobs.images[pointerType],0.0,0.0,0.0,0.0,0.0,0.0); } } config = cfg::Config_GetNextItem(config); } while (config != NULL); } return; } BOOL __cdecl lego::front::Pointer_GetType(char *name,Pointer_Type *out_pointerType) { int cmp; char **pName; int i; i = 0; pName = globs::pointerGlobs.pointerName; do { cmp = std::_stricmp(*pName,name); if (cmp == 0) { *out_pointerType = i; return TRUE; } pName = pName + 1; i += Pointer_Blank; } while (pName < &globs::pointerGlobs.timer); return 0; } Image * __cdecl lego::front::Pointer_GetImage(Pointer_Type pointerType) { return globs::pointerGlobs.images[pointerType]; } void __cdecl lego::front::Pointer_SetCurrent_IfTimerFinished(Pointer_Type pointerType) { if ((ushort)((ushort)(globs::pointerGlobs.timer < 0.0) << 8 | (ushort)(globs::pointerGlobs.timer == 0.0) << 0xe) != 0) { globs::pointerGlobs.currType = pointerType; } return; } void __cdecl lego::front::Pointer_SetCurrent(Pointer_Type pointerType,float timer) { globs::pointerGlobs.currType = pointerType; globs::pointerGlobs.timer = timer; return; } Pointer_Type __cdecl lego::front::Pointer_GetCurrentType(void) { return globs::pointerGlobs.currType; } void __cdecl lego::front::Pointer_DrawPointer(uint mouseX,uint mouseY) { Image *image; uint uVar1; Point2F destPos; Area2F destArea; destPos.x = (float)(ulonglong)mouseX; destPos.y = (float)(ulonglong)mouseY; if (globs::pointerGlobs.imageIsFlic[globs::pointerGlobs.currType] != TRUE) { // Draw a BMP image pointer image = globs::pointerGlobs.images[globs::pointerGlobs.currType]; if (globs::pointerGlobs.images[globs::pointerGlobs.currType] == NULL) { image = globs::pointerGlobs.images[0]; } lego::image::Image_DisplayScaled(image,NULL,&destPos,NULL); return; } // Draw a FLIC image pointer destArea.x = (float)globs::pointerGlobs.flicOffsets[globs::pointerGlobs.currType].x + destPos.x; destArea.y = (float)globs::pointerGlobs.flicOffsets[globs::pointerGlobs.currType].y + destPos.y; uVar1 = gfx::AnimClone_IsLws__Flic_GetWidth ((AnimClone *)globs::pointerGlobs.images[globs::pointerGlobs.currType]); destArea.width = (float)(ulonglong)uVar1; uVar1 = lego::image::Flic_GetHeight ((Flic *)globs::pointerGlobs.images[globs::pointerGlobs.currType]); destArea.height = (float)(ulonglong)uVar1; lego::image::Image_DisplayScaled(globs::pointerGlobs.images[1],NULL,&destPos,NULL); // GAME1_CAMERADISABLED (0x100000) lego::image::Flic_Animate ((Flic *)globs::pointerGlobs.images[globs::pointerGlobs.currType],&destArea, ~globs::legoGlobs.flags1 >> 0x14 & 1,TRUE); return; } void __cdecl lego::front::Pointer_Update(float elapsedAbs) { if ((ushort)((ushort)(globs::pointerGlobs.timer < 0.0) << 8 | (ushort)(globs::pointerGlobs.timer == 0.0) << 0xe) == 0) { globs::pointerGlobs.timer = globs::pointerGlobs.timer - elapsedAbs; } return; } // [|LangSFX]::: void __cdecl lego::ai::Priorities_LoadImages(Config *config,char *gameName) { char *arrayID; Config *prop; BOOL BVar1; int numSubParts; char *pcVar2; Image *pIVar3; AI_Priority priorityType; char *stringParts [10]; char *stringPartsSub [10]; char buff [512]; AI_Priority priorityType_; arrayID = cfg::Config_BuildStringID(gameName,"PriorityImages",0); for (prop = cfg::Config_FindArray(config,arrayID); prop != NULL; prop = cfg::Config_GetNextItem(prop)) { BVar1 = AIPriority_GetType(prop->key,&priorityType); if (BVar1 != 0) { std::sprintf(buff,"%s",prop->value); util::Util_Tokenise(buff,stringParts,":"); numSubParts = util::Util_Tokenise(stringParts[0],stringPartsSub,"|"); priorityType_ = priorityType; pcVar2 = util::Util_StrCpy(stringPartsSub[0]); globs::prioritiesGlobs.langPriorityName[priorityType_] = pcVar2; if (numSubParts == 2) { snd::SFX_GetType(stringPartsSub[1],globs::prioritiesGlobs.sfxPriorityName + priorityType_); } pIVar3 = lego::image::Image_LoadBMPScaled(stringParts[1],0,0); globs::prioritiesGlobs.priorityImage[priorityType] = pIVar3; pIVar3 = lego::image::Image_LoadBMPScaled(stringParts[2],0,0); globs::prioritiesGlobs.priorityPressImage[priorityType] = pIVar3; pIVar3 = lego::image::Image_LoadBMPScaled(stringParts[3],0,0); globs::prioritiesGlobs.priorityOffImage[priorityType] = pIVar3; } } return; } void __cdecl lego::ai::Priorities_Reset(void) { uint *pValue; uint i; i = 0; if (globs::prioritiesGlobs.count != 0) { pValue = globs::prioritiesGlobs.initialValues; do { // prioritiesGlobs.buttonTypes[i] = prioritiesGlobs.initialTypes[i]; // // AITask_Game_SetPriorityValue(prioritiesGlobs.buttonTypes[i], // prioritiesGlobs.initialValues[i]); // AITask_Game_SetPriorityOff(prioritiesGlobs.buttonTypes[i], // prioritiesGlobs.initialOff[i]); pValue[-0x6c] = pValue[-0x1b]; AITask_Game_SetPriorityValue(pValue[-0x1b],*pValue); AITask_Game_SetPriorityOff(pValue[-0x6c],pValue[0x1b]); i += 1; pValue = pValue + 1; } while (i < globs::prioritiesGlobs.count); } return; } BOOL __cdecl lego::ai::Priorities_LoadLevel(Config *config,char *gameName,char *levelName) { char *arrayID; Config *prop; BOOL BVar1; BoolTri BVar2; globs::prioritiesGlobs.count = 0; arrayID = cfg::Config_BuildStringID(gameName,levelName,"Priorities",0); for (prop = cfg::Config_FindArray(config,arrayID); prop != NULL; prop = cfg::Config_GetNextItem(prop)) { BVar1 = AIPriority_GetType(prop->key,(AI_Priority *)&levelName); if (BVar1 != 0) { globs::prioritiesGlobs.buttonTypes[globs::prioritiesGlobs.count] = (AI_Priority)levelName; globs::prioritiesGlobs.initialTypes[globs::prioritiesGlobs.count] = (AI_Priority)levelName; globs::prioritiesGlobs.initialValues[globs::prioritiesGlobs.count] = globs::prioritiesGlobs.count * -5 + 0x50; AITask_Game_SetPriorityValue ((AI_Priority)levelName, globs::prioritiesGlobs.initialValues[globs::prioritiesGlobs.count]); BVar2 = util::Util_GetBoolFromString(prop->value); if (BVar2 == BOOL3_TRUE) { // Priority needs to be explicitly defined as ON in Lego.cfg AITask_Game_SetPriorityOff((AI_Priority)levelName,FALSE); globs::prioritiesGlobs.initialOff[globs::prioritiesGlobs.count] = FALSE; } else { AITask_Game_SetPriorityOff((AI_Priority)levelName,TRUE); globs::prioritiesGlobs.initialOff[globs::prioritiesGlobs.count] = TRUE; } globs::prioritiesGlobs.count += 1; } } return TRUE; } void __cdecl lego::ai::Priorities_LoadPositions(Config *config,char *gameName) { char *keyPath; char *tempPositionValue; int iVar1; int orderIndex; float *pPointY; char *parts [16]; char *gameName_00; gameName_00 = gameName; orderIndex = 0; pPointY = &globs::prioritiesGlobs.buttonPoints[0].y; do { orderIndex += 1; std::itoa(orderIndex,(char *)&gameName,10); keyPath = cfg::Config_BuildStringID(gameName_00,"PrioritiesImagePositions",&gameName,0); tempPositionValue = cfg::Config_GetTempStringValue(config,keyPath); if (tempPositionValue != NULL) { // NO! BAD BAD BAD! Util_Tokenise changes the passed input value!! util::Util_Tokenise(tempPositionValue,parts,","); iVar1 = std::atoi(parts[0]); pPointY[-1] = (float)iVar1; iVar1 = std::atoi(parts[1]); *pPointY = (float)iVar1; } pPointY = pPointY + 2; } while (pPointY < globs::prioritiesGlobs.initialTypes + 1); return; } BOOL __cdecl lego::ai::Priorities_HandleInput (uint mouseX,uint mouseY,BOOL leftButton,BOOL leftButtonLast,BOOL leftReleased) { BOOL BVar1; float *pPointY; AI_Priority *pType; uint orderIndex; Point2F hoverPt; float x3; float y3; uint local_20; undefined4 uStack28; uint local_18; undefined4 uStack20; uint local_10; undefined4 uStack12; uint local_8; undefined4 uStack4; float mouseXf; uint hoverHeight; uint hoverWidth; Image *image; float mouseYf; AI_Priority priorityType; BVar1 = front::Panel_IsFullyClosed(Panel_PriorityList); if ((BVar1 == 0) && (BVar1 = front::Panel_IsSliding(Panel_PriorityList), BVar1 == 0)) { front::Panel_GetPosition(Panel_PriorityList,&x3,&y3); orderIndex = 0; if (globs::prioritiesGlobs.count != 0) { pPointY = &globs::prioritiesGlobs.buttonPoints[0].y; pType = globs::prioritiesGlobs.buttonTypes; do { priorityType = *pType; image = globs::prioritiesGlobs.priorityImage[priorityType]; if (image != NULL) { uStack28 = 0; hoverPt.x = pPointY[-1] + x3; local_20 = mouseX; hoverHeight = image->height; mouseXf = (float)(ulonglong)mouseX; hoverWidth = image->width; hoverPt.y = y3 + *pPointY; // if (mouseX >= hoverPt.x && mouseX < (hoverPt.x + hoverHeight)) if ((hoverPt.x <= mouseXf) && (uStack20 = 0, local_18 = hoverWidth, (ushort)((ushort)(mouseXf < (float)(ulonglong)hoverWidth + hoverPt.x) << 8 | (ushort)(mouseXf == (float)(ulonglong)hoverWidth + hoverPt.x) << 0xe) != 0)) { uStack12 = 0; local_10 = mouseY; mouseYf = (float)(ulonglong)mouseY; // if (mouseY >= hoverPt.y && mouseY < (hoverPt.y + hoverHeight)) if ((hoverPt.y <= mouseYf) && (uStack4 = 0, local_8 = hoverHeight, (ushort)((ushort)(mouseYf < (float)(ulonglong)hoverHeight + hoverPt.y) << 8 | (ushort)(mouseYf == (float)(ulonglong)hoverHeight + hoverPt.y) << 0xe) != 0)) { globs::prioritiesGlobs.flags |= PRIORITIES_GLOB_FLAG_HOVER; Priorities_SetHoverArea(&hoverPt,hoverWidth - 1,hoverHeight - 1); if (leftButton == 0) { if ((globs::s_PriorityList_Index == orderIndex) && (globs::s_PriorityList_Type == priorityType)) { front::ToolTip_SetContent (ToolTip_Priority,globs::prioritiesGlobs.langPriorityName[priorityType]) ; front::ToolTip_Activate(ToolTip_Priority); front::Interface_SetSFX_004df1f4 (globs::prioritiesGlobs.sfxPriorityName[priorityType]); } else { front::ToolTip_Activate(ToolTip_Null); globs::s_PriorityList_Index = orderIndex; globs::s_PriorityList_Type = priorityType; } } BVar1 = Priorities_ChangePriorityPressed(orderIndex,leftButton,leftButtonLast); if ((BVar1 != 0) && (leftReleased != 0)) { Priorities_MovePriorityUpOrTop(orderIndex); } return TRUE; } } } orderIndex += 1; pType = pType + 1; pPointY = pPointY + 2; } while (orderIndex < globs::prioritiesGlobs.count); } Priorities_ChangePriorityPressed(AI_Priority_Count,leftButton,leftButtonLast); } return FALSE; } BOOL __cdecl lego::ai::Priorities_ChangePriorityPressed(uint orderIndex,BOOL leftButton,BOOL leftButtonLast) { uint origPressIndex; origPressIndex = globs::prioritiesGlobs.pressIndex; if (leftButton == 0) { globs::prioritiesGlobs.pressIndex = AI_Priority_Count; } else { if (globs::prioritiesGlobs.pressIndex == AI_Priority_Count) { if (leftButtonLast == 0) { globs::prioritiesGlobs.pressIndex = orderIndex; globs::prioritiesGlobs.flags = globs::prioritiesGlobs.flags | PRIORITIES_GLOB_FLAG_PRESSED; return (uint)(orderIndex == AI_Priority_Count); } } else { if (globs::prioritiesGlobs.pressIndex == orderIndex) { globs::prioritiesGlobs.flags = globs::prioritiesGlobs.flags | PRIORITIES_GLOB_FLAG_PRESSED; return (uint)(globs::prioritiesGlobs.pressIndex == orderIndex); } } } return (uint)(origPressIndex == orderIndex); } // Sets the area used to draw a green rectangle around the current moused-over priority. // Hover is only drawn when PRIORITIES_GLOB_FLAG_HOVER flag is set. void __cdecl lego::ai::Priorities_SetHoverArea(Point2F *point,uint widthM1,uint heightM1) { globs::prioritiesGlobs.hoverArea.x = point->x; globs::prioritiesGlobs.hoverArea.y = point->y; globs::prioritiesGlobs.hoverArea.width = (float)(ulonglong)widthM1; globs::prioritiesGlobs.hoverArea.height = (float)(ulonglong)heightM1; return; } void __cdecl lego::ai::Priorities_MovePriorityUpOrTop(uint orderIndex) { if (((byte)globs::panelGlobs.flags & 2) != 0) { Priorities_MovePriorityTop(orderIndex); return; } if (((byte)globs::panelGlobs.flags & 4) != 0) { Priorities_MovePriorityUp(orderIndex); } return; } void __cdecl lego::ai::Priorities_MovePriorityTop(uint orderIndex) { AI_Priority priorityType; uint index; int priorityValue; int i; AI_Priority currPriorityType; if ((orderIndex != 0) && (orderIndex < globs::prioritiesGlobs.count)) { currPriorityType = globs::prioritiesGlobs.buttonTypes[orderIndex]; i = 0; if (orderIndex != 0) { priorityValue = 0x50; index = orderIndex; do { // globs::prioritiesGlobs.priorityTypeTable_1[index - 1] priorityType = globs::prioritiesGlobs.sfxPriorityName[index + 0x1a]; globs::prioritiesGlobs.buttonTypes[index] = priorityType; AITask_Game_SetPriorityValue(priorityType,priorityValue + orderIndex * -5); i += 1; priorityValue += 5; index = orderIndex - i; } while (index != 0); } globs::prioritiesGlobs.buttonTypes[0] = currPriorityType; AITask_Game_SetPriorityValue(currPriorityType,0x50); } lrr::Lego_SetPointerSFX(PointerSFX_Okay_TopPriority); return; } void __cdecl lego::ai::Priorities_MovePriorityUp(uint orderIndex) { AI_Priority currPriorityType; if ((orderIndex != 0) && (orderIndex < globs::prioritiesGlobs.count)) { currPriorityType = globs::prioritiesGlobs.buttonTypes[orderIndex]; // prioritiesGlobs.priorityTypeTable_1[orderIndex - 1] globs::prioritiesGlobs.buttonTypes[orderIndex] = globs::prioritiesGlobs.sfxPriorityName[orderIndex + 0x1a]; globs::prioritiesGlobs.sfxPriorityName[orderIndex + 0x1a] = currPriorityType; AITask_Game_SetPriorityValue (globs::prioritiesGlobs.buttonTypes[orderIndex],orderIndex * -5 + 0x50); // prioritiesGlobs.priorityTypeTable_1[orderIndex - 1] AITask_Game_SetPriorityValue (globs::prioritiesGlobs.sfxPriorityName[orderIndex + 0x1a],orderIndex * -5 + 0x55); Priorities_MoveCursorToPriorityUpButton(orderIndex - 1); } lrr::Lego_SetPointerSFX(PointerSFX_Okay); return; } void __cdecl lego::ai::Priorities_TurnPriorityOff(uint orderIndex) { BOOL isOff; if (orderIndex < globs::prioritiesGlobs.count) { isOff = AITask_Game_IsPriorityOff(globs::prioritiesGlobs.buttonTypes[orderIndex]); AITask_Game_SetPriorityOff(globs::prioritiesGlobs.buttonTypes[orderIndex],(uint)(isOff == 0)); // Hardcoded handling to warn player about turning off things they don't know anything // about. // // if (isOff && priorityType == AI_Priority_Crystal || priorityType == AI_Priority_Ore) if (((isOff == 0) != 0) && ((globs::prioritiesGlobs.buttonTypes[orderIndex] == AI_Priority_Crystal || (globs::prioritiesGlobs.buttonTypes[orderIndex] == AI_Priority_Ore)))) { front::Text_DisplayMessage(Text_CrystalOreDisabled,TRUE,FALSE); } } return; } void __cdecl lego::ai::Priorities_MoveCursorToPriorityUpButton(uint orderIndex) { int y; PanelButtonType buttonType; longlong lVar1; float x3; float y3; Area2F buttonArea; switch(orderIndex) { case 0: // There isn't any "Move Up" button for the highest priority. Priorities_MoveCursorToPriorityImage(0); return; case 1: buttonType = PanelButton_PriorityList_UpOne1; break; case 2: buttonType = PanelButton_PriorityList_UpOne2; break; case 3: buttonType = PanelButton_PriorityList_UpOne3; break; case 4: buttonType = PanelButton_PriorityList_UpOne4; break; case 5: buttonType = PanelButton_PriorityList_UpOne5; break; case 6: buttonType = PanelButton_PriorityList_UpOne6; break; case 7: buttonType = PanelButton_PriorityList_UpOne7; break; case 8: buttonType = PanelButton_PriorityList_UpOne8; break; default: goto switchD_0045d821_caseD_9; } front::Panel_GetPosition(Panel_PriorityList,&x3,&y3); front::Panel_Button_GetArea(Panel_PriorityList,buttonType,&buttonArea); lVar1 = __ftol((float10)buttonArea.height * (float10)0.5 + (float10)buttonArea.y + (float10)y3); y = (int)lVar1; lVar1 = __ftol((float10)buttonArea.width * (float10)0.5 + (float10)buttonArea.x + (float10)x3); input::Input_SetCursorPos((int)lVar1,y); switchD_0045d821_caseD_9: return; } void __cdecl lego::ai::Priorities_MoveCursorToPriorityImage(uint orderIndex) { int y; longlong lVar1; float x3; float y3; uint centerSize; undefined4 local_4; Image *priorityImage; AI_Priority priorityType; priorityType = globs::prioritiesGlobs.buttonTypes[orderIndex]; if (globs::prioritiesGlobs.priorityImage[priorityType] != NULL) { front::Panel_GetPosition(Panel_PriorityList,&x3,&y3); priorityImage = globs::prioritiesGlobs.priorityImage[priorityType]; local_4 = 0; centerSize = priorityImage->height >> 1; lVar1 = __ftol((float10)globs::prioritiesGlobs.buttonPoints[orderIndex].y + (float10)y3 + (float10)centerSize); y = (int)lVar1; centerSize = priorityImage->width >> 1; local_4 = 0; lVar1 = __ftol((float10)globs::prioritiesGlobs.buttonPoints[orderIndex].x + (float10)x3 + (float10)centerSize); input::Input_SetCursorPos((int)lVar1,y); } return; } void __cdecl lego::ai::Priorities_Draw(void) { Image *image; BOOL BVar1; uint orderIndex; AI_Priority *pType; float *pPointY; Point2F destPos; float x3; float y3; AI_Priority priorityType; BVar1 = front::Panel_IsFullyClosed(Panel_PriorityList); if (BVar1 == 0) { front::Panel_GetPosition(Panel_PriorityList,&x3,&y3); orderIndex = 0; if (globs::prioritiesGlobs.count != 0) { pPointY = &globs::prioritiesGlobs.buttonPoints[0].y; pType = globs::prioritiesGlobs.buttonTypes; do { destPos.x = pPointY[-1] + x3; destPos.y = y3 + *pPointY; priorityType = *pType; BVar1 = AITask_Game_IsPriorityOff(priorityType); if (BVar1 == 0) { if (((globs::prioritiesGlobs.flags & PRIORITIES_GLOB_FLAG_PRESSED) == PRIORITIES_GLOB_FLAG_NONE) || (globs::prioritiesGlobs.pressIndex != orderIndex)) { image = globs::prioritiesGlobs.priorityImage[priorityType]; } else { image = globs::prioritiesGlobs.priorityPressImage[priorityType]; } } else { image = globs::prioritiesGlobs.priorityOffImage[priorityType]; } if (image != NULL) { lego::image::Image_DisplayScaled(image,NULL,&destPos,NULL); } orderIndex += 1; pType = pType + 1; pPointY = pPointY + 2; } while (orderIndex < globs::prioritiesGlobs.count); } // Hover and pressed flags are handled/assigned every tick, rather than updated as // needed. if ((globs::prioritiesGlobs.flags & PRIORITIES_GLOB_FLAG_HOVER) != PRIORITIES_GLOB_FLAG_NONE) { front::Interface_DrawHoverOutline(&globs::prioritiesGlobs.hoverArea); globs::prioritiesGlobs.flags &= ~PRIORITIES_GLOB_FLAG_HOVER; } globs::prioritiesGlobs.flags &= ~PRIORITIES_GLOB_FLAG_PRESSED; } return; } BOOL __cdecl lego::game::PTL_Initialise(char *filename,char *gameName) { uint uVar1; Config *prop; Config *prop_00; Message_Type MVar2; globs::ptlGlobs.count = 0; prop = cfg::Config_Load(filename); if (prop != NULL) { prop_00 = cfg::Config_FindArray(prop,gameName); uVar1 = globs::ptlGlobs.count; while (prop_00 != NULL) { globs::ptlGlobs.count = uVar1 + 1; MVar2 = Message_ParsePTLName(prop_00->key); globs::ptlGlobs.table[uVar1].fromType = MVar2; MVar2 = Message_ParsePTLName(prop_00->value); globs::ptlGlobs.table[uVar1].toType = MVar2; prop_00 = cfg::Config_GetNextItem(prop_00); uVar1 = globs::ptlGlobs.count; } globs::ptlGlobs.count = uVar1; cfg::Config_Free(prop); return TRUE; } return FALSE; } void __cdecl lego::game::PTL_TranslateEvent(Message_Event *ref_message) { uint i; PTL_Property *ptlProp; // for (uint i = 0; i < ptlGlobs.count; i++) { // if (ref_message->type == ptlGlobs.table[i].fromType) { // ref_message->type = ptlGlobs.table[i].toType; // return; // } // } i = 0; if (globs::ptlGlobs.count != 0) { // pPTLProp = ptlGlobs.table; ptlProp = (PTL_Property *)&globs::ptlGlobs; while (ref_message->type != ptlProp->fromType) { i += 1; ptlProp = ptlProp + 1; if (globs::ptlGlobs.count <= i) { return; } } ref_message->type = ptlProp->toType; } return; } void __cdecl lego::game::RadarMap_SetZoom(RadarMap *radarMap,float zoom) { radarMap->zoom = zoom; return; } void __cdecl lego::game::RadarMap_Initialise(void) { RadarMap_Globs *pRVar1; RadarMap_Globs *pRVar2; float *pfVar3; int iVar4; int iVar5; uint i; float *pfVar6; pRVar1 = &globs::radarmapGlobs; do { iVar5 = 3; pRVar2 = pRVar1; do { pRVar1 = (RadarMap_Globs *)&pRVar2->colourTable[0].green; iVar5 += -1; pRVar2->colourTable[0].red = pRVar2->colourTable[0].red * 0.003921569; pRVar2 = pRVar1; } while (iVar5 != 0); } while (pRVar1 < (RadarMap_Globs *)&globs::radarmapGlobs.highlightBlockPos); // Set all float_c fields to 1.0f (for table_1 and table_2) pfVar3 = &globs::radarmapGlobs.arrowPointsFrom[0].w; do { pfVar3[0x50] = 1.0; *pfVar3 = 1.0; pfVar3 = pfVar3 + 4; } while (pfVar3 < &globs::radarmapGlobs.arrowPointsTo[0].w); globs::radarmapGlobs.arrowPointsFrom[0].x = 320.0; globs::radarmapGlobs.arrowPointsFrom[0].y = 40.0; globs::radarmapGlobs.arrowPointsTo[0].x = 420.0; globs::radarmapGlobs.arrowPointsTo[0].y = 180.0; globs::radarmapGlobs.arrowPointsFrom[1].x = 420.0; globs::radarmapGlobs.arrowPointsFrom[1].y = 180.0; globs::radarmapGlobs.arrowPointsTo[1].x = 360.0; globs::radarmapGlobs.arrowPointsTo[1].y = 180.0; globs::radarmapGlobs.arrowPointsFrom[2].x = 360.0; globs::radarmapGlobs.arrowPointsFrom[2].y = 180.0; globs::radarmapGlobs.arrowPointsTo[2].x = 360.0; globs::radarmapGlobs.arrowPointsTo[2].y = 400.0; globs::radarmapGlobs.arrowPointsFrom[3].x = 360.0; globs::radarmapGlobs.arrowPointsFrom[3].y = 400.0; globs::radarmapGlobs.arrowPointsTo[3].x = 280.0; globs::radarmapGlobs.arrowPointsTo[3].y = 400.0; globs::radarmapGlobs.arrowPointsFrom[4].x = 280.0; globs::radarmapGlobs.arrowPointsFrom[4].y = 400.0; globs::radarmapGlobs.arrowPointsTo[4].x = 280.0; globs::radarmapGlobs.arrowPointsTo[4].y = 180.0; globs::radarmapGlobs.arrowPointsFrom[5].x = 280.0; globs::radarmapGlobs.arrowPointsFrom[5].y = 180.0; globs::radarmapGlobs.arrowPointsTo[5].x = 220.0; globs::radarmapGlobs.arrowPointsTo[5].y = 180.0; globs::radarmapGlobs.arrowPointsFrom[6].x = 220.0; globs::radarmapGlobs.arrowPointsFrom[6].y = 180.0; globs::radarmapGlobs.arrowPointsTo[6].x = 320.0; globs::radarmapGlobs.arrowPointsTo[6].y = 40.0; globs::radarmapGlobs.arrowPointCount = 7; i = 0; pfVar3 = &globs::radarmapGlobs.arrowPointsFrom[0].y; do { iVar5 = 2; pfVar6 = pfVar3; do { // More hardcoded resolution behaviors. This divides as: // appWidth() / 640.0 // appHeight() / 480.0 iVar4 = main::appWidth(); pfVar6[-1] = (float)iVar4 * 0.0015625 * pfVar6[-1]; iVar4 = main::appHeight(); iVar5 += -1; *pfVar6 = (float)iVar4 * 0.002083333 * *pfVar6; pfVar6 = pfVar6 + 0x50; } while (iVar5 != 0); i += 1; pfVar3 = pfVar3 + 4; } while (i < globs::radarmapGlobs.arrowPointCount); globs::radarmapGlobs.highlightBlockPos.x = -1; globs::radarmapGlobs.highlightBlockPos.y = -1; return; } RadarMap * __cdecl lego::game::RadarMap_Create(Map3D *map,Area2F *screenRect,float zoom) { float fVar1; RadarMap *radarMap; float10 fVar2; radarMap = (RadarMap *)io::Mem_Alloc(0x3c); if (radarMap != NULL) { (radarMap->screenRect).x = screenRect->x; (radarMap->screenRect).y = screenRect->y; (radarMap->screenRect).width = screenRect->width; fVar1 = screenRect->height; radarMap->zoom = zoom; (radarMap->screenRect).height = fVar1; fVar2 = lego::map::Map3D_BlockSize(map); radarMap->blockSize = (float)fVar2; radarMap->map = map; return radarMap; } return NULL; } // Multiple-use function to free data void __cdecl lego::game::RadarMap_Free_UnwindMultiUse(RadarMap *radarMap) { io::Mem_Free(radarMap); return; } void __cdecl lego::game::RadarMap_DrawSurveyDotCircle (RadarMap *radarMap,Point2F *center,float radius,float brightness) { longlong lVar1; Area2F rect; Area2F oldClipWindow; float c; rect.height = 0.0; rect.x = center->x; rect.y = center->y; rect.width = radius; draw::Draw_GetClipWindow(&oldClipWindow); draw::Draw_SetClipWindow(&radarMap->screenRect); RadarMap_TransformRect(radarMap,&rect); c = brightness * 0.7 - -0.3; lVar1 = __ftol((float10)rect.width); draw::Draw_DotCircle ((Point2F *)&rect,(uint)lVar1,(uint)lVar1 * 2,c * 0.7,c * 0.9,c,DrawEffect_None); draw::Draw_SetClipWindow(&oldClipWindow); return; } // WARNING: Function: _alloca4k replaced with injection: alloca_probe void __cdecl lego::game::RadarMap_Draw(RadarMap *radarMap,Point2F *position) { float fVar1; float fVar2; BOOL BVar3; uint uVar4; int iVar5; Map3D *pMVar6; uint uVar7; float *pfVar8; Point2F *pPVar9; uint uVar10; Vector4F *transform4d; float *pfVar11; float *pfVar12; Point2F *pPVar13; Vector3F *pVVar14; float *pfVar15; uint uStack46860; uint uStack46856; uint uStack46852; uint uStack46848; float *pfStack46844; Vector3F VStack46840; uint uStack46828; uint uStack46824; int iStack46820; int iStack46816; Area2F AStack46812; Vector3F VStack46796; Vector3F VStack46784; Vector3F VStack46772; Vector4F VStack46760; float fStack46744; undefined4 uStack46740; undefined4 uStack46736; undefined4 uStack46732; float fStack46728; float fStack46724; undefined4 uStack46720; undefined4 uStack46716; undefined4 uStack46712; float fStack46708; undefined4 uStack46704; undefined4 uStack46700; undefined4 uStack46696; undefined4 uStack46692; undefined4 uStack46688; undefined4 uStack46684; float fStack46680; undefined4 uStack46676; undefined4 uStack46672; undefined4 uStack46668; float fStack46664; float fStack46660; undefined4 uStack46656; undefined4 uStack46652; undefined4 uStack46648; float fStack46644; undefined4 uStack46640; undefined4 uStack46636; Point2F PStack46632; Point2F aPStack46624 [3]; float fStack46600; float fStack46596; Area2F AStack46592; Vector3F aVStack46576 [8]; Point2F aPStack46480 [20]; Point2F aPStack46320 [20]; float afStack46156 [59]; Vector3F aVStack45920 [60]; Point2F aPStack45200 [200]; Point2F aPStack43600 [200]; Draw_Rect aDStack42000 [1499]; undefined4 uStack4; uStack4 = 0x45de8a; fVar1 = (radarMap->screenRect).width; (radarMap->centerPos).x = position->x; fVar2 = radarMap->zoom; (radarMap->centerPos).y = position->y; uVar10 = 0; uVar7 = 0; uStack46856 = 0; uStack46860 = 0; uStack46824 = 0; uStack46828 = 0; VStack46840.x = ((fVar1 * 0.5) / fVar2) * radarMap->blockSize; VStack46840.y = (((radarMap->screenRect).height * 0.5) / radarMap->zoom) * radarMap->blockSize; lego::map::Map3D_FUN_0044fad0 (radarMap->map,position->x - VStack46840.x,VStack46840.y + position->y, (int *)&uStack46828,(int *)&uStack46824); lego::map::Map3D_FUN_0044fad0 (radarMap->map,position->x + VStack46840.x,position->y - VStack46840.y,&iStack46820, &iStack46816); draw::Draw_GetClipWindow(&AStack46592); draw::Draw_SetClipWindow(&radarMap->screenRect); uStack46852 = uStack46824; uStack46848 = uStack46828; iVar5 = iStack46820; if ((int)uStack46824 <= iStack46816) { do { uVar4 = uStack46848; if ((int)uStack46848 <= iVar5) { pfStack46844 = &aPStack45200[uVar7].y; pPVar9 = aPStack45200 + uVar7; pfVar8 = &aPStack43600[uVar7].y; pPVar13 = aPStack43600 + uVar7; pfVar12 = &aDStack42000[uVar10].rect.width; do { BVar3 = RadarMap_GetBlockColour((Draw_Rect *)(pfVar12 + -2),uStack46848,uStack46852); if (BVar3 != 0) { BVar3 = front::Interface_GetFlashingState(); if (((BVar3 != 0) && (uStack46848 == globs::radarmapGlobs.highlightBlockPos.x)) && (uStack46852 == globs::radarmapGlobs.highlightBlockPos.y)) { pfVar12[2] = 1.0; pfVar12[3] = 0.0; pfVar12[4] = 0.0; } pMVar6 = radarMap->map; fVar1 = radarMap->blockSize; fVar2 = radarMap->blockSize; ((Area2F *)(pfVar12 + -2))->x = (float)uStack46848 * radarMap->blockSize + (pMVar6->worldDimensions_fnegx).width; pfVar12[-1] = -((float)uStack46852 * fVar2) + (pMVar6->worldDimensions_fnegx).height; pfVar12[1] = fVar1; *pfVar12 = fVar1; RadarMap_TransformRect(radarMap,(Area2F *)(pfVar12 + -2)); *pfVar12 = *pfVar12 - 1.0; pfVar12[1] = pfVar12[1] - 1.0; BVar3 = Level_Block_IsReinforced(uStack46848,uStack46852); if ((BVar3 != 0) && (uStack46860 < 200)) { fVar1 = *pfVar12; fVar2 = pfVar12[-1]; pPVar13->x = pfVar12[-2]; *pfVar8 = fVar2; fVar1 = (fVar1 - 1.0) + pfVar12[-2]; pPVar9->x = fVar1; pPVar13[1].x = fVar1; *pfStack46844 = fVar2; pfVar8[2] = fVar2; pPVar9[1].x = fVar1; fVar2 = (pfVar12[1] - 1.0) + pfVar12[-1]; pfStack46844[2] = fVar2; pPVar13[2].x = fVar1; pfVar8[4] = fVar2; pPVar9[2].x = pfVar12[-2]; pfStack46844[4] = fVar2; pPVar13[3].x = pfVar12[-2]; pfVar8[6] = fVar2; pPVar9[3].x = pfVar12[-2]; pfStack46844[6] = pfVar12[-1]; uStack46860 += 4; pPVar13 = pPVar13 + 4; pfVar8 = pfVar8 + 8; pPVar9 = pPVar9 + 4; pfStack46844 = pfStack46844 + 8; } uStack46856 += 1; pfVar12 = pfVar12 + 7; } uStack46848 += 1; uVar4 = uStack46828; iVar5 = iStack46820; uVar7 = uStack46860; uVar10 = uStack46856; } while ((int)uStack46848 <= iStack46820); } uStack46852 += 1; uStack46848 = uVar4; } while ((int)uStack46852 <= iStack46816); } ddraw::DirectDraw_Clear(&radarMap->screenRect,0); draw::Draw_RectList2Ex(aDStack42000,uVar10,DrawEffect_None); // Draw reinforcement yellow borders around blocks draw::Draw_LineListEx (aPStack43600,aPStack45200,uVar7,globs::radarmapGlobs.colourTable[0].red, globs::radarmapGlobs.colourTable[0].green,globs::radarmapGlobs.colourTable[0].blue, DrawEffect_None); (radarMap->worldRect).x = position->x - VStack46840.x; (radarMap->worldRect).y = position->y - VStack46840.y; (radarMap->worldRect).width = position->x + VStack46840.x; fVar1 = position->y; radarMap->drawRectList = aDStack42000; radarMap->drawRectCount = 0; (radarMap->worldRect).height = VStack46840.y + fVar1; LegoObject_RunThroughListsSkipUpgradeParts(RadarMap_Callback_AddObjectDrawRect,radarMap); draw::Draw_RectList2Ex(radarMap->drawRectList,radarMap->drawRectCount,DrawEffect_None); if (globs::legoGlobs.viewMode == ViewMode_Top) { VStack46760.x = 0.0; VStack46760.y = 0.0; VStack46760.z = 0.0; VStack46760.w = 1.0; iVar5 = main::appWidth(); uStack46740 = 0; fStack46744 = (float)iVar5; uStack46736 = 0; uStack46732 = 1065353216; iVar5 = main::appWidth(); fStack46728 = (float)iVar5; iVar5 = main::appHeight(); uStack46720 = 0; fStack46724 = (float)iVar5; uStack46716 = 0x3f800000; uStack46712 = 0; iVar5 = main::appHeight(); uStack46704 = 0; fStack46708 = (float)iVar5; uStack46700 = 0x3f800000; uStack46696 = 0; uStack46692 = 0; uStack46688 = 0x3f800000; uStack46684 = 0x3f800000; iVar5 = main::appWidth(); uStack46676 = 0; fStack46680 = (float)iVar5; uStack46672 = 0x3f800000; uStack46668 = 0x3f800000; iVar5 = main::appWidth(); fStack46664 = (float)iVar5; iVar5 = main::appHeight(); uStack46656 = 0x3f800000; fStack46660 = (float)iVar5; uStack46652 = 0x3f800000; uStack46648 = 0; iVar5 = main::appHeight(); uStack46640 = 0x3f800000; fStack46644 = (float)iVar5; uStack46636 = 0x3f800000; VStack46784.x = 0.0; VStack46784.y = 0.0; pMVar6 = lrr::Lego_GetMap(); VStack46772.x = 0.0; pVVar14 = aVStack46576; VStack46784.z = pMVar6->float_20 * 0.5; VStack46772.y = 0.0; VStack46772.z = -1.0; transform4d = &VStack46760; iVar5 = 8; do { lego::view::Viewport_InverseTransform(globs::legoGlobs.viewMain,pVVar14,transform4d); transform4d = transform4d + 1; pVVar14 = pVVar14 + 1; iVar5 += -1; } while (iVar5 != 0); uStack46856 = 0; uVar7 = globs::radarmapGlobs.arrowPointCount; do { uVar10 = 0; if (uVar7 != 0) { pfVar8 = &globs::radarmapGlobs.arrowPointsFrom[0].z; pVVar14 = aVStack45920 + uStack46856 * 0x28; do { if (uStack46856 == 0) { pfVar8[0x50] = 0.0; *pfVar8 = 0.0; } else { pfVar8[0x50] = 1.0; *pfVar8 = 1.0; } lego::view::Viewport_InverseTransform (globs::legoGlobs.viewMain,pVVar14 + -0x14,(Vector4F *)(pfVar8 + -2)); lego::view::Viewport_InverseTransform (globs::legoGlobs.viewMain,pVVar14,(Vector4F *)(pfVar8 + 0x4e)); uVar10 += 1; pVVar14 = pVVar14 + 1; pfVar8 = pfVar8 + 4; uVar7 = globs::radarmapGlobs.arrowPointCount; } while (uVar10 < globs::radarmapGlobs.arrowPointCount); } uStack46856 += 1; } while (uStack46856 < 2); pfVar8 = afStack46156; pfVar12 = &aPStack46480[0].y; uStack46860 = 2; do { uVar10 = 0; pfVar11 = pfVar8; pfVar15 = pfVar12; if (uVar7 != 0) { do { VStack46840.x = pfVar11[0x77] - pfVar11[-1]; VStack46840.y = pfVar11[0x78] - *pfVar11; VStack46840.z = pfVar11[0x79] - pfVar11[1]; math::Maths_RayPlaneIntersection (&VStack46796,(Vector3F *)(pfVar11 + -1),&VStack46840,&VStack46784,&VStack46772) ; AStack46812.x = VStack46796.x; AStack46812.y = VStack46796.y; RadarMap_TransformRect(radarMap,&AStack46812); pfVar15[-1] = AStack46812.x; *pfVar15 = AStack46812.y; uVar10 += 1; pfVar11 = pfVar11 + 3; pfVar15 = pfVar15 + 2; uVar7 = globs::radarmapGlobs.arrowPointCount; } while (uVar10 < globs::radarmapGlobs.arrowPointCount); } pfVar12 = pfVar12 + 0x28; pfVar8 = pfVar8 + 0x3c; uStack46860 += -1; } while (uStack46860 != 0); draw::Draw_LineListEx(aPStack46480,aPStack46320,uVar7,1.0,1.0,1.0,DrawEffect_HalfTrans); pfVar8 = &PStack46632.y; pfVar12 = &aVStack46576[0].y; iVar5 = 4; do { VStack46840.x = pfVar12[0xb] - pfVar12[-1]; VStack46840.y = pfVar12[0xc] - *pfVar12; VStack46840.z = pfVar12[0xd] - pfVar12[1]; math::Maths_RayPlaneIntersection (&VStack46796,(Vector3F *)(pfVar12 + -1),&VStack46840,&VStack46784,&VStack46772); AStack46812.x = VStack46796.x; AStack46812.y = VStack46796.y; RadarMap_TransformRect(radarMap,&AStack46812); pfVar8[-1] = AStack46812.x; *pfVar8 = AStack46812.y; pfVar12 = pfVar12 + 3; pfVar8 = pfVar8 + 2; iVar5 += -1; } while (iVar5 != 0); fStack46600 = PStack46632.x; fStack46596 = PStack46632.y; draw::Draw_LineListEx(&PStack46632,aPStack46624,4,0.7,0.7,0.7,DrawEffect_HalfTrans); } draw::Draw_SetClipWindow(&AStack46592); return; } BOOL __cdecl lego::game::RadarMap_CanShowObject(LegoObject *liveObj) { StatsFlags2 sflags2; LegoObject_Type objType; objType = liveObj->type; // objType is [VEHICLE, MINIFIGURE, ROCKMONSTER, CRYSTAL, // ORE, UPGRADEPART, ELECTRICFENCE, PATH] if ((((((objType != LegoObject_ElectricFenceStud) && (objType != LegoObject_Boulder)) && (objType != LegoObject_Dynamite)) && ((objType != LegoObject_OohScary && (objType != LegoObject_Pusher)))) && ((objType != LegoObject_Freezer && ((objType != LegoObject_LaserShot && (objType != LegoObject_Barrier)))))) && ((objType != LegoObject_IceCube && ((objType != LegoObject_Building && (objType != LegoObject_SpiderWeb)))))) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); // not (statsFlags2 & STATS2_DONTSHOWONRADAR) return ~sflags2 >> 0x1d & 1; } return 0; } BOOL __cdecl lego::game::RadarMap_Callback_AddObjectDrawRect(LegoObject *liveObj,RadarMap *radarMap) { float fVar1; BOOL BVar2; Point2F wPos; LegoObject_Type objType; BVar2 = RadarMap_CanShowObject(liveObj); if (BVar2 == 0) { return 0; } LegoObject_GetPosition(liveObj,&wPos.x,&wPos.y); if (((((radarMap->worldRect).x <= wPos.x) && (fVar1 = (radarMap->worldRect).width, (ushort)((ushort)(wPos.x < fVar1) << 8 | (ushort)(wPos.x == fVar1) << 0xe) != 0)) && ((radarMap->worldRect).y <= wPos.y)) && (fVar1 = (radarMap->worldRect).height, (ushort)((ushort)(wPos.y < fVar1) << 8 | (ushort)(wPos.y == fVar1) << 0xe) != 0)) { objType = liveObj->type; if (objType == LegoObject_RockMonster) { radarMap->drawRectList[radarMap->drawRectCount].r = globs::radarmapGlobs.colourTable[15].red; radarMap->drawRectList[radarMap->drawRectCount].g = globs::radarmapGlobs.colourTable[15].green ; radarMap->drawRectList[radarMap->drawRectCount].b = globs::radarmapGlobs.colourTable[15].blue; fVar1 = 0.3333333; } else { if ((objType == LegoObject_PowerCrystal) || (objType == LegoObject_Ore)) { radarMap->drawRectList[radarMap->drawRectCount].r = globs::radarmapGlobs.colourTable[16].red ; radarMap->drawRectList[radarMap->drawRectCount].g = globs::radarmapGlobs.colourTable[16].green; radarMap->drawRectList[radarMap->drawRectCount].b = globs::radarmapGlobs.colourTable[16].blue; fVar1 = 0.25; } else { radarMap->drawRectList[radarMap->drawRectCount].r = globs::radarmapGlobs.colourTable[14].red ; radarMap->drawRectList[radarMap->drawRectCount].g = globs::radarmapGlobs.colourTable[14].green; radarMap->drawRectList[radarMap->drawRectCount].b = globs::radarmapGlobs.colourTable[14].blue; fVar1 = 0.3333333; } } radarMap->drawRectList[radarMap->drawRectCount].rect.x = wPos.x - fVar1 * 0.5 * radarMap->blockSize; radarMap->drawRectList[radarMap->drawRectCount].rect.y = fVar1 * 0.5 * radarMap->blockSize + wPos.y; radarMap->drawRectList[radarMap->drawRectCount].rect.width = fVar1 * radarMap->blockSize; radarMap->drawRectList[radarMap->drawRectCount].rect.height = fVar1 * radarMap->blockSize; RadarMap_TransformRect(radarMap,&radarMap->drawRectList[radarMap->drawRectCount].rect); radarMap->drawRectCount = radarMap->drawRectCount + 1; } return 0; } BOOL __cdecl lego::game::RadarMap_InsideRadarScreen(RadarMap *radarMap,uint mouseX,uint mouseY) { if (((((radarMap->screenRect).x <= (float)(ulonglong)mouseX) && ((float)(ulonglong)mouseX < (radarMap->screenRect).width + (radarMap->screenRect).x)) && ((radarMap->screenRect).y <= (float)(ulonglong)mouseY)) && ((float)(ulonglong)mouseY < (radarMap->screenRect).height + (radarMap->screenRect).y)) { return TRUE; } return 0; } BOOL __cdecl lego::game::RadarMap_ScreenToWorldBlockPos (RadarMap *radarMap,uint mouseX,uint mouseY,Point2F *optout_worldPos,int *out_bx, int *out_by) { float fVar1; float fVar2; float fVar3; float fVar4; BOOL BVar5; fVar1 = (float)(ulonglong)mouseX; if (((radarMap->screenRect).x <= fVar1) && (fVar2 = (radarMap->screenRect).width + (radarMap->screenRect).x, (ushort)((ushort)(fVar2 < fVar1) << 8 | (ushort)(fVar2 == fVar1) << 0xe) == 0)) { fVar2 = (float)(ulonglong)mouseY; if (((radarMap->screenRect).y <= fVar2) && (fVar3 = (radarMap->screenRect).height + (radarMap->screenRect).y, (ushort)((ushort)(fVar3 < fVar2) << 8 | (ushort)(fVar3 == fVar2) << 0xe) == 0)) { fVar3 = 1.0 / radarMap->zoom; fVar4 = (radarMap->screenRect).width * 0.5; fVar2 = radarMap->blockSize * (((radarMap->screenRect).y + fVar4) - fVar2) * fVar3 + (radarMap->centerPos).y; fVar1 = (radarMap->centerPos).x + -(radarMap->blockSize * (((radarMap->screenRect).x + fVar4) - fVar1) * fVar3); BVar5 = lego::map::Map3D_WorldToBlockPos_NoZ(radarMap->map,fVar1,fVar2,out_bx,out_by); if (BVar5 != 0) { if (optout_worldPos != NULL) { optout_worldPos->x = fVar1; optout_worldPos->y = fVar2; } return TRUE; } } } return 0; } BOOL __cdecl lego::game::RadarMap_TrySelectObject (RadarMap *radarMap,uint mouseX,uint mouseY,LegoObject **out_liveObj, Point2F *optout_objPosition) { BOOL BVar1; Point2I blockPos; SearchRadarObjectInArea search; search.worldPos.x = 0.0; search.worldPos.y = 0.0; search.radius = 0.0; search.object = NULL; BVar1 = RadarMap_ScreenToWorldBlockPos (radarMap,mouseX,mouseY,&search.worldPos,&blockPos.x,&blockPos.y); if (BVar1 != 0) { BVar1 = Level_Block_IsSolidBuilding(blockPos.x,blockPos.y,TRUE); if (BVar1 == 0) { search.radius = radarMap->blockSize * 0.1666667; } else { search.radius = radarMap->blockSize; } BVar1 = LegoObject_RunThroughListsSkipUpgradeParts (RadarMap_Callback_FindObjectInClickArea,&search); if (BVar1 != 0) { *out_liveObj = search.object; if (optout_objPosition != NULL) { LegoObject_GetPosition(search.object,&optout_objPosition->x,&optout_objPosition->y); } return TRUE; } } return 0; } BOOL __cdecl lego::game::RadarMap_Callback_FindObjectInClickArea (LegoObject *liveObj,SearchRadarObjectInArea *search) { Point2F position; LegoObject_GetPosition(liveObj,&position.x,&position.y); if ((ABS(position.x - (search->worldPos).x) <= search->radius) && (ABS(position.y - (search->worldPos).y) <= search->radius)) { search->object = liveObj; return TRUE; } return 0; } void __cdecl lego::game::RadarMap_TransformRect(RadarMap *radarMap,Area2F *ref_rect) { float arrowTiltOrZoom; float blockSize; float screenRect_height; float screenRect_width; float screenRect_x; float screenRect_y; screenRect_width = (radarMap->screenRect).width; screenRect_height = (radarMap->screenRect).height; screenRect_x = (radarMap->screenRect).x; screenRect_y = (radarMap->screenRect).y; ref_rect->x = ref_rect->x - (radarMap->centerPos).x; ref_rect->y = ref_rect->y - (radarMap->centerPos).y; ref_rect->x = (radarMap->zoom / radarMap->blockSize) * ref_rect->x; ref_rect->y = (radarMap->zoom / radarMap->blockSize) * ref_rect->y; ref_rect->width = (radarMap->zoom / radarMap->blockSize) * ref_rect->width; arrowTiltOrZoom = radarMap->zoom; blockSize = radarMap->blockSize; ref_rect->x = ref_rect->x + screenRect_width * 0.5 + screenRect_x; ref_rect->y = (screenRect_height * 0.5 + screenRect_y) - ref_rect->y; ref_rect->height = (arrowTiltOrZoom / blockSize) * ref_rect->height; return; } BOOL __cdecl lego::game::RadarMap_GetBlockColour(Draw_Rect *drawRect,uint bx,uint by) { uint by_00; BOOL BVar1; Point2I blockPos; uint bx_00; by_00 = by; bx_00 = bx; blockPos.x = bx; blockPos.y = by; Level_Block_GetSurfaceType(bx,by,&bx); BVar1 = Level_Block_IsWall(bx_00,by_00); if (BVar1 == 0) { BVar1 = Level_Block_IsNotWallOrGround(bx_00,by_00); if ((BVar1 != 0) && (BVar1 = Level_Block_IsSurveyed(bx_00,by_00), BVar1 != 0)) { if (((globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by_00 + bx_00] .flags1 & BLOCK1_HIDDEN) != BLOCK1_NONE) { // SURFACE_UNDISCOVERED drawRect->r = globs::radarmapGlobs.colourTable[29].red; drawRect->g = globs::radarmapGlobs.colourTable[29].green; drawRect->b = globs::radarmapGlobs.colourTable[29].blue; return TRUE; } switch(bx) { case 1: // SURFACE_IMMOVABLE drawRect->r = globs::radarmapGlobs.colourTable[8].red; drawRect->g = globs::radarmapGlobs.colourTable[8].green; drawRect->b = globs::radarmapGlobs.colourTable[8].blue; return TRUE; case 2: // SURFACE_HARD drawRect->r = globs::radarmapGlobs.colourTable[7].red; drawRect->g = globs::radarmapGlobs.colourTable[7].green; drawRect->b = globs::radarmapGlobs.colourTable[7].blue; return TRUE; case 3: // SURFACE_MEDIUM drawRect->r = globs::radarmapGlobs.colourTable[6].red; drawRect->g = globs::radarmapGlobs.colourTable[6].green; drawRect->b = globs::radarmapGlobs.colourTable[6].blue; return TRUE; case 4: // SURFACE_LOOSE drawRect->r = globs::radarmapGlobs.colourTable[5].red; drawRect->g = globs::radarmapGlobs.colourTable[5].green; drawRect->b = globs::radarmapGlobs.colourTable[5].blue; return TRUE; case 5: // SURFACE_SOIL drawRect->r = globs::radarmapGlobs.colourTable[4].red; drawRect->g = globs::radarmapGlobs.colourTable[4].green; drawRect->b = globs::radarmapGlobs.colourTable[4].blue; return TRUE; case 6: goto switchD_0045ef37_caseD_6; case 7: // SURFACE_WATER_unused drawRect->r = globs::radarmapGlobs.colourTable[2].red; drawRect->g = globs::radarmapGlobs.colourTable[2].green; drawRect->b = globs::radarmapGlobs.colourTable[2].blue; return TRUE; case 8: switchD_0045ef37_caseD_8: // SURFACE_ORESEAM drawRect->r = globs::radarmapGlobs.colourTable[24].red; drawRect->g = globs::radarmapGlobs.colourTable[24].green; drawRect->b = globs::radarmapGlobs.colourTable[24].blue; return TRUE; case 9: // SURFACE_LAKE drawRect->r = globs::radarmapGlobs.colourTable[27].red; drawRect->g = globs::radarmapGlobs.colourTable[27].green; drawRect->b = globs::radarmapGlobs.colourTable[27].blue; return TRUE; case 10: switchD_0045ef37_caseD_a: // SURFACE_CRYSTALSEAM drawRect->r = globs::radarmapGlobs.colourTable[25].red; drawRect->g = globs::radarmapGlobs.colourTable[25].green; drawRect->b = globs::radarmapGlobs.colourTable[25].blue; return TRUE; case 0xb: switchD_0045ef37_caseD_b: // SURFACE_RECHARGESEAM drawRect->r = globs::radarmapGlobs.colourTable[26].red; drawRect->g = globs::radarmapGlobs.colourTable[26].green; drawRect->b = globs::radarmapGlobs.colourTable[26].blue; return TRUE; default: goto switchD_0045ef37_caseD_b; } } BVar1 = Level_Block_IsGround(bx_00,by_00); if (BVar1 == 0) { return 0; } if (bx != Lego_SurfaceType_Lava) { if (bx == Lego_SurfaceType_Water) { // SURFACE_WATER_unused drawRect->r = globs::radarmapGlobs.colourTable[2].red; drawRect->g = globs::radarmapGlobs.colourTable[2].green; drawRect->b = globs::radarmapGlobs.colourTable[2].blue; return TRUE; } if (bx == Lego_SurfaceType_Lake) { // SURFACE_LAKE drawRect->r = globs::radarmapGlobs.colourTable[27].red; drawRect->g = globs::radarmapGlobs.colourTable[27].green; drawRect->b = globs::radarmapGlobs.colourTable[27].blue; return TRUE; } if (((globs::legoGlobs.currLevel)->blocks[(globs::legoGlobs.currLevel)->width * by_00 + bx_00] .flags1 & BLOCK1_FOUNDATION) != BLOCK1_NONE) { drawRect->r = globs::radarmapGlobs.colourTable[28].red; drawRect->g = globs::radarmapGlobs.colourTable[28].green; drawRect->b = globs::radarmapGlobs.colourTable[28].blue; return TRUE; } BVar1 = Level_Block_IsPath(&blockPos); if (BVar1 != 0) { BVar1 = Level_Block_IsPowered(&blockPos); if (BVar1 != 0) { // SURFACE_PATH (powered) drawRect->r = globs::radarmapGlobs.colourTable[22].red; drawRect->g = globs::radarmapGlobs.colourTable[22].green; drawRect->b = globs::radarmapGlobs.colourTable[22].blue; return TRUE; } // SURFACE_PATH (unpowered) drawRect->r = globs::radarmapGlobs.colourTable[23].red; drawRect->g = globs::radarmapGlobs.colourTable[23].green; drawRect->b = globs::radarmapGlobs.colourTable[23].blue; return TRUE; } drawRect->r = globs::radarmapGlobs.colourTable[1].red; drawRect->g = globs::radarmapGlobs.colourTable[1].green; drawRect->b = globs::radarmapGlobs.colourTable[1].blue; return TRUE; } switchD_0045ef37_caseD_6: // SURFACE_LAVA drawRect->r = globs::radarmapGlobs.colourTable[3].red; drawRect->g = globs::radarmapGlobs.colourTable[3].green; drawRect->b = globs::radarmapGlobs.colourTable[3].blue; } else { BVar1 = Level_Block_IsDestroyedConnection(bx_00,by_00); if (BVar1 == 0) { if (true) { switch(bx) { case 1: // SURFACE_IMMOVABLE drawRect->r = globs::radarmapGlobs.colourTable[13].red; drawRect->g = globs::radarmapGlobs.colourTable[13].green; drawRect->b = globs::radarmapGlobs.colourTable[13].blue; return TRUE; case 2: // SURFACE_HARD drawRect->r = globs::radarmapGlobs.colourTable[12].red; drawRect->g = globs::radarmapGlobs.colourTable[12].green; drawRect->b = globs::radarmapGlobs.colourTable[12].blue; return TRUE; case 3: // SURFACE_MEDIUM drawRect->r = globs::radarmapGlobs.colourTable[11].red; drawRect->g = globs::radarmapGlobs.colourTable[11].green; drawRect->b = globs::radarmapGlobs.colourTable[11].blue; return TRUE; case 4: // SURFACE_LOOSE drawRect->r = globs::radarmapGlobs.colourTable[10].red; drawRect->g = globs::radarmapGlobs.colourTable[10].green; drawRect->b = globs::radarmapGlobs.colourTable[10].blue; return TRUE; case 5: // SURFACE_SOIL drawRect->r = globs::radarmapGlobs.colourTable[9].red; drawRect->g = globs::radarmapGlobs.colourTable[9].green; drawRect->b = globs::radarmapGlobs.colourTable[9].blue; return TRUE; case 8: goto switchD_0045ef37_caseD_8; case 10: goto switchD_0045ef37_caseD_a; case 0xb: goto switchD_0045ef37_caseD_b; } } } else { switch(bx) { case 1: // SURFACE_IMMOVABLE drawRect->r = globs::radarmapGlobs.colourTable[21].red; drawRect->g = globs::radarmapGlobs.colourTable[21].green; drawRect->b = globs::radarmapGlobs.colourTable[21].blue; return 1; case 2: // SURFACE_HARD drawRect->r = globs::radarmapGlobs.colourTable[20].red; drawRect->g = globs::radarmapGlobs.colourTable[20].green; drawRect->b = globs::radarmapGlobs.colourTable[20].blue; return 1; case 3: // SURFACE_MEDIUM drawRect->r = globs::radarmapGlobs.colourTable[19].red; drawRect->g = globs::radarmapGlobs.colourTable[19].green; drawRect->b = globs::radarmapGlobs.colourTable[19].blue; return TRUE; case 4: // SURFACE_LOOSE drawRect->r = globs::radarmapGlobs.colourTable[18].red; drawRect->g = globs::radarmapGlobs.colourTable[18].green; drawRect->b = globs::radarmapGlobs.colourTable[18].blue; return TRUE; case 5: // SURFACE_SOIL drawRect->r = globs::radarmapGlobs.colourTable[17].red; drawRect->g = globs::radarmapGlobs.colourTable[17].green; drawRect->b = globs::radarmapGlobs.colourTable[17].blue; return TRUE; } } } switchD_0045ef37_caseD_b: return TRUE; } BOOL __cdecl lego::reward::Reward_Initialise(void) { int iVar1; uint uVar2; RewardLevel *pRVar3; char **ppcVar4; char *ITEM_NAMES [10]; ITEM_NAMES[0] = "Crystals"; ITEM_NAMES[1] = "Ore"; ITEM_NAMES[2] = "Diggable"; ITEM_NAMES[3] = "Constructions"; ITEM_NAMES[4] = "Caverns"; ITEM_NAMES[5] = "Figures"; ITEM_NAMES[6] = "RockMonsters"; ITEM_NAMES[7] = "Oxygen"; ITEM_NAMES[8] = "Timer"; ITEM_NAMES[9] = "Score"; globs::rewardGlobs.base = (RewardLevel *)io::Mem_Alloc(0x318c); pRVar3 = globs::rewardGlobs.base; // std::memset(_, 0, 0x318c); for (iVar1 = 0xc63; iVar1 != 0; iVar1 += -1) { pRVar3->Enabled = 0; pRVar3 = (RewardLevel *)&pRVar3->saveHasCapture; } uVar2 = 0; ppcVar4 = ITEM_NAMES; (globs::rewardGlobs.base)->itemPtr = (globs::rewardGlobs.base)->items; (globs::rewardGlobs.base)->itemCount = 10; do { std::sprintf((globs::rewardGlobs.base)->itemPtr->name + uVar2,"%s",*ppcVar4); uVar2 += 0x210; ppcVar4 = ppcVar4 + 1; } while (uVar2 < 0x14a0); uVar2 = 0; do { Reward_LoadItemImages ((RewardLevelItem *)((globs::rewardGlobs.base)->itemPtr->name + (uVar2 - 4))); uVar2 += 0x210; } while (uVar2 < 0x14a0); uVar2 = 0; do { Reward_LoadItemText((RewardLevelItem *)((globs::rewardGlobs.base)->itemPtr->name + (uVar2 - 4))) ; uVar2 += 0x210; } while (uVar2 < 0x14a0); uVar2 = 0; do { Reward_LoadItemFlics ((RewardLevelItem *)((globs::rewardGlobs.base)->itemPtr->name + (uVar2 - 4))); uVar2 += 0x210; } while (uVar2 < 0x14a0); uVar2 = 0; do { Reward_LoadItemFonts ((RewardLevelItem *)((globs::rewardGlobs.base)->itemPtr->name + (uVar2 - 4))); uVar2 += 0x210; } while (uVar2 < 0x14a0); uVar2 = 0; do { Reward_LoadItemSounds ((RewardLevelItem *)((globs::rewardGlobs.base)->itemPtr->name + (uVar2 - 4))); uVar2 += 0x210; } while (uVar2 < 0x14a0); uVar2 = 0; do { Reward_LoadItemBoxImages ((RewardLevelItem *)((globs::rewardGlobs.base)->itemPtr->name + (uVar2 - 4))); uVar2 += 0x210; } while (uVar2 < 0x14a0); return TRUE; } void __cdecl lego::reward::Reward_LoadItemSounds(RewardLevelItem *rewardItem) { char *pcVar1; pcVar1 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,"Reward","Sounds",rewardItem->name,0); pcVar1 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar1); rewardItem->SoundName = pcVar1; return; } void __cdecl lego::reward::Reward_LoadItemFonts(RewardLevelItem *rewardItem) { char *pcVar1; Font *pFVar2; pcVar1 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,"Reward","Fonts",rewardItem->name,0); pcVar1 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar1); if (pcVar1 != NULL) { pFVar2 = lego::image::Font_Load(pcVar1); rewardItem->Font = pFVar2; if (pFVar2 != NULL) { return; } } rewardItem->Font = globs::rewardGlobs.font; return; } void __cdecl lego::reward::Reward_LoadItemBoxImages(RewardLevelItem *rewardItem) { char *pcVar1; int iVar2; Image *image; char reduceName [64]; char valueBuffer [128]; char *stringParts [100]; pcVar1 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,"Reward","BoxImages",rewardItem->name,0); pcVar1 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar1); if (pcVar1 == NULL) { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEIMAGES) == MAIN_FLAG_NONE) { std::sprintf(reduceName,"!%s",rewardItem->name); pcVar1 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","Images",reduceName,0) ; pcVar1 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar1); } if (pcVar1 == NULL) { return; } } util::Util_Tokenise(pcVar1,stringParts,"|"); std::sprintf(valueBuffer,"%s",stringParts[0]); iVar2 = std::atoi(stringParts[1]); (rewardItem->BoxImagePosition).x = iVar2; iVar2 = std::atoi(stringParts[2]); (rewardItem->BoxImagePosition).y = iVar2; image = lego::image::Image_LoadBMPScaled(valueBuffer,0,0); rewardItem->BoxImage = image; if (image != NULL) { lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); rewardItem->flags = rewardItem->flags | REWARDITEM_FLAG_BOXIMAGES; io::Mem_Free(pcVar1); } return; } void __cdecl lego::reward::Reward_LoadItemImages(RewardLevelItem *rewardItem) { char *pcVar1; int iVar2; Image *image; char local_250 [64]; char local_210 [128]; char *local_190; char *local_18c; char *local_188; pcVar1 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,"Reward","Images",rewardItem->name,0); pcVar1 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar1); if (pcVar1 == NULL) { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEIMAGES) == MAIN_FLAG_NONE) { std::sprintf(local_250,"!%s",rewardItem->name); pcVar1 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","Images",local_250,0); pcVar1 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar1); } if (pcVar1 == NULL) { return; } } util::Util_Tokenise(pcVar1,&local_190,"|"); std::sprintf(local_210,"%s",local_190); iVar2 = std::atoi(local_18c); (rewardItem->ImagePosition).x = iVar2; iVar2 = std::atoi(local_188); (rewardItem->ImagePosition).y = iVar2; image = lego::image::Image_LoadBMPScaled(local_210,0,0); rewardItem->Image = image; if (image != NULL) { lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); rewardItem->flags = rewardItem->flags | REWARDITEM_FLAG_IMAGES; io::Mem_Free(pcVar1); } return; } void __cdecl lego::reward::Reward_LoadItemText(RewardLevelItem *rewardItem) { RewardItemFlags RVar1; char *pcVar2; int iVar3; char *stringParts [100]; pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","Text",rewardItem->name,0) ; pcVar2 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar2); if (pcVar2 != NULL) { util::Util_Tokenise(pcVar2,stringParts,"|"); std::sprintf(rewardItem->Text,"%s",stringParts[0]); front::Front_Util_StringReplaceChar(rewardItem->Text,'_',' '); iVar3 = std::atoi(stringParts[1]); (rewardItem->TextPosition).x = iVar3; iVar3 = std::atoi(stringParts[2]); RVar1 = rewardItem->flags; (rewardItem->TextPosition).y = iVar3; rewardItem->flags = RVar1 | (REWARDITEM_FLAG_VALUETEXT|REWARDITEM_FLAG_NAMETEXT| REWARDITEM_FLAG_NAMETEXT_HALFTRANS); io::Mem_Free(pcVar2); } return; } void __cdecl lego::reward::Reward_LoadItemFlics(RewardLevelItem *rewardItem) { RewardItemFlags RVar1; char *pcVar2; int iVar3; char reduceName [64]; char valueBuffer [128]; char *stringParts [100]; pcVar2 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,"Reward","Flics",rewardItem->name,0); pcVar2 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar2); if (pcVar2 == NULL) { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEFLICS) == MAIN_FLAG_NONE) { std::sprintf(reduceName,"!%s",rewardItem->name); pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","Flics",reduceName,0); pcVar2 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar2); } if (pcVar2 == NULL) { return; } } util::Util_Tokenise(pcVar2,stringParts,"|"); std::sprintf(valueBuffer,"%s",stringParts[0]); std::sprintf(rewardItem->FlicName,"%s",valueBuffer); iVar3 = std::atoi(stringParts[1]); (rewardItem->FlicPosition).x = iVar3; iVar3 = std::atoi(stringParts[2]); (rewardItem->FlicPosition).y = iVar3; iVar3 = std::atoi(stringParts[3]); (rewardItem->FlicSize).width = iVar3; iVar3 = std::atoi(stringParts[4]); RVar1 = rewardItem->flags; (rewardItem->FlicSize).height = iVar3; rewardItem->flags = RVar1 | REWARDITEM_FLAG_FLIC; io::Mem_Free(pcVar2); return; } void __cdecl lego::reward::Reward_Shutdown(void) { RewardLevelItem *rewardItem; uint uVar1; uVar1 = 0; do { if (((globs::rewardGlobs.base)->itemPtr->name[uVar1 - 4] & REWARDITEM_FLAG_IMAGES) != 0) { Reward_FreeItemImage ((RewardLevelItem *)((globs::rewardGlobs.base)->itemPtr->name + (uVar1 - 4))); } rewardItem = (RewardLevelItem *)((globs::rewardGlobs.base)->itemPtr->name + (uVar1 - 4)); if ((*(byte *)&rewardItem->flags & REWARDITEM_FLAG_VALUETEXT) != 0) { Reward_FreeItemFont(rewardItem); } uVar1 += 0x210; } while (uVar1 < 0x14a0); io::Mem_Free(globs::rewardGlobs.base); return; } void __cdecl lego::reward::Reward_FreeItemImage(RewardLevelItem *rewardItem) { lego::image::Image_Remove(rewardItem->Image); return; } void __cdecl lego::reward::Reward_FreeItemFont(RewardLevelItem *rewardItem) { lego::image::Font_Remove(rewardItem->Font); return; } BOOL __cdecl lego::reward::Reward_LoadGraphics(Config *config,char *gameName) { char *pcVar1; float10 fVar2; uint width; uint height; char *stringParts [100]; lrr::Lego_GetLevel(); height = 0; width = 0; globs::rewardGlobs.config = config; globs::rewardGlobs.gameName = gameName; pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","Wallpaper",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); globs::rewardGlobs.wallpaper = lego::image::Image_LoadBMPScaled(pcVar1,width,height); pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","Display",0); globs::rewardGlobs.display = cfg::Config_GetBoolValue(config,pcVar1); if (globs::rewardGlobs.display == BOOL3_ERROR) { globs::rewardGlobs.display = FALSE; } pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","CentreText",0); globs::rewardGlobs.centerText = cfg::Config_GetBoolValue(config,pcVar1); if (globs::rewardGlobs.centerText == BOOL3_ERROR) { globs::rewardGlobs.centerText = FALSE; } pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","ScrollSpeed",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","ScrollSpeed",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); } fVar2 = std::atof(pcVar1); globs::rewardGlobs.scrollSpeed = (float)fVar2; pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","VertSpacing",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","VertSpacing",0); pcVar1 = cfg::Config_GetTempStringValue(config,pcVar1); } fVar2 = std::atof(pcVar1); globs::rewardGlobs.vertSpacing = (float)fVar2; pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","Font",0); globs::rewardGlobs.fontName = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","TitleFont",0); globs::rewardGlobs.titleFontName = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","BackFont",0); globs::rewardGlobs.backFontName = cfg::Config_GetStringValue(config,pcVar1); globs::rewardGlobs.font = lego::image::Font_Load(globs::rewardGlobs.fontName); globs::rewardGlobs.titleFont = lego::image::Font_Load(globs::rewardGlobs.titleFontName); globs::rewardGlobs.backFont = lego::image::Font_Load(globs::rewardGlobs.backFontName); Reward_LoadButtons(config,gameName); pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","CompleteText",0); globs::rewardGlobs.completeText = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","FailedText",0); globs::rewardGlobs.failedText = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","QuitText",0); globs::rewardGlobs.quitText = cfg::Config_GetStringValue(config,pcVar1); pcVar1 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","TextPos",0); pcVar1 = cfg::Config_GetStringValue(globs::rewardGlobs.config,pcVar1); if (pcVar1 != NULL) { util::Util_Tokenise(pcVar1,stringParts,"|"); globs::rewardGlobs.textPos.x = std::atoi(stringParts[0]); globs::rewardGlobs.textPos.y = std::atoi(stringParts[1]); } return TRUE; } BOOL __cdecl lego::reward::Reward_LoadButtons(Config *config,char *gameName) { char *pcVar1; int iVar2; char *parts [100]; pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","SaveButton",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 != NULL) { util::Util_Tokenise(pcVar1,parts,"|"); globs::rewardGlobs.saveButton = lego::image::Image_LoadBMPScaled(parts[0],0,0); if (globs::rewardGlobs.saveButton != NULL) { globs::rewardGlobs.saveButton_hi = lego::image::Image_LoadBMPScaled(parts[1],0,0); globs::rewardGlobs.saveButton_in = lego::image::Image_LoadBMPScaled(parts[2],0,0); globs::rewardGlobs.saveButton_dim = lego::image::Image_LoadBMPScaled(parts[3],0,0); iVar2 = std::atoi(parts[4]); globs::rewardGlobs.saveButtonPosition.x = (float)iVar2; iVar2 = std::atoi(parts[5]); globs::rewardGlobs.saveButtonPosition.y = (float)iVar2; lego::image::Image_SetupTrans(globs::rewardGlobs.saveButton,0.0,0.0,0.0,0.0,0.0,0.0); if (globs::rewardGlobs.saveButton_hi != NULL) { lego::image::Image_SetupTrans(globs::rewardGlobs.saveButton_hi,0.0,0.0,0.0,0.0,0.0,0.0); } if (globs::rewardGlobs.saveButton_in != NULL) { lego::image::Image_SetupTrans(globs::rewardGlobs.saveButton_in,0.0,0.0,0.0,0.0,0.0,0.0); } } io::Mem_Free(pcVar1); } pcVar1 = cfg::Config_BuildStringID(gameName,"Reward","AdvanceButton",0); pcVar1 = cfg::Config_GetStringValue(config,pcVar1); if (pcVar1 != NULL) { util::Util_Tokenise(pcVar1,parts,"|"); globs::rewardGlobs.advanceButton = lego::image::Image_LoadBMPScaled(parts[0],0,0); if (globs::rewardGlobs.advanceButton != NULL) { globs::rewardGlobs.advanceButton_hi = lego::image::Image_LoadBMPScaled(parts[1],0,0); globs::rewardGlobs.advanceButton_in = lego::image::Image_LoadBMPScaled(parts[2],0,0); globs::rewardGlobs.advanceButton_dim = lego::image::Image_LoadBMPScaled(parts[3],0,0); iVar2 = std::atoi(parts[4]); globs::rewardGlobs.advanceButtonPosition.x = (float)iVar2; iVar2 = std::atoi(parts[5]); globs::rewardGlobs.advanceButtonPosition.y = (float)iVar2; lego::image::Image_SetupTrans(globs::rewardGlobs.advanceButton,0.0,0.0,0.0,0.0,0.0,0.0); if (globs::rewardGlobs.advanceButton_hi != NULL) { lego::image::Image_SetupTrans(globs::rewardGlobs.advanceButton_hi,0.0,0.0,0.0,0.0,0.0,0.0); } if (globs::rewardGlobs.advanceButton_in != NULL) { lego::image::Image_SetupTrans(globs::rewardGlobs.advanceButton_in,0.0,0.0,0.0,0.0,0.0,0.0); } } io::Mem_Free(pcVar1); } if ((globs::rewardGlobs.saveButton != NULL) && (globs::rewardGlobs.advanceButton != NULL)) { return TRUE; } return FALSE; } BOOL __cdecl lego::reward::Reward_CreateLevel(void) { int iVar1; Lego_Level *level; char *pcVar2; BoolTri BVar3; uint uVar4; int iVar5; int iVar6; undefined4 *puVar7; RewardLevel *reward; undefined4 *puVar8; float10 fVar9; level = lrr::Lego_GetLevel(); globs::rewardGlobs.level = (RewardLevel *)io::Mem_Alloc(0x318c); reward = globs::rewardGlobs.level; // std:::memset(_, 0, 0x318c); for (iVar5 = 0xc63; iVar5 != 0; iVar5 += -1) { reward->Enabled = 0; reward = (RewardLevel *)&reward->saveHasCapture; } pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,level->name,"Reward","Enable",0); BVar3 = cfg::Config_GetBoolValue(globs::rewardGlobs.config,pcVar2); (globs::rewardGlobs.level)->Enabled = BVar3; if ((globs::rewardGlobs.level)->Enabled == BOOL3_ERROR) { (globs::rewardGlobs.level)->Enabled = 0; } pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,level->name,"Reward","Modifier",0); pcVar2 = cfg::Config_GetTempStringValue(globs::rewardGlobs.config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,level->name,"Reward","Modifier",0); pcVar2 = cfg::Config_GetTempStringValue(globs::rewardGlobs.config,pcVar2); } iVar5 = std::atoi(pcVar2); (globs::rewardGlobs.level)->Modifier = iVar5; pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","Timer",0); pcVar2 = cfg::Config_GetTempStringValue(globs::rewardGlobs.config,pcVar2); if (pcVar2 == NULL) { pcVar2 = ____EMPTYSTR__; } else { pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","Timer",0); pcVar2 = cfg::Config_GetTempStringValue(globs::rewardGlobs.config,pcVar2); } fVar9 = std::atof(pcVar2); globs::rewardGlobs.timer = (float)fVar9; if ((float10)0.0 == fVar9) { globs::rewardGlobs.timer = 76.9375; } pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","DisplayText",0); globs::rewardGlobs.displayText = cfg::Config_GetBoolValue(globs::rewardGlobs.config,pcVar2); if (globs::rewardGlobs.displayText == BOOL3_ERROR) { globs::rewardGlobs.displayText = 1; } pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","DisplayImages",0); globs::rewardGlobs.displayImages = cfg::Config_GetBoolValue(globs::rewardGlobs.config,pcVar2); if (globs::rewardGlobs.displayImages == BOOL3_ERROR) { globs::rewardGlobs.displayImages = 1; } pcVar2 = cfg::Config_BuildStringID(globs::rewardGlobs.gameName,"Reward","DisplayFlics",0); globs::rewardGlobs.displayFlics = cfg::Config_GetBoolValue(globs::rewardGlobs.config,pcVar2); if (globs::rewardGlobs.displayFlics == BOOL3_ERROR) { globs::rewardGlobs.displayFlics = 1; } (globs::rewardGlobs.level)->itemPtr = (globs::rewardGlobs.level)->items; uVar4 = 0; (globs::rewardGlobs.level)->itemCount = 10; do { iVar5 = uVar4 - 4; iVar1 = uVar4 - 4; uVar4 += 0x210; puVar7 = (undefined4 *)((globs::rewardGlobs.base)->itemPtr->name + iVar5); puVar8 = (undefined4 *)((globs::rewardGlobs.level)->itemPtr->name + iVar1); for (iVar6 = 0x84; iVar6 != 0; iVar6 += -1) { *puVar8 = *puVar7; puVar7 = puVar7 + 1; puVar8 = puVar8 + 1; } } while (uVar4 < 0x14a0); uVar4 = 0; do { Reward_LoadLevelItemImportance ((RewardLevelItem *)((globs::rewardGlobs.level)->itemPtr->name + (uVar4 - 4))); uVar4 += 0x210; } while (uVar4 < 0x14a0); uVar4 = 0; do { Reward_LoadLevelItemQuota ((RewardLevelItem *)((globs::rewardGlobs.level)->itemPtr->name + (uVar4 - 4))); uVar4 += 0x210; } while (uVar4 < 0x14a0); // HARDCODED: Set Caverns::Quota = 1, for Level03 ("Rubble Trouble!") iVar5 = std::_stricmp(level->name,"Levels::Level03"); if (iVar5 == 0) { (globs::rewardGlobs.level)->itemPtr[4].Quota = 1; } return 1; } void __cdecl lego::reward::Reward_LoadLevelItemImportance(RewardLevelItem *rewardItem) { Lego_Level *level; char *pcVar1; float10 fVar2; level = lrr::Lego_GetLevel(); pcVar1 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,level->name,"Reward","Importance",rewardItem->name ,0); pcVar1 = cfg::Config_GetTempStringValue(globs::rewardGlobs.config,pcVar1); if (pcVar1 != NULL) { pcVar1 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,level->name,"Reward","Importance", rewardItem->name,0); pcVar1 = cfg::Config_GetTempStringValue(globs::rewardGlobs.config,pcVar1); fVar2 = std::atof(pcVar1); rewardItem->Importance = (float)fVar2; return; } fVar2 = std::atof(____EMPTYSTR__); rewardItem->Importance = (float)fVar2; return; } void __cdecl lego::reward::Reward_LoadLevelItemQuota(RewardLevelItem *rewardItem) { Lego_Level *level; char *pcVar1; int iVar2; level = lrr::Lego_GetLevel(); pcVar1 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,level->name,"Reward","Quota",rewardItem->name,0); pcVar1 = cfg::Config_GetTempStringValue(globs::rewardGlobs.config,pcVar1); if (pcVar1 != NULL) { pcVar1 = cfg::Config_BuildStringID (globs::rewardGlobs.gameName,level->name,"Reward","Quota",rewardItem->name,0) ; pcVar1 = cfg::Config_GetTempStringValue(globs::rewardGlobs.config,pcVar1); iVar2 = std::atoi(pcVar1); rewardItem->Quota = iVar2; return; } iVar2 = std::atoi(____EMPTYSTR__); rewardItem->Quota = iVar2; return; } void __cdecl lego::reward::Reward_FreeLevel(void) { io::Mem_Free(globs::rewardGlobs.level); return; } // Unused parameter is always Lego_Level::unused_rewardID (field_10) RewardLevel * __cdecl lego::reward::GetRewardLevel2(undefined4 unused_rewardID) { return globs::rewardGlobs.level; } // No different from above (GetRewardLevel2(undefined4)) RewardLevel * __cdecl lego::reward::GetRewardLevel(void) { Lego_Level *level; RewardLevel *reward; level = lrr::Lego_GetLevel(); if (level == NULL) { return NULL; } reward = GetRewardLevel2(level->unused_rewardID); return reward; } void __cdecl lego::reward::RewardQuota_CountUnits(void) { Lego_Level *level; RewardLevel *pRVar1; RewardBuildingCounts *pRVar2; int iVar3; RewardBuildingCounts *pRVar4; RewardBuildingCounts buildingCounts; level = lrr::Lego_GetLevel(); if (level == NULL) { return; } pRVar1 = GetRewardLevel2(level->unused_rewardID); if (pRVar1 == NULL) { return; } pRVar2 = RewardQuota_CountBuildings(&buildingCounts); pRVar4 = &globs::rewardGlobs.current.buildingCounts; for (iVar3 = 0x66; iVar3 != 0; iVar3 += -1) { pRVar4->nameTable[0] = pRVar2->nameTable[0]; pRVar2 = (RewardBuildingCounts *)(pRVar2->nameTable + 1); pRVar4 = (RewardBuildingCounts *)(pRVar4->nameTable + 1); } // table[REWARDTYPE_FIGURES] globs::rewardGlobs.current.items[5].numDestroyed = nerps::NERPsRuntime_GetPreviousLevelObjectsBuilt("Pilot",0); return; } RewardBuildingCounts * __cdecl lego::reward::RewardQuota_CountBuildings(RewardBuildingCounts *out_buildingCounts) { uint uVar1; int iVar2; uint objLevel; RewardBuildingCounts *pRVar3; LegoObject_ID objID; RewardBuildingCounts *pRVar4; RewardBuildingCounts buildingCounts; buildingCounts.count = 0; game::LegoObject_RunThroughListsSkipUpgradeParts (RewardQuota_LiveObjectCallback_CountBuildings,&buildingCounts); buildingCounts.numPrevLevels_unk = 0; objID = 0; do { objLevel = 0; do { uVar1 = game::LegoObject_GetPreviousLevelObjectsBuilt(LegoObject_Building,objID,objLevel); objLevel += 1; buildingCounts.numPrevLevels_unk = buildingCounts.numPrevLevels_unk + uVar1; } while (objLevel < 0x10); objID += 1; } while (objID < 0xf); pRVar3 = &buildingCounts; pRVar4 = out_buildingCounts; for (iVar2 = 0x66; iVar2 != 0; iVar2 += -1) { pRVar4->nameTable[0] = pRVar3->nameTable[0]; pRVar3 = (RewardBuildingCounts *)(pRVar3->nameTable + 1); pRVar4 = (RewardBuildingCounts *)(pRVar4->nameTable + 1); } return out_buildingCounts; } BOOL __cdecl lego::reward::RewardQuota_LiveObjectCallback_CountBuildings (LegoObject *liveObj,RewardBuildingCounts *search) { RewardBuildingCounts *pRVar1; char *pcVar2; int objIndex; game::LegoObject_GetTypeAndID(liveObj,(LegoObject_Type *)&liveObj,(LegoObject_ID *)&objIndex); pRVar1 = search; // if (objType == OBJECT_BUILDING) if (liveObj == (LegoObject *)&DAT_00000004) { pcVar2 = game::Object_GetTypeName(LegoObject_Building,objIndex); pRVar1->nameTable[pRVar1->count] = pcVar2; pRVar1->count = pRVar1->count + 1; } return 0; } BOOL __cdecl lego::reward::Reward_Prepare(void) { undefined *puVar1; float fVar2; uint uVar3; uint uVar4; Lego_Level *level; RewardLevel *reward; uint uVar5; Map3D *surfMap; int iVar6; char *pcVar7; Image *pIVar8; uint uVar9; RewardBuildingCounts *pRVar10; Image *pIVar11; RewardBuildingCounts *pRVar12; char (*out_buffer) [64]; float10 fVar13; ulonglong uVar14; uint local_30; uint local_28; uint local_24; uint local_20; uint local_1c; Point2I local_18; uint local_10; undefined4 uStack12; uint local_8; undefined4 uStack4; Lego_SurfaceType8 terrain; level = lrr::Lego_GetLevel(); if (level == NULL) { return 0; } reward = GetRewardLevel2(level->unused_rewardID); if (reward != NULL) { if (globs::rewardGlobs.current.saveHasCapture != 0) { pIVar8 = &globs::rewardGlobs.current.saveCaptureImage; pIVar11 = &reward->saveCaptureImage; for (iVar6 = 8; iVar6 != 0; iVar6 += -1) { pIVar11->surface = pIVar8->surface; pIVar8 = (Image *)&pIVar8->width; pIVar11 = (Image *)&pIVar11->width; } reward->saveHasCapture = TRUE; } reward->items[0].countdownRatio = 0.0; reward->items[1].countdownRatio = 0.0; reward->items[2].countdown = globs::rewardGlobs.current.items[2].countdown; reward->items[4].countdown = globs::rewardGlobs.current.items[4].countdown; reward->items[2].countdownRatio = 0.0; reward->float_1b04 = 0.0; reward->float_1b08 = 0.0; uVar5 = Reward_GetLevelObjectsBuilt("Pilot",0,0); reward->items[5].numGenerated = uVar5; reward->items[5].numDestroyed = globs::rewardGlobs.current.items[5].numDestroyed; reward->items[5].damageTaken = globs::rewardGlobs.current.items[5].damageTaken; uVar5 = globs::rewardGlobs.current.items[6].numGenerated; reward->items[6].numGenerated = globs::rewardGlobs.current.items[6].numGenerated; reward->items[6].numDestroyed = globs::rewardGlobs.current.items[6].numDestroyed; fVar2 = (float)(ulonglong)(uVar5 * 100); if ((ushort)((ushort)(globs::rewardGlobs.current.items[6].damageTaken < fVar2) << 8 | (ushort)(globs::rewardGlobs.current.items[6].damageTaken == fVar2) << 0xe) != 0) { fVar2 = globs::rewardGlobs.current.items[6].damageTaken; } reward->items[6].damageTaken = fVar2; reward->items[6].numAttacked = globs::rewardGlobs.current.items[6].numAttacked; pRVar10 = &globs::rewardGlobs.current.buildingCounts; pRVar12 = &reward->buildingCounts; for (iVar6 = 0x66; iVar6 != 0; iVar6 += -1) { pRVar12->nameTable[0] = pRVar10->nameTable[0]; pRVar10 = (RewardBuildingCounts *)(pRVar10->nameTable + 1); pRVar12 = (RewardBuildingCounts *)(pRVar12->nameTable + 1); } uVar5 = 0; reward->field_1c8 = 0; fVar2 = (globs::legoGlobs.currLevel)->oxygenLevel; reward->items[7].countdownRatio = (float)&DAT_42c80000; reward->items[7].countdown = fVar2; reward->items[8].countdown = globs::rewardGlobs.current.items[8].countdown; reward->items[8].countdownRatio = globs::rewardGlobs.current.items[8].countdownRatio / reward->items[8].countdown; surfMap = level->map; if (surfMap->blockWidth != 0) { do { uVar9 = 0; if (surfMap->blockHeight != 0) { do { terrain = level->blocks[uVar9 * level->width + uVar5].terrain; reward->field_1c8 = reward->field_1c8 + 1; local_18.x = uVar5; local_18.y = uVar9; lrr::Lego_GetBlockCryOre(&local_18,&local_28,&local_1c,&local_24,&local_20); local_10 = local_28; uStack12 = 0; uStack4 = 0; reward->items[0].countdownRatio = (float)(ulonglong)local_28 + reward->items[0].countdownRatio; local_8 = local_24; reward->items[1].countdownRatio = (float)(ulonglong)local_24 + reward->items[1].countdownRatio; if ((*(byte *)&level->blocks[uVar9 * level->width + uVar5].flags1 & 8) == 0) { if (terrain != Lego_SurfaceType8_Immovable) { reward->items[2].countdownRatio = reward->items[2].countdownRatio - -1.0; reward->float_1b04 = reward->float_1b04 - -1.0; } if (terrain == Lego_SurfaceType8_CrystalSeam) { reward->items[0].countdownRatio = reward->items[0].countdownRatio - -4.0; } } else { if ((terrain != Lego_SurfaceType8_Water) && (terrain != Lego_SurfaceType8_Lava)) { reward->float_1b04 = reward->float_1b04 - -1.0; } } if ((level->blocks[uVar9 * level->width + uVar5].flags1 & (BLOCK1_FOUNDATION|BLOCK1_UNUSED_PATHTYPE|BLOCK1_PATH|BLOCK1_LAYEDPATH)) != BLOCK1_NONE) { reward->float_1b08 = reward->float_1b08 - -1.0; reward->items[2].countdownRatio = reward->items[2].countdownRatio - -1.0; } uVar9 += 1; } while (uVar9 < level->map->blockHeight); } surfMap = level->map; uVar5 += 1; } while (uVar5 < surfMap->blockWidth); } fVar2 = reward->items[2].countdownRatio; uVar5 = (reward->buildingCounts).count; uVar9 = (reward->buildingCounts).numPrevLevels_unk; reward->uintConstructCount_1cc = uVar5; reward->uintConstruct_1d0 = uVar9; local_30 = 0; reward->items[1].countdownRatio = reward->items[1].countdownRatio - fVar2 * -4.0; if (uVar5 != 0) { out_buffer = reward->buildingNameBuffers; pRVar10 = &reward->buildingCounts; do { std::sprintf((char *)out_buffer,"%s",pRVar10->nameTable[0]); local_30 += 1; pRVar10 = (RewardBuildingCounts *)(pRVar10->nameTable + 1); out_buffer = out_buffer[1]; } while (local_30 < reward->uintConstructCount_1cc); } uVar5 = reward->items[5].numGenerated; uVar9 = reward->uintConstruct_1d0; reward->items[0].countdown = (float)(ulonglong)(uint)level->crystals; uVar3 = reward->items[5].numDestroyed; reward->items[1].countdown = (float)(ulonglong)(uint)level->ore; uVar4 = reward->items[6].numGenerated; reward->items[5].countdownRatio = (float)(ulonglong)uVar5; reward->items[5].countdown = (float)(ulonglong)(uVar5 - uVar3); reward->items[6].countdown = reward->items[6].damageTaken; uVar5 = reward->uintConstructCount_1cc; reward->items[6].countdownRatio = (float)(ulonglong)(uVar4 * 100); uVar9 = (uVar5 - uVar9) + 1; local_8 = reward->items[8].Quota; reward->items[3].countdownRatio = (float)(ulonglong)uVar5; reward->items[3].countdown = (float)(ulonglong)uVar9; if (local_8 == 0) { reward->items[8].percentFloat = 0.0; local_8 = uVar9; } else { fVar13 = (float10)reward->items[8].countdown * (float10)0.04; uStack4 = 0; if ((float10)(ulonglong)local_8 <= fVar13) { reward->items[8].percentFloat = (float)&DAT_42c80000; } else { uVar14 = __ftol(((float10)100.0 / (float10)(ulonglong)local_8) * fVar13); reward->items[8].percentFloat = (float)(uVar14 & 0xffffffff); fVar2 = reward->items[8].percentFloat; if ((ushort)((ushort)(fVar2 < 100.0) << 8 | (ushort)(fVar2 == 100.0) << 0xe) == 0) { puVar1 = &DAT_42c80000; } else { puVar1 = (undefined *)reward->items[8].percentFloat; } reward->items[8].percentFloat = (float)puVar1; if ((float)puVar1 < 0.0) { puVar1 = NULL; } reward->items[8].percentFloat = (float)puVar1; local_8 = (uint)uVar14; } } uVar5 = reward->items[3].Quota; if (uVar5 != 0) { uVar14 = 100 / (ulonglong)uVar5; local_8 = (uint)uVar14; reward->items[3].percentFloat = (float)uVar14 * reward->items[3].countdown; } uVar5 = reward->items[4].Quota; if (uVar5 != 0) { uVar14 = 100 / (ulonglong)uVar5; local_8 = (uint)uVar14; reward->items[4].percentFloat = (float)uVar14 * reward->items[4].countdown; } uVar5 = reward->items[0].Quota; if (uVar5 != 0) { reward->items[0].countdownRatio = (float)(ulonglong)uVar5; local_8 = uVar5; } uStack4 = 0; uVar5 = 0; do { if (uVar5 != 0x1080) { pcVar7 = reward->itemPtr->name + (uVar5 - 4); if ((ushort)((ushort)(*(float *)(pcVar7 + 0x38) < 100.0) << 8 | (ushort)(*(float *)(pcVar7 + 0x38) == 100.0) << 0xe) == 0) { puVar1 = &DAT_42c80000; } else { puVar1 = *(undefined **)(pcVar7 + 0x38); } *(undefined **)(pcVar7 + 0x38) = puVar1; if ((float)puVar1 < 0.0) { puVar1 = NULL; } *(undefined **)(pcVar7 + 0x38) = puVar1; } uVar5 += 0x210; } while (uVar5 < 0x14a0); Reward_PrepareCalculate(); Reward_PrepareScroll(); reward = &globs::rewardGlobs.current; for (iVar6 = 0xc63; iVar6 != 0; iVar6 += -1) { reward->Enabled = 0; reward = (RewardLevel *)&reward->saveHasCapture; } return TRUE; } return 0; } uint __cdecl lego::reward::Reward_GetLevelObjectsBuilt(char *objName,int objLevel,BOOL currentLevel) { BOOL BVar1; uint count; LegoObject_Type objType; BVar1 = lrr::Lego_GetObjectByName(objName,&objType,(LegoObject_ID *)&objName,NULL); if (BVar1 != 0) { count = game::LegoObject_GetLevelObjectsBuilt (objType,(LegoObject_ID)objName,objLevel,currentLevel); return count; } return 0; } BOOL __cdecl lego::reward::Reward_PrepareCalculate(void) { float fVar1; float fVar2; float fVar3; undefined *puVar4; Lego_Level *pLVar5; RewardLevel *pRVar6; uint uVar7; pLVar5 = lrr::Lego_GetLevel(); if (pLVar5 == NULL) { return 0; } pRVar6 = GetRewardLevel2(pLVar5->unused_rewardID); if (pRVar6 == NULL) { return 0; } pRVar6->items[9].countdown = 0.0; pRVar6->items[9].countdownRatio = 0.0; pRVar6->items[9].percentFloat = 0.0; puVar4 = &DAT_42c80000; if (pRVar6->items[0].countdownRatio != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->items[0].countdownRatio) * pRVar6->items[0].countdown); } pRVar6->items[0].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[0].percentFloat = (float)puVar4; puVar4 = &DAT_42c80000; if (pRVar6->items[1].countdownRatio != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->items[1].countdownRatio) * pRVar6->items[1].countdown); } pRVar6->items[1].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[1].percentFloat = (float)puVar4; puVar4 = &DAT_42c80000; if (pRVar6->items[2].countdownRatio != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->items[2].countdownRatio) * pRVar6->items[2].countdown); } pRVar6->items[2].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[2].percentFloat = (float)puVar4; puVar4 = &DAT_42c80000; if (pRVar6->float_1b04 != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->float_1b04) * pRVar6->float_1b08); } pRVar6->float_1b0c = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->float_1b0c = (float)puVar4; puVar4 = &DAT_42c80000; if (pRVar6->items[7].countdownRatio != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->items[7].countdownRatio) * pRVar6->items[7].countdown); } pRVar6->items[7].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[7].percentFloat = (float)puVar4; puVar4 = &DAT_42c80000; if (pRVar6->items[3].countdownRatio != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->items[3].countdownRatio) * pRVar6->items[3].countdown); } pRVar6->items[3].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[3].percentFloat = (float)puVar4; puVar4 = &DAT_42c80000; if (pRVar6->items[5].countdownRatio != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->items[5].countdownRatio) * pRVar6->items[5].countdown); } pRVar6->items[5].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[5].percentFloat = (float)puVar4; puVar4 = &DAT_42c80000; if (pRVar6->items[6].countdownRatio != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->items[6].countdownRatio) * pRVar6->items[6].countdown); } pRVar6->items[6].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[6].percentFloat = (float)puVar4; uVar7 = 0; if (0.0 < pRVar6->items[5].Importance) { do { uVar7 += 1; fVar1 = pRVar6->items[5].percentFloat; fVar2 = pRVar6->items[5].Importance; fVar3 = pRVar6->items[9].countdown; pRVar6->items[9].countdownRatio = pRVar6->items[9].countdownRatio - -100.0; pRVar6->items[9].countdown = fVar1 + fVar3; } while ((float)(ulonglong)uVar7 < fVar2); } uVar7 = 0; if (0.0 < pRVar6->items[0].Importance) { do { uVar7 += 1; fVar1 = pRVar6->items[0].percentFloat; fVar2 = pRVar6->items[0].Importance; fVar3 = pRVar6->items[9].countdown; pRVar6->items[9].countdownRatio = pRVar6->items[9].countdownRatio - -100.0; pRVar6->items[9].countdown = fVar1 + fVar3; } while ((float)(ulonglong)uVar7 < fVar2); } uVar7 = 0; if (0.0 < pRVar6->items[7].Importance) { do { uVar7 += 1; fVar1 = pRVar6->items[7].percentFloat; fVar2 = pRVar6->items[7].Importance; fVar3 = pRVar6->items[9].countdown; pRVar6->items[9].countdownRatio = pRVar6->items[9].countdownRatio - -100.0; pRVar6->items[9].countdown = fVar1 + fVar3; } while ((float)(ulonglong)uVar7 < fVar2); } uVar7 = 0; if (0.0 < pRVar6->items[3].Importance) { do { uVar7 += 1; fVar1 = pRVar6->items[3].percentFloat; fVar2 = pRVar6->items[3].Importance; fVar3 = pRVar6->items[9].countdown; pRVar6->items[9].countdownRatio = pRVar6->items[9].countdownRatio - -100.0; pRVar6->items[9].countdown = fVar1 + fVar3; } while ((float)(ulonglong)uVar7 < fVar2); } uVar7 = 0; if (0.0 < pRVar6->items[4].Importance) { do { uVar7 += 1; fVar1 = pRVar6->items[4].percentFloat; fVar2 = pRVar6->items[4].Importance; fVar3 = pRVar6->items[9].countdown; pRVar6->items[9].countdownRatio = pRVar6->items[9].countdownRatio - -100.0; pRVar6->items[9].countdown = fVar1 + fVar3; } while ((float)(ulonglong)uVar7 < fVar2); } uVar7 = 0; if (0.0 < pRVar6->items[8].Importance) { fVar1 = pRVar6->items[9].countdownRatio; fVar2 = pRVar6->items[9].countdown; do { uVar7 += 1; fVar1 = fVar1 - -100.0; fVar2 = (100.0 - pRVar6->items[8].percentFloat) + fVar2; } while ((float)(ulonglong)uVar7 < pRVar6->items[8].Importance); pRVar6->items[9].countdown = fVar2; pRVar6->items[9].countdownRatio = fVar1; } uVar7 = 0; if (0.0 < pRVar6->items[6].Importance) { do { uVar7 += 1; fVar1 = pRVar6->items[6].percentFloat; fVar2 = pRVar6->items[6].Importance; fVar3 = pRVar6->items[9].countdown; pRVar6->items[9].countdownRatio = pRVar6->items[9].countdownRatio - -100.0; pRVar6->items[9].countdown = fVar1 + fVar3; } while ((float)(ulonglong)uVar7 < fVar2); } fVar1 = pRVar6->items[9].countdown; fVar2 = pRVar6->items[9].countdownRatio; if ((ushort)((ushort)(fVar1 < fVar2) << 8 | (ushort)(fVar1 == fVar2) << 0xe) == 0) { pRVar6->items[9].countdown = pRVar6->items[9].countdownRatio; } if (pRVar6->items[9].countdown < 0.0) { pRVar6->items[9].countdown = 0.0; } puVar4 = &DAT_42c80000; if (pRVar6->items[9].countdownRatio != 0.0) { puVar4 = (undefined *)((100.0 / pRVar6->items[9].countdownRatio) * pRVar6->items[9].countdown); } pRVar6->items[9].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[9].percentFloat = (float)puVar4; puVar4 = (undefined *)((float)(ulonglong)(uint)pRVar6->Modifier + pRVar6->items[9].percentFloat); pRVar6->items[9].percentFloat = (float)puVar4; if ((ushort)((ushort)((float)puVar4 < 100.0) << 8 | (ushort)((float)puVar4 == 100.0) << 0xe) == 0) { puVar4 = &DAT_42c80000; } pRVar6->items[9].percentFloat = (float)puVar4; return TRUE; } BOOL __cdecl lego::reward::Reward_PrepareScroll(void) { Lego_Level *level; RewardLevel *rewardFront; float heightf; LevelStatus status; char *text; float widthf; heightf = (float)globs::mainGlobs.appHeight; widthf = (float)globs::mainGlobs.appWidth; level = lrr::Lego_GetLevel(); if (level == NULL) { return 0; } rewardFront = GetRewardLevel2(level->unused_rewardID); if (rewardFront != NULL) { Reward_PrepareValueText(); RewardScroll_Create(&globs::rewardGlobs.scroll,0,heightf * 0.05,widthf, heightf - heightf * 0.2857143,globs::rewardGlobs.scrollSpeed); RewardScroll_SetDelay_Unk(globs::rewardGlobs.scroll,400.0); // This has no effect. (flags |= 0;) RewardScroll_AddFlags(globs::rewardGlobs.scroll,REWARDSCROLL_NONE); // Add label to display level name at top of screen. RewardScroll_AddLabel (globs::rewardGlobs.scroll,level->FullName,globs::rewardGlobs.titleFont,0.0, (float)globs::mainGlobs.appHeight * 0.04, REWARDSCROLL_LABEL_CENTERED|REWARDSCROLL_LABEL_NOSCROLL); status = level->status; text = globs::rewardGlobs.completeText; if (((status == LEVELSTATUS_COMPLETE) || (text = globs::rewardGlobs.failedText, status == LEVELSTATUS_FAILED)) || (text = globs::rewardGlobs.quitText, status == LEVELSTATUS_FAILED_CRYSTALS)) { text = util::Util_RemoveUnderscores(text); std::sprintf(globs::rewardGlobs.statusMessage,"%s",text); } // Add label to display completion message just below level name. RewardScroll_AddLabel (globs::rewardGlobs.scroll,globs::rewardGlobs.statusMessage,globs::rewardGlobs.font, 0.0,globs::rewardGlobs.vertSpacing,REWARDSCROLL_LABEL_CENTERED); return TRUE; } return 0; } BOOL __cdecl lego::reward::Reward_PrepareValueText(void) { char cVar1; Lego_Level *level; RewardLevel *reward; int iVar2; uint uVar3; uint uVar4; uint uVar5; undefined4 *puVar6; char *pcVar7; char *pcVar8; undefined4 *puVar9; float10 fVar10; longlong lVar11; ulonglong uVar12; char *pcVar13; char buff2 [128]; char buff1 [128]; level = lrr::Lego_GetLevel(); if (level == NULL) { return 0; } reward = GetRewardLevel2(level->unused_rewardID); if (reward == NULL) { return 0; } lVar11 = __ftol((float10)reward->items[0].percentFloat); reward->items[0].percentInt = (int)lVar11; std::sprintf(reward->items[0].valueText,"%d%%%%",(int)lVar11); lVar11 = __ftol((float10)reward->items[1].percentFloat); reward->items[1].percentInt = (int)lVar11; std::sprintf(reward->items[1].valueText,"%d%%%%",(int)lVar11); lVar11 = __ftol((float10)reward->items[2].percentFloat); reward->items[2].percentInt = (int)lVar11; std::sprintf(reward->items[2].valueText,"%d%%%%",(int)lVar11); lVar11 = __ftol((float10)reward->float_1b0c); *(int *)&reward->field_0x1b24 = (int)lVar11; std::sprintf((char *)&reward->field_0x1ba8,"%d",(int)lVar11); uVar3 = reward->uintConstructCount_1cc; reward->items[3].percentInt = uVar3; std::sprintf(reward->items[3].valueText,"%d",uVar3); lVar11 = __ftol((float10)reward->items[4].percentFloat); reward->items[4].percentInt = (int)lVar11; std::sprintf(reward->items[4].valueText,"%d%%%%",(int)lVar11); lVar11 = __ftol((float10)reward->items[5].percentFloat); reward->items[5].percentInt = (int)lVar11; std::sprintf(reward->items[5].valueText,"%d%%%%",(int)lVar11); if (100.0 <= reward->items[6].damageTaken) { fVar10 = (float10)100.0; } else { fVar10 = (float10)reward->items[6].damageTaken; } lVar11 = __ftol(fVar10); reward->items[6].percentInt = (int)lVar11; std::sprintf(reward->items[6].valueText,"%d%%%%",(int)lVar11); lVar11 = __ftol((float10)reward->items[7].percentFloat); reward->items[7].percentInt = (int)lVar11; std::sprintf(reward->items[7].valueText,"%d%%%%",(int)lVar11); uVar12 = __ftol((float10)reward->items[8].countdown * (float10)reward->items[8].countdownRatio * (float10)0.04); reward->items[8].percentInt = (int)uVar12; uVar3 = (uint)((uVar12 & 0xffffffff) % 359999); std::sprintf(buff1,____EMPTYSTR__); if (uVar3 < 0xe11) { pcVar13 = "00:"; } else { uVar4 = (uVar3 - 1) / 0xe10; uVar5 = uVar4; do { uVar3 -= 0xe10; uVar5 -= 1; } while (uVar5 != 0); if (uVar4 < 10) { pcVar13 = "0%d:"; } else { pcVar13 = "%d:"; } std::sprintf(buff2,pcVar13,uVar4); pcVar13 = buff2; } uVar5 = 0xffffffff; do { pcVar7 = pcVar13; if (uVar5 == 0) break; uVar5 -= 1; pcVar7 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar7; } while (cVar1 != '\0'); uVar5 = ~uVar5; iVar2 = -1; pcVar13 = buff1; do { pcVar8 = pcVar13; if (iVar2 == 0) break; iVar2 += -1; pcVar8 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar8; } while (cVar1 != '\0'); puVar6 = (undefined4 *)(pcVar7 + -uVar5); puVar9 = (undefined4 *)(pcVar8 + -1); for (uVar4 = uVar5 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar9 = *puVar6; puVar6 = puVar6 + 1; puVar9 = puVar9 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } if (uVar3 < 0x3d) { pcVar13 = "00."; } else { uVar4 = (uVar3 - 1) / 0x3c; uVar5 = uVar4; do { uVar3 -= 0x3c; uVar5 -= 1; } while (uVar5 != 0); if (uVar4 < 10) { pcVar13 = "0%d."; } else { pcVar13 = "%d."; } std::sprintf(buff2,pcVar13,uVar4); pcVar13 = buff2; } uVar5 = 0xffffffff; do { pcVar7 = pcVar13; if (uVar5 == 0) break; uVar5 -= 1; pcVar7 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar7; } while (cVar1 != '\0'); uVar5 = ~uVar5; iVar2 = -1; pcVar13 = buff1; do { pcVar8 = pcVar13; if (iVar2 == 0) break; iVar2 += -1; pcVar8 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar8; } while (cVar1 != '\0'); puVar6 = (undefined4 *)(pcVar7 + -uVar5); puVar9 = (undefined4 *)(pcVar8 + -1); for (uVar4 = uVar5 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar9 = *puVar6; puVar6 = puVar6 + 1; puVar9 = puVar9 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } if (uVar3 < 2) { pcVar13 = "00"; } else { if (uVar3 - 1 < 10) { pcVar13 = "0%d"; } else { pcVar13 = "%d"; } std::sprintf(buff2,pcVar13,uVar3 - 1); pcVar13 = buff2; } uVar3 = 0xffffffff; do { pcVar7 = pcVar13; if (uVar3 == 0) break; uVar3 -= 1; pcVar7 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar7; } while (cVar1 != '\0'); uVar3 = ~uVar3; iVar2 = -1; pcVar13 = buff1; do { pcVar8 = pcVar13; if (iVar2 == 0) break; iVar2 += -1; pcVar8 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar8; } while (cVar1 != '\0'); puVar6 = (undefined4 *)(pcVar7 + -uVar3); puVar9 = (undefined4 *)(pcVar8 + -1); for (uVar5 = uVar3 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar9 = *puVar6; puVar6 = puVar6 + 1; puVar9 = puVar9 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } std::sprintf(reward->items[8].valueText,"%s",buff1); lVar11 = __ftol((float10)reward->items[9].percentFloat); reward->items[9].percentInt = (int)lVar11; std::sprintf(reward->items[9].valueText,"%d%%%%",(int)lVar11); return TRUE; } BOOL __cdecl lego::reward::Reward_Show(void) { Lego_Level *level_reg; RewardLevel *reward; BOOL BVar1; Movie_t *mov; Reward_Type rewardTypeCapped; int i1; int off2; int i3; int off4; char *fName; int off1; int i2; int off3; Reward_Type rewardType; RewardUIState curState; float timer; BOOL finished; float lastTime; float delta; BOOL saved; Lego_Level *level; undefined4 uStack20; uint tmp_time1; undefined4 uStack12; uint tmp_time2; undefined4 uStack4; curState = REWARDSTATE_0; finished = 0; saved = 0; rewardType = Reward_Crystals; level = (Lego_Level *)main::Main_GetTime(); uStack20 = 0; timer = globs::rewardGlobs.timer; lastTime = (float)ZEXT48(level); level_reg = lrr::Lego_GetLevel(); if (level_reg == NULL) { return 0; } level = level_reg; reward = GetRewardLevel2(level_reg->unused_rewardID); if (reward != NULL) { BVar1 = Reward_LoopBegin(); if (BVar1 != 0) { while ((((int)curState < 4 || (globs::INPUT.mslb != 0)) || (globs::INPUT.lClicked != 0))) { tmp_time1 = main::Main_GetTime(); uStack12 = 0; delta = ((float)(ulonglong)tmp_time1 - lastTime) * 0.001; tmp_time2 = main::Main_GetTime(); uStack4 = 0; lastTime = (float)(ulonglong)tmp_time2; timer = delta + timer; Reward_UpdateState(&rewardType,&curState,&timer); // IsKeyReleased(KEY_SPACE) (57) (or is mouse pressed) // "Jump to next state(?)." if ((((globs::INPUT.Key_Map[57] == false) && (globs::INPUT.prevKey_Map[57] != false)) || (globs::INPUT.lClicked != 0)) && ((int)curState < REWARDSTATE_3)) { curState += REWARDSTATE_1; if (curState == REWARDSTATE_3) { curState = REWARDSTATE_2; } if (((int)curState < REWARDSTATE_2) || (level_reg->status != LEVELSTATUS_COMPLETE)) { rewardType = Reward_Score; } else { rewardType = Reward_Type_Count; } } if (globs::rewardGlobs.wallpaper != NULL) { lego::image::Image_DisplayScaled(globs::rewardGlobs.wallpaper,NULL,NULL,NULL); } i1 = 0; // for (int i1 = 0; i1 < rewardType; i1++) if (0 < (int)rewardType) { off1 = 0; do { Reward_DrawItem((RewardLevelItem *)(reward->itemPtr->name + off1 + -4), REWARDITEM_FLAG_IMAGES,rewardType); i1 += 1; off1 += 0x210; } while (i1 < (int)rewardType); } i2 = 0; // for (int i2 = 0; i2 < min(rewardType, 9); i2++) off2 = 0; while( true ) { rewardTypeCapped = rewardType; if (9 < (int)rewardType) { rewardTypeCapped = Reward_Score; } if ((int)rewardTypeCapped <= i2) break; Reward_DrawItem((RewardLevelItem *)(reward->itemPtr->name + off2 + -4), REWARDITEM_FLAG_BOXIMAGES,rewardType); i2 += 1; off2 += 0x210; } i3 = 0; // for (int i3 = 0; i3 < rewardType; i3++) if (0 < (int)rewardType) { off3 = 0; do { Reward_DrawItem((RewardLevelItem *)(reward->itemPtr->name + off3 + -4), REWARDITEM_FLAG_FLIC,rewardType); i3 += 1; off3 += 0x210; } while (i3 < (int)rewardType); } Reward_DrawAllValues(&rewardType,&finished); if ((finished != 0) && (Reward_DrawScore(rewardType), (int)curState < REWARDSTATE_3)) { Reward_HandleButtons(&curState,&saved); } RewardScroll_DrawLabels(globs::rewardGlobs.scroll); if (curState == REWARDSTATE_3) { curState = REWARDSTATE__COUNT; } Reward_HandleDebugKeys(&rewardType,&curState,&finished,&timer); Reward_LoopUpdate(delta); level_reg = level; } RewardScroll_Free(&globs::rewardGlobs.scroll); // for (int i = 0; i < 10; i++) off4 = 0; do { if ((reward->itemPtr->name[off4 + -4] & 4U) != 0) { lego::image::Flic_Close(*(Flic **)((int)&reward->itemPtr->Flic + off4)); *(undefined4 *)((int)&reward->itemPtr->Flic + off4) = 0; } off4 += 0x210; } while (off4 < 0x14a0); snd::Sound3D_Stream_Stop(TRUE); if ((level_reg->status == LEVELSTATUS_COMPLETE) && (globs::legoGlobs.EndGameAVI1 != NULL)) { BVar1 = front::Front_Save_IsGame100Percented(); if ((BVar1 == 0) || (fName = globs::legoGlobs.EndGameAVI2, globs::legoGlobs.EndGameAVI2 == NULL)) { fName = globs::legoGlobs.EndGameAVI1; } BVar1 = io::File_Exists(fName); if (BVar1 != 0) { mov = video::Movie_Load(fName); // not skippable front::Front_PlayMovie(mov,FALSE); video::Movie_Free(mov); } snd::SFX_AddToQueue(SFX_AmbientMusicLoop,SoundMode_Loop); front::Front_Callback_TriggerPlayCredits(); snd::Sound3D_Stream_Stop(TRUE); } return TRUE; } return 0; } return 0; } void __cdecl lego::reward::Reward_DrawItem (RewardLevelItem *rewardItem,RewardItemFlags flags,Reward_Type rewardType) { char *pcVar1; RewardLevelItem *pRVar2; Flic *fsp; int iVar3; uint uVar4; Point2F local_3c; float local_34; Point2F local_30; float local_28; float local_24; float local_20; float local_1c; float local_18; float local_14; Area2F destArea; if (rewardType == Reward_Crystals) { iVar3 = 0; } else { iVar3 = rewardType + Reward_Type_Invalid; } pRVar2 = (globs::rewardGlobs.level)->itemPtr; if (((globs::rewardGlobs.displayImages != 0) && ((*(byte *)&rewardItem->flags & REWARDITEM_FLAG_IMAGES) != 0)) && ((flags & REWARDITEM_FLAG_IMAGES) != REWARDITEM_FLAG_NONE)) { local_3c.x = (float)(rewardItem->ImagePosition).y; local_30.x = (float)(ulonglong)(uint)(rewardItem->ImagePosition).x; local_3c.y = 0.0; local_30.y = (float)(ulonglong)(uint)local_3c.x; lego::image::Image_DisplayScaled(rewardItem->Image,NULL,&local_30,NULL); } if (((globs::rewardGlobs.displayImages != 0) && ((*(byte *)&rewardItem->flags & REWARDITEM_FLAG_BOXIMAGES) != 0)) && ((flags & REWARDITEM_FLAG_BOXIMAGES) != REWARDITEM_FLAG_NONE)) { local_30.x = (float)(rewardItem->BoxImagePosition).y; local_3c.x = (float)(ulonglong)(uint)(rewardItem->BoxImagePosition).x; local_30.y = 0.0; local_3c.y = (float)(ulonglong)(uint)local_30.x; lego::image::Image_DisplayScaled(rewardItem->BoxImage,NULL,&local_3c,NULL); } if (((globs::rewardGlobs.displayFlics != 0) && ((*(byte *)&rewardItem->flags & REWARDITEM_FLAG_FLIC) != 0)) && ((flags & REWARDITEM_FLAG_FLIC) != REWARDITEM_FLAG_NONE)) { if (rewardItem->Flic == NULL) { lego::image::Flic_Setup(rewardItem->FlicName,&rewardItem->Flic,FLICDISK); } destArea.x = (float)(ulonglong)(uint)(rewardItem->FlicPosition).x; local_30.x = (float)(rewardItem->FlicSize).height; destArea.y = (float)(ulonglong)(uint)(rewardItem->FlicPosition).y; destArea.width = (float)(ulonglong)(uint)(rewardItem->FlicSize).width; fsp = rewardItem->Flic; local_30.y = 0.0; destArea.height = (float)(ulonglong)(uint)local_30.x; lego::image::Flic_Animate(fsp,&destArea,(uint)(fsp->currentframe < 0x23),FALSE); } if (globs::rewardGlobs.displayText != 0) { if (((*(byte *)&rewardItem->flags & REWARDITEM_FLAG_VALUETEXT) != 0) && ((flags & REWARDITEM_FLAG_VALUETEXT) != REWARDITEM_FLAG_NONE)) { uVar4 = lego::image::Font_GetStringWidth(rewardItem->Font,rewardItem->valueText); lego::image::Font_PrintF (rewardItem->Font,(rewardItem->TextPosition).x - (uVar4 >> 1), (rewardItem->TextPosition).y,rewardItem->valueText); if (rewardType < Reward_Type_Count) { pcVar1 = pRVar2[iVar3].Text; uVar4 = lego::image::Font_GetStringWidth(globs::rewardGlobs.titleFont,pcVar1); lego::image::Font_PrintF (globs::rewardGlobs.titleFont,globs::rewardGlobs.textPos.x - (uVar4 >> 1), globs::rewardGlobs.textPos.y,pcVar1); } } if ((globs::rewardGlobs.displayText != 0) && ((((rewardItem->flags & REWARDITEM_FLAG_NAMETEXT) != REWARDITEM_FLAG_NONE && ((flags & REWARDITEM_FLAG_NAMETEXT) != REWARDITEM_FLAG_NONE)) || (((rewardItem->flags & REWARDITEM_FLAG_NAMETEXT_HALFTRANS) != REWARDITEM_FLAG_NONE && ((flags & REWARDITEM_FLAG_NAMETEXT_HALFTRANS) != REWARDITEM_FLAG_NONE)))))) { local_1c = 0.1176471; local_18 = 0.1176471; local_14 = 0.1176471; local_28 = 0.2352941; local_24 = 0.2352941; local_20 = 0.2352941; local_3c.x = 0.0; local_3c.y = 0.0; local_34 = 0.0; uVar4 = lego::image::Font_GetStringWidth(rewardItem->Font,rewardItem->valueText); local_30.x = (float)(uVar4 + 0x14); destArea.x = (float)(ulonglong)(((rewardItem->TextPosition).x - (uVar4 >> 1)) - 10); destArea.y = (float)(ulonglong)(uint)(rewardItem->TextPosition).y; local_30.y = 0.0; destArea.width = (float)(ulonglong)(uint)local_30.x; local_30.x = (float)lego::image::Font_GetHeight(rewardItem->Font); local_30.y = 0.0; destArea.height = (float)(ulonglong)(uint)local_30.x; front::ToolTip_DrawBox ((Area2F)CONCAT412(destArea.height, CONCAT48(destArea.width,CONCAT44(destArea.y,destArea.x))), local_1c,local_18,local_14,local_28,local_24,local_20,local_3c.x,local_3c.y, local_34,flags & REWARDITEM_FLAG_NAMETEXT_HALFTRANS); lego::image::Font_PrintF (rewardItem->Font,(rewardItem->TextPosition).x - (uVar4 >> 1), (rewardItem->TextPosition).y,rewardItem->valueText); if (rewardType < Reward_Type_Count) { pcVar1 = pRVar2[iVar3].Text; uVar4 = lego::image::Font_GetStringWidth(globs::rewardGlobs.titleFont,pcVar1); local_30.x = (float)(uVar4 + 0x14); destArea.x = (float)(ulonglong)((globs::rewardGlobs.textPos.x - (uVar4 >> 1)) - 10); destArea.y = (float)(ulonglong)(uint)globs::rewardGlobs.textPos.y; local_30.y = 0.0; destArea.width = (float)(ulonglong)(uint)local_30.x; local_30.x = (float)lego::image::Font_GetHeight(globs::rewardGlobs.titleFont); local_30.y = 0.0; destArea.height = (float)(ulonglong)(uint)local_30.x; front::ToolTip_DrawBox ((Area2F)CONCAT412(destArea.height, CONCAT48(destArea.width,CONCAT44(destArea.y,destArea.x))), local_1c,local_18,local_14,local_28,local_24,local_20,local_3c.x,local_3c.y, local_34,0); lego::image::Font_PrintF (globs::rewardGlobs.titleFont,globs::rewardGlobs.textPos.x - (uVar4 >> 1), globs::rewardGlobs.textPos.y,pcVar1); } } } return; } void __cdecl lego::reward::Reward_DrawScore(Reward_Type rewardType) { char cVar1; Lego_Level *level; RewardLevel *reward; uint uVar2; RewardLevelItem *pRVar3; int iVar4; char *pcVar5; char buff2 [32]; char buff1 [32]; level = lrr::Lego_GetLevel(); if (level == NULL) { return; } reward = GetRewardLevel2(level->unused_rewardID); if (reward == NULL) { return; } if (level->status == LEVELSTATUS_COMPLETE) { Reward_DrawItem(reward->itemPtr + 9,REWARDITEM_FLAG_VALUETEXT,rewardType); std::sprintf(buff2,"%s",reward->itemPtr[9].Text); pRVar3 = reward->itemPtr; uVar2 = 0xffffffff; iVar4 = 0; pcVar5 = pRVar3[9].Text; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); if (0 < (int)(~uVar2 - 1)) { do { if (pRVar3[9].Text[iVar4] == ' ') { buff2[iVar4] = '\0'; std::sprintf(buff1,"%s",buff2 + iVar4 + 1); } pRVar3 = reward->itemPtr; uVar2 = 0xffffffff; iVar4 += 1; pcVar5 = pRVar3[9].Text; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); } while (iVar4 < (int)(~uVar2 - 1)); } pcVar5 = buff2; iVar4 = reward->itemPtr[9].TextPosition.y + -0x28; uVar2 = lego::image::Font_GetStringWidth(globs::rewardGlobs.backFont,buff2); lego::image::Font_PrintF (globs::rewardGlobs.backFont,reward->itemPtr[9].TextPosition.x - (uVar2 >> 1),iVar4, pcVar5); } return; } void __cdecl lego::reward::Reward_HandleButtons(RewardUIState *out_state,BOOL *out_saved) { float fVar1; bool bVar2; Lego_Level *level; RewardLevel *reward; BOOL BVar3; Image *image; bVar2 = false; level = lrr::Lego_GetLevel(); if (level == NULL) { return; } reward = GetRewardLevel2(level->unused_rewardID); if (reward == NULL) { return; } if (level->status == LEVELSTATUS_COMPLETE) { fVar1 = (float)globs::INPUT.msx; image = globs::rewardGlobs.saveButton; if (((((ushort)((ushort)(fVar1 < globs::rewardGlobs.saveButtonPosition.x) << 8 | (ushort)(fVar1 == globs::rewardGlobs.saveButtonPosition.x) << 0xe) == 0) && (fVar1 < (float)(ulonglong)(globs::rewardGlobs.saveButton)->width + globs::rewardGlobs.saveButtonPosition.x)) && (fVar1 = (float)globs::INPUT.msy, (ushort)((ushort)(fVar1 < globs::rewardGlobs.saveButtonPosition.y) << 8 | (ushort)(fVar1 == globs::rewardGlobs.saveButtonPosition.y) << 0xe) == 0)) && (fVar1 < (float)(ulonglong)(globs::rewardGlobs.saveButton)->height + globs::rewardGlobs.saveButtonPosition.y)) { front::ToolTip_Activate(ToolTip_Reward_Save); if (((globs::INPUT.mslb != 0) && (image = globs::rewardGlobs.saveButton_in, globs::rewardGlobs.saveButton_in != NULL)) || (image = globs::rewardGlobs.saveButton_hi, globs::rewardGlobs.saveButton_hi != NULL)) { lego::image::Image_DisplayScaled(image,NULL,&globs::rewardGlobs.saveButtonPosition,NULL); } BVar3 = lrr::Lego_UpdateGameCtrlLeftButtonLast(); if (BVar3 != 0) { bVar2 = true; snd::SFX_Random_PlaySoundNormal(SFX_Okay,FALSE); Reward_GotoSaveMenu(); *out_saved = TRUE; snd::SFX_Sound3D_StopSound(SFX_MusicLoop); snd::SFX_AddToQueue(SFX_MusicLoop,SoundMode_Loop); } goto LAB_004621e1; } } else { image = globs::rewardGlobs.saveButton_dim; if (globs::rewardGlobs.saveButton_dim == NULL) goto LAB_004621e1; } lego::image::Image_DisplayScaled(image,NULL,&globs::rewardGlobs.saveButtonPosition,NULL); LAB_004621e1: fVar1 = (float)globs::INPUT.msx; if ((((ushort)((ushort)(fVar1 < globs::rewardGlobs.advanceButtonPosition.x) << 8 | (ushort)(fVar1 == globs::rewardGlobs.advanceButtonPosition.x) << 0xe) != 0) || ((float)(ulonglong)(globs::rewardGlobs.advanceButton)->width + globs::rewardGlobs.advanceButtonPosition.x <= fVar1)) || ((fVar1 = (float)globs::INPUT.msy, (ushort)((ushort)(fVar1 < globs::rewardGlobs.advanceButtonPosition.y) << 8 | (ushort)(fVar1 == globs::rewardGlobs.advanceButtonPosition.y) << 0xe) != 0 || ((float)(ulonglong)(globs::rewardGlobs.advanceButton)->height + globs::rewardGlobs.advanceButtonPosition.y <= fVar1)))) { lego::image::Image_DisplayScaled (globs::rewardGlobs.advanceButton,NULL,&globs::rewardGlobs.advanceButtonPosition,NULL) ; } else { front::ToolTip_Activate(ToolTip_Reward_Advance); if (((globs::INPUT.mslb != 0) && (image = globs::rewardGlobs.advanceButton_in, globs::rewardGlobs.advanceButton_in != NULL)) || (image = globs::rewardGlobs.advanceButton_hi, globs::rewardGlobs.advanceButton_hi != NULL) ) { lego::image::Image_DisplayScaled(image,NULL,&globs::rewardGlobs.advanceButtonPosition,NULL); } BVar3 = lrr::Lego_UpdateGameCtrlLeftButtonLast(); if (BVar3 != 0) { bVar2 = true; *out_state = REWARDSTATE_3; snd::SFX_Random_PlaySoundNormal(SFX_Okay,FALSE); Reward_GotoAdvance(); } } if ((!bVar2) && (BVar3 = lrr::Lego_UpdateGameCtrlLeftButtonLast(), BVar3 != 0)) { snd::SFX_Random_PlaySoundNormal(SFX_NotOkay,FALSE); } return; } void __cdecl lego::reward::Reward_GotoSaveMenu(void) { Lego_Level *level2; BOOL BVar1; BOOL BVar2; LevelSet *levelSet; int iVar3; SaveData *lastSave; RewardLevel *rewardLevel; SaveData *pSVar4; Lego_Level *level; uint uVar5; SaveStruct_18 saveStruct18; SaveData copySave; char *levelID; level2 = lrr::Lego_GetLevel(); front::Front_IsMissionSelected(); BVar1 = front::Front_IsTutorialSelected(); front::Front_SaveOptionParameters(); BVar2 = front::Front_IsFrontEndEnabled(); if (BVar2 != 0) { levelID = level2->name; levelSet = front::Front_Levels_GetTutoOrMissions(); iVar3 = front::Front_LevelSet_IndexOf(levelSet,levelID); front::Front_Save_GetRewardLevel(iVar3); iVar3 = save::Front_Save_GetSaveNumber(); lastSave = save::Front_Save_GetCurrentSaveData(); save::Front_Save_CopySaveData(©Save); rewardLevel = GetRewardLevel(); if (BVar1 == 0) { BVar1 = game::Objective_IsObjectiveAchieved(); if (BVar1 != 0) { do { front::Front_RunScreenMenuType(Menu_Screen_Save); } while (globs::frontGlobs.saveMenuKeepOpen != 0); if (globs::frontGlobs.saveMenuHasSaved == 1) { BVar1 = front::Front_Save_GetHasNoSaveData(); if (BVar1 != 0) { front::Front_Save_WriteEmptySaveFiles(); front::Front_Save_SetHasNoSaveData(FALSE); } pSVar4 = save::Front_Save_GetCurrentSaveData(); if (pSVar4 != NULL) { pSVar4 = save::Front_Save_GetCurrentSaveData(); if ((pSVar4 != lastSave) && (lastSave != NULL)) { front::Front_Save_SetSaveData(©Save); level = lrr::Lego_GetLevel(); levelID = level->name; levelSet = front::Front_Levels_GetTutoOrMissions(); uVar5 = front::Front_LevelSet_IndexOf(levelSet,levelID); front::Front_Save_SetLevelCompleted(uVar5); levelID = level2->name; levelSet = front::Front_Levels_GetTutoOrMissions(); iVar3 = front::Front_LevelSet_IndexOf(levelSet,levelID); front::Front_Save_SetRewardLevel(iVar3,rewardLevel); save::Object_Save_CopyStruct18(&saveStruct18); front::Front_Save_SetSaveStruct18(&saveStruct18); front::Front_Save_WriteCurrentSaveFiles(); return; } level = lrr::Lego_GetLevel(); levelID = level->name; levelSet = front::Front_Levels_GetTutoOrMissions(); uVar5 = front::Front_LevelSet_IndexOf(levelSet,levelID); front::Front_Save_SetLevelCompleted(uVar5); levelID = level2->name; levelSet = front::Front_Levels_GetTutoOrMissions(); iVar3 = front::Front_LevelSet_IndexOf(levelSet,levelID); front::Front_Save_SetRewardLevel(iVar3,rewardLevel); save::Object_Save_CopyStruct18(&saveStruct18); front::Front_Save_SetSaveStruct18(&saveStruct18); front::Front_Save_WriteCurrentSaveFiles(); return; } level2 = lrr::Lego_GetLevel(); levelID = level2->name; levelSet = front::Front_Levels_GetTutoOrMissions(); front::Front_LevelSet_IndexOf(levelSet,levelID); return; } save::Front_Save_SetSaveNumber(iVar3); lastSave = save::Front_Save_GetCurrentSaveData(); if (lastSave != NULL) { level = lrr::Lego_GetLevel(); levelID = level->name; levelSet = front::Front_Levels_GetTutoOrMissions(); uVar5 = front::Front_LevelSet_IndexOf(levelSet,levelID); front::Front_Save_SetLevelCompleted(uVar5); levelID = level2->name; levelSet = front::Front_Levels_GetTutoOrMissions(); iVar3 = front::Front_LevelSet_IndexOf(levelSet,levelID); front::Front_Save_SetRewardLevel(iVar3,rewardLevel); save::Object_Save_CopyStruct18(&saveStruct18); front::Front_Save_SetSaveStruct18(&saveStruct18); } } } } return; } void __cdecl lego::reward::Reward_GotoAdvance(void) { Lego_Level *level; LevelSet *levelSet; uint levelIndex; int iVar1; RewardLevel *reward; SaveData *localSave; SaveData *currSave; uint uVar2; SaveReward *pSVar3; MenuItem_SelectData *selectData; char *levelName; BOOL keepLocked; level = lrr::Lego_GetLevel(); levelName = level->name; levelSet = front::Front_Levels_GetTutoOrMissions(); levelIndex = front::Front_LevelSet_IndexOf(levelSet,levelName); iVar1 = save::Front_Save_GetSaveNumber(); if (iVar1 == -1) { save::Front_Save_SetSaveNumber(5); } level = lrr::Lego_GetLevel(); if (level->status == LEVELSTATUS_COMPLETE) { front::Front_Save_SetLevelCompleted(levelIndex); } reward = GetRewardLevel(); front::Front_Save_SetRewardLevel(levelIndex,reward); if (iVar1 == -1) { localSave = save::Front_Save_GetSaveDataAt(5); if (localSave != NULL) { pSVar3 = localSave->missionsTable + 1; for (uVar2 = localSave->missionsCount * 0x3190 - 0x3190 >> 2; uVar2 != 0; uVar2 -= 1) { pSVar3->flags = SAVEREWARD_FLAG_NONE; pSVar3 = (SaveReward *)&pSVar3->reward; } for (iVar1 = 0; iVar1 != 0; iVar1 += -1) { *(undefined *)&pSVar3->flags = 0; pSVar3 = (SaveReward *)((int)&pSVar3->flags + 1); } level = lrr::Lego_GetLevel(); if (level->status == LEVELSTATUS_COMPLETE) { front::Front_Save_SetLevelCompleted(levelIndex); } reward = GetRewardLevel(); front::Front_Save_SetRewardLevel(levelIndex,reward); } front::Front_Save_WriteCurrentSaveFiles(); save::Front_Save_ReadSaveFile(5,globs::frontGlobs.saveData + 5,FALSE); } keepLocked = FALSE; // MainMenuFull -> Menu2 "Missions" -> Item1 LevelSelect (programmatically added) selectData = (MenuItem_SelectData *)(globs::frontGlobs.mainMenuSet)->menus[1]->items[1]->itemData; levelSet = &globs::frontGlobs.missionLevels; currSave = save::Front_Save_GetCurrentSaveData(); front::Front_Levels_UpdateAvailable (globs::frontGlobs.startMissionLink,currSave->missionsTable,levelSet,selectData, keepLocked); front::Front_Save_SetShouldClearUnlockedLevels(FALSE); return; } void __cdecl lego::reward::Reward_HandleDebugKeys (Reward_Type *ref_rewardType,RewardUIState *ref_state,BOOL *ref_finished,float *ref_timer) { Lego_Level *level; RewardLevel *reward; int off; level = lrr::Lego_GetLevel(); if (level == NULL) { return; } reward = GetRewardLevel2(level->unused_rewardID); if (reward == NULL) { return; } if (((byte)globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != 0) { // IsKeyDown(KEY_SPACE) (57) && IsKeyPressed(KEY_ESCAPE) (1) // "Terminate the program." if (((globs::INPUT.Key_Map[57] != false) && (globs::INPUT.Key_Map[1] != false)) && (globs::INPUT.prevKey_Map[1] != globs::INPUT.Key_Map[1])) { lrr::Lego_Exit(); } // IsKeyPressed(KEY_R) (19) // "Restart the rewards showcase from the beginning." if ((globs::INPUT.Key_Map[19] != false) && (globs::INPUT.prevKey_Map[19] != globs::INPUT.Key_Map[19])) { *ref_rewardType = Reward_Crystals; *ref_state = REWARDSTATE_0; *ref_timer = globs::rewardGlobs.timer; *ref_finished = 0; snd::SFX_Sound3D_StopSound(SFX_MusicLoop); snd::SFX_AddToQueue(SFX_MusicLoop,SoundMode_Loop); off = 0; do { Reward_PlayFlic((RewardLevelItem *)(reward->itemPtr->name + off + -4)); off += 0x210; } while (off < 0x14a0); } } return; } void __cdecl lego::reward::Reward_PlayFlic(RewardLevelItem *rewardItem) { if ((*(byte *)&rewardItem->flags & REWARDITEM_FLAG_FLIC) != 0) { lego::image::Flic_Close(rewardItem->Flic); lego::image::Flic_Setup(rewardItem->FlicName,&rewardItem->Flic,FLICDISK); } return; } void __cdecl lego::reward::Reward_UpdateState (Reward_Type *ref_rewardType,RewardUIState *ref_state,float *ref_timer) { char *sfxName; bool bVar1; Lego_Level *level; RewardLevel *reward; Reward_Type RVar2; BOOL BVar3; int off; bool bVar4; SFX_ID sfxType; bVar1 = false; level = lrr::Lego_GetLevel(); if (level == NULL) { return; } reward = GetRewardLevel2(level->unused_rewardID); if (reward == NULL) { return; } if (globs::rewardGlobs.timer <= *ref_timer) { bVar4 = *ref_state == REWARDSTATE_0; if (!bVar4) goto LAB_004627c2; bVar1 = true; } bVar4 = *ref_state == REWARDSTATE_0; LAB_004627c2: if ((!bVar4) && (globs::rewardGlobs.timer + globs::rewardGlobs.timer <= *ref_timer)) { level = lrr::Lego_GetLevel(); if ((level->status == LEVELSTATUS_COMPLETE) && ((int)*ref_rewardType < 10)) { bVar1 = true; } } if (bVar1) { *ref_timer = *ref_timer - globs::rewardGlobs.timer; RVar2 = *ref_rewardType; if ((int)RVar2 < 10) { RVar2 += Reward_Ore; } *ref_rewardType = RVar2; sfxName = reward->itemPtr[RVar2 + Reward_Type_Invalid].SoundName; if (sfxName != NULL) { BVar3 = snd::SFX_GetType(sfxName,&sfxType); if (BVar3 != 0) { snd::SFX_AddToQueue(sfxType,SoundMode_Once); } } RVar2 = *ref_rewardType; if (9 < (int)RVar2) { if (*ref_state == REWARDSTATE_0) { *ref_rewardType = Reward_Score; *ref_state = *ref_state + REWARDSTATE_1; return; } if ((9 < (int)RVar2) && (1 < (int)*ref_state)) { if (10 < (int)RVar2) { *ref_rewardType = Reward_Type_Count; *ref_state = *ref_state + REWARDSTATE_1; return; } off = 0; do { Reward_PlayFlic((RewardLevelItem *)(reward->itemPtr->name + off + -4)); off += 0x210; } while (off < 0x14a0); } } } return; } void __cdecl lego::reward::Reward_DrawAllValues(Reward_Type *in_rewardType,BOOL *out_finished) { Reward_Type rewardType; Lego_Level *level; RewardLevel *reward; Reward_Type rewardTypeCapped; int off; int i; level = lrr::Lego_GetLevel(); if (level == NULL) { return; } reward = GetRewardLevel2(level->unused_rewardID); if (reward == NULL) { return; } if (((*in_rewardType == Reward_Type_Count) || ((level->status != LEVELSTATUS_COMPLETE && (*in_rewardType == Reward_Score)))) && ((reward->items[9].Flic == NULL || (((globs::rewardGlobs.displayFlics == 0 || (0x21 < (reward->itemPtr[9].Flic)->currentframe)) || (level->status != LEVELSTATUS_COMPLETE)))))) { *out_finished = TRUE; } i = 0; off = 0; while( true ) { rewardType = *in_rewardType; rewardTypeCapped = rewardType; if (9 < (int)rewardType) { rewardTypeCapped = Reward_Score; } if ((int)rewardTypeCapped <= i) break; Reward_DrawItem((RewardLevelItem *)(reward->itemPtr->name + off + -4),REWARDITEM_FLAG_VALUETEXT, rewardType); i += 1; off += 0x210; } // These calls serve no purpose lego::image::Font_GetStringWidth(globs::rewardGlobs.titleFont,level->FullName); lego::image::Font_GetStringWidth(globs::rewardGlobs.titleFont,globs::rewardGlobs.statusMessage); return; } void __cdecl lego::reward::Reward_LoopUpdate(float elapsedSeconds) { front::Pointer_Update(1.0); front::Pointer_SetCurrent_IfTimerFinished(Pointer_Standard); front::Pointer_DrawPointer(globs::INPUT.msx,globs::INPUT.msy); lrr::Lego_UpdateGameCtrlLeftButtonLast(); globs::INPUT.lClicked = FALSE; snd::SFX_Update(elapsedSeconds); // param_1 / 25.0 * 1000.0 (related to milliseconds) front::ToolTip_Update(globs::INPUT.msx,globs::INPUT.msy,elapsedSeconds * 0.04 * 1000.0); main::Main_LoopUpdate(TRUE); return; } BOOL __cdecl lego::reward::Reward_LoopBegin(void) { Lego_Level *level; RewardLevel *reward; level = lrr::Lego_GetLevel(); if (level != NULL) { reward = GetRewardLevel2(level->unused_rewardID); if (reward != NULL) { if ((globs::rewardGlobs.display != 0) && (reward->Enabled != 0)) { while( true ) { // IsKeyUp(KEY_SPACE) && !IsKeyReleased(KEY_SPACE) (57) if ((((globs::INPUT.Key_Map[57] == false) || (globs::INPUT.prevKey_Map[57] == globs::INPUT.Key_Map[57])) && (globs::INPUT.Key_Map[57] == false)) && ((globs::INPUT.prevKey_Map[57] == false && (true)))) break; main::Main_LoopUpdate(TRUE); } globs::INPUT.lClicked = 0; snd::SFX_AddToQueue(SFX_MusicLoop,SoundMode_Loop); return TRUE; } Reward_GotoAdvance(); } } return 0; } void __cdecl lego::reward::RewardQuota_UpdateTimers(float elapsedGame) { globs::rewardGlobs.current.items[8].countdownRatio = elapsedGame + globs::rewardGlobs.current.items[8].countdownRatio; globs::rewardGlobs.current.items[8].countdown = globs::rewardGlobs.current.items[8].countdown - -1.0; return; } void __cdecl lego::reward::RewardQuota_WallDestroyed(void) { // table[REWARDTYPE_DIGGABLE] globs::rewardGlobs.current.items[2].countdown = globs::rewardGlobs.current.items[2].countdown - -1.0; return; } void __cdecl lego::reward::RewardQuota_CavernDiscovered(void) { // table[REWARDTYPE_CAVERNS] globs::rewardGlobs.current.items[4].countdown = globs::rewardGlobs.current.items[4].countdown - -1.0; return; } void __cdecl lego::reward::RewardQuota_RockMonsterGenerated(void) { // table[REWARDTYPE_ROCKMONSTERS] globs::rewardGlobs.current.items[6].numGenerated += 1; return; } void __cdecl lego::reward::RewardQuota_RockMonsterDestroyed(void) { // table[REWARDTYPE_ROCKMONSTERS] globs::rewardGlobs.current.items[6].numDestroyed += 1; return; } // Seems to be when a rock monster is attacked with a weapon. void __cdecl lego::reward::RewardQuota_RockMonsterAttacked(void) { // table[REWARDTYPE_ROCKMONSTERS] globs::rewardGlobs.current.items[6].numAttacked += 1; return; } void __cdecl lego::reward::RewardQuota_RockMonsterDamageDealt(float damage) { globs::rewardGlobs.current.items[6].damageTaken = damage + globs::rewardGlobs.current.items[6].damageTaken; return; } void __cdecl lego::reward::RewardQuota_MiniFigureDamageTaken(float damage) { globs::rewardGlobs.current.items[5].damageTaken = damage + globs::rewardGlobs.current.items[5].damageTaken; return; } RewardScroll * __cdecl lego::reward::RewardScroll_Create (RewardScroll **out_scroll,float zero,float heightDiv20,float width,float bottomSubDiv3pt5 ,float scrollSpeed) { RewardScroll *front; RewardScrollLabel **itemsTable; RewardScrollLabel *pRVar1; int iVar2; RewardScroll *pRVar3; front = (RewardScroll *)io::Mem_Alloc(0x28); if (front != NULL) { pRVar3 = front; // std::memset(front, 0, 0x28); for (iVar2 = 10; iVar2 != 0; iVar2 += -1) { pRVar3->yInitial = 0.0; pRVar3 = (RewardScroll *)&pRVar3->xPos; } itemsTable = (RewardScrollLabel **)io::Mem_Alloc(4); front->labels = itemsTable; pRVar1 = (RewardScrollLabel *)io::Mem_Alloc(0x20); *itemsTable = pRVar1; // std::memset(itemsTable[0], 0, 0x20); for (iVar2 = 8; iVar2 != 0; iVar2 += -1) { pRVar1->mode = REWARDSCROLL_MODE_NONE; pRVar1 = (RewardScrollLabel *)&pRVar1->xPos; } front->scrollSpeed = scrollSpeed; front->xPos = zero; front->yPos = heightDiv20; front->width = width; front->height = bottomSubDiv3pt5; front->yInitial = heightDiv20; } *out_scroll = front; return front; } BOOL __cdecl lego::reward::RewardScroll_Free(RewardScroll **ref_scroll) { RewardScroll *scroll; uint i; char *text; i = 0; scroll = *ref_scroll; if (scroll->labelCount != 0) { do { text = scroll->labels[i]->text; if (text != NULL) { io::Mem_Free(text); } io::Mem_Free((*ref_scroll)->labels[i]); scroll = *ref_scroll; i += 1; } while (i < scroll->labelCount); } if ((*ref_scroll)->labels != NULL) { io::Mem_Free((*ref_scroll)->labels); } io::Mem_Free(*ref_scroll); return TRUE; } RewardScrollLabel * __cdecl lego::reward::RewardScroll_AddLabel (RewardScroll *scroll,char *text,Font *font,float xPos,float yPos, RewardScrollLabelFlags labelFlags) { char cVar1; RewardScrollLabel **itemsTable; RewardScrollLabel *item; char *textCpy; int iVar2; uint uVar3; uint idx; if (font == NULL) { return NULL; } idx = scroll->labelCount; scroll->labelCount = idx + 1; itemsTable = (RewardScrollLabel **)io::Mem_ReAlloc(scroll->labels,(idx + 1) * 4); scroll->labels = itemsTable; item = (RewardScrollLabel *)io::Mem_Alloc(0x20); scroll->labels[idx] = item; item = scroll->labels[idx]; for (iVar2 = 8; iVar2 != 0; iVar2 += -1) { item->mode = REWARDSCROLL_MODE_NONE; item = (RewardScrollLabel *)&item->xPos; } scroll->labels[idx]->xPos = xPos; scroll->labels[idx]->yPos = yPos; uVar3 = 0xffffffff; textCpy = text; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *textCpy; textCpy = textCpy + 1; } while (cVar1 != '\0'); textCpy = (char *)io::Mem_Alloc(~uVar3); scroll->labels[idx]->text = textCpy; std::sprintf(scroll->labels[idx]->text,"%s",text); scroll->labels[idx]->mode = REWARDSCROLL_MODE_TEXT; scroll->labels[idx]->font = font; scroll->labels[idx]->flags = scroll->labels[idx]->flags | labelFlags; return scroll->labels[idx]; } // This name is purely speculation. The passed value is 400.0 void __cdecl lego::reward::RewardScroll_SetDelay_Unk(RewardScroll *scroll,float curScrollY) { scroll->curScrollY = curScrollY; return; } void __cdecl lego::reward::RewardScroll_AddFlags(RewardScroll *scroll,RewardScrollFlags flags) { scroll->flags = scroll->flags | flags; return; } BOOL __cdecl lego::reward::RewardScroll_DrawLabels(RewardScroll *scroll) { float fVar1; RewardScrollLabel **pLabel; uint strWidth; RewardScrollLabelFlags RVar2; RewardScroll *pRVar3; longlong lVar4; ulonglong textYPos; int textXPos; uint i; int dec; Size2F destSize; Point2F destPos; RewardScrollLabel *label; RewardScrollLabelMode labelMode; RewardScroll *scroll_00; scroll_00 = scroll; i = 0; if (scroll->labelCount != 0) { do { label = scroll_00->labels[i]; lVar4 = __ftol((float10)label->xPos + (float10)scroll_00->xPos); textXPos = (int)lVar4; textYPos = __ftol((float10)label->yPos + (float10)scroll_00->yPos); scroll = (RewardScroll *)textYPos; if ((*(byte *)&scroll_00->flags & 1) != 0) { if ((float)(int)scroll < scroll_00->yInitial) { lVar4 = __ftol((float10)scroll_00->curScrollY + (float10)scroll_00->height); do { scroll = (RewardScroll *)((int)&scroll->yInitial + (int)lVar4); textYPos = ZEXT48(scroll); } while ((float)(int)scroll < scroll_00->yInitial); } pRVar3 = (RewardScroll *)textYPos; fVar1 = scroll_00->curScrollY + scroll_00->yInitial + scroll_00->height; if ((ushort)((ushort)((float)(int)scroll < fVar1) << 8 | (ushort)((float)(int)scroll == fVar1) << 0xe) == 0) { lVar4 = __ftol((float10)scroll_00->height); do { pRVar3 = (RewardScroll *)((int)pRVar3 - (int)lVar4); textYPos = ZEXT48(pRVar3); scroll = pRVar3; } while ((ushort)((ushort)((float)(int)pRVar3 < fVar1) << 8 | (ushort)((float)(int)pRVar3 == fVar1) << 0xe) == 0); } } labelMode = label->mode; if (labelMode == REWARDSCROLL_MODE_WINDOW) { front::TextWindow_ChangePosition(label->textWnd,textXPos,(int)textYPos); front::TextWindow_Update (scroll_00->labels[i]->textWnd,0,globs::mainGlobs.fixedFrameTiming,NULL); LAB_00462e93: destPos.x = (float)textXPos; pLabel = scroll_00->labels + i; destPos.y = (float)(int)scroll; destSize.width = (float)(ulonglong)(*pLabel)->image->width; destSize.height = (float)(ulonglong)(*pLabel)->image->height; lego::image::Image_DisplayScaled((*pLabel)->image,NULL,&destPos,&destSize); LAB_00462ef7: label = scroll_00->labels[i]; // Centered flag maybe(?) if ((*(byte *)&label->flags & REWARDSCROLL_LABEL_CENTERED) != 0) { strWidth = lego::image::Font_GetStringWidth(label->font,label->text); lVar4 = __ftol(((float10)scroll_00->width - (float10)scroll_00->xPos) * (float10)-0.5); textXPos += -(int)lVar4 - (strWidth >> 1); } textYPos &= 0xffffffff; label = scroll_00->labels[i]; RVar2 = label->flags & REWARDSCROLL_LABEL_NOSCROLL; if (RVar2 != REWARDSCROLL_LABEL_NONE) { textYPos = __ftol((float10)label->yPos); scroll = (RewardScroll *)textYPos; } if ((RVar2 != REWARDSCROLL_LABEL_NONE) || ((fVar1 = (float)(int)scroll, fVar1 < scroll_00->height + scroll_00->yInitial && ((ushort)((ushort)(fVar1 < scroll_00->yInitial) << 8 | (ushort)(fVar1 == scroll_00->yInitial) << 0xe) == 0)))) { lego::image::Font_PrintF(label->font,textXPos,(int)textYPos,label->text); } } else { if (labelMode == REWARDSCROLL_MODE_IMAGE) goto LAB_00462e93; if (labelMode == REWARDSCROLL_MODE_TEXT) goto LAB_00462ef7; } i += 1; } while (i < scroll_00->labelCount); } scroll_00->yPos = scroll_00->yPos - scroll_00->scrollSpeed; if (((byte)globs::legoGlobs.flags2 & GAME2_ALLOWDEBUGKEYS) != 0) { // IsKeyDown(KEY_S) (31) // "Stop scroll speed (set to zero)." if (globs::INPUT.Key_Map[31] != false) { scroll_00->scrollSpeed = 0.0; } // IsKeyDown(KEY_R) (19) // "Reset scroll position. (Also restarts rewards UI, defined somewhere else)." if (globs::INPUT.Key_Map[19] != false) { scroll_00->yPos = scroll_00->yInitial; } // IsKeyDown(KEY_EQUALS) (13) // "Decrease (increase upwards) scrollSpeed." if (globs::INPUT.Key_Map[13] != false) { scroll_00->scrollSpeed = scroll_00->scrollSpeed - -0.01; } // IsKeyDown(KEY_MINUS) (12) // "Increase (increase downwards) scrollSpeed." if (globs::INPUT.Key_Map[12] != false) { scroll_00->scrollSpeed = scroll_00->scrollSpeed - 0.01; } scroll = NULL; dec = 0; do { // Ghidra really messed this one up... // "Assign leveled scrollSpeed. [0 = 100%, 9 = 90%..., 1 = 10%]" // // for (int k = 0; k < 10; k++) // IsKeyDown(KEY_ONE + k) (2) if (*(char *)((int)&scroll[0x2f7e3].yPos + 2) != '\0') { pRVar3 = scroll; if (scroll_00->scrollSpeed < 0.0) { pRVar3 = (RewardScroll *)dec; } scroll_00->scrollSpeed = (float)(int)pRVar3 * 0.1; } scroll = (RewardScroll *)((int)&scroll->yInitial + 1); dec += -1; } while (-10 < dec); } return TRUE; } BOOL __cdecl lego::game::Roof_Initialise(Container *root,uint width,uint height) { uint i; uint count; globs::roofGlobs.contMesh = gfx::Container_MakeMesh2(root,Container_MeshType_Immediate); if (globs::roofGlobs.contMesh != NULL) { globs::roofGlobs.texture = NULL; count = height * width; globs::roofGlobs.hidden = 0; globs::roofGlobs.grid = (RoofBlock *)io::Mem_Alloc(count * 8); if (globs::roofGlobs.grid != NULL) { i = 0; if (count != 0) { do { globs::roofGlobs.grid[i].groupID = D3DRMGROUP_0; // = ROOF_HIDDEN; // TRUE equate only present because of Ghidra register propagation *(undefined *)&globs::roofGlobs.grid[i].flags = TRUE; i += 1; } while (i < count); } globs::roofGlobs.dimensions.width = width; globs::roofGlobs.dimensions.height = height; globs::roofGlobs.needsUpdate = TRUE; globs::roofGlobs.visibleCount = 0; return TRUE; } gfx::Container_Remove(globs::roofGlobs.contMesh); } return FALSE; } BOOL __cdecl lego::game::Roof_SetTexture(char *filename) { D3DRMGroupIndex count; D3DRMGroupIndex groupID; if (globs::roofGlobs.texture != NULL) { gfx::Container_FreeTexture(globs::roofGlobs.texture); } globs::roofGlobs.texture = gfx::Container_LoadTexture2(filename,TRUE,NULL,NULL); if (globs::roofGlobs.texture != NULL) { count = gfx::Container_Mesh_GetGroupCount(globs::roofGlobs.contMesh); groupID = D3DRMGROUP_0; if (count != D3DRMGROUP_0) { do { gfx::Container_Mesh_SetTexture(globs::roofGlobs.contMesh,groupID,globs::roofGlobs.texture); groupID += 1; } while (groupID < count); } return TRUE; } return 0; } void __cdecl lego::game::Roof_Shutdown(void) { if (globs::roofGlobs.grid != NULL) { io::Mem_Free(globs::roofGlobs.grid); } globs::roofGlobs.grid = NULL; if (globs::roofGlobs.contMesh != NULL) { gfx::Container_Remove(globs::roofGlobs.contMesh); } globs::roofGlobs.contMesh = NULL; gfx::Container_FreeTexture(globs::roofGlobs.texture); return; } // FLAGS: // 0x1 - get/set : unset if true (adds mesh group, texture, then hides?) // 0x2 - set : implicit set to true (this block has lowered vertices that need updating?) // 0x4 - set : specifies how assigned vertices are ordered/shifted. void __cdecl lego::game::Roof_SetBlockRoofVertices (uint bx,uint by,Vector3F *vertPos0,Vector3F *vertPos1,Vector3F *vertPos2, Vector3F *vertPos3) { ushort uVar1; byte flagsByte; D3DRMGroupIndex groupID; Vertex vertices [4]; uint faceData [6]; bool bShiftVertices; RoofBlock *roof; roof = globs::roofGlobs.grid + by * globs::roofGlobs.dimensions.width + bx; // I'm not sure how this is supposed to function for already-visible roof tiles (maybe // it's handled separately?) // // if (roof->flags & ROOF_HIDDEN) // (0x1) has roof never been visible? bShiftVertices = false; if ((*(byte *)&roof->flags & ROOF_HIDDEN) != 0) { faceData[0] = 0; faceData[2] = 3; faceData[5] = 3; faceData[1] = 1; faceData[3] = 1; faceData[4] = 2; groupID = gfx::Container_Mesh_AddGroup(globs::roofGlobs.contMesh,4,2,3,faceData); roof->groupID = groupID; if (groupID != D3DRMGROUP_ALLGROUPS) { gfx::Container_Mesh_SetTexture(globs::roofGlobs.contMesh,groupID,globs::roofGlobs.texture); gfx::Container_Mesh_SetPerspectiveCorrection(globs::roofGlobs.contMesh,roof->groupID,TRUE); gfx::Container_Mesh_HideGroup(globs::roofGlobs.contMesh,roof->groupID,TRUE); // &= ~ROOF_HIDDEN; // (~0x1) roof mesh has been created, unset flag *(byte *)&roof->flags = *(byte *)&roof->flags & 0xfe; } } // At least one block has been added that needs processing by RoofMesh_Update globs::roofGlobs.needsUpdate = TRUE; *(byte *)&roof->flags = *(byte *)&roof->flags | ROOF_FLAG_NEEDUPDATE; if (vertPos2->z <= vertPos0->z) { if ((ushort)((ushort)(vertPos2->z < vertPos1->z) << 8 | (ushort)(vertPos2->z == vertPos1->z) << 0xe) != 0) { uVar1 = (ushort)(vertPos2->z < vertPos3->z) << 8 | (ushort)(vertPos2->z == vertPos3->z) << 0xe ; goto joined_r0x0046334a; } } else { if ((ushort)((ushort)(vertPos0->z < vertPos1->z) << 8 | (ushort)(vertPos0->z == vertPos1->z) << 0xe) != 0) { uVar1 = (ushort)(vertPos0->z < vertPos3->z) << 8 | (ushort)(vertPos0->z == vertPos3->z) << 0xe ; joined_r0x0046334a: if (uVar1 != 0) goto LAB_00463350; } } bShiftVertices = true; LAB_00463350: if (bShiftVertices) { // Assign vertex positions in order: [1->3], [2->2], [3->1], [0->0] vertices[3].position.x = vertPos1->x; vertices[3].position.y = vertPos1->y; vertices[3].position.z = vertPos1->z; vertices[2].position.x = vertPos2->x; vertices[2].position.y = vertPos2->y; vertices[2].position.z = vertPos2->z; vertices[1].position.x = vertPos3->x; vertices[1].position.y = vertPos3->y; vertices[1].position.z = vertPos3->z; vertices[0].position.x = vertPos0->x; vertices[0].position.y = vertPos0->y; vertices[0].position.z = vertPos0->z; // |= ROOF_SHIFTVERTICES; // (0x4) flagsByte = *(byte *)&roof->flags | ROOF_FLAG_SHIFTVERTICES; } else { // Assign vertex positions in order: [0->3], [1->2], [2->1], [3->0] vertices[3].position.x = vertPos0->x; vertices[3].position.y = vertPos0->y; vertices[3].position.z = vertPos0->z; vertices[2].position.x = vertPos1->x; vertices[2].position.y = vertPos1->y; vertices[2].position.z = vertPos1->z; vertices[1].position.x = vertPos2->x; vertices[1].position.y = vertPos2->y; vertices[1].position.z = vertPos2->z; vertices[0].position.x = vertPos3->x; vertices[0].position.y = vertPos3->y; vertices[0].position.z = vertPos3->z; // &= ~ROOF_SHIFTVERTICES; // (~0x4) flagsByte = *(byte *)&roof->flags & 0xfb; } *(byte *)&roof->flags = flagsByte; vertices[3].normal.x = 0.0; vertices[3].normal.z = 0.0; vertices[2].normal.x = 0.0; vertices[2].normal.z = 0.0; vertices[1].normal.x = 0.0; vertices[1].normal.z = 0.0; vertices[0].normal.x = 0.0; vertices[0].normal.z = 0.0; vertices[3].normal.y = 0.0; vertices[2].normal.y = 0.0; vertices[1].normal.y = 0.0; vertices[0].normal.y = 0.0; // white (no coloration) vertices[3].colour = 0xffffffff; vertices[2].colour = 0xffffffff; vertices[1].colour = 0xffffffff; vertices[0].colour = 0xffffffff; vertices[3].tu = 0.0; vertices[3].tv = 1.0; vertices[2].tu = 1.0; vertices[2].tv = 1.0; vertices[1].tu = 1.0; vertices[1].tv = 0.0; vertices[0].tu = 0.0; vertices[0].tv = 0.0; gfx::Container_Mesh_SetVertices(globs::roofGlobs.contMesh,roof->groupID,0,4,vertices); return; } // FLAGS: // 0x2 - get/set : unset if true // 0x4 - get : shift down vertex index void __cdecl lego::game::Roof_Update(void) { float fVar1; uint dirIndex; BOOL BVar2; uint width; uint i; int idx; float *pNormalZ; Point2I *pDir; uint x; uint y; int j; Vector3F worldPos; Point2I DIRECTIONS_4X4 [16]; Vertex vertices [4]; RoofBlock *roof; if (globs::roofGlobs.needsUpdate != 0) { globs::roofGlobs.needsUpdate = 0; y = 0; width = globs::roofGlobs.dimensions.width; if (globs::roofGlobs.dimensions.height != 0) { do { x = 0; if (width != 0) { do { idx = y * width + x; // Roof vertex has been updated by RoofMesh_LowerRoofVertices. // Update it here, and unset the flag. roof = globs::roofGlobs.grid + idx; if ((*(byte *)&globs::roofGlobs.grid[idx].flags & ROOF_FLAG_NEEDUPDATE) != 0) { DIRECTIONS_4X4[2].y = 1; DIRECTIONS_4X4[3].y = 1; DIRECTIONS_4X4[5].x = 1; DIRECTIONS_4X4[6].x = 1; DIRECTIONS_4X4[6].y = 1; DIRECTIONS_4X4[7].y = 1; DIRECTIONS_4X4[10].x = 1; DIRECTIONS_4X4[11].x = 1; DIRECTIONS_4X4[1].x = -1; DIRECTIONS_4X4[3].x = -1; DIRECTIONS_4X4[9].y = -1; DIRECTIONS_4X4[10].y = -1; DIRECTIONS_4X4[13].x = -1; DIRECTIONS_4X4[13].y = -1; DIRECTIONS_4X4[14].y = -1; DIRECTIONS_4X4[15].x = -1; DIRECTIONS_4X4[0].x = 0; DIRECTIONS_4X4[0].y = 0; DIRECTIONS_4X4[1].y = 0; DIRECTIONS_4X4[2].x = 0; DIRECTIONS_4X4[4].x = 0; DIRECTIONS_4X4[4].y = 0; DIRECTIONS_4X4[5].y = 0; DIRECTIONS_4X4[7].x = 0; DIRECTIONS_4X4[8].x = 0; DIRECTIONS_4X4[8].y = 0; DIRECTIONS_4X4[9].x = 0; DIRECTIONS_4X4[11].y = 0; DIRECTIONS_4X4[12].x = 0; DIRECTIONS_4X4[12].y = 0; DIRECTIONS_4X4[14].x = 0; DIRECTIONS_4X4[15].y = 0; gfx::Container_Mesh_GetVertices(globs::roofGlobs.contMesh,roof->groupID,0,4,vertices); i = 0; // loop for DIRECTIONS_4X4[i...][] pNormalZ = &vertices[0].normal.z; do { // Some counter-clockwise flag maybe? dirIndex = i; // GHIDRA FAIL: setting 0x4 flag equate causes Ghidra to hang // // if (roof->flags & ROOF_SHIFTVERTICES) // (0x4) if ((*(byte *)&roof->flags & 4) != 0) { dirIndex = i - 1 & 3; } j = 4; // loop for DIRECTIONS_4X4[dirIndex][j...] pDir = DIRECTIONS_4X4 + dirIndex * 4; do { BVar2 = Roof_GetBlockPlaneNormal(x + pDir->x,pDir->y + y,&worldPos); if (BVar2 != 0) { pNormalZ[-2] = worldPos.x + pNormalZ[-2]; pNormalZ[-1] = worldPos.y + pNormalZ[-1]; *pNormalZ = worldPos.z + *pNormalZ; } pDir = pDir + 1; j += -1; } while (j != 0); i += 1; fVar1 = 1.0 / SQRT(pNormalZ[-2] * pNormalZ[-2] + *pNormalZ * *pNormalZ + pNormalZ[-1] * pNormalZ[-1]); *pNormalZ = fVar1 * *pNormalZ; pNormalZ[-2] = fVar1 * pNormalZ[-2]; pNormalZ[-1] = fVar1 * pNormalZ[-1]; pNormalZ = pNormalZ + 9; } while (i < 4); gfx::Container_Mesh_SetVertices(globs::roofGlobs.contMesh,roof->groupID,0,4,vertices); // &= ~ROOF_NEEDUPDATE; // (~0x2) updated, so clear flag *(byte *)&roof->flags = *(byte *)&roof->flags & 0xfd; width = globs::roofGlobs.dimensions.width; } x += 1; } while (x < width); } y += 1; } while (y < (uint)globs::roofGlobs.dimensions.height); } } return; } void __cdecl lego::game::Roof_Hide(BOOL hide) { if (globs::roofGlobs.hidden != hide) { globs::roofGlobs.hidden = hide; if (hide != 0) { gfx::Container_Hide(globs::roofGlobs.contMesh,TRUE); return; } gfx::Container_Hide(globs::roofGlobs.contMesh,FALSE); } return; } // I'm not actually sure if this is supposed to be "visible" blocks. But it's a // list of blocks that are assigned and cleared, all in a single FP update loop. void __cdecl lego::game::Roof_AddVisibleBlock(uint bx,uint by) { int idx; RoofBlock *roof; idx = by * globs::roofGlobs.dimensions.width + bx; roof = globs::roofGlobs.grid + idx; gfx::Container_Mesh_HideGroup(globs::roofGlobs.contMesh,globs::roofGlobs.grid[idx].groupID,FALSE); globs::roofGlobs.visibleTable[globs::roofGlobs.visibleCount] = roof; globs::roofGlobs.visibleCount = globs::roofGlobs.visibleCount + 1; return; } void __cdecl lego::game::Roof_HideAllVisibleBlocks(void) { uint i; RoofBlock **pRoof; i = 0; if (globs::roofGlobs.visibleCount != 0) { pRoof = globs::roofGlobs.visibleTable; do { gfx::Container_Mesh_HideGroup(globs::roofGlobs.contMesh,(*pRoof)->groupID,TRUE); i += 1; pRoof = pRoof + 1; } while (i < globs::roofGlobs.visibleCount); } globs::roofGlobs.visibleCount = 0; return; } // FLAGS: // 0x1 - get : if false, this function succeeds (assuming correct block bounds) // // I'm really not sure about the math for this one, or what kind of vector is // really being returned. But it's used for setting vertex normals. BOOL __cdecl lego::game::Roof_GetBlockPlaneNormal(uint bx,uint by,Vector3F *out_normal) { float fVar1; float fVar2; float fVar3; float fVar4; Vector3F normal1; Vector3F normal2; Vertex vertices [4]; if (((bx < (uint)globs::roofGlobs.dimensions.width) && (by < (uint)globs::roofGlobs.dimensions.height)) && ((*(byte *)&globs::roofGlobs.grid[by * globs::roofGlobs.dimensions.width + bx].flags & ROOF_FLAG_HIDDEN) == 0)) { gfx::Container_Mesh_GetVertices (globs::roofGlobs.contMesh, globs::roofGlobs.grid[by * globs::roofGlobs.dimensions.width + bx].groupID,0,4, vertices); math::Maths_PlaneNormal (&normal1,&vertices[0].position,&vertices[1].position,&vertices[2].position); math::Maths_PlaneNormal (&normal2,&vertices[2].position,&vertices[3].position,&vertices[0].position); fVar3 = normal2.y + normal1.y; fVar1 = normal2.z + normal1.z; fVar2 = normal2.x + normal1.x; fVar4 = 1.0 / SQRT(fVar2 * fVar2 + fVar1 * fVar1 + fVar3 * fVar3); out_normal->x = fVar4 * fVar2; out_normal->y = fVar4 * fVar3; out_normal->z = fVar4 * fVar1; return TRUE; } return 0; } void __cdecl lego::front::ScrollInfo_Initialise(char *filename,BOOL index,uint unkFlags,int param_4,int param_5) { Image *pIVar1; char **ppcVar2; ppcVar2 = (char **)¶m_5; if (filename != NULL) { do { globals::g_ScrollInfos[index].flags = 1; globals::g_ScrollInfos[index].flags = (-(uint)((char *)unkFlags != NULL) & 8) + 9; pIVar1 = lego::image::Image_LoadBMPScaled(filename,0,0); globals::g_ScrollInfos[index].image = pIVar1; if (pIVar1 != NULL) { globals::g_ScrollInfos[index].flags = globals::g_ScrollInfos[index].flags | 4; } filename = *ppcVar2; globals::g_ScrollInfos[index].panelType = param_4; index = (BOOL)ppcVar2[1]; unkFlags = (uint)ppcVar2[2]; param_4 = (int)ppcVar2[3]; ppcVar2 = ppcVar2 + 4; } while (filename != NULL); } return; } void __cdecl lego::front::ScrollInfo_SetXYOrSize_Unk(BOOL index,uint x_or_width,uint y_or_height) { globals::g_ScrollInfos[index].pointOrSize.x = (float)(ulonglong)x_or_width; globals::g_ScrollInfos[index].pointOrSize.y = (float)(ulonglong)y_or_height; return; } void __cdecl lego::front::ScrollInfo_AddStruct1C (BOOL index,BOOL use50InsteadOf4c,Area2F *rect,char *opt_filename1,char *opt_filename2) { float fVar1; float fVar2; ScrollInfoSubStruct_1c *pSVar3; Image *pIVar4; if (use50InsteadOf4c == 0) { pSVar3 = (ScrollInfoSubStruct_1c *)io::Mem_Alloc(0x1c); globals::g_ScrollInfos[index].ptr1c_c = pSVar3; } else { pSVar3 = (ScrollInfoSubStruct_1c *)io::Mem_Alloc(0x1c); globals::g_ScrollInfos[index].ptr1c_10 = pSVar3; } (pSVar3->point1).x = rect->x; (pSVar3->point1).y = rect->y; (pSVar3->point2).x = rect->width + rect->x; fVar1 = rect->height; fVar2 = rect->y; pSVar3->image1 = NULL; pSVar3->image2 = NULL; (pSVar3->point2).y = fVar1 + fVar2; if (opt_filename1 != NULL) { pIVar4 = lego::image::Image_LoadBMPScaled(opt_filename1,0,0); pSVar3->image1 = pIVar4; } if (opt_filename2 != NULL) { pIVar4 = lego::image::Image_LoadBMPScaled(opt_filename2,0,0); pSVar3->image2 = pIVar4; } pSVar3->flags = 0; return; } void __cdecl lego::front::ScrollInfo_AddCreateStruct28 (BOOL index,Area2F *area,int number,int param_4,char *filename) { ScrollInfoSubStruct_28 *pSVar1; Image *pIVar2; pSVar1 = (ScrollInfoSubStruct_28 *)io::Mem_Alloc(0x28); globals::g_ScrollInfos[index].substruct28 = pSVar1; pIVar2 = lego::image::Image_LoadBMPScaled(filename,0,0); (globals::g_ScrollInfos[index].substruct28)->image = pIVar2; ((globals::g_ScrollInfos[index].substruct28)->point1).x = area->x; ((globals::g_ScrollInfos[index].substruct28)->point1).y = area->y; ((globals::g_ScrollInfos[index].substruct28)->point2).x = area->width + area->x; ((globals::g_ScrollInfos[index].substruct28)->point2).y = area->height + area->y; (globals::g_ScrollInfos[index].substruct28)->field_10 = 0; (globals::g_ScrollInfos[index].substruct28)->field_14 = 0; (globals::g_ScrollInfos[index].substruct28)->intM1_1c = number + -1; (globals::g_ScrollInfos[index].substruct28)->int_20 = param_4; return; } BOOL __cdecl lego::front::ScrollInfo_Mouse_FUN_00463b60 (int *out_param_1,uint mouseX,uint mouseY,BOOL param_4,BOOL param_5) { uint uVar1; Panel_Type PVar2; float *pfVar3; float fVar4; float fVar5; BOOL BVar6; int iVar7; BOOL BVar8; Image *pIVar9; ScrollInfoSubStruct_1c *pSVar10; longlong lVar11; int local_60; Panel_Type *local_5c; BVar8 = 0; local_60 = 0; local_5c = &globals::g_ScrollInfos[0].panelType; do { if (((*(byte *)(local_5c + 1) & 4) != 0) && (BVar6 = Panel_IsFullyClosed(*local_5c), BVar6 == 0) ) { pIVar9 = NULL; do { if (pIVar9 == NULL) { pSVar10 = (ScrollInfoSubStruct_1c *)local_5c[-3]; } else { pSVar10 = (ScrollInfoSubStruct_1c *)local_5c[-2]; } if ((BVar8 == 0) && (BVar6 = ScrollInfo_FUN_00463ec0 ((ScrollInfoStruct_20 *)(local_5c + -6),pSVar10,mouseX,mouseY), BVar6 != 0)) { *out_param_1 = local_60; if (param_4 == 0) { if (globals::g_ScrollInfos[1].image != (Image *)0x3) { if (pIVar9 != globals::g_ScrollInfos[1].image) goto LAB_00463c6b; PVar2 = local_5c[-1]; uVar1 = *(uint *)(PVar2 + 0x20); if (pIVar9 == NULL) { if (uVar1 < *(uint *)(PVar2 + 0x1c)) { iVar7 = uVar1 + 1; LAB_00463c54: *(int *)(PVar2 + 0x20) = iVar7; } } else { if (uVar1 != 0) { iVar7 = uVar1 - 1; goto LAB_00463c54; } } *(undefined4 *)(local_5c[-1] + 0x24) = 1; pSVar10->flags = pSVar10->flags & 0xfffffffb | 2; goto LAB_00463c6b; } BVar8 = 1; pSVar10->flags = pSVar10->flags & 0xfffffffb | 2; } else { if (globals::g_ScrollInfos[1].image == (Image *)0x3) { if (param_5 == 0) { BVar8 = 1; globals::g_ScrollInfos[1].image = pIVar9; pSVar10->flags = pSVar10->flags & 0xfffffffd | 4; } else { LAB_00463c6b: BVar8 = 1; } } else { if (pIVar9 != globals::g_ScrollInfos[1].image) goto LAB_00463c6b; BVar8 = 1; pSVar10->flags = pSVar10->flags & 0xfffffffd | 4; } } } else { pSVar10->flags = pSVar10->flags & 0xfffffff9; } pIVar9 = (Image *)((int)&pIVar9->surface + 1); } while (pIVar9 < (Image *)0x2); if ((BVar8 == 0) && (BVar6 = ScrollInfo_FUN_00463f50((ScrollInfoStruct_20 *)(local_5c + -6),mouseX,mouseY), BVar6 != 0)) { if (param_4 == 0) { if (globals::g_ScrollInfos[1].image == (Image *)0x3) { globals::g_ScrollInfos[1].image = (Image *)0x2; } globs::s_ScrollInfo_BOOL_005023c0 = TRUE; } else { if (globals::g_ScrollInfos[1].image == (Image *)0x2) { if ((*(byte *)(local_5c + 1) & 8) == 0) { pfVar3 = (float *)local_5c[-1]; fVar4 = (float)(ulonglong)(uint)pfVar3[7] / (pfVar3[2] - *pfVar3); fVar5 = (((float)(ulonglong)mouseX - globs::panelGlobs.panelTable[*local_5c].position.x) - (float)local_5c[-5]) - *pfVar3; } else { PVar2 = local_5c[-1]; fVar4 = (float)(ulonglong)*(uint *)(PVar2 + 0x1c) / (*(float *)(PVar2 + Panel_Type_Count) - *(float *)(PVar2 + Panel_MessagesSide) ); fVar5 = (((float)(ulonglong)mouseY - globs::panelGlobs.panelTable[*local_5c].position.y) - (float)local_5c[-4]) - *(float *)(PVar2 + Panel_MessagesSide); } lVar11 = math::ScrollInfo_MathX_RoundToLL(fVar5 / fVar4); BVar8 = 1; *(int *)(local_5c[-1] + 0x20) = (int)lVar11; *(undefined4 *)(local_5c[-1] + 0x24) = 1; *out_param_1 = local_60; goto LAB_00463da4; } } BVar8 = 1; *out_param_1 = local_60; } else { globs::s_ScrollInfo_BOOL_005023c0 = 0; } LAB_00463da4: pfVar3 = (float *)local_5c[-1]; if (pfVar3[9] != 0.0) { fVar4 = pfVar3[7]; if ((*(byte *)(local_5c + 1) & 8) == 0) { if (fVar4 == 0.0) { fVar4 = *pfVar3 - (float)(ulonglong)*(uint *)((int)pfVar3[6] + 4); } else { fVar4 = (float)(ulonglong)(uint)pfVar3[8] * ((float)(ulonglong)(uint)fVar4 / ((pfVar3[2] - *pfVar3) - (float)(ulonglong)*(uint *)((int)pfVar3[6] + 4))); } pfVar3[4] = fVar4; } else { if (fVar4 == 0.0) { pfVar3[5] = 0.0; } else { pfVar3[5] = (float)(ulonglong)(uint)pfVar3[8] * ((float)(ulonglong)(uint)fVar4 / ((pfVar3[3] - pfVar3[1]) - (float)(ulonglong)*(uint *)((int)pfVar3[6] + 8))) ; } } *(undefined4 *)(local_5c[-1] + 0x24) = 0; } } local_5c = local_5c + 8; local_60 += 1; if ((Panel_Type *)((int)&globals::g_ScrollInfos[1].substruct28 + 3) < local_5c) { if ((param_4 == 0) && (globs::s_ScrollInfo_BOOL_005023c0 == 0)) { globals::g_ScrollInfos[1].image = (Image *)0x3; } return BVar8; } } while( true ); } BOOL __cdecl lego::front::ScrollInfo_FUN_00463ec0 (ScrollInfoStruct_20 *param_1,ScrollInfoSubStruct_1c *param_2,int mouseX,int mouseY) { Panel_Type PVar1; float fVar2; float fVar3; longlong lVar4; longlong lVar5; PVar1 = param_1->panelType; lVar4 = __ftol((float10)globs::panelGlobs.panelTable[PVar1].position.x + (float10)(param_1->pointOrSize).x); lVar5 = __ftol((float10)globs::panelGlobs.panelTable[PVar1].position.y + (float10)(param_1->pointOrSize).y); fVar2 = (float)(mouseX - (int)lVar4); if (((((param_2->point1).x <= fVar2) && (fVar3 = (float)(mouseY - (int)lVar5), fVar3 < (param_2->point2).y)) && ((param_2->point1).y <= fVar3)) && (fVar2 < (param_2->point2).x)) { return TRUE; } return 0; } BOOL __cdecl lego::front::ScrollInfo_FUN_00463f50(ScrollInfoStruct_20 *param_1,int mouseX,int mouseY) { ScrollInfoSubStruct_28 *pSVar1; float fVar2; float fVar3; longlong lVar4; longlong lVar5; Panel_Type panelType; panelType = param_1->panelType; lVar4 = __ftol((float10)globs::panelGlobs.panelTable[panelType].position.x + (float10)(param_1->pointOrSize).x); lVar5 = __ftol((float10)globs::panelGlobs.panelTable[panelType].position.y + (float10)(param_1->pointOrSize).y); fVar2 = (float)(mouseX - (int)lVar4); pSVar1 = param_1->substruct28; if (((((pSVar1->point1).x <= fVar2) && (fVar3 = (float)(mouseY - (int)lVar5), fVar3 < (pSVar1->point2).y)) && ((pSVar1->point1).y <= fVar3)) && (fVar2 < (pSVar1->point2).x)) { return TRUE; } return 0; } void __cdecl lego::front::ScrollInfo_Update(BOOL index) { ScrollInfoSubStruct_28 *pSVar1; ScrollInfoSubStruct_1c *pSVar2; uint uVar3; Image *image; Point2F local_10; Point2F local_8; local_10.x = globals::g_ScrollInfos[index].pointOrSize.x + globs::panelGlobs.panelTable[globals::g_ScrollInfos[index].panelType].position.x; local_10.y = globals::g_ScrollInfos[index].pointOrSize.y + globs::panelGlobs.panelTable[globals::g_ScrollInfos[index].panelType].position.y; lego::image::Image_DisplayScaled(globals::g_ScrollInfos[index].image,NULL,&local_10,NULL); uVar3 = 0; do { if (uVar3 == 0) { pSVar2 = globals::g_ScrollInfos[index].ptr1c_c; } else { pSVar2 = globals::g_ScrollInfos[index].ptr1c_10; } if (((pSVar2->flags & 2) == 0) || (pSVar2->image1 == NULL)) { if (((pSVar2->flags & 4) != 0) && (pSVar2->image2 != NULL)) { local_8.x = (pSVar2->point1).x; local_8.y = (pSVar2->point1).y; image = pSVar2->image2; goto LAB_004640a7; } } else { local_8.x = (pSVar2->point1).x; local_8.y = (pSVar2->point1).y; image = pSVar2->image1; LAB_004640a7: local_8.y = local_8.y + local_10.y; local_8.x = local_8.x + local_10.x; lego::image::Image_DisplayScaled(image,NULL,&local_8,NULL); } uVar3 += 1; if (1 < uVar3) { pSVar1 = globals::g_ScrollInfos[index].substruct28; local_8.x = (float)pSVar1->field_10 + local_10.x + (pSVar1->point1).x; local_8.y = (pSVar1->point1).y + (float)pSVar1->field_14 + local_10.y; lego::image::Image_DisplayScaled(pSVar1->image,NULL,&local_8,NULL); return; } } while( true ); } longlong __cdecl lego::math::ScrollInfo_MathX_RoundToLL(float x) { float10 fVar1; longlong lVar2; double x_; x_ = (double)x; fVar1 = std::floor(x_); if ((float10)x - fVar1 < (float10)0.5) { fVar1 = std::floor(x_); lVar2 = __ftol(fVar1); return lVar2; } fVar1 = std::ceil(x_); lVar2 = __ftol(fVar1); return lVar2; } void __cdecl lego::front::ScrollInfo_GetSubStruct28_Fields1C_20(BOOL index,int *out_field1c,int *out_field20) { *out_field1c = (globals::g_ScrollInfos[index].substruct28)->intM1_1c; *out_field20 = (globals::g_ScrollInfos[index].substruct28)->int_20; return; } void __cdecl lego::front::ScrollInfo_SetSubStruct28_Fields1C_20(BOOL index,int field1c,int field20) { (globals::g_ScrollInfos[index].substruct28)->intM1_1c = field1c; (globals::g_ScrollInfos[index].substruct28)->int_20 = field20; (globals::g_ScrollInfos[index].substruct28)->bool_24 = TRUE; return; } // `tileDepth` is the Z height of each coloured square when drawing the building placement grid. SelectPlace * __cdecl lego::gfx::SelectPlace_Create(Container *root,float tileDepth) { uint uVar1; SelectPlace *buffer; Container *pCVar2; uint *puVar3; uint *puVar4; uint *puVar5; uint uVar6; uint uVar7; uint uVar8; int iVar9; Vector3F *pVVar10; D3DRMGroupIndex groupID; float TV_COORDS [4]; float TU_COORDS [4]; uint FACE_UNK [6]; Vector3F VERT_POSES [5]; uint faceData [30]; Vertex vertices [4]; buffer = (SelectPlace *)io::Mem_Alloc(8); if (buffer != NULL) { buffer->contMesh = NULL; buffer->tileDepth = 0.0; pCVar2 = Container_MakeMesh2(root,Container_MeshType_Transparent); buffer->contMesh = pCVar2; if (pCVar2 != NULL) { TU_COORDS[0] = 0.0; FACE_UNK[1] = 1; FACE_UNK[3] = 1; TU_COORDS[1] = 1.0; TU_COORDS[2] = 1.0; TU_COORDS[3] = 0.0; TV_COORDS[0] = 0.0; TV_COORDS[1] = 0.0; TV_COORDS[2] = 1.0; TV_COORDS[3] = 1.0; VERT_POSES[0].x = 0.0; VERT_POSES[0].y = 0.0; VERT_POSES[0].z = -1.0; VERT_POSES[1].x = 0.0; VERT_POSES[1].y = 1.0; VERT_POSES[1].z = 0.0; VERT_POSES[2].x = 1.0; VERT_POSES[2].y = 0.0; VERT_POSES[2].z = 0.0; VERT_POSES[3].x = 0.0; VERT_POSES[3].y = -1.0; VERT_POSES[3].z = 0.0; VERT_POSES[4].x = -1.0; VERT_POSES[4].y = 0.0; VERT_POSES[4].z = 0.0; FACE_UNK[0] = 0; FACE_UNK[2] = 3; FACE_UNK[4] = 2; FACE_UNK[5] = 3; uVar8 = 0; puVar4 = faceData; do { puVar5 = FACE_UNK; iVar9 = 6; puVar3 = puVar4; do { puVar4 = puVar3 + 1; uVar6 = *puVar5; puVar5 = puVar5 + 1; iVar9 += -1; *puVar3 = uVar8 + uVar6; puVar3 = puVar4; } while (iVar9 != 0); uVar8 += 4; } while (uVar8 < 20); groupID = D3DRMGROUP_0; buffer->tileDepth = tileDepth; do { Container_Mesh_AddGroup(buffer->contMesh,20,10,3,faceData); uVar8 = 0; pVVar10 = VERT_POSES; do { puVar4 = &vertices[0].colour; uVar6 = 0; do { uVar7 = uVar6 + 4; puVar4[-5] = (uint)pVVar10->x; puVar4[-4] = (uint)pVVar10->y; puVar4[-3] = (uint)pVVar10->z; uVar1 = *(uint *)((int)TU_COORDS + uVar6); *puVar4 = 0xffffffff; puVar4[-2] = uVar1; puVar4[-1] = *(uint *)((int)TV_COORDS + uVar6); puVar4 = puVar4 + 9; uVar6 = uVar7; } while (uVar7 < 0x10); Container_Mesh_SetVertices(buffer->contMesh,groupID,uVar8,4,vertices); uVar8 += 4; pVVar10 = pVVar10 + 1; } while (uVar8 < 20); Container_Mesh_SetQuality(buffer->contMesh,groupID,Gouraud); groupID += 1; } while (groupID < 10); Container_Hide(buffer->contMesh,TRUE); return buffer; } io::Mem_Free(buffer); } return NULL; } // Translate and rotate a set of integer points (max of 20). // Returns a pointer to a temporary buffer that will be modified when this function is next called. // // DIRECTION_UP is "no rotation" Point2I * __cdecl lego::gfx::SelectPlace_TransformShapePoints (Point2I *translation,Point2I *shapePoints,uint shapeCount,Direction rotation) { Point2I *dstPoint; uint signBit; int swapPoint_x; if (shapeCount != 0) { signBit = (int)(rotation + 0x8000) >> 0x1f; dstPoint = globs::s_TransformShapePoints; do { // POINTER MATH to get shapePoints[i] from dstPoints[i] // dstPoint->x = shapePoints[i].x; // dstPoint->y = shapePoints[i].y; dstPoint->x = *(int *)((int)&dstPoint->x + (int)&shapePoints[-0xa0479].x); dstPoint->y = *(int *)((int)((int)shapePoints + -0x5023c4) + (int)dstPoint); // apply rotation to dstPoints[i] // positive modulus (direction % 4) if (true) { // case DIRECTION_UP: // (x, y) no change switch(((rotation + 0x8000 ^ signBit) - signBit & 3 ^ signBit) - signBit) { default: goto switchD_0046441a_caseD_0; case DIRECTION_RIGHT: // (-y, x) swapPoint_x = dstPoint->x; dstPoint->x = -dstPoint->y; goto LAB_00464440; case DIRECTION_DOWN: // (-x, -y) dstPoint->x = -dstPoint->x; swapPoint_x = dstPoint->y; break; case DIRECTION_LEFT: // (y, -x) swapPoint_x = dstPoint->x; dstPoint->x = dstPoint->y; } swapPoint_x = -swapPoint_x; LAB_00464440: dstPoint->y = swapPoint_x; } switchD_0046441a_caseD_0: // apply translation to dstPoints[i] dstPoint->x = dstPoint->x + translation->x; shapeCount -= 1; dstPoint->y = dstPoint->y + translation->y; dstPoint = dstPoint + 1; } while (shapeCount != 0); } return globs::s_TransformShapePoints; } // Checks the validity of a selection placement and updates the render state of the SelectPlace // tiles. // Returns the temporary result of SelectPlace_TransformShapePoints, or null. // `waterEntrances` is a signed int, because a value of `-1` (or lower) is required to define the // origin tile as a Yellow Path tile. Point2I * __cdecl lego::gfx::SelectPlace_CheckAndUpdate (SelectPlace *selectPlace,Point2I *blockPos,Point2I *shapePoints,uint shapeCount, Direction direction,Map3D *map,int waterEntrances) { D3DRMGroupIndex group; Point2I *pShape; BOOL BVar1; float *pfVar2; uint *puVar3; Vertex *pVVar4; Vertex *pVVar5; int *piVar6; uint uVar7; int iVar8; int *piVar9; Point2I *pPVar10; int iVar11; Point2I *pPVar12; float red; float green; uint local_3d0; Point2I *local_3cc; Point2I *local_3c8; float blue; D3DRMGroupIndex local_3c0; Point2I local_3ac; BOOL okRoughness; Point2I DIRECTIONS [4]; uint VERT_INDEX [20]; Vector3F selectVertPoses [8]; Vertex vertices [20]; bool adjacentPath; bool anyConnection; byte canPlace; bool pathConnection; bool shapeHasPath; VERT_INDEX[2] = 2; VERT_INDEX[11] = 2; VERT_INDEX[12] = 2; VERT_INDEX[3] = 3; VERT_INDEX[6] = 5; VERT_INDEX[9] = 5; VERT_INDEX[15] = 3; VERT_INDEX[16] = 3; VERT_INDEX[1] = 1; VERT_INDEX[7] = 1; VERT_INDEX[8] = 1; canPlace = 1; VERT_INDEX[14] = 7; VERT_INDEX[17] = 7; VERT_INDEX[10] = 6; VERT_INDEX[13] = 6; uVar7 = 0; local_3c0 = D3DRMGROUP_0; VERT_INDEX[0] = 0; VERT_INDEX[4] = 0; VERT_INDEX[5] = 4; VERT_INDEX[18] = 4; VERT_INDEX[19] = 0; pShape = SelectPlace_TransformShapePoints(blockPos,shapePoints,shapeCount,direction); okRoughness = lego::map::Map3D_CheckBuildingTolerance ((globs::legoGlobs.currLevel)->map,pShape,shapeCount, (globs::legoGlobs.currLevel)->BuildingTolerance, (globs::legoGlobs.currLevel)->BuildingMaxVariation); pathConnection = false; anyConnection = false; shapeHasPath = false; if (shapeCount != 0) { DIRECTIONS[1].x = 1; DIRECTIONS[2].y = 1; DIRECTIONS[0].x = 0; DIRECTIONS[0].y = -1; DIRECTIONS[1].y = 0; DIRECTIONS[2].x = 0; DIRECTIONS[3].x = -1; DIRECTIONS[3].y = 0; piVar6 = &pShape->y; pPVar12 = pShape; pPVar10 = pShape; do { local_3c8 = pPVar10 + 1; adjacentPath = false; piVar9 = &DIRECTIONS[0].y; local_3cc = (Point2I *)0x4; do { local_3ac.x = piVar9[-1] + pPVar12->x; local_3ac.y = *piVar6 + *piVar9; BVar1 = game::Level_Block_IsPath(&local_3ac); if ((BVar1 != 0) && (BVar1 = game::Level_Block_IsPathBuilding(&local_3ac), BVar1 == 0)) { anyConnection = true; adjacentPath = true; } piVar9 = piVar9 + 2; local_3cc = (Point2I *)((int)local_3cc + -1); } while (local_3cc != NULL); if (((uVar7 < shapeCount - 1) && (pPVar12->x == local_3c8->x)) && (*piVar6 == pPVar10[1].y)) { if (adjacentPath) { pathConnection = true; } uVar7 += 1; pPVar12 = pPVar12 + 1; piVar6 = piVar6 + 2; shapeHasPath = true; local_3c8 = pPVar10 + 2; } uVar7 += 1; pPVar12 = pPVar12 + 1; piVar6 = piVar6 + 2; pPVar10 = local_3c8; } while (uVar7 < shapeCount); } if (shapeHasPath) { anyConnection = pathConnection; } local_3d0 = 0; group = D3DRMGROUP_0; if (shapeCount != 0) { local_3ac.x = shapeCount - 1; pPVar10 = pShape; pPVar12 = pShape; do { local_3cc = pPVar12 + 1; if (((local_3d0 < (uint)local_3ac.x) && (pPVar10->x == local_3cc->x)) && (pPVar10->y == pPVar12[1].y)) { iVar8 = TRUE; local_3c8 = (Point2I *)TRUE; if (waterEntrances + 1 <= local_3c0) goto LAB_0046471f; } else { local_3c8 = NULL; LAB_0046471f: iVar8 = 0; } BVar1 = game::Level_CanBuildOnBlock(pPVar10->x,pPVar10->y,(BOOL)local_3c8,iVar8); if (((BVar1 == 0) || (!anyConnection)) || (red = (float)game::Level_BlockPointerCheck(blockPos), red != 0.0)) { canPlace = 0; red = 0.6; green = 0.0; LAB_004647ee: blue = 0.0; } else { if (iVar8 == 0) { if (local_3c8 != NULL) { red = 0.7; green = 0.7; goto LAB_004647ee; } if (okRoughness == 0) { canPlace = 0; red = 0.7; green = 0.0; blue = 0.7; } else { red = 0.0; green = 0.7; blue = 0.1; } } else { green = 0.7; blue = 0.9; } } Container_Mesh_SetColourAlpha(selectPlace->contMesh,local_3c0,red,green,blue,0.2); Container_Mesh_SetEmissive(selectPlace->contMesh,local_3c0,red * 0.5,green * 0.5,blue * 0.5); BVar1 = lego::map::Map3D_IsInsideDimensions(map,pPVar10->x,pPVar10->y); if (BVar1 == 0) { Container_Mesh_HideGroup(selectPlace->contMesh,local_3c0,TRUE); } else { lego::map::Map3D_GetBlockVertexPositions_NoRot(map,pPVar10->x,pPVar10->y,selectVertPoses); iVar8 = 4; pfVar2 = &selectVertPoses[0].z; do { iVar8 += -1; pfVar2[10] = pfVar2[-2]; pfVar2[0xb] = pfVar2[-1]; pfVar2[0xc] = *pfVar2; *pfVar2 = *pfVar2 - selectPlace->tileDepth; pfVar2 = pfVar2 + 3; } while (iVar8 != 0); Container_Mesh_GetVertices(selectPlace->contMesh,local_3c0,0,0x14,vertices); puVar3 = VERT_INDEX; pVVar4 = vertices; iVar8 = 5; do { iVar11 = 4; pVVar5 = pVVar4; do { uVar7 = *puVar3; puVar3 = puVar3 + 1; pVVar4 = pVVar5 + 1; iVar11 += -1; (pVVar5->position).x = selectVertPoses[uVar7].x; (pVVar5->position).y = selectVertPoses[uVar7].y; (pVVar5->position).z = selectVertPoses[uVar7].z; pVVar5 = pVVar4; } while (iVar11 != 0); iVar8 += -1; } while (iVar8 != 0); Container_Mesh_SetVertices(selectPlace->contMesh,local_3c0,0,0x14,vertices); Container_Mesh_HideGroup(selectPlace->contMesh,local_3c0,FALSE); } local_3c0 += 1; if (local_3c8 != NULL) { local_3d0 += 1; pPVar10 = pPVar10 + 1; local_3cc = pPVar12 + 2; } local_3d0 += 1; pPVar10 = pPVar10 + 1; pPVar12 = local_3cc; group = local_3c0; } while (local_3d0 < shapeCount); } for (; group < 10; group = group + 1) { Container_Mesh_HideGroup(selectPlace->contMesh,group,TRUE); } return (Point2I *)(-(uint)canPlace & (uint)pShape); } void __cdecl lego::gfx::SelectPlace_Hide(SelectPlace *selectPlace,BOOL hide) { Container_Hide(selectPlace->contMesh,hide); return; } void __cdecl lego::snd::SFX_Initialise(void) { uint uVar1; // new uint[495] globs::sfxGlobs.hashNameList = (uint *)io::Mem_Alloc(0x7bc); uVar1 = util::Util_HashString("SFX_NULL",0,1); *globs::sfxGlobs.hashNameList = uVar1; uVar1 = util::Util_HashString("SFX_Stamp",0,1); globs::sfxGlobs.hashNameList[1] = uVar1; uVar1 = util::Util_HashString("SFX_Drill",0,1); globs::sfxGlobs.hashNameList[2] = uVar1; uVar1 = util::Util_HashString("SFX_DrillFade",0,1); globs::sfxGlobs.hashNameList[3] = uVar1; uVar1 = util::Util_HashString("SFX_RockBreak",0,1); globs::sfxGlobs.hashNameList[4] = uVar1; uVar1 = util::Util_HashString("SFX_Drip",0,1); globs::sfxGlobs.hashNameList[5] = uVar1; uVar1 = util::Util_HashString("SFX_Ambient",0,1); globs::sfxGlobs.hashNameList[6] = uVar1; uVar1 = util::Util_HashString("SFX_AmbientLoop",0,1); globs::sfxGlobs.hashNameList[7] = uVar1; uVar1 = util::Util_HashString("SFX_Step",0,1); globs::sfxGlobs.hashNameList[8] = uVar1; uVar1 = util::Util_HashString("SFX_RockMonster",0,1); globs::sfxGlobs.hashNameList[9] = uVar1; uVar1 = util::Util_HashString("SFX_RockMonster2",0,1); globs::sfxGlobs.hashNameList[10] = uVar1; uVar1 = util::Util_HashString("SFX_RockMonsterStep",0,1); globs::sfxGlobs.hashNameList[0xb] = uVar1; uVar1 = util::Util_HashString("SFX_MFDeposit",0,1); globs::sfxGlobs.hashNameList[0xc] = uVar1; uVar1 = util::Util_HashString("SFX_ButtonPressed",0,1); globs::sfxGlobs.hashNameList[0xd] = uVar1; uVar1 = util::Util_HashString("SFX_MFLift",0,1); globs::sfxGlobs.hashNameList[0xe] = uVar1; uVar1 = util::Util_HashString("SFX_MFThrow",0,1); globs::sfxGlobs.hashNameList[0xf] = uVar1; uVar1 = util::Util_HashString("SFX_Walker",0,1); globs::sfxGlobs.hashNameList[0x10] = uVar1; uVar1 = util::Util_HashString("SFX_YesSir",0,1); globs::sfxGlobs.hashNameList[0x11] = uVar1; uVar1 = util::Util_HashString("SFX_Build",0,1); globs::sfxGlobs.hashNameList[0x12] = uVar1; uVar1 = util::Util_HashString("SFX_Okay",0,1); globs::sfxGlobs.hashNameList[0x13] = uVar1; uVar1 = util::Util_HashString("SFX_NotOkay",0,1); globs::sfxGlobs.hashNameList[0x14] = uVar1; uVar1 = util::Util_HashString("SFX_InterfaceSlideOnScreen",0,1); globs::sfxGlobs.hashNameList[0x15] = uVar1; uVar1 = util::Util_HashString("SFX_InterfaceSlideOffScreen",0,1); globs::sfxGlobs.hashNameList[0x16] = uVar1; uVar1 = util::Util_HashString("SFX_PanelSlideOnScreen",0,1); globs::sfxGlobs.hashNameList[0x17] = uVar1; uVar1 = util::Util_HashString("SFX_PanelSlideOffScreen",0,1); globs::sfxGlobs.hashNameList[0x18] = uVar1; uVar1 = util::Util_HashString("SFX_Siren",0,1); globs::sfxGlobs.hashNameList[0x19] = uVar1; uVar1 = util::Util_HashString("SFX_CrystalRecharge",0,1); globs::sfxGlobs.hashNameList[0x1a] = uVar1; uVar1 = util::Util_HashString("SFX_Laser",0,1); globs::sfxGlobs.hashNameList[0x1b] = uVar1; uVar1 = util::Util_HashString("SFX_LaserHit",0,1); globs::sfxGlobs.hashNameList[0x1c] = uVar1; uVar1 = util::Util_HashString("SFX_LazerRecharge",0,1); globs::sfxGlobs.hashNameList[0x1d] = uVar1; uVar1 = util::Util_HashString("SFX_TopPriority",0,1); globs::sfxGlobs.hashNameList[0x1e] = uVar1; uVar1 = util::Util_HashString("SFX_ImmovableRock",0,1); globs::sfxGlobs.hashNameList[0x1f] = uVar1; uVar1 = util::Util_HashString("SFX_Wall",0,1); globs::sfxGlobs.hashNameList[0x20] = uVar1; uVar1 = util::Util_HashString("SFX_Floor",0,1); globs::sfxGlobs.hashNameList[0x21] = uVar1; uVar1 = util::Util_HashString("SFX_BoulderHit",0,1); globs::sfxGlobs.hashNameList[0x22] = uVar1; uVar1 = util::Util_HashString("SFX_Place",0,1); globs::sfxGlobs.hashNameList[0x23] = uVar1; uVar1 = util::Util_HashString("SFX_PlaceOre",0,1); globs::sfxGlobs.hashNameList[0x24] = uVar1; uVar1 = util::Util_HashString("SFX_PlaceCrystal",0,1); globs::sfxGlobs.hashNameList[0x25] = uVar1; uVar1 = util::Util_HashString("SFX_Lava",0,1); globs::sfxGlobs.hashNameList[0x26] = uVar1; uVar1 = util::Util_HashString("SFX_RockWipe",0,1); globs::sfxGlobs.hashNameList[0x27] = uVar1; uVar1 = util::Util_HashString("SFX_FallIn",0,1); globs::sfxGlobs.hashNameList[0x28] = uVar1; uVar1 = util::Util_HashString("SFX_MusicLoop",0,1); globs::sfxGlobs.hashNameList[0x29] = uVar1; uVar1 = util::Util_HashString("SFX_CaptainSlide",0,1); globs::sfxGlobs.hashNameList[0x2a] = uVar1; uVar1 = util::Util_HashString("SFX_Dynamite",0,1); globs::sfxGlobs.hashNameList[0x2b] = uVar1; uVar1 = util::Util_HashString("SFX_AmbientMusicLoop",0,1); globs::sfxGlobs.hashNameList[0x2c] = uVar1; gfx::Container_SetSoundTriggerCallback(SFX_Container_SoundTriggerCallback,NULL); return; } void __cdecl lego::snd::SFX_Container_SoundTriggerCallback(char *sfxName,Container *cont,void *data) { BOOL BVar1; BVar1 = SFX_GetType(sfxName,(SFX_ID *)&sfxName); if (BVar1 != 0) { SFX_Random_PlaySound3DOnContainer(cont,(SFX_ID)sfxName,FALSE,TRUE,NULL); } return; } void __cdecl lego::snd::SFX_SetSamplePopulateMode(BOOL on) { if (on != 0) { globs::sfxGlobs.flags = globs::sfxGlobs.flags | SFX_GLOB_FLAG_POPULATEMODE; return; } globs::sfxGlobs.flags = globs::sfxGlobs.flags & ~SFX_GLOB_FLAG_POPULATEMODE; return; } BOOL __cdecl lego::snd::SFX_GetType(char *sfxName,SFX_ID *out_sfxID) { SFX_ID SVar1; uint uVar2; SFX_ID SVar3; uint *puVar4; if (sfxName != NULL) { // hash_string(sfxName, false (!bIgnoreBlanks), true (bIgnoreCase)) uVar2 = util::Util_HashString(sfxName,FALSE,TRUE); SVar3 = SFX_NULL; SVar1 = globs::sfxGlobs.hashNameCount + SFX_Preload_Count; puVar4 = globs::sfxGlobs.hashNameList; if (SVar1 != SFX_NULL) { do { if (uVar2 == *puVar4) { *out_sfxID = SVar3; return TRUE; } SVar3 += SFX_Stamp; puVar4 = puVar4 + 1; } while (SVar3 < SVar1); } // This flag presumably states the SFX table is still being built if (((byte)globs::sfxGlobs.flags & SFX_GLOB_FLAG_POPULATEMODE) != 0) { *out_sfxID = SVar1; // hash_string(sfxName, false (!bIgnoreBlanks), true (bIgnoreCase)) uVar2 = util::Util_HashString(sfxName,FALSE,TRUE); globs::sfxGlobs.hashNameList[SVar1] = uVar2; globs::sfxGlobs.hashNameCount = globs::sfxGlobs.hashNameCount + 1; return TRUE; } } return FALSE; } // value is modified via Util_Tokenise BOOL __cdecl lego::snd::SFX_LoadSampleProperty(char *value,SFX_ID sfxID) { char cVar1; uint uVar2; SFX_Property *pSVar3; char cVar4; int iVar5; char *pcVar6; BOOL stream; char *pcVar7; SFX_Property *pSVar8; char **local_1e0; int numParts; BOOL success; SFX_Property *lastItem; char volBuff [64]; char filename_parts [100]; pSVar8 = globs::sfxGlobs.samplePropTable + sfxID; stream = 0; success = 1; lastItem = NULL; globs::sfxGlobs.samplePropTable[sfxID].next = NULL; numParts = util::Util_Tokenise(value,(char **)filename_parts,","); if (numParts != 0) { local_1e0 = (char **)filename_parts; do { pcVar7 = *local_1e0; cVar1 = *pcVar7; if (cVar1 == '*') { pcVar7 = pcVar7 + 1; } iVar5 = 0; if (*pcVar7 == '#') { cVar4 = pcVar7[1]; pcVar7 = pcVar7 + 1; if (cVar4 != '#') { pcVar6 = volBuff; do { *pcVar6 = cVar4; cVar4 = pcVar7[1]; pcVar6 = pcVar6 + 1; pcVar7 = pcVar7 + 1; } while (cVar4 != '#'); } iVar5 = std::atoi(volBuff); pcVar7 = pcVar7 + 1; } if (*pcVar7 == '@') { stream = 1; pcVar7 = pcVar7 + 1; } iVar5 = Sound3D_Load(pcVar7,stream,(uint)(cVar1 == '*'),iVar5); pSVar8->sound3DHandle = iVar5; uVar2 = globs::sfxGlobs.sampleGroupCount; if (iVar5 == -1) { success = 0; pSVar3 = lastItem; } else { pSVar3 = pSVar8; if (lastItem != NULL) { pSVar8 = globs::sfxGlobs.sampleGroupTable + globs::sfxGlobs.sampleGroupCount; globs::sfxGlobs.sampleGroupCount += 1; lastItem->next = pSVar8; globs::sfxGlobs.sampleGroupTable[uVar2].next = NULL; pSVar3 = pSVar8; } } lastItem = pSVar3; local_1e0 = local_1e0 + 1; numParts += -1; } while (numParts != 0); } return success; } int __cdecl lego::snd::SFX_Random_GetSound3DHandle(SFX_ID sfxID) { short rng; uint groupIndex; SFX_Property *sfxGroup; SFX_Property *sfxProp; int swapHandle; groupIndex = 0; if (sfxID != SFX_NULL) { if (globs::sfxGlobs.samplePropTable[sfxID].next != NULL) { sfxProp = globs::sfxGlobs.samplePropTable + sfxID; for (sfxGroup = sfxProp; sfxGroup != NULL; sfxGroup = sfxGroup->next) { groupIndex += 1; } rng = math::Maths_Rand(); sfxGroup = sfxProp; for (groupIndex = (uint)(int)rng % groupIndex; groupIndex != 0; groupIndex -= 1) { sfxGroup = sfxGroup->next; } swapHandle = sfxGroup->sound3DHandle; sfxGroup->sound3DHandle = sfxProp->sound3DHandle; sfxProp->sound3DHandle = swapHandle; } return globs::sfxGlobs.samplePropTable[sfxID].sound3DHandle; } return -1; } void __cdecl lego::snd::SFX_StopGlobalSample(void) { if ((globs::sfxGlobs.globalSampleSoundHandle != -1) && ((ushort)((ushort)(globs::sfxGlobs.globalSampleDuration < 0.0) << 8 | (ushort)(globs::sfxGlobs.globalSampleDuration == 0.0) << 0xe) == 0)) { SFX_Sound3D_StopSound(globs::sfxGlobs.globalSampleSoundHandle); globs::sfxGlobs.globalSampleSoundHandle = -1; globs::sfxGlobs.globalSampleDuration = 0.0; } return; } BOOL __cdecl lego::snd::SFX_SetGlobalSampleDurationIfLE0_AndNullifyHandle(float duration) { if ((ushort)((ushort)(globs::sfxGlobs.globalSampleDuration < 0.0) << 8 | (ushort)(globs::sfxGlobs.globalSampleDuration == 0.0) << 0xe) != 0) { globs::sfxGlobs.globalSampleDuration = duration; globs::sfxGlobs.globalSampleSoundHandle = -1; return TRUE; } return FALSE; } BOOL __cdecl lego::snd::SFX_Random_SetAndPlayGlobalSample(SFX_ID sfxID,int *optout_handle) { float10 playTime; if ((ushort)((ushort)(globs::sfxGlobs.globalSampleDuration < 0.0) << 8 | (ushort)(globs::sfxGlobs.globalSampleDuration == 0.0) << 0xe) != 0) { globs::sfxGlobs.globalSampleSoundHandle = SFX_Random_PlaySoundNormal(sfxID,FALSE); if (globs::sfxGlobs.globalSampleSoundHandle != -1) { playTime = SFX_Random_GetSamplePlayTime(sfxID); globs::sfxGlobs.globalSampleSFXType = sfxID; globs::sfxGlobs.globalSampleDuration = (float)(playTime * (float10)25.0); if (optout_handle != NULL) { *optout_handle = globs::sfxGlobs.globalSampleSoundHandle; } return TRUE; } } return FALSE; } void __cdecl lego::snd::SFX_AddToQueue(SFX_ID sfxID,SoundMode mode) { if (globs::sfxGlobs.soundQueueCount_1 < 10) { globs::sfxGlobs.soundQueueSFXTable_1[globs::sfxGlobs.soundQueueCount_1] = sfxID; globs::sfxGlobs.soundQueueModesTable_1[globs::sfxGlobs.soundQueueCount_1] = mode; globs::sfxGlobs.soundQueueCount_1 += 1; } return; } // The return value of this function is a sound3DHandle, BUT ONLY when AudioFlag 0x8 is unset!!!! int __cdecl lego::snd::SFX_Random_PlaySoundNormal(SFX_ID sfxID,BOOL loop) { SFX_Instance *in_EAX; uint instCount; SFX_Instance *sfxInst; instCount = globs::sfxGlobs.sfxInstanceCount; if (((byte)globs::sfxGlobs.flags & SFX_GLOB_FLAG_QUEUEMODE) == 0) { in_EAX = (SFX_Instance *)sfxID; if ((sfxID != SFX_NULL) && (((byte)globs::sfxGlobs.flags & SFX_GLOB_FLAG_SOUNDON) != 0)) { in_EAX = (SFX_Instance *)SFX_Random_GetSound3DHandle(sfxID); if (in_EAX != NULL) { in_EAX = (SFX_Instance *)Sound3D_Play2(Sound3DPlay_Normal,NULL,(int)in_EAX,loop,NULL); } } } else { if (globs::sfxGlobs.sfxInstanceCount < 10) { sfxInst = globs::sfxGlobs.sfxInstanceTable + globs::sfxGlobs.sfxInstanceCount; globs::sfxGlobs.sfxInstanceCount = globs::sfxGlobs.sfxInstanceCount + 1; sfxInst->sampleIndex = sfxID; globs::sfxGlobs.sfxInstanceTable[instCount].flags = globs::sfxGlobs.sfxInstanceTable[instCount].flags & ~SFX_INSTANCE_FLAG_SOUND3D; return (int)sfxInst; } } return (int)in_EAX; } void __cdecl lego::snd::SFX_Random_SetBufferVolume(SFX_ID sfxID,int volume) { int rngSound3DHandle; rngSound3DHandle = SFX_Random_GetSound3DHandle(sfxID); Sound3D_SetBufferVolume(rngSound3DHandle,volume); return; } int __cdecl lego::snd::SFX_Random_GetBufferVolume(SFX_ID sfxID) { int rngSound3DHandle; rngSound3DHandle = SFX_Random_GetSound3DHandle(sfxID); rngSound3DHandle = Sound3D_GetBufferVolume(rngSound3DHandle); return rngSound3DHandle; } int __cdecl lego::snd::SFX_Random_PlaySound3DOnContainer (Container *cont,SFX_ID sfxID,BOOL loop,BOOL onCont,Vector3F *opt_wPos) { IDirect3DRMFrame3 *frame; int playHandle; if (cont == NULL) { frame = NULL; } else { frame = gfx::Container_GetMasterFrame(cont); } playHandle = SFX_Random_PlaySound3DOnFrame(frame,sfxID,loop,onCont,opt_wPos); return playHandle; } int __cdecl lego::snd::SFX_Random_PlaySound3DOnFrame (IDirect3DRMFrame3 *frame,SFX_ID sfxID,BOOL loop,BOOL onFrame,Vector3F *opt_wPos) { int rngSound3DHandle; int playHandle; uint instCount; SFX_Instance *sfxInst; instCount = globs::sfxGlobs.sfxInstanceCount; if (((byte)globs::sfxGlobs.flags & SFX_GLOB_FLAG_QUEUEMODE) == 0) { if ((sfxID != SFX_NULL) && (((byte)globs::sfxGlobs.flags & SFX_GLOB_FLAG_SOUNDON) != 0)) { rngSound3DHandle = SFX_Random_GetSound3DHandle(sfxID); if (rngSound3DHandle != 0) { if (onFrame != 0) { playHandle = Sound3D_Play2(Sound3DPlay_OnFrame,frame,rngSound3DHandle,loop,NULL); return playHandle; } playHandle = Sound3D_Play2(Sound3DPlay_OnPos,NULL,rngSound3DHandle,loop,opt_wPos); return playHandle; } } } else { if (globs::sfxGlobs.sfxInstanceCount < 10) { sfxInst = globs::sfxGlobs.sfxInstanceTable + globs::sfxGlobs.sfxInstanceCount; globs::sfxGlobs.sfxInstanceCount = globs::sfxGlobs.sfxInstanceCount + 1; sfxInst->sampleIndex = sfxID; globs::sfxGlobs.sfxInstanceTable[instCount].frame = frame; globs::sfxGlobs.sfxInstanceTable[instCount].flags = ((onFrame & 1U) << 1 | loop & 1U) << 1 | globs::sfxGlobs.sfxInstanceTable[instCount].flags & ~(SFX_INSTANCE_FLAG_LOOPING|SFX_INSTANCE_FLAG_ONFRAME) | SFX_INSTANCE_FLAG_SOUND3D; if (opt_wPos != NULL) { globs::sfxGlobs.sfxInstanceTable[instCount].position.x = opt_wPos->x; globs::sfxGlobs.sfxInstanceTable[instCount].position.y = opt_wPos->y; globs::sfxGlobs.sfxInstanceTable[instCount].position.z = opt_wPos->z; return 0; } } } return 0; } float10 __cdecl lego::snd::SFX_Random_GetSamplePlayTime(SFX_ID sfxID) { int rngSound3DHandle; float10 playTime; rngSound3DHandle = SFX_Random_GetSound3DHandle(sfxID); if (rngSound3DHandle != 0) { playTime = Sound3D_GetSamplePlayTime(rngSound3DHandle); return playTime; } return (float10)0.0; } void __cdecl lego::snd::SFX_Sound3D_StopSound(int sound3DHandle) { Sound3D_StopSound(sound3DHandle); return; } void __cdecl lego::snd::SFX_Update(float elapsed) { BOOL origQueueMode; uint uVar1; SFX_ID *pSVar2; SoundMode *pSVar3; uint i; SFX_ID *pSVar4; SoundMode *pSVar5; origQueueMode = SFX_IsQueueMode(); globs::sfxGlobs.globalSampleDuration = globs::sfxGlobs.globalSampleDuration - elapsed; SFX_SetQueueMode(FALSE,FALSE); i = 0; if (globs::sfxGlobs.soundQueueCount_2 != 0) { pSVar2 = globs::sfxGlobs.soundQueueSFXTable_2; do { SFX_Random_PlaySoundNormal(*pSVar2,pSVar2[10]); i += 1; pSVar2 = pSVar2 + 1; } while (i < globs::sfxGlobs.soundQueueCount_2); } if (origQueueMode != 0) { SFX_SetQueueMode_AndFlush(TRUE); } // std::memcpy(globals::g_SoundQueueIndexes_Unk2_TABLE, // globals::g_SoundQueueIndexes_Unk1_TABLE, // globals::g_SoundQueue_Unk1_COUNT * sizeof(int)); pSVar2 = globs::sfxGlobs.soundQueueSFXTable_1; pSVar4 = globs::sfxGlobs.soundQueueSFXTable_2; for (uVar1 = globs::sfxGlobs.soundQueueCount_1; uVar1 != 0; uVar1 -= 1) { *pSVar4 = *pSVar2; pSVar2 = pSVar2 + 1; pSVar4 = pSVar4 + 1; } // globals::g_SoundQueue_Unk2_COUNT = globals::g_SoundQueue_Unk1_COUNT; // // std::memcpy(globals::g_SoundQueueModes_Unk2_TABLE, // globals::g_SoundQueueModes_Unk1_TABLE, // globals::g_SoundQueue_Unk1_COUNT * sizeof(int)); pSVar3 = globs::sfxGlobs.soundQueueModesTable_1; pSVar5 = globs::sfxGlobs.soundQueueModesTable_2; for (uVar1 = globs::sfxGlobs.soundQueueCount_1; globs::sfxGlobs.soundQueueCount_2 = globs::sfxGlobs.soundQueueCount_1, uVar1 != 0; uVar1 -= 1) { *pSVar5 = *pSVar3; pSVar3 = pSVar3 + 1; pSVar5 = pSVar5 + 1; } globs::sfxGlobs.soundQueueCount_1 = 0; SFX_Sound3D_Update(); return; } // This entire function is Sound3D_Update() inlined. void __cdecl lego::snd::SFX_Sound3D_Update(void) { Sound3D_SoundRecord *pSVar1; uint in_ECX; Sound3D_SoundRecord *pSVar2; IDirect3DRMFrame3 **ppIVar3; uint uStack4; pSVar2 = globs::sound3DGlobs.soundRecord; ppIVar3 = globs::sound3DGlobs.updateFrameList; uStack4 = in_ECX; do { if (*ppIVar3 != NULL) { Sound3D_SoundCallback(*ppIVar3,NULL,0.0); } ppIVar3 = ppIVar3 + 1; } while (ppIVar3 < &globs::sound3DGlobs.reserved1); if (pSVar2 != NULL) { do { pSVar1 = pSVar2->next; (*(code *)pSVar2->soundBuff->lpVtbl->GetStatus)(pSVar2->soundBuff,&uStack4); if ((uStack4 & 1) == 0) { Sound3D_RemoveSound(pSVar2->frame,pSVar2->sound3DBuff); } pSVar2 = pSVar1; } while (pSVar1 != NULL); } Sound3D_Stream_CheckPosition(0); Sound3D_Stream_CheckPosition(1); return; } void __cdecl lego::snd::SFX_SetSoundOn(BOOL soundOn,BOOL stopAll) { if (soundOn != 0) { globs::sfxGlobs.flags = globs::sfxGlobs.flags | SFX_GLOB_FLAG_SOUNDON; return; } globs::sfxGlobs.flags &= ~SFX_GLOB_FLAG_SOUNDON; if (stopAll != 0) { Sound3D_StopAllSounds(); } globs::sfxGlobs.globalSampleSFXType = SFX_NULL; return; } void __cdecl lego::snd::SFX_SetSoundOn_AndStopAll(BOOL soundOn) { SFX_SetSoundOn(soundOn,TRUE); return; } BOOL __cdecl lego::snd::SFX_IsQueueMode(void) { return globs::sfxGlobs.flags & SFX_GLOB_FLAG_QUEUEMODE; } void __cdecl lego::snd::SFX_SetQueueMode_AndFlush(BOOL on) { SFX_SetQueueMode(on,TRUE); return; } void __cdecl lego::snd::SFX_SetQueueMode(BOOL on,BOOL flushQueued) { SFX_InstanceFlags SVar1; SFX_InstanceFlags *pSVar2; uint i; if (on != 0) { globs::sfxGlobs.flags = globs::sfxGlobs.flags | SFX_GLOB_FLAG_QUEUEMODE; return; } globs::sfxGlobs.flags &= ~SFX_GLOB_FLAG_QUEUEMODE; if (flushQueued != 0) { i = 0; if (globs::sfxGlobs.sfxInstanceCount != 0) { pSVar2 = &globs::sfxGlobs.sfxInstanceTable[0].flags; do { SVar1 = *pSVar2; if ((SVar1 & SFX_INSTANCE_FLAG_SOUND3D) == SFX_INSTANCE_FLAG_NONE) { SFX_Random_PlaySoundNormal(pSVar2[-5],(int)(SVar1 << 0x1e) >> 0x1f); } else { SFX_Random_PlaySound3DOnFrame ((IDirect3DRMFrame3 *)pSVar2[-4],pSVar2[-5],(int)(SVar1 << 30) >> 31, (int)(SVar1 << 29) >> 31,(Vector3F *)(pSVar2 + -3)); } i += 1; pSVar2 = pSVar2 + 6; } while (i < globs::sfxGlobs.sfxInstanceCount); } globs::sfxGlobs.sfxInstanceCount = 0; } return; } BOOL __cdecl lego::snd::SFX_IsSoundOn(void) { return globs::sfxGlobs.flags & SFX_GLOB_FLAG_SOUNDON; } BOOL __cdecl lego::effect::Smoke_Initialise(void) { globs::smokeGlobs.firstSmoke = NULL; globs::smokeGlobs.lastSmoke = NULL; globs::smokeGlobs.textureCount = 0; return TRUE; } void __cdecl lego::effect::Smoke_LoadTextures(char *dirname,char *basename,uint textureCount) { Container_Texture *texture; uint i; Container_Texture **pTexture; char buffBmp [260]; char buffDir [260]; i = 0; globs::smokeGlobs.textureCount = textureCount; if (textureCount != 0) { // pTexture = smokeGlobs.textureList; pTexture = (Container_Texture **)&globs::smokeGlobs; do { std::sprintf(buffDir,"%s\\",dirname); std::sprintf(buffBmp,"%s%i.bmp",basename,i); texture = gfx::Mesh_LoadTexture(buffDir,buffBmp,NULL,NULL); *pTexture = texture; i += 1; pTexture = pTexture + 1; } while (i < textureCount); } return; } // thickness: a range of (0.0f,1.0f], which simply determines the number of smoke groups (clouds?). // 0 is invalid. 0.1 -> 1 cloud, 0.9 -> 9 clouds, 1.0 -> 10 clouds (max). // // Valid Smoke_Type modes: 0, 1, 2 Smoke * __cdecl lego::effect::Smoke_CreateSmokeArea (Container *optin_attachedCont,uint bx,uint by,Vector3F *dirVec,float r,float g,float b, float thickness,float animSpeed,Smoke_Type smokeType,uint randomness,SFX_ID sfxID) { Smoke_Group *pSVar1; float fVar2; float fVar3; float fVar4; Smoke *smoke; Map3D *map; Container *root; Container *cont; Mesh *pMVar5; D3DRMGroupIndex groupID; uint uVar6; int iVar7; Smoke *pSVar8; uint uVar9; uint uVar10; float10 fVar11; ulonglong uVar12; longlong lVar13; Vector3F worldPos; uint faceData [6]; uVar10 = 0; faceData[0] = 0; faceData[1] = 3; faceData[2] = 2; faceData[3] = 2; faceData[4] = 1; faceData[5] = 0; smoke = (Smoke *)io::Mem_Alloc(0x2a8); // std::memset(smoke, 0, sizeof(Smoke)); pSVar8 = smoke; for (iVar7 = 0xaa; iVar7 != 0; iVar7 += -1) { pSVar8->groupList[0].used = 0; pSVar8 = (Smoke *)&pSVar8->groupList[0].randVec; } if ((smokeType == Smoke_Type_Looping) || (smokeType == Smoke_Type_Dissipate)) { map = lrr::Lego_GetMap(); root = gfx::Container_GetRoot(); uVar12 = __ftol((float10)map->blockSize * (float10)0.6); lego::map::Map3D_BlockToWorldPos(map,bx,by,&worldPos.x,&worldPos.y); fVar2 = (float)(uVar12 & 0xffffffff) * 0.5; worldPos.x = ((float)(((ulonglong)randomness % 4254) % (uVar12 & 0xffffffff)) - fVar2) + worldPos.x; worldPos.y = ((float)(((ulonglong)randomness % 1515) % (uVar12 & 0xffffffff)) - fVar2) + worldPos.y; fVar11 = lego::map::Map3D_GetWorldZ(map,worldPos.x,worldPos.y); worldPos.z = (float)fVar11; cont = gfx::Container_Create(root); smoke->cont = cont; gfx::Container_SetPosition(cont,NULL,worldPos.x,worldPos.y,worldPos.z); smoke->flags = SMOKE_FLAG_OWNCONTAINER; (smoke->sfxOrigin).x = worldPos.x; (smoke->sfxOrigin).y = worldPos.y; (smoke->sfxOrigin).z = worldPos.z; // 1-in-4 chance for SFX: `(randomness % 4) == 0`. if ((randomness & 3) == 0) { smoke->sfxID = sfxID; } } else { if (smokeType == Smoke_Type_Attach) { smoke->flags = SMOKE_FLAG_BROKEN_UNK_4; smoke->cont = optin_attachedCont; } } (smoke->dirVec).x = dirVec->x; fVar3 = dirVec->y; (smoke->dirVec).y = fVar3; fVar4 = dirVec->z; (smoke->dirVec).z = fVar4; fVar2 = (smoke->dirVec).x; fVar2 = 1.0 / SQRT(fVar2 * fVar2 + fVar4 * fVar4 + fVar3 * fVar3); (smoke->dirVec).x = fVar2 * (smoke->dirVec).x; (smoke->dirVec).y = fVar2 * (smoke->dirVec).y; (smoke->dirVec).z = fVar2 * (smoke->dirVec).z; (smoke->colour).red = r; (smoke->colour).green = g; (smoke->colour).blue = b; if (smokeType == Smoke_Type_Dissipate) { smoke->groupCount = 4; smoke->numRepeats = 0; smoke->flags = smoke->flags | SMOKE_FLAG_REPEATCOUNT; smoke->animSpeed = 2.0; } else { // FIXME: Change to && comparison for proper range check. if (((ushort)((ushort)(thickness < 0.0) << 8 | (ushort)(thickness == 0.0) << 0xe) == 0) || (thickness < 1.0)) { lVar13 = __ftol((float10)thickness * (float10)10.0); smoke->groupCount = (uint)lVar13; } else { smoke->groupCount = 10; } smoke->animSpeed = animSpeed; } pMVar5 = gfx::Mesh_CreateOnFrame (smoke->cont->activityFrame,Smoke_MeshRenderCallback,0x4800,smoke, Mesh_Type_Norm); smoke->mesh = pMVar5; if (smoke->groupCount != 0) { do { groupID = gfx::Mesh_AddGroup(smoke->mesh,4,2,3,faceData); pSVar1 = smoke->groupList + groupID; gfx::Mesh_SetGroupTexture (smoke->mesh,groupID, globs::smokeGlobs.textureList[uVar10 % globs::smokeGlobs.textureCount]); gfx::Mesh_SetGroupColour(smoke->mesh,groupID,r,g,b,Mesh_Colour_Diffuse); gfx::Mesh_SetGroupColour(smoke->mesh,groupID,r * 0.2,g * 0.2,b * 0.2,Mesh_Colour_Emissive); gfx::Mesh_HideGroup(smoke->mesh,groupID,TRUE); uVar6 = std::rand(); uVar9 = (int)uVar6 >> 0x1f; // preserve-sign modulus: // -5=-1, -4=0, -3=-3, -2=-2, -1=-1, 0=0, 1=1, 2=2, 3=3, 4=0, 5=1, ... // // Signed right shift will take the MSB 1's with it: (-1 >> 31 == -1), (-2 >> 31 == -1) // Basically, if negative, then we have a full uint32 mask: 0xffffffff, otherwise 0. pSVar1->float_28 = (float)(((uVar6 ^ uVar9) - uVar9 & 3 ^ uVar9) - uVar9) - -6.0; uVar6 = std::rand(); uVar9 = (int)uVar6 >> 0x1f; fVar2 = ((float)(((uVar6 ^ uVar9) - uVar9 & 3 ^ uVar9) - uVar9) + pSVar1->float_28) - -2.0; pSVar1->float_2c = fVar2; if ((*(byte *)&smoke->flags & SMOKE_FLAG_REPEATCOUNT) == 0) { // /= 2.0f; pSVar1->float_28 = pSVar1->float_28 * 0.5; } else { // *= 2.0f; pSVar1->float_2c = fVar2 + fVar2; } uVar10 += 1; } while (uVar10 < smoke->groupCount); } smoke->newSmokeTimer = 0.0; if (smokeType != Smoke_Type_Dissipate) { // JUST WHAT IS THIS OUTER `FOR 0-9` LOOP DOING??? // // Is the second inner loop really meant to be in this outer loop?? // This probably has to do with whatever jank is happening with `smoke->timer_258`. iVar7 = 10; do { // WARNING: Smoke_Group_Show changes `smoke->timer_258`. So we can't be assured that // This condition will always succeed. if ((ushort)((ushort)(smoke->newSmokeTimer < 0.0) << 8 | (ushort)(smoke->newSmokeTimer == 0.0) << 0xe) != 0) { uVar10 = 0; pSVar8 = smoke; if (smoke->groupCount != 0) { do { if (pSVar8->groupList[0].used == 0) { Smoke_Group_Show(smoke,uVar10); break; } uVar10 += 1; pSVar8 = (Smoke *)(pSVar8->groupList + 1); } while (uVar10 < smoke->groupCount); } } uVar10 = 0; // Some kind of change to counteract Smoke_Group_Show or Smoke_Group_Update??? smoke->newSmokeTimer = smoke->newSmokeTimer - 5.0; pSVar8 = smoke; if (smoke->groupCount != 0) { do { if (pSVar8->groupList[0].used != 0) { Smoke_Group_Update(smoke,uVar10,5.0); } uVar10 += 1; pSVar8 = (Smoke *)(pSVar8->groupList + 1); } while (uVar10 < smoke->groupCount); } iVar7 += -1; } while (iVar7 != 0); } smoke->previous = globs::smokeGlobs.lastSmoke; if (globs::smokeGlobs.firstSmoke != NULL) { (globs::smokeGlobs.lastSmoke)->next = smoke; globs::smokeGlobs.lastSmoke = smoke; return smoke; } globs::smokeGlobs.firstSmoke = smoke; globs::smokeGlobs.lastSmoke = smoke; return smoke; } void __cdecl lego::effect::Smoke_RemoveAll(void) { Smoke *smoke; Smoke *smokeNext; smoke = globs::smokeGlobs.firstSmoke; if (globs::smokeGlobs.firstSmoke != NULL) { do { smokeNext = smoke->next; Smoke_Remove(smoke,smoke->cont); smoke = smokeNext; } while (smokeNext != NULL); } globs::smokeGlobs.firstSmoke = NULL; return; } void __cdecl lego::effect::Smoke_Remove(Smoke *smoke,Container *attachedCont) { if ((*(byte *)&smoke->flags & SMOKE_FLAG_OWNCONTAINER) == 0) { // Remove mesh from the passed attached container. // NOTE: attachedCont is always passed `smoke->cont`. gfx::Mesh_Remove(smoke->mesh,attachedCont->activityFrame); } else { gfx::Mesh_Remove(smoke->mesh,smoke->cont->activityFrame); gfx::Container_Remove(smoke->cont); } if (globs::smokeGlobs.lastSmoke == smoke) { globs::smokeGlobs.lastSmoke = smoke->previous; if (globs::smokeGlobs.lastSmoke == NULL) { globs::smokeGlobs.firstSmoke = globs::smokeGlobs.lastSmoke; // BUG: SFX_Sound3D_StopSound(smoke->soundHandle) isn't called during this return!!! io::Mem_Free(smoke); return; } } // Splice our smoke item out of the doubly-linked list. if (smoke->next != NULL) { smoke->next->previous = smoke->previous; if (smoke->next->previous == NULL) { globs::smokeGlobs.firstSmoke = smoke->next; } } if (smoke->previous != NULL) { smoke->previous->next = smoke->next; } if (smoke->sound3DPlayHandle != 0) { snd::SFX_Sound3D_StopSound(smoke->sound3DPlayHandle); } io::Mem_Free(smoke); return; } void __cdecl lego::effect::Smoke_HideAll(BOOL hide) { Smoke *smoke; Smoke **pSmokeNext; smoke = globs::smokeGlobs.firstSmoke; if (globs::smokeGlobs.firstSmoke != NULL) { do { Smoke_Hide(smoke,hide); pSmokeNext = &smoke->next; smoke = *pSmokeNext; } while (*pSmokeNext != NULL); } return; } void __cdecl lego::effect::Smoke_Hide(Smoke *smoke,BOOL hide) { gfx::Mesh_Hide(smoke->mesh,hide); if (hide != 0) { smoke->flags = smoke->flags | SMOKE_FLAG_HIDDEN; return; } smoke->flags = smoke->flags & ~SMOKE_FLAG_HIDDEN; return; } void __cdecl lego::effect::Smoke_Update(float elapsedGame) { SmokeFlags SVar1; int playHandle; uint groupID; Smoke *pSVar2; Smoke *smoke; bool noGroupsUsed; Smoke *smokeNext; smoke = globs::smokeGlobs.firstSmoke; if (globs::smokeGlobs.firstSmoke != NULL) { do { smokeNext = smoke->next; noGroupsUsed = true; if (((*(byte *)&smoke->flags & SMOKE_FLAG_SFXFAILED) == 0) && (smoke->sound3DPlayHandle == 0)) { if (smoke->sfxID != SFX_NULL) { // Start looping sound, so this will only be called once per smoke until Smoke_Remove. playHandle = snd::SFX_Random_PlaySound3DOnContainer (NULL,smoke->sfxID,TRUE,FALSE,&smoke->sfxOrigin); smoke->sound3DPlayHandle = playHandle; } if (smoke->sound3DPlayHandle == 0) { // SFX failed to play, but we don't want to try playing it again. // This flag usage is really awkward, in that its ONLY used to // prevent the outer if statement condition from succeeding. smoke->flags = smoke->flags | SMOKE_FLAG_SFXFAILED; } } SVar1 = smoke->flags; if ((SVar1 & SMOKE_FLAG_HIDDEN) == SMOKE_FLAG_NONE) { if (((SVar1 & SMOKE_FLAG_REPEATCOUNT) == SMOKE_FLAG_NONE) || ((SVar1 & SMOKE_FLAG_REPEATEND) == SMOKE_FLAG_NONE)) { if ((ushort)((ushort)(smoke->newSmokeTimer < 0.0) << 8 | (ushort)(smoke->newSmokeTimer == 0.0) << 0xe) != 0) { groupID = 0; pSVar2 = smoke; if (smoke->groupCount != 0) { do { if (pSVar2->groupList[0].used == 0) { Smoke_Group_Show(smoke,groupID); break; } groupID += 1; pSVar2 = (Smoke *)(pSVar2->groupList + 1); } while (groupID < smoke->groupCount); } } smoke->newSmokeTimer = smoke->newSmokeTimer - elapsedGame; } groupID = 0; pSVar2 = smoke; if (smoke->groupCount != 0) { do { if (pSVar2->groupList[0].used != 0) { Smoke_Group_Update(smoke,groupID,elapsedGame); noGroupsUsed = false; } groupID += 1; pSVar2 = (Smoke *)(pSVar2->groupList + 1); } while (groupID < smoke->groupCount); } if ((((smoke->flags & SMOKE_FLAG_REPEATCOUNT) != SMOKE_FLAG_NONE) && ((smoke->flags & SMOKE_FLAG_REPEATEND) != SMOKE_FLAG_NONE)) && (noGroupsUsed)) { Smoke_Remove(smoke,smoke->cont); } } smoke = smokeNext; } while (smokeNext != NULL); } return; } void __cdecl lego::effect::Smoke_Group_Show(Smoke *smoke,uint groupID) { Smoke_Group *pSVar1; float fVar2; int iVar3; Vector3F local_18; Vector3F local_c; pSVar1 = smoke->groupList + groupID; if ((smoke->flags & SMOKE_FLAG_REPEATCOUNT) != SMOKE_FLAG_NONE) { if (smoke->numRepeats == 3) { // This flags operation has no effect because of the `smoke->flags = SMOKE_FLAG_UNK_4;` // assignment halfway down the function. smoke->flags = smoke->flags | SMOKE_FLAG_REPEATEND; } smoke->numRepeats = smoke->numRepeats + 1; } pSVar1->used = TRUE; gfx::Mesh_HideGroup(smoke->mesh,groupID,FALSE); math::Maths_Vector3DRandom(&local_18); // vector_4 = { [ 0.00, 0.17], [ 0.00, 0.17], [-1.00,-0.83] }; local_18.z = -ABS(local_18.z) * 0.17 - 0.83; (pSVar1->randVec).x = local_18.x * 0.17; (pSVar1->randVec).y = local_18.y * 0.17; (pSVar1->randVec).z = local_18.z; local_18.z = (smoke->dirVec).z + local_18.z; fVar2 = -smoke->animSpeed / local_18.z; local_18.z = fVar2 * local_18.z; local_18.x = fVar2 * ((smoke->dirVec).x + local_18.x * 0.17); local_18.y = fVar2 * ((smoke->dirVec).y + local_18.y * 0.17); // Was this meant to be an or-equals instead of an assignment??? smoke->flags = SMOKE_FLAG_BROKEN_UNK_4; gfx::Container_GetPosition(smoke->cont,NULL,&local_c); (pSVar1->position).x = local_c.x; pSVar1->timer_30 = 0.0; pSVar1->timerUp_38 = 0.0; (pSVar1->position).y = local_c.y; (pSVar1->position).z = local_c.z; (pSVar1->moveVec).x = local_18.x; (pSVar1->moveVec).y = local_18.y; (pSVar1->moveVec).z = local_18.z; iVar3 = std::rand(); pSVar1->int_34 = iVar3 % 0x1e + 0x28; smoke->newSmokeTimer = (0.5 / smoke->animSpeed) * pSVar1->float_2c; return; } void __cdecl lego::effect::Smoke_Group_Update(Smoke *smoke,uint groupID,float elapsedGame) { float fVar1; float fVar2; float zElapsed; Smoke_Group *sgroup; fVar1 = smoke->groupList[groupID].moveVec.y; sgroup = smoke->groupList + groupID; fVar2 = (sgroup->moveVec).z * elapsedGame; (sgroup->position).x = smoke->groupList[groupID].moveVec.x * elapsedGame + (sgroup->position).x; (sgroup->position).y = (sgroup->position).y + fVar1 * elapsedGame; (sgroup->position).z = (sgroup->position).z + fVar2; zElapsed = ABS(fVar2) + sgroup->timerUp_38; sgroup->timerUp_38 = zElapsed; if ((float)sgroup->int_34 <= zElapsed) { sgroup->used = FALSE; gfx::Mesh_HideGroup(smoke->mesh,groupID,TRUE); return; } // Fade away as smoke rises. sgroup->timer_30 = elapsedGame + sgroup->timer_30; gfx::Mesh_SetGroupMaterialValues (smoke->mesh,groupID,0.7 - (zElapsed / (float)sgroup->int_34) * 0.7,Mesh_Colour_Alpha); return; } void __cdecl lego::effect::Smoke_MeshRenderCallback(Mesh *mesh,Smoke *data,Viewport *view) { Container *light; Smoke *smoke; uint groupID; Vector3F lightPos; light = lrr::Lego_GetCurrentViewLight(); gfx::Container_GetPosition(light,NULL,&lightPos); groupID = 0; smoke = data; if (data->groupCount != 0) { do { if (smoke->groupList[0].used != 0) { Smoke_Group_MeshRenderCallback(data,groupID,view,&lightPos); } groupID += 1; smoke = (Smoke *)(smoke->groupList + 1); } while (groupID < data->groupCount); } return; } void __cdecl lego::effect::Smoke_Group_MeshRenderCallback (Smoke *smoke,uint groupID,Viewport *view,Vector3F *lightPos) { Container *cont; Vector3F local_80; Vector3F perpendicular; Vector3F vertPoses [4]; Vector3F viewDir; Point2F textCoords [4]; Vector3F viewUp; float scalar2; float baseScalar; float scalar1; Smoke_Group *sgroup; textCoords[0].x = 0.0; textCoords[0].y = 1.0; textCoords[1].x = 0.0; textCoords[1].y = 0.0; textCoords[2].x = 1.0; textCoords[2].y = 0.0; textCoords[3].x = 1.0; textCoords[3].y = 1.0; sgroup = smoke->groupList + groupID; cont = lego::view::Viewport_GetCamera(view); gfx::Container_GetOrientation(cont,NULL,&viewDir,&viewUp); // Vector3F local_74 = { dir.y, -dir.x, 0.0f }; // Perpendicular of 2D vector. perpendicular.y = viewDir.x * -1.0 - 0.0; perpendicular.x = 0.0 - viewDir.y * -1.0; local_80.x = 0.0; local_80.y = 0.0; local_80.z = -1.0; perpendicular.z = 0.0; // 0.3f and 0.7f are lazy radians(?) // // if (dir.z > 0.3f) if ((ushort)((ushort)(viewDir.z < 0.3) << 8 | (ushort)(viewDir.z == 0.3) << 0xe) == 0) { // SIDE EFFECTS: perpendicular (axis) is normalised by internal D3DRMVectorRotate call. math::Maths_Vector3DRotate(&local_80,&local_80,&perpendicular,0.7); } baseScalar = sgroup->timerUp_38 / (float)sgroup->int_34 - -1.0; scalar1 = sgroup->float_28 * baseScalar; scalar2 = sgroup->float_2c * baseScalar; perpendicular.x = scalar1 * perpendicular.x; perpendicular.y = scalar1 * perpendicular.y; perpendicular.z = scalar1 * perpendicular.z; vertPoses[0].x = (sgroup->position).x + perpendicular.x; vertPoses[1].x = (sgroup->position).x - perpendicular.x; vertPoses[0].y = (sgroup->position).y + perpendicular.y; vertPoses[1].y = (sgroup->position).y - perpendicular.y; local_80.x = scalar2 * local_80.x; vertPoses[0].z = (sgroup->position).z + perpendicular.z; vertPoses[1].z = (sgroup->position).z - perpendicular.z; local_80.y = scalar2 * local_80.y; local_80.z = scalar2 * local_80.z; vertPoses[2].x = vertPoses[1].x - local_80.x; vertPoses[3].x = vertPoses[0].x - local_80.x; vertPoses[2].y = vertPoses[1].y - local_80.y; vertPoses[3].y = vertPoses[0].y - local_80.y; vertPoses[2].z = vertPoses[1].z - local_80.z; vertPoses[3].z = vertPoses[0].z - local_80.z; gfx::Mesh_SetVertices_PointNormalAt(smoke->mesh,groupID,0,4,vertPoses,lightPos,textCoords); return; } void __cdecl lego::game::SpiderWeb_Initialise(Lego_Level *level) { uint uVar1; int iVar2; SpiderWeb_Block *pSVar3; globs::spiderwebGlobs.webBlocks = (SpiderWeb_Block *)io::Mem_Alloc(level->width * level->height * 0xc); if (globs::spiderwebGlobs.webBlocks != NULL) { pSVar3 = globs::spiderwebGlobs.webBlocks; for (uVar1 = level->width * level->height * 3 & 0x3fffffff; uVar1 != 0; uVar1 -= 1) { pSVar3->object = NULL; pSVar3 = (SpiderWeb_Block *)&pSVar3->health; } for (iVar2 = 0; iVar2 != 0; iVar2 += -1) { *(undefined *)&pSVar3->object = 0; pSVar3 = (SpiderWeb_Block *)((int)&pSVar3->object + 1); } } globs::spiderwebGlobs.level = level; return; } void __cdecl lego::game::SpiderWeb_Shutdown(void) { if (globs::spiderwebGlobs.webBlocks != NULL) { io::Mem_Free(globs::spiderwebGlobs.webBlocks); globs::spiderwebGlobs.webBlocks = NULL; } return; } void __cdecl lego::game::SpiderWeb_Restart(Lego_Level *level) { SpiderWeb_Shutdown(); SpiderWeb_Initialise(level); return; } BOOL __cdecl lego::game::SpiderWeb_SpawnAt(uint bx,uint by) { BOOL BVar1; LegoObject *webObj; Point2F local_8; uint by_00; by_00 = by; if ((globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].flags & BLOCKWEB_FLAG_ACTIVE) == BLOCKWEB_FLAG_NONE) { BVar1 = SpiderWeb_GetAngle(bx,by,(float *)&by); if (BVar1 != 0) { lego::map::Map3D_BlockToWorldPos ((globs::spiderwebGlobs.level)->map,bx,by_00,&local_8.x,&local_8.y); webObj = LegoObject_CreateInWorld (globs::legoGlobs.contSpiderWeb,LegoObject_SpiderWeb,0,0,local_8.x, local_8.y,(float)by); SpiderWeb_Add(bx,by_00,webObj); (globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by_00 + bx].object)-> flags1 = (globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by_00 + bx]. object)->flags1 | LIVEOBJ1_EXPANDING; gfx::Container_SetActivity ((globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by_00 + bx] .object)->other,"Expand"); gfx::Container_SetAnimationTime ((globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by_00 + bx] .object)->other,0.0); return TRUE; } } return 0; } void __cdecl lego::game::SpiderWeb_Add(int bx,int by,LegoObject *webObj) { globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].object = webObj; globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].flags = globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].flags | BLOCKWEB_FLAG_ACTIVE; // 100.0f globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].health = (float)&DAT_42c80000; return; } BOOL __cdecl lego::game::SpiderWeb_GetAngle(int bx,int by,float *out_theta) { int idx; Lego_Block *blocks; uint width; width = (globs::spiderwebGlobs.level)->width; blocks = (globs::spiderwebGlobs.level)->blocks; idx = by * width + bx; if ((*(byte *)&blocks[idx].flags1 & BLOCK1_FLOOR) == 0) { return 0; } if (((*(byte *)&(blocks + idx)[1].flags1 & BLOCK1_WALL) == 0) || ((*(byte *)&(blocks + idx)[-1].flags1 & BLOCK1_WALL) == 0)) { if ((*(byte *)&blocks[(by + 1) * width + bx].flags1 & BLOCK1_WALL) == 0) { return 0; } if ((*(byte *)&blocks[(by + -1) * width + bx].flags1 & BLOCK1_WALL) == 0) { return 0; } if (out_theta != NULL) { *out_theta = 0.0; } } else { if (out_theta != NULL) { *out_theta = 1.570796; return TRUE; } } return TRUE; } BOOL __cdecl lego::game::SpiderWeb_CheckCollision(LegoObject *liveObj) { LegoObject *liveObj_00; BOOL BVar1; uint local_24; Point2F local_20; Point2F local_18; undefined4 local_10; Point2F local_c; undefined4 local_4; liveObj_00 = liveObj; BVar1 = LegoObject_GetBlockPos(liveObj,(int *)&local_24,(int *)&liveObj); if (BVar1 != 0) { if ((globs::spiderwebGlobs.webBlocks [(globs::spiderwebGlobs.level)->width * (int)liveObj + local_24].flags & BLOCKWEB_FLAG_ACTIVE) != BLOCKWEB_FLAG_NONE) { lego::map::Map3D_BlockToWorldPos ((globs::spiderwebGlobs.level)->map,local_24,(uint)liveObj,&local_c.x,&local_c.y); LegoObject_GetFaceDirection (globs::spiderwebGlobs.webBlocks [(globs::spiderwebGlobs.level)->width * (int)liveObj + local_24].object,&local_20); local_18.x = local_20.x; local_18.y = local_20.y; local_4 = 0; local_10 = 0; BVar1 = tools::Weapon_LegoObject_Collision_FUN_00470520(liveObj_00,&local_c,&local_18,0); if (BVar1 != 0) { liveObj_00->flags1 = liveObj_00->flags1 | LIVEOBJ1_CAUGHTINWEB; (globs::spiderwebGlobs.webBlocks [(globs::spiderwebGlobs.level)->width * (int)liveObj + local_24].object)->flags1 = (globs::spiderwebGlobs.webBlocks [(globs::spiderwebGlobs.level)->width * (int)liveObj + local_24].object)->flags1 | LIVEOBJ1_CAUGHTINWEB; return TRUE; } } } return 0; } BOOL __cdecl lego::game::SpiderWeb_Update(float elapsedGame) { BOOL BVar1; BVar1 = LegoObject_RunThroughListsSkipUpgradeParts(SpiderWeb_LiveObjectCallback,&elapsedGame); return BVar1; } BOOL __cdecl lego::game::SpiderWeb_LiveObjectCallback(LegoObject *liveObj,float *pElapsedGame) { LegoObject *pLVar1; BOOL BVar2; int idx; uint weaponID; float10 damage; LegoObject *liveObj_00; int local_4; SpiderWeb_Block *webBlocks; pLVar1 = liveObj; if (liveObj->type == LegoObject_SpiderWeb) { // Remove inactive SpiderWebs LegoObject_GetBlockPos(liveObj,&local_4,(int *)&liveObj); if (((globs::spiderwebGlobs.webBlocks [(globs::spiderwebGlobs.level)->width * (int)liveObj + local_4].flags & BLOCKWEB_FLAG_ACTIVE) != BLOCKWEB_FLAG_NONE) && (BVar2 = SpiderWeb_GetAngle(local_4,(int)liveObj,NULL), BVar2 == 0)) { SpiderWeb_Remove(local_4,(int)liveObj); return 0; } } else { if ((liveObj->flags1 & LIVEOBJ1_CAUGHTINWEB) != LIVEOBJ1_NONE) { // Object already caught in web, damage web (and remove if health is zeroed) LegoObject_GetBlockPos(liveObj,&local_4,(int *)&liveObj); webBlocks = globs::spiderwebGlobs.webBlocks; idx = (globs::spiderwebGlobs.level)->width * (int)liveObj + local_4; // if false, object is not longer in a block with spider webs if ((globs::spiderwebGlobs.webBlocks[idx].flags & BLOCKWEB_FLAG_ACTIVE) != BLOCKWEB_FLAG_NONE) { liveObj_00 = pLVar1; weaponID = tools::Weapon_GetWeaponIDByName("SpiderWeb"); damage = tools::Weapon_GetDamageForObject(weaponID,liveObj_00); globs::spiderwebGlobs.webBlocks [(globs::spiderwebGlobs.level)->width * (int)liveObj + local_4].health = (float)((float10)webBlocks[idx].health - damage * (float10)*pElapsedGame); if (0.0 <= globs::spiderwebGlobs.webBlocks [(globs::spiderwebGlobs.level)->width * (int)liveObj + local_4].health) { return 0; } SpiderWeb_Remove(local_4,(int)liveObj); } pLVar1->flags1 = pLVar1->flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP|LIVEOBJ1_RUNNINGAWAY| LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_SLIPPING|LIVEOBJ1_SCAREDBYPLAYER| LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING|LIVEOBJ1_CANTDO); return 0; } SpiderWeb_CheckCollision(liveObj); } return 0; } void __cdecl lego::game::SpiderWeb_Remove(int bx,int by) { int idx; (globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].object)->flags3 = (globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].object)-> flags3 | LIVEOBJ3_REMOVING; (globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].object)->flags1 = (globs::spiderwebGlobs.webBlocks[(globs::spiderwebGlobs.level)->width * by + bx].object)-> flags1 & (LIVEOBJ1_MOVING|LIVEOBJ1_LIFTING|LIVEOBJ1_TURNING|LIVEOBJ1_DRILLING| LIVEOBJ1_DRILLINGSTART|LIVEOBJ1_UNUSED_20|LIVEOBJ1_REINFORCING|LIVEOBJ1_TURNRIGHT| LIVEOBJ1_EXPANDING|LIVEOBJ1_GATHERINGROCK|LIVEOBJ1_CARRYING|LIVEOBJ1_UNK_800| LIVEOBJ1_GETTINGHIT|LIVEOBJ1_STORING|LIVEOBJ1_UNK_4000|LIVEOBJ1_WAITING| LIVEOBJ1_UNK_10000|LIVEOBJ1_ENTERING_WALLHOLE|LIVEOBJ1_CLEARING|LIVEOBJ1_PLACING| LIVEOBJ1_CRUMBLING|LIVEOBJ1_TELEPORTINGDOWN|LIVEOBJ1_TELEPORTINGUP| LIVEOBJ1_RUNNINGAWAY|LIVEOBJ1_REPAIRDRAINING|LIVEOBJ1_SLIPPING| LIVEOBJ1_SCAREDBYPLAYER|LIVEOBJ1_UNUSED_10000000|LIVEOBJ1_RESTING|LIVEOBJ1_EATING| LIVEOBJ1_CANTDO); idx = (globs::spiderwebGlobs.level)->width * by + bx; globs::spiderwebGlobs.webBlocks[idx].flags = globs::spiderwebGlobs.webBlocks[idx].flags & ~BLOCKWEB_FLAG_ACTIVE; return; } BOOL __cdecl lego::stats::Stats_Initialise(Config *config,char *gameName) { uint *puVar1; BoolTri *pBVar2; float fVar3; char *pcVar4; Config *prop; BOOL BVar5; uint uVar6; ObjectStats **ppOVar7; ObjectStats *pOVar8; SFX_ID SVar9; BoolTri BVar10; int iVar11; char **ppcVar12; uint uVar13; float10 fVar14; SFX_ID *pSVar15; LegoObject_Type objType; LegoObject_ID objIndex; char *local_144; uint local_140; BoolTri local_13c; char **local_138; char *local_134; char *local_130; char **local_12c; BoolTri local_128; char *local_124; float local_120; float local_11c; char *local_118; float local_114; float local_110; float local_10c; float local_108; float local_104; float local_100; float local_fc; float local_f8; float local_f4; float local_f0; float local_ec; SFX_ID local_e8; SFX_ID local_e4; SFX_ID local_e0; int local_dc; int local_d8; int local_d4; uint local_d0; undefined4 uStack204; char *local_c8 [32]; char *local_48; char *local_44 [4]; char *local_34; char *local_28; char *local_20; local_48 = NULL; ppcVar12 = local_44; for (iVar11 = 0x11; iVar11 != 0; iVar11 += -1) { *ppcVar12 = NULL; ppcVar12 = ppcVar12 + 1; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",0); for (prop = cfg::Config_FindArray(config,pcVar4); prop != NULL; prop = cfg::Config_GetNextItem(prop)) { local_128 = BOOL3_FALSE; local_13c = BOOL3_FALSE; local_140 = 0; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Levels",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Levels",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } local_134 = (char *)std::atoi(pcVar4); BVar5 = lrr::Lego_GetObjectByName(prop->key,&objType,&objIndex,NULL); if (BVar5 != 0) { if (globs::statsGlobs.objectStats[objType] == NULL) { uVar6 = lrr::Lego_GetObjectTypeIDCount(objType); ppOVar7 = (ObjectStats **)io::Mem_Alloc(uVar6 * 4); globs::statsGlobs.objectStats[objType] = ppOVar7; for (uVar6 &= 0x3fffffff; uVar6 != 0; uVar6 -= 1) { *ppOVar7 = NULL; ppOVar7 = ppOVar7 + 1; } for (iVar11 = 0; iVar11 != 0; iVar11 += -1) { *(undefined *)ppOVar7 = 0; ppOVar7 = (ObjectStats **)((int)ppOVar7 + 1); } } globs::statsGlobs.objectLevels[objType][objIndex] = (uint)local_134; uVar6 = (int)local_134 * 0x150; pOVar8 = (ObjectStats *)io::Mem_Alloc(uVar6); globs::statsGlobs.objectStats[objType][objIndex] = pOVar8; pOVar8 = globs::statsGlobs.objectStats[objType][objIndex]; for (uVar6 >>= 2; uVar6 != 0; uVar6 -= 1) { *(undefined4 *)pOVar8->unused_typeName = 0; pOVar8 = (ObjectStats *)(pOVar8->unused_typeName + 4); } for (iVar11 = 0; iVar11 != 0; iVar11 += -1) { pOVar8->unused_typeName[0] = '\0'; pOVar8 = (ObjectStats *)(pOVar8->unused_typeName + 1); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RouteSpeed",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_12c = local_c8; local_144 = NULL; local_130 = local_134; do { fVar14 = std::atof(*local_12c); *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + (int)local_144 + -4) = (float)fVar14; local_144 = (char *)((int)local_144 + 0x150); local_12c = local_12c + 1; local_130 = local_130 + -1; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"SoilDrillTime",0); local_34 = cfg::Config_GetStringValue(config,pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"LooseDrillTime",0); local_44[3] = cfg::Config_GetStringValue(config,pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"MedDrillTime",0); local_44[2] = cfg::Config_GetStringValue(config,pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"HardDrillTime",0); local_44[1] = cfg::Config_GetStringValue(config,pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"SeamDrillTime",0); local_28 = cfg::Config_GetStringValue(config,pcVar4); if (local_28 == NULL) { local_20 = NULL; } else { local_20 = util::Util_StrCpy(local_28); } local_12c = &local_48; local_114 = (float)(0x24 - (int)&local_48); local_120 = 2.522337e-44; do { pcVar4 = *local_12c; local_118 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = (char *)((int)local_114 + (int)local_12c); ppcVar12 = local_c8; local_130 = local_134; do { fVar14 = std::atof(*ppcVar12); ppcVar12 = ppcVar12 + 1; *(float *)(globs::statsGlobs.objectStats[objType][objIndex]->unused_typeName + (int)local_144) = (float)(fVar14 * (float10)25.0); local_144 = (char *)((int)local_144 + 0x150); local_130 = local_130 + -1; pcVar4 = local_118; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } local_12c = local_12c + 1; local_120 = (float)((int)local_120 + -1); } while (local_120 != 0.0); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"BuildingBase",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { local_144 = (char *)0xffffffff; } else { local_144 = (char *)game::Construction_GetBuildingBase(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CostCrystal",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CostCrystal",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } local_d8 = std::atoi(pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CostOre",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CostOre",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } local_d4 = std::atoi(pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CostRefinedOre",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CostRefinedOre",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } local_124 = (char *)std::atoi(pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TrackDist",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TrackDist",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_120 = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"AlertRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"AlertRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_114 = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CollHeight",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CollHeight",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_118 = (char *)(float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"HealthDecayRate",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"HealthDecayRate",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_110 = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"EnergyDecayRate",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"EnergyDecayRate",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_100 = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PickSphere",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PickSphere",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_130 = (char *)(float)fVar14; pSVar15 = &local_e0; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"DrillSound",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); BVar5 = snd::SFX_GetType(pcVar4,pSVar15); if (BVar5 == 0) { local_e0 = SFX_Drill; } pSVar15 = &local_e8; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"DrillFadeSound",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); BVar5 = snd::SFX_GetType(pcVar4,pSVar15); if (BVar5 == 0) { local_e8 = SFX_DrillFade; } pSVar15 = &local_e4; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"EngineSound",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); SVar9 = snd::SFX_GetType(pcVar4,pSVar15); if (SVar9 == SFX_NULL) { local_e4 = SVar9; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RestPercent",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RestPercent",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_10c = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CarryMinHealth",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CarryMinHealth",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_104 = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"StampRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"StampRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_fc = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"AttackRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"AttackRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_f8 = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"WaterEntrances",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"WaterEntrances",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } local_f4 = (float)std::atoi(pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RubbleCoef",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RubbleCoef",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_11c = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PathCoef",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PathCoef",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_138 = (char **)(float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"OxygenCoef",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"OxygenCoef",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_108 = (float)fVar14; pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Capacity",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Capacity",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } local_dc = std::atoi(pcVar4); if (local_11c == 0.0) { local_11c = 1.0; } if ((float)local_138 == 0.0) { local_138 = (char **)0x3f800000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CollRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CollRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_12c = (char **)(float)fVar14; if ((float10)0.0 == fVar14) { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CollBox",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,","); fVar14 = std::atof(local_c8[0]); local_f0 = (float)fVar14; fVar14 = std::atof(local_c8[1]); local_ec = (float)fVar14; fVar3 = local_ec; if ((ushort)((ushort)(local_f0 < local_ec) << 8 | (ushort)(local_f0 == local_ec) << 0xe) == 0) { fVar3 = local_f0; } local_12c = (char **)(fVar3 * 0.5); local_140 = 0x100; } } else { local_140 = 0x80; } if (local_134 != NULL) { iVar11 = 0; pcVar4 = local_134; do { *(char ***) ((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x48) = local_12c; *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x4c) = local_114; pOVar8 = globs::statsGlobs.objectStats[objType][objIndex]; *(float *)((int)pOVar8->DrillTimes + iVar11 + 0x7c) = local_f0; *(float *)((int)pOVar8->DrillTimes + iVar11 + 0x80) = local_ec; *(char **)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x54) = local_130; *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x58) = local_120; *(char **)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x50) = local_118; *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x5c) = local_110; *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x60) = local_100; *(char **)((int)&globs::statsGlobs.objectStats[objType][objIndex]->BuildingBase + iVar11) = local_144; *(SFX_ID *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->DrillSound + iVar11) = local_e0; *(SFX_ID *) ((int)&globs::statsGlobs.objectStats[objType][objIndex]->DrillFadeSound + iVar11) = local_e8; *(SFX_ID *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->EngineSound + iVar11) = local_e4; *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x68) = local_10c; pcVar4 = pcVar4 + -1; *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x6c) = local_104; *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x70) = local_fc; *(float *)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x74) = local_f8; *(float *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x80) = local_f4; *(float *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x7c) = local_11c; *(char ***) (globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x78) = local_138; *(float *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x74) = local_108; *(int *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x70) = local_dc; *(int *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->CostCrystal + iVar11) = local_d8; *(int *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->CostOre + iVar11) = local_d4; *(char **)((int)&globs::statsGlobs.objectStats[objType][objIndex]->CostRefinedOre + iVar11 ) = local_124; iVar11 = iVar11 + 0x150; } while (pcVar4 != NULL); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"SingleWidthDig",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_138 = local_c8; iVar11 = 0; local_144 = local_134; do { BVar10 = util::Util_GetBoolFromString(*local_138); if (BVar10 == BOOL3_TRUE) { *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags1 + iVar11) = *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags1 + iVar11 ) | 1; } local_138 = local_138 + 1; iVar11 += 0x150; local_144 = local_144 + -1; pcVar4 = local_124; } while (local_144 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RepairValue",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = NULL; ppcVar12 = local_c8; local_130 = local_134; do { fVar14 = std::atof(*ppcVar12); ppcVar12 = ppcVar12 + 1; *(float *)(local_144 + (int)&globs::statsGlobs.objectStats[objType][objIndex]->RepairValue) = (float)fVar14; local_144 = local_144 + 0x150; local_130 = local_130 + -1; pcVar4 = local_124; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"SurveyRadius",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = NULL; ppcVar12 = local_c8; local_130 = local_134; do { iVar11 = std::atoi(*ppcVar12); ppcVar12 = ppcVar12 + 1; *(int *)(local_144 + (int)&globs::statsGlobs.objectStats[objType][objIndex]->SurveyRadius) = iVar11; local_144 = local_144 + 0x150; local_130 = local_130 + -1; pcVar4 = local_124; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"MaxCarry",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = NULL; ppcVar12 = local_c8; local_130 = local_134; do { iVar11 = std::atoi(*ppcVar12); ppcVar12 = ppcVar12 + 1; *(int *)(local_144 + (int)&globs::statsGlobs.objectStats[objType][objIndex]->MaxCarry) = iVar11; local_144 = local_144 + 0x150; local_130 = local_130 + -1; pcVar4 = local_124; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CarryStart",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = NULL; ppcVar12 = local_c8; local_130 = local_134; do { iVar11 = std::atoi(*ppcVar12); ppcVar12 = ppcVar12 + 1; *(int *)(local_144 + (int)&globs::statsGlobs.objectStats[objType][objIndex]->CarryStart) = iVar11; local_144 = local_144 + 0x150; local_130 = local_130 + -1; pcVar4 = local_124; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CrystalDrain",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = NULL; ppcVar12 = local_c8; local_130 = local_134; do { iVar11 = std::atoi(*ppcVar12); ppcVar12 = ppcVar12 + 1; *(int *)(local_144 + (int)&globs::statsGlobs.objectStats[objType][objIndex]->CrystalDrain) = iVar11; local_144 = local_144 + 0x150; local_130 = local_130 + -1; pcVar4 = local_124; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"NumOfToolsCanCarry",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = NULL; ppcVar12 = local_c8; local_130 = local_134; do { iVar11 = std::atoi(*ppcVar12); ppcVar12 = ppcVar12 + 1; *(int *)(local_144 + (int)&globs::statsGlobs.objectStats[objType][objIndex]->NumOfToolsCanCarry) = iVar11; local_144 = local_144 + 0x150; local_130 = local_130 + -1; pcVar4 = local_124; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UpgradeTime",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = NULL; ppcVar12 = local_c8; local_130 = local_134; do { fVar14 = std::atof(*ppcVar12); ppcVar12 = ppcVar12 + 1; *(float *)(local_144 + (int)&globs::statsGlobs.objectStats[objType][objIndex]->UpgradeTime) = (float)(fVar14 * (float10)25.0); local_144 = local_144 + 0x150; local_130 = local_130 + -1; pcVar4 = local_124; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"FunctionCoef",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_124 = pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_144 = NULL; ppcVar12 = local_c8; local_130 = local_134; do { fVar14 = std::atof(*ppcVar12); ppcVar12 = ppcVar12 + 1; local_144 = local_144 + 0x150; *(float *)(local_144 + (int)&globs::statsGlobs.objectStats[objType][objIndex][-1].FunctionCoef) = (float)fVar14; local_130 = local_130 + -1; pcVar4 = local_124; } while (local_130 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UpgradeCostOre",0); local_144 = cfg::Config_GetStringValue(config,pcVar4); if (local_144 != NULL) { util::Util_Tokenise(local_144,local_c8,":"); local_138 = local_c8 + 3; uVar6 = 0; do { iVar11 = std::atoi(*local_138); uVar13 = uVar6 + 0x150; local_138 = local_138 + -1; *(int *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + (uVar6 - 0x54)) = iVar11; uVar6 = uVar13; } while (uVar13 < 0x540); io::Mem_Free(local_144); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UpgradeCostStuds",0); local_144 = cfg::Config_GetStringValue(config,pcVar4); if (local_144 != NULL) { util::Util_Tokenise(local_144,local_c8,":"); local_138 = local_c8 + 3; uVar6 = 0; do { iVar11 = std::atoi(*local_138); uVar13 = uVar6 + 0x150; *(int *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + (uVar6 - 0x50)) = iVar11; local_138 = local_138 + -1; uVar6 = uVar13; } while (uVar13 < 0x540); io::Mem_Free(local_144); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"ProcessOre",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 2; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"ProcessCrystal",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 4; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"StoreObjects",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 8; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"ManTeleporter",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x80000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"SmallTeleporter",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x10; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"BigTeleporter",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x20; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"WaterTeleporter",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x40; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"SnaxULike",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x4000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"ToolStore",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x100000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CauseSlip",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x200; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RandomMove",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x400; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanScare",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x800; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanScareScorpion",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x40000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RandomEnterWall",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x1000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"ScaredByPlayer",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x2000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"GrabMinifigure",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x8000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanBeDriven",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x20000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanSteal",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x80000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanClearRubble",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x10000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RouteAvoidance",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x20000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"BumpDamage",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x40000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x200000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Debug",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x400000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Smooth",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x800000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CrossWater",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x1000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CrossLand",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x2000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_OnGround",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x4000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_QuickDestroy",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x8000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_AnimateByPitch",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_140 |= 0x10000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"ScaredByBigBangs",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c = BVar10; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UpgradeBuilding",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= BOOL3_ERROR; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanBeShotAt",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x40000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UseBigTeleporter",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x800; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UseSmallTeleporter",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x1000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UseWaterTeleporter",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x2000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UseLegoManTeleporter",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x400000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TrainPilot",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_12c = (char **)pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_138 = local_c8; iVar11 = 0; local_144 = local_134; do { BVar10 = util::Util_GetBoolFromString(*local_138); if (BVar10 == BOOL3_TRUE) { *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11) = *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11 ) | 4; } local_138 = local_138 + 1; iVar11 += 0x150; local_144 = local_144 + -1; pcVar4 = (char *)local_12c; } while (local_144 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TrainSailor",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_12c = (char **)pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_138 = local_c8; iVar11 = 0; local_144 = local_134; do { BVar10 = util::Util_GetBoolFromString(*local_138); if (BVar10 == BOOL3_TRUE) { *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11) = *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11 ) | 8; } local_138 = local_138 + 1; iVar11 += 0x150; local_144 = local_144 + -1; pcVar4 = (char *)local_12c; } while (local_144 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TrainDriver",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_12c = (char **)pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_138 = local_c8; iVar11 = 0; local_144 = local_134; do { BVar10 = util::Util_GetBoolFromString(*local_138); if (BVar10 == BOOL3_TRUE) { *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11) = *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11 ) | 0x10; } local_138 = local_138 + 1; iVar11 += 0x150; local_144 = local_144 + -1; pcVar4 = (char *)local_12c; } while (local_144 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TrainDynamite",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_12c = (char **)pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_138 = local_c8; iVar11 = 0; local_144 = local_134; do { BVar10 = util::Util_GetBoolFromString(*local_138); if (BVar10 == BOOL3_TRUE) { *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11) = *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11 ) | 0x20; } local_138 = local_138 + 1; iVar11 += 0x150; local_144 = local_144 + -1; pcVar4 = (char *)local_12c; } while (local_144 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TrainRepair",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_12c = (char **)pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_138 = local_c8; iVar11 = 0; local_144 = local_134; do { BVar10 = util::Util_GetBoolFromString(*local_138); if (BVar10 == BOOL3_TRUE) { *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11) = *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11 ) | 0x40; } local_138 = local_138 + 1; iVar11 += 0x150; local_144 = local_144 + -1; pcVar4 = (char *)local_12c; } while (local_144 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TrainScanner",0); pcVar4 = cfg::Config_GetStringValue(config,pcVar4); local_12c = (char **)pcVar4; if (pcVar4 != NULL) { util::Util_Tokenise(pcVar4,local_c8,":"); if (local_134 != NULL) { local_138 = local_c8; iVar11 = 0; local_144 = local_134; do { BVar10 = util::Util_GetBoolFromString(*local_138); if (BVar10 == BOOL3_TRUE) { *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11) = *(uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11 ) | 0x80; } local_138 = local_138 + 1; iVar11 += 0x150; local_144 = local_144 + -1; pcVar4 = (char *)local_12c; } while (local_144 != NULL); } io::Mem_Free(pcVar4); } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Tracker",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x100; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PowerBuilding",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x600; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"SelfPowered",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x400; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"AttackPaths",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x4000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"SplitOnZeroHealth",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x8000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanBeHitByFence",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x10000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanDoubleSelect",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x20000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"DrainPower",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x80000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"UseHoles",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x100000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CrossLava",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x200000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"DamageCausesCallToArms",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x800000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanFreeze",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x1000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanLaser",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x2000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanPush",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x4000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"DontShowDamage",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x8000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RemoveReinforcement",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x10000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"DontShowOnRadar",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x20000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"InvisibleDriver",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x40000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Unselectable",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_13c |= 0x80000000; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CarryVehicles",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 = BVar10; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"VehicleCanBeCarried",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= BOOL3_ERROR; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"CanStrafe",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= 4; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"ClassAsLarge",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= 8; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"GetOutAtLand",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= 0x10; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"GetInAtLand",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= 0x20; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"TakeCarryingDrivers",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= 0x40; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"ShowHealthBar",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= 0x80; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"NeedsPilot",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= 0x100; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"EnterToolStore",0); BVar10 = cfg::Config_GetBoolValue(config,pcVar4); if (BVar10 == BOOL3_TRUE) { local_128 |= 0x200; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Turn",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Turn",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_138 = (char **)(float)fVar14; if (fVar14 == (float10)0.0) { local_138 = (char **)&DAT_3d75c28f; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Speed",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Speed",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_11c = (float)fVar14; if (fVar14 == (float10)0.0) { local_11c = 2.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Tightness",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Tightness",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_12c = (char **)(float)fVar14; if (fVar14 == (float10)0.0) { local_12c = (char **)1073741824; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_GoalUpdate",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_GoalUpdate",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_108 = (float)fVar14; if (fVar14 == (float10)0.0) { local_108 = 2.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Height",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Height",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_f4 = (float)fVar14; if (fVar14 == (float10)0.0) { local_f4 = 30.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Randomness",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Randomness",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_f8 = (float)fVar14; if (fVar14 == (float10)0.0) { local_f8 = 2.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Size",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_Size",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } local_d0 = std::atoi(pcVar4); uStack204 = 0; local_114 = (float)local_d0; if ((float)(ulonglong)local_d0 == 0.0) { local_114 = 7.006492e-45; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_AttackTime",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"Flocks_AttackTime",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_fc = (float)fVar14; if (fVar14 == (float10)0.0) { local_fc = 300.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"AwarenessRange",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"AwarenessRange",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_104 = (float)fVar14; if (fVar14 == (float10)0.0) { local_104 = 0.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PainThreshold",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PainThreshold",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_10c = (float)fVar14; if (fVar14 == (float10)0.0) { local_10c = 0.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"FreezerTime",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"FreezerTime",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_130 = (char *)(float)fVar14; if (fVar14 == (float10)0.0) { local_130 = NULL; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"FreezerDamage",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"FreezerDamage",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_120 = (float)fVar14; if (fVar14 == (float10)0.0) { local_120 = 0.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PusherDist",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PusherDist",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_110 = (float)fVar14; if (fVar14 == (float10)0.0) { local_110 = 0.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PusherDamage",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"PusherDamage",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_100 = (float)fVar14; if (fVar14 == (float10)0.0) { local_100 = 0.0; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"LaserDamage",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"LaserDamage",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_118 = (char *)(float)fVar14; if (fVar14 == (float10)0.0) { local_118 = NULL; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"WakeRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"WakeRadius",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); local_144 = (char *)(float)fVar14; if (fVar14 == (float10)0.0) { local_144 = (char *)1101004800; } pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RandomMoveTime",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"Stats",prop->key,"RandomMoveTime",0); pcVar4 = cfg::Config_GetTempStringValue(config,pcVar4); } fVar14 = std::atof(pcVar4); if (fVar14 == (float10)0.0) { fVar14 = (float10)200.0; } if (local_134 != NULL) { iVar11 = 0; pcVar4 = local_134; do { puVar1 = (uint *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags1 + iVar11) ; *puVar1 = *puVar1 | local_140; pBVar2 = (BoolTri *) ((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags2 + iVar11); *pBVar2 = *pBVar2 | local_13c; pBVar2 = (BoolTri *) ((int)&globs::statsGlobs.objectStats[objType][objIndex]->flags3 + iVar11); *pBVar2 = *pBVar2 | local_128; *(float *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->RandomMoveTime + iVar11 ) = (float)fVar14; *(char ***)((int)&globs::statsGlobs.objectStats[objType][objIndex]->Flocks_Turn + iVar11) = local_138; *(float *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->Flocks_Speed + iVar11) = local_11c; *(char ***) ((int)&globs::statsGlobs.objectStats[objType][objIndex]->Flocks_Tightness + iVar11) = local_12c; *(float *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->Flocks_GoalUpdate + iVar11) = local_108; *(float *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->Flocks_Height + iVar11) = local_f4; *(float *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->Flocks_Randomness + iVar11) = local_f8; *(float *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->Flocks_Size + iVar11) = local_114; *(float *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->Flocks_AttackTime + iVar11) = local_fc; *(float *)((int)&globs::statsGlobs.objectStats[objType][objIndex]->AwarenessRange + iVar11 ) = local_104; pcVar4 = pcVar4 + -1; *(float *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x68) = local_10c; *(float *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x38) = local_100; *(float *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x3c) = local_110; *(char **)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x34) = local_118; *(float *)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x40) = local_120; *(char **)(globs::statsGlobs.objectStats[objType][objIndex][1].unused_typeName + iVar11 + -0x44) = local_130; *(char **)((int)globs::statsGlobs.objectStats[objType][objIndex]->DrillTimes + iVar11 + 0x78) = local_144; iVar11 = iVar11 + 0x150; } while (pcVar4 != NULL); } } } Stats_AddToolTaskType(LegoObject_ToolType_Drill,AITask_Type_Dig); Stats_AddToolTaskType(LegoObject_ToolType_Spade,AITask_Type_Clear); Stats_AddToolTaskType(LegoObject_ToolType_Hammer,AITask_Type_Reinforce); Stats_AddToolTaskType(LegoObject_ToolType_Spanner,AITask_Type_Repair); return TRUE; } void __cdecl lego::stats::Stats_AddToolTaskType(LegoObject_ToolType toolType,AITask_Type taskType) { uint *pTaskCount; pTaskCount = &globs::statsGlobs.toolStats[toolType].taskCount; globs::statsGlobs.toolStats[toolType].taskTypes[globs::statsGlobs.toolStats[toolType].taskCount] = taskType; *pTaskCount = *pTaskCount + 1; return; } uint __cdecl lego::stats::Stats_GetCostOre(LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { return globs::statsGlobs.objectStats[objType][objID][objLevel].CostOre; } uint __cdecl lego::stats::Stats_GetCostCrystal(LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { return globs::statsGlobs.objectStats[objType][objID][objLevel].CostCrystal; } uint __cdecl lego::stats::Stats_GetCostRefinedOre(LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { return globs::statsGlobs.objectStats[objType][objID][objLevel].CostRefinedOre; } int __cdecl lego::stats::StatsObject_GetCrystalDrain(LegoObject *liveObj) { return globs::statsGlobs.objectStats[liveObj->type][liveObj->id][liveObj->objLevel].CrystalDrain; } uint __cdecl lego::stats::StatsObject_GetCapacity(LegoObject *liveObj) { return globs::statsGlobs.objectStats[liveObj->type][liveObj->id][liveObj->objLevel].Capacity; } uint __cdecl lego::stats::StatsObject_GetMaxCarry(LegoObject *liveObj) { return globs::statsGlobs.objectStats[liveObj->type][liveObj->id][liveObj->objLevel].MaxCarry; } uint __cdecl lego::stats::StatsObject_GetCarryStart(LegoObject *liveObj) { return globs::statsGlobs.objectStats[liveObj->type][liveObj->id][liveObj->objLevel].CarryStart; } BOOL __cdecl lego::stats::StatsObject_SetObjectLevel(LegoObject *liveObj,uint newLevel) { LegoObject_Type objType; int objIndex; uint oldLevel; objType = liveObj->type; objIndex = liveObj->id; if (newLevel < globs::statsGlobs.objectLevels[objType][objIndex]) { oldLevel = liveObj->objLevel; if (newLevel != oldLevel) { globs::objectGlobs.objectPrevLevels[objType][objIndex][oldLevel] = globs::objectGlobs.objectPrevLevels[objType][objIndex][oldLevel] + 1; globs::objectGlobs.objectTotalLevels[liveObj->type][liveObj->id][newLevel] = globs::objectGlobs.objectTotalLevels[liveObj->type][liveObj->id][newLevel] + 1; } liveObj->objLevel = newLevel; liveObj->stats = globs::statsGlobs.objectStats[liveObj->type][liveObj->id] + newLevel; return TRUE; } return FALSE; } float10 __cdecl lego::stats::StatsObject_GetRouteSpeed(LegoObject *liveObj) { return (float10)liveObj->stats->RouteSpeed; } float10 __cdecl lego::stats::StatsObject_GetDrillTimeType(LegoObject *liveObj,Lego_SurfaceType surfaceType) { return (float10)liveObj->stats->DrillTimes[surfaceType]; } float10 __cdecl lego::stats::StatsObject_GetRubbleCoef(LegoObject *liveObj) { return (float10)liveObj->stats->RubbleCoef; } float10 __cdecl lego::stats::StatsObject_GetWakeRadius(LegoObject *liveObj) { return (float10)liveObj->stats->WakeRadius; } float10 __cdecl lego::stats::StatsObject_GetPathCoef(LegoObject *liveObj) { return (float10)liveObj->stats->PathCoef; } float10 __cdecl lego::stats::StatsObject_GetCollRadius(LegoObject *liveObj) { return (float10)liveObj->stats->CollRadius; } float10 __cdecl lego::stats::StatsObject_GetCollHeight(LegoObject *liveObj) { return (float10)liveObj->stats->CollHeight; } float10 __cdecl lego::stats::StatsObject_GetPickSphere(LegoObject *liveObj) { return (float10)liveObj->stats->PickSphere; } float10 __cdecl lego::stats::StatsObject_GetPainThreshold(LegoObject *liveObj) { return (float10)liveObj->stats->PainThreshold; } float10 __cdecl lego::stats::StatsObject_GetAlertRadius(LegoObject *liveObj) { return (float10)liveObj->stats->AlertRadius; } Size2F * __cdecl lego::stats::StatsObject_GetCollBox(LegoObject *liveObj) { return &liveObj->stats->CollBox; } float10 __cdecl lego::stats::StatsObject_GetTrackDist(LegoObject *liveObj) { return (float10)liveObj->stats->TrackDist; } float10 __cdecl lego::stats::StatsObject_GetHealthDecayRate(LegoObject *liveObj) { return (float10)liveObj->stats->HealthDecayRate; } float10 __cdecl lego::stats::StatsObject_GetEnergyDecayRate(LegoObject *liveObj) { return (float10)liveObj->stats->EnergyDecayRate; } float10 __cdecl lego::stats::Stats_GetOxygenCoef(LegoObject_Type objType,LegoObject_ID objID) { return (float10)globs::statsGlobs.objectStats[objType][objID]->OxygenCoef; } float10 __cdecl lego::stats::StatsObject_GetOxygenCoef(LegoObject *liveObj) { return (float10)liveObj->stats->OxygenCoef; } uint __cdecl lego::stats::StatsObject_GetSurveyRadius(LegoObject *liveObj) { return liveObj->stats->SurveyRadius; } StatsFlags1 __cdecl lego::stats::StatsObject_GetStatsFlags1(LegoObject *liveObj) { return liveObj->stats->flags1; } StatsFlags2 __cdecl lego::stats::StatsObject_GetStatsFlags2(LegoObject *liveObj) { return liveObj->stats->flags2; } StatsFlags3 __cdecl lego::stats::StatsObject_GetStatsFlags3(LegoObject *liveObj) { return liveObj->stats->flags3; } StatsFlags1 __cdecl lego::stats::Stats_GetStatsFlags1(LegoObject_Type objType,LegoObject_ID objID) { return globs::statsGlobs.objectStats[objType][objID]->flags1; } StatsFlags2 __cdecl lego::stats::Stats_GetStatsFlags2(LegoObject_Type objType,LegoObject_ID objID) { return globs::statsGlobs.objectStats[objType][objID]->flags2; } StatsFlags3 __cdecl lego::stats::Stats_GetStatsFlags3(LegoObject_Type objType,LegoObject_ID objID) { return globs::statsGlobs.objectStats[objType][objID]->flags3; } float10 __cdecl lego::stats::StatsObject_GetRepairValue(LegoObject *liveObj) { return (float10)liveObj->stats->RepairValue; } uint __cdecl lego::stats::Stats_GetLevels(LegoObject_Type objType,LegoObject_ID objID) { return *(uint *)(objID * 4 + 0x503c28 + objType * 0x3c); } uint __cdecl lego::stats::Stats_GetWaterEntrances(LegoObject_Type objType,LegoObject_ID objID,uint objLevel) { return globs::statsGlobs.objectStats[objType][objID][objLevel].WaterEntrances; } SFX_ID __cdecl lego::stats::StatsObject_GetDrillSoundType(LegoObject *liveObj,BOOL fade) { if (fade != 0) { return liveObj->stats->DrillFadeSound; } return liveObj->stats->DrillSound; } SFX_ID __cdecl lego::stats::StatsObject_GetEngineSound(LegoObject *liveObj) { return liveObj->stats->EngineSound; } float10 __cdecl lego::stats::StatsObject_GetRestPercent(LegoObject *liveObj) { return (float10)liveObj->stats->RestPercent; } float10 __cdecl lego::stats::StatsObject_GetCarryMinHealth(LegoObject *liveObj) { return (float10)liveObj->stats->CarryMinHealth; } float10 __cdecl lego::stats::StatsObject_GetAttackRadius(LegoObject *liveObj) { return (float10)liveObj->stats->AttackRadius; } float10 __cdecl lego::stats::StatsObject_GetStampRadius(LegoObject *liveObj) { return (float10)liveObj->stats->StampRadius; } uint __cdecl lego::stats::StatsObject_GetNumOfToolsCanCarry(LegoObject *liveObj) { return liveObj->stats->NumOfToolsCanCarry; } float10 __cdecl lego::stats::StatsObject_GetUpgradeTime(LegoObject *liveObj) { return (float10)liveObj->stats->UpgradeTime; } float10 __cdecl lego::stats::StatsObject_GetFunctionCoef(LegoObject *liveObj) { return (float10)liveObj->stats->FunctionCoef; } uint __cdecl lego::stats::Stats_GetUpgradeCostOre (LegoObject_Type objType,LegoObject_ID objID,LegoObject_UpgradeType upgradeType) { return globs::statsGlobs.objectStats[objType][objID][upgradeType].UpgradeCostOre; } uint __cdecl lego::stats::Stats_GetUpgradeCostStuds (LegoObject_Type objType,LegoObject_ID objID,LegoObject_UpgradeType upgradeType) { return globs::statsGlobs.objectStats[objType][objID][upgradeType].UpgradeCostStuds; } BOOL __cdecl lego::stats::Stats_FindToolFromTaskType(AITask_Type taskType,LegoObject_ToolType *out_toolType) { ToolStats *pToolStats; uint j; AITask_Type *pTaskType; uint i; i = 0; pToolStats = globs::statsGlobs.toolStats; do { // pTaskType = &pToolStats->taskTypes[0]; j = 0; pTaskType = pToolStats->taskTypes; if (pToolStats->taskCount != 0) { do { if (taskType == *pTaskType) { *out_toolType = i; return TRUE; } j += 1; pTaskType = pTaskType + 1; } while (j < pToolStats->taskCount); } pToolStats = pToolStats + 1; i += LegoObject_ToolType_Spade; } while (pToolStats < &globals::g_Teleporter_BOOL_00504188); return FALSE; } float10 __cdecl lego::stats::StatsObject_GetFlocks_Height(LegoObject *liveObj) { return (float10)liveObj->stats->Flocks_Height; } float10 __cdecl lego::stats::StatsObject_GetFlocks_Randomness(LegoObject *liveObj) { return (float10)liveObj->stats->Flocks_Randomness; } float10 __cdecl lego::stats::StatsObject_GetFlocks_Turn(LegoObject *liveObj) { return (float10)liveObj->stats->Flocks_Turn; } float10 __cdecl lego::stats::StatsObject_GetFlocks_Tightness(LegoObject *liveObj) { return (float10)liveObj->stats->Flocks_Tightness; } float10 __cdecl lego::stats::StatsObject_GetFlocks_Speed(LegoObject *liveObj) { return (float10)liveObj->stats->Flocks_Speed; } uint __cdecl lego::stats::StatsObject_GetFlocks_Size(LegoObject *liveObj) { return liveObj->stats->Flocks_Size; } float10 __cdecl lego::stats::StatsObject_GetFlocks_GoalUpdate(LegoObject *liveObj) { return (float10)liveObj->stats->Flocks_GoalUpdate; } float10 __cdecl lego::stats::StatsObject_GetFlocks_AttackTime(LegoObject *liveObj) { return (float10)liveObj->stats->Flocks_AttackTime; } float10 __cdecl lego::stats::StatsObject_GetAwarenessRange(LegoObject *liveObj) { return (float10)liveObj->stats->AwarenessRange; } float10 __cdecl lego::stats::StatsObject_GetPusherDist(LegoObject *liveObj) { return (float10)liveObj->stats->PusherDist; } float10 __cdecl lego::stats::StatsObject_GetPusherDamage(LegoObject *liveObj) { return (float10)liveObj->stats->PusherDamage; } float10 __cdecl lego::stats::StatsObject_GetLaserDamage(LegoObject *liveObj) { return (float10)liveObj->stats->LaserDamage; } float10 __cdecl lego::stats::StatsObject_GetFreezerDamage(LegoObject *liveObj) { return (float10)liveObj->stats->FreezerDamage; } float10 __cdecl lego::stats::StatsObject_GetFreezerTime(LegoObject *liveObj) { return (float10)liveObj->stats->FreezerTime; } // This function will ALTER OBJECT STATS by removing the SelfPowered flag. void __cdecl lego::debug::StatsObject_Debug_ToggleSelfPowered(LegoObject *liveObj) { StatsFlags2 statsFlags2; ObjectStats *stats; stats = liveObj->stats; statsFlags2 = stats->flags2; if ((statsFlags2 & STATS2_SELFPOWERED) != STATS2_NONE) { // WTF Ghidra... // stats->flags2 &= ~STATS2_SELFPOWERED; // 0x400 stats->flags2 = statsFlags2 & (STATS2_SCAREDBYBIGBANGS|STATS2_UPGRADEBUILDING|STATS2_TRAINPILOT|STATS2_TRAINSAILOR| STATS2_TRAINDRIVER|STATS2_TRAINDYNAMITE|STATS2_TRAINREPAIR|STATS2_TRAINSCANNER| STATS2_TRACKER|STATS2_GENERATEPOWER|STATS2_USEBIGTELEPORTER|STATS2_USESMALLTELEPORTER| STATS2_USEWATERTELEPORTER|STATS2_ATTACKPATHS|STATS2_SPLITONZEROHEALTH| STATS2_CANBEHITBYFENCE|STATS2_CANDOUBLESELECT|STATS2_CANBESHOTAT|STATS2_DRAINPOWER| STATS2_USEHOLES|STATS2_CROSSLAVA|STATS2_USELEGOMANTELEPORTER|STATS2_DAMAGECAUSESCALLTOARMS |STATS2_CANFREEZE|STATS2_CANLASER|STATS2_CANPUSH|STATS2_DONTSHOWDAMAGE| STATS2_REMOVEREINFORCEMENT|STATS2_DONTSHOWONRADAR|STATS2_INVISIBLEDRIVER| STATS2_UNSELECTABLE); game::LegoObject_UpdatePowerConsumption(liveObj); return; } stats->flags2 = statsFlags2 | STATS2_SELFPOWERED; game::LegoObject_UpdatePowerConsumption(liveObj); return; } // Previously named Teleporter_Free (old name conflict with "Teleporter_RemoveAll", now Restart). void __cdecl lego::unk::Teleporter_RemoveAll(TeleporterService *teleporter) { if (teleporter != NULL) { Teleporter_RemoveAll(teleporter->next); io::Mem_Free(teleporter); } return; } // Previously named Teleporter_RemoveAll (old name conflict with "Teleporter_Free", now RemoveAll). void __cdecl lego::unk::Teleporter_Restart(void) { globs::teleporterGlobs.count = 0; Teleporter_RemoveAll(globs::teleporterGlobs.current); globs::teleporterGlobs.current = NULL; return; } BOOL __cdecl lego::unk::Teleporter_LiveObjectCallback_Service(LegoObject *liveObj,SearchTeleporter_10 *search) { uint *puVar1; if (liveObj->type == search->objType) { liveObj->teleporter_modeFlags = search->modeFlags; liveObj->teleporter_teleportFlags = search->teleportFlags; if ((*(byte *)&search->modeFlags & 2) != 0) { liveObj->teleporter = search->teleporter; puVar1 = &search->teleporter->count; *puVar1 = *puVar1 + 1; } globs::teleporterGlobs.count += 1; liveObj->flags4 = liveObj->flags4 | LIVEOBJ4_UNK_8; } return 0; } // This function is weird, it returns EDX:EAX, but what for?? Point2F __cdecl lego::unk::Teleporter_GetCameraPosition(void) { Map3D *surfMap; LegoCamera *cam; Vector3F *out_worldPos; Point2F local_14; Vector3F surfPosition; cam = globs::legoGlobs.cameraMain; if (globs::legoGlobs.viewMode != ViewMode_Top) { cam = globs::legoGlobs.cameraFP; } out_worldPos = &surfPosition; surfMap = lrr::Lego_GetMap(); lego::view::Camera_GetTopdownWorldPos(cam,surfMap,out_worldPos); return (Point2F)CONCAT44(surfPosition.y,surfPosition.x); } void __cdecl lego::unk::Teleporter_Add(TeleporterService *teleporter) { teleporter->next = globs::teleporterGlobs.current; globs::teleporterGlobs.current = teleporter; return; } BOOL __cdecl lego::unk::Teleporter_LiveObjectCallback_Unk(LegoObject *liveObj,TeleportObjectType teleportObjType) { LegoObject_Type objType; objType = Teleporter_GetServiceObjectType(teleportObjType); if ((liveObj->type == objType) && (liveObj->teleporter_modeFlags != 0)) { globals::g_Teleporter_BOOL_00504188 = FALSE; } return FALSE; } BOOL __cdecl lego::unk::Teleporter_ServiceAll(TeleportObjectType teleportObjTypes) { TeleportObjectType teleObjFlag; uint i; i = 0; do { teleObjFlag = 1 << ((byte)i & 0x1f); globals::g_Teleporter_BOOL_00504188 = TRUE; if ((teleportObjTypes & teleObjFlag) != TELEPORT_SERVIVE_NONE) { game::LegoObject_RunThroughListsSkipUpgradeParts (Teleporter_LiveObjectCallback_Unk,(void *)teleObjFlag); if (globals::g_Teleporter_BOOL_00504188 == 0) { return FALSE; } } i += 1; } while (i < 31); return TRUE; } void __cdecl lego::unk::Teleporter_Start(TeleportObjectType teleportObjType,uint modeFlags,uint teleportFlags) { Point2F cameraPos; SearchTeleporter_10 search; search.objType = Teleporter_GetServiceObjectType(teleportObjType); search.modeFlags = modeFlags; search.teleportFlags = teleportFlags; if ((modeFlags & 2) != 0) { search.teleporter = (TeleporterService *)io::Mem_Alloc(0x20); Teleporter_Add(search.teleporter); (search.teleporter)->count = 0; if ((teleportFlags & 2) != 0) { cameraPos = Teleporter_GetCameraPosition(); ((search.teleporter)->cameraPos).x = SUB84(cameraPos,0); ((search.teleporter)->cameraPos).y = (float)((ulonglong)cameraPos >> 0x20); (search.teleporter)->float_8 = 0.0; (search.teleporter)->float_c = globs::teleporterGlobs.floatValue_3_0; } if ((teleportFlags & 1) != 0) { (search.teleporter)->int_14 = globs::teleporterGlobs.intValue_40; } (search.teleporter)->flags = teleportFlags; } game::LegoObject_RunThroughListsSkipUpgradeParts(Teleporter_LiveObjectCallback_Service,&search); return; } BOOL __cdecl lego::unk::Teleporter_LiveObjectCallback_Update(LegoObject *liveObj,void *data_unused) { uint uVar1; float fVar2; float fVar3; short rng; Point2F position; TeleporterService *teleporter; if ((liveObj->teleporter_modeFlags & 1) != 0) { liveObj->health = -1.0; liveObj->teleporter_teleportFlags = 0; liveObj->teleporter_modeFlags = 4; globs::teleporterGlobs.count = globs::teleporterGlobs.count - 1; return 0; } if ((liveObj->teleporter_modeFlags & 2) != 0) { uVar1 = liveObj->teleporter_teleportFlags; if ((uVar1 & 2) == 0) { if ((uVar1 & 1) == 0) { if ((uVar1 & 4) != 0) { liveObj->health = -1.0; liveObj->flags3 = liveObj->flags3 | LIVEOBJ3_REMOVING; globs::teleporterGlobs.count -= 1; } } else { teleporter = liveObj->teleporter; rng = math::Maths_Rand(); if ((int)rng % teleporter->int_14 == 0) { liveObj->health = -1.0; teleporter->count = teleporter->count - 1; goto LAB_0046a960; } } } else { teleporter = liveObj->teleporter; // I think this teleports objects with priority to "near" the camera // when the level completed, as time progresses, units farther away // are teleported. game::LegoObject_GetPosition(liveObj,&position.x,&position.y); fVar3 = position.x - (teleporter->cameraPos).x; fVar2 = position.y - (teleporter->cameraPos).y; teleporter = liveObj->teleporter; if (SQRT(fVar2 * fVar2 + fVar3 * fVar3) < teleporter->float_8) { liveObj->health = -1.0; teleporter->count = teleporter->count - 1; LAB_0046a960: liveObj->teleporter_modeFlags = 4; liveObj->teleporter = NULL; liveObj->teleporter_teleportFlags = 0; globs::teleporterGlobs.count = globs::teleporterGlobs.count - 1; return 0; } } } return 0; } BOOL __cdecl lego::unk::Teleporter_UpdateService(TeleporterService *teleporter,float elapsedGame) { if (teleporter != NULL) { do { if ((teleporter->count != 0) && (teleporter->flags == 2)) { teleporter->float_8 = teleporter->float_c * elapsedGame + teleporter->float_8; } teleporter = teleporter->next; } while (teleporter != NULL); } return (BOOL)teleporter; } void __cdecl lego::unk::Teleporter_Update(float elapsedGame) { Teleporter_UpdateService(globs::teleporterGlobs.current,elapsedGame); if (globs::teleporterGlobs.count != 0) { game::LegoObject_RunThroughListsSkipUpgradeParts(Teleporter_LiveObjectCallback_Update,NULL); } return; } LegoObject_Type __cdecl lego::unk::Teleporter_GetServiceObjectType(TeleportObjectType teleportObjType) { if ((teleportObjType & TELEPORT_SERVIVE_VEHICLE) != TELEPORT_SERVIVE_NONE) { return LegoObject_Vehicle; } if ((teleportObjType & TELEPORT_SERVIVE_MINIFIGURE) != TELEPORT_SERVIVE_NONE) { return LegoObject_MiniFigure; } if ((teleportObjType & TELEPORT_SERVIVE_ROCKMONSTER) != TELEPORT_SERVIVE_NONE) { return LegoObject_RockMonster; } if ((teleportObjType & TELEPORT_SERVIVE_BUILDING) != TELEPORT_SERVIVE_NONE) { return LegoObject_Building; } if ((teleportObjType & TELEPORT_SERVIVE_BOULDER) != TELEPORT_SERVIVE_NONE) { return LegoObject_Boulder; } if ((teleportObjType & TELEPORT_SERVIVE_POWERCRYSTAL) != TELEPORT_SERVIVE_NONE) { return LegoObject_PowerCrystal; } if ((teleportObjType & TELEPORT_SERVIVE_ORE) != TELEPORT_SERVIVE_NONE) { return LegoObject_Ore; } if ((teleportObjType & TELEPORT_SERVIVE_DYNAMITE) != TELEPORT_SERVIVE_NONE) { return LegoObject_Dynamite; } if ((teleportObjType & TELEPORT_SERVIVE_BARRIER) != TELEPORT_SERVIVE_NONE) { return LegoObject_Barrier; } if ((teleportObjType & TELEPORT_SERVIVE_UPGRADEPART) != TELEPORT_SERVIVE_NONE) { return LegoObject_UpgradePart; } if ((teleportObjType & TELEPORT_SERVIVE_ELECTRICFENCE) != TELEPORT_SERVIVE_NONE) { return LegoObject_ElectricFence; } if ((teleportObjType & TELEPORT_SERVIVE_SPIDERWEB) != TELEPORT_SERVIVE_NONE) { return LegoObject_SpiderWeb; } // OBJECT_OOHSCARY return -(uint)((teleportObjType & TELEPORT_SERVIVE_OOHSCARY) != TELEPORT_SERVIVE_NONE) & 0xd; } void __cdecl lego::front::Text_Load (TextWindow *param_1,TextWindow *param_2,int imageX,int imageY,float pauseTime) { if (pauseTime == 0.0) { globs::textGlobs.textName[0] = "Text_Walk"; globs::textGlobs.textName[1] = "Text_Drill"; globs::textGlobs.textName[2] = "Text_NoDrill"; globs::textGlobs.textName[3] = "Text_CantDrill"; globs::textGlobs.textName[4] = "Text_Reinforce"; globs::textGlobs.textName[5] = "Text_NoReinforce"; globs::textGlobs.textName[6] = "Text_CantReinforce"; globs::textGlobs.textName[7] = "Text_PickupCrystal"; globs::textGlobs.textName[8] = "Text_Encyclopedia"; globs::textGlobs.textName[9] = "Text_RadarHelp"; globs::textGlobs.textName[10] = "Text_BuildHelp"; globs::textGlobs.textName[11] = "Text_SelectionHelp"; globs::textGlobs.textName[12] = "Text_Drive"; globs::textGlobs.textName[13] = "Text_CantDrive"; globs::textGlobs.textName[14] = "Text_MakeTeleporter"; globs::textGlobs.textName[15] = "Text_CannotPlaceBuilding"; globs::textGlobs.textName[16] = "Text_CrystalOreDisabled"; globs::textGlobs.textName[17] = "Text_CrystalFound"; globs::textGlobs.textName[18] = "Text_CavernDiscovered"; globs::textGlobs.textName[19] = "Text_OreFound"; globs::textGlobs.textName[20] = "Text_AirSupplyLow"; globs::textGlobs.textName[21] = "Text_AirSupplyRunningOut"; globs::textGlobs.textName[22] = "Text_SpaceToContinue"; globs::textGlobs.textName[23] = "Text_GameCompleted"; globs::textGlobs.textName[24] = "Text_ManTrained"; globs::textGlobs.textName[25] = "Text_UnitUpgraded"; globs::textGlobs.currType = Text_Type_Count; globs::textGlobs.textCount = 26; globs::textGlobs.textOnlyWindow = param_1; globs::textGlobs.textImageWindow = param_2; globs::textGlobs.TextImagePosition.x = imageX; globs::textGlobs.TextImagePosition.y = imageY; globs::textGlobs.TextPauseTime = (float)&DAT_42c80000; // 316 (passed from Game_Init) // 425 (passed from Game_Init) // 100.0 return; } globs::textGlobs.textName[0] = "Text_Walk"; globs::textGlobs.textName[1] = "Text_Drill"; globs::textGlobs.textName[2] = "Text_NoDrill"; globs::textGlobs.textName[3] = "Text_CantDrill"; globs::textGlobs.textName[4] = "Text_Reinforce"; globs::textGlobs.textName[5] = "Text_NoReinforce"; globs::textGlobs.textName[6] = "Text_CantReinforce"; globs::textGlobs.textName[7] = "Text_PickupCrystal"; globs::textGlobs.textName[8] = "Text_Encyclopedia"; globs::textGlobs.textName[9] = "Text_RadarHelp"; globs::textGlobs.textName[10] = "Text_BuildHelp"; globs::textGlobs.textName[11] = "Text_SelectionHelp"; globs::textGlobs.textName[12] = "Text_Drive"; globs::textGlobs.textName[13] = "Text_CantDrive"; globs::textGlobs.textName[14] = "Text_MakeTeleporter"; globs::textGlobs.textName[15] = "Text_CannotPlaceBuilding"; globs::textGlobs.textName[16] = "Text_CrystalOreDisabled"; globs::textGlobs.textName[17] = "Text_CrystalFound"; globs::textGlobs.textName[18] = "Text_CavernDiscovered"; globs::textGlobs.textName[19] = "Text_OreFound"; globs::textGlobs.textName[20] = "Text_AirSupplyLow"; globs::textGlobs.textName[21] = "Text_AirSupplyRunningOut"; globs::textGlobs.textName[22] = "Text_SpaceToContinue"; globs::textGlobs.textName[23] = "Text_GameCompleted"; globs::textGlobs.textName[24] = "Text_ManTrained"; globs::textGlobs.textName[25] = "Text_UnitUpgraded"; globs::textGlobs.currType = Text_Type_Count; globs::textGlobs.textCount = 26; globs::textGlobs.textOnlyWindow = param_1; globs::textGlobs.textImageWindow = param_2; globs::textGlobs.TextImagePosition.x = imageX; globs::textGlobs.TextImagePosition.y = imageY; globs::textGlobs.TextPauseTime = pauseTime; return; } void __cdecl lego::front::Text_Initialise (char *filename,uint param_2,uint param_3,uint unused_int,Area2F *param_5, Area2F *unused_rect,float param_7) { // 409 (passed from Game_Init) globs::textGlobs.uint_498 = param_3; globs::textGlobs.MsgPanel_Rect1.x = param_5->x; globs::textGlobs.MsgPanel_Rect1.y = param_5->y; globs::textGlobs.MsgPanel_Rect1.width = param_5->width; globs::textGlobs.MsgPanel_Rect1.height = param_5->height; globs::textGlobs.float_4ac = (globs::textGlobs.MsgPanel_Rect1.y + globs::textGlobs.MsgPanel_Rect1.height) - (float)(globs::textGlobs.textOnlyWindow)->font->fontHeight; // 20.0 (passed from Game_Init) // 42 (passed from Game_Init) globs::textGlobs.MsgPanel_Float20 = param_7; globs::textGlobs.MsgPanel_Float42 = (float)(ulonglong)param_2; Text_UpdatePositionAndSize(); return; } void __cdecl lego::front::Text_UpdatePositionAndSize(void) { int ypos; uint height; longlong lVar1; globs::textGlobs.float_4b8 = (float)(ulonglong)globs::textGlobs.uint_498; lVar1 = __ftol((float10)globs::textGlobs.MsgPanel_Rect1.y); ypos = (int)lVar1; lVar1 = __ftol((float10)globs::textGlobs.MsgPanel_Rect1.x); TextWindow_ChangePosition(globs::textGlobs.textOnlyWindow,(int)lVar1,ypos); lVar1 = __ftol((float10)globs::textGlobs.MsgPanel_Rect1.height); height = (uint)lVar1; lVar1 = __ftol((float10)globs::textGlobs.MsgPanel_Rect1.width); TextWindow_ChangeSize(globs::textGlobs.textOnlyWindow,(uint)lVar1,height); globs::textGlobs.MsgPanel_Rect2.x = globs::textGlobs.MsgPanel_Rect1.x; globs::textGlobs.MsgPanel_Rect2.y = globs::textGlobs.MsgPanel_Rect1.y; globs::textGlobs.MsgPanel_Rect2.width = globs::textGlobs.MsgPanel_Rect1.width; globs::textGlobs.MsgPanel_Rect2.height = globs::textGlobs.MsgPanel_Rect1.height; globs::textGlobs.TextPanelFlags = globs::textGlobs.TextPanelFlags & ~TEXT_GLOB_FLAG_UNK_1; return; } void __cdecl lego::front::Text_Clear(void) { Text_UpdatePositionAndSize(); globs::textGlobs.currType = Text_Type_Count; globs::textGlobs.jankCounter = 0; globs::textGlobs.currText = NULL; globs::textGlobs.TextPanelFlags = TEXT_GLOB_FLAG_NONE; TextWindow_Clear(globs::textGlobs.textOnlyWindow); TextWindow_Clear(globs::textGlobs.textImageWindow); return; } BOOL __cdecl lego::front::Text_GetTextType(char *textName,Text_Type *out_textType) { int iVar1; Text_Globs *pTVar2; int index; index = 0; pTVar2 = &globs::textGlobs; do { iVar1 = std::_stricmp(pTVar2->textName[0],textName); if (iVar1 == 0) { *out_textType = index; return 1; } pTVar2 = (Text_Globs *)(pTVar2->textName + 1); // index++ index += Text_Drill; // index < TEXT__COUNT (26) } while (pTVar2 < (Text_Globs *)globs::textGlobs.textMessages); return 0; } void __cdecl lego::front::Text_SetMessage(Text_Type textType,char *textMessage) { char *pcVar1; char cVar2; char *pcVar3; uint uVar4; if (globs::textGlobs.textMessages[textType] != NULL) { io::Mem_Free(globs::textGlobs.textMessages[textType]); } uVar4 = 0xffffffff; pcVar3 = textMessage; do { if (uVar4 == 0) break; uVar4 -= 1; cVar2 = *pcVar3; pcVar3 = pcVar3 + 1; } while (cVar2 != '\0'); pcVar3 = (char *)io::Mem_Alloc(~uVar4); globs::textGlobs.textMessages[textType] = pcVar3; cVar2 = *textMessage; while (cVar2 != '\0') { cVar2 = *textMessage; if (cVar2 == '_') { *pcVar3 = ' '; } else { if ((cVar2 == '\\') && (textMessage[1] == 'n')) { *pcVar3 = '\n'; textMessage = textMessage + 1; } else { *pcVar3 = cVar2; } } pcVar1 = textMessage + 1; pcVar3 = pcVar3 + 1; textMessage = textMessage + 1; cVar2 = *pcVar1; } *pcVar3 = '\0'; if (globs::textGlobs.textImages[textType] != NULL) { lego::image::Image_Remove(globs::textGlobs.textImages[textType]); globs::textGlobs.textImages[textType] = NULL; } return; } void __cdecl lego::front::Text_SetMessageWithImage(Text_Type textType,char *message,char *filename,char *sfxName) { Image *image; Text_SetMessage(textType,message); std::sprintf((char *)globs::textGlobs.textImagesSFX[textType],"%s",sfxName); image = lego::image::Image_LoadBMPScaled(filename,0,0); globs::textGlobs.textImages[textType] = image; if (image != NULL) { lego::image::Image_SetupTrans(image,0.0,0.0,0.0,0.0,0.0,0.0); } return; } void __cdecl lego::front::Text_SetNERPsMessage(char *text,uint unusedCounter) { globs::textGlobs.currText = text; // See Text_Update for description on jankCounter. if (unusedCounter == 0) { // Disable counter, otherwise the value is the number of ticks to countdown from. unusedCounter = 0x8000; } globs::textGlobs.jankCounter = unusedCounter | 0x10000; nerps::NERPs_Level_NERPMessage_Parse(text,NULL,TRUE); globs::textGlobs.TextPanelFlags = globs::textGlobs.TextPanelFlags | TEXT_GLOB_FLAG_UNK_1; return; } void __cdecl lego::front::Text_DisplayMessage(Text_Type textType,BOOL changeTiming,BOOL setFlag4) { TutorialFlags TVar1; BOOL BVar2; if (changeTiming == SFX_NULL) { if ((ushort)((ushort)(globs::textGlobs.float_488 < 0.0) << 8 | (ushort)(globs::textGlobs.float_488 == 0.0) << 0xe) != 0) { globs::textGlobs.currType = textType; } } else { globs::textGlobs.currType = textType; globs::textGlobs.float_488 = globs::textGlobs.TextPauseTime; } TVar1 = nerps::funcs::NERPFunc__GetTutorialFlags(NULL); if (TVar1 == TUTORIAL_NONE) { BVar2 = snd::SFX_GetType((char *)globs::textGlobs.textImagesSFX[textType], (SFX_ID *)&changeTiming); if (BVar2 != 0) { snd::SFX_Random_SetAndPlayGlobalSample(changeTiming,NULL); } } if ((globs::textGlobs.currType == textType) && (setFlag4 != 0)) { globs::textGlobs.TextPanelFlags = globs::textGlobs.TextPanelFlags | TEXT_GLOB_FLAG_UNK_4; return; } globs::textGlobs.TextPanelFlags = globs::textGlobs.TextPanelFlags & ~TEXT_GLOB_FLAG_UNK_4; return; } void __cdecl lego::front::Text_Update(float elapsedAbs) { char *format; float fVar1; Text_Type TVar2; int iVar3; BOOL BVar4; uint uVar5; Image *image; TextWindow *pTVar6; bool bVar7; longlong lVar8; int local_20c; Point2F local_208; char local_200 [512]; TVar2 = globs::textGlobs.currType; image = NULL; bVar7 = true; if (globs::textGlobs.jankCounter == 0) { BVar4 = nerps::NERPsRuntime_IsMessagePermit(); if ((BVar4 != 0) && (globs::textGlobs.currType != Text_Type_Count)) { image = globs::textGlobs.textImages[globs::textGlobs.currType]; format = globs::textGlobs.textMessages[globs::textGlobs.currType]; bVar7 = image == NULL; pTVar6 = globs::textGlobs.textOnlyWindow; if (!bVar7) { local_208.x = (float)(ulonglong)(uint)globs::textGlobs.TextImagePosition.x; local_208.y = (float)(ulonglong)(uint)globs::textGlobs.TextImagePosition.y; pTVar6 = globs::textGlobs.textImageWindow; } if (format != NULL) { iVar3 = 1; if ((globs::textGlobs.TextPanelFlags & TEXT_GLOB_FLAG_UNK_4) != TEXT_GLOB_FLAG_NONE) { iVar3 = Interface_GetFlashingState(); } if (iVar3 != 0) { TextWindow_PrintFOverlay(pTVar6,TRUE,format); } } if ((ushort)((ushort)(globs::textGlobs.float_488 < 0.0) << 8 | (ushort)(globs::textGlobs.float_488 == 0.0) << 0xe) != 0) { globs::textGlobs.currType = Text_Type_Count; } globs::textGlobs.float_488 = globs::textGlobs.float_488 - elapsedAbs; } } else { if (globs::textGlobs.currText == NULL) { globs::textGlobs.jankCounter = 0; } else { nerps::NERPs_Level_NERPMessage_Parse(globs::textGlobs.currText,local_200,FALSE); TextWindow_PrintFOverlay(globs::textGlobs.textOnlyWindow,0,local_200); // THE JANK COUNTER: // bits 0-14 : Counter value. // bit 15 : Counter decrement disabled flag. // bit 16 : When counter value is decremented past zero, switches to bit 15 flag. // Bit 16 is ALWAYS set with the counter value (or bit 15 flag when // counter == 0). // From how this counter field is used. The decrement operation and counter value // CHANGES ABSOLUTELY NOTHING. if ((globs::textGlobs.jankCounter & 0x8000) == 0) { globs::textGlobs.jankCounter -= 1; } } } if (((globs::legoGlobs.flags1 & GAME1_FREEZEINTERFACE) != GAME1_NONE) && (TVar2 != Text_SpaceToContinue)) { Text_UpdatePositionAndSize(); Panel_SetPosition(Panel_Messages,globs::textGlobs.MsgPanel_Float42,globs::textGlobs.float_4b8); Panel_Draw(Panel_Messages,0.0); Panel_AirMeter_DrawJuice(Panel_Messages,(globs::legoGlobs.currLevel)->oxygenLevel); Panel_AirMeter_DrawOxygenLow(Panel_Messages); return; } if (!bVar7) { Text_UpdatePositionAndSize(); Panel_SetPosition(Panel_Messages,globs::textGlobs.MsgPanel_Float42,globs::textGlobs.float_4b8); Panel_Draw(Panel_Messages,0.0); Panel_AirMeter_DrawJuice(Panel_Messages,(globs::legoGlobs.currLevel)->oxygenLevel); Panel_AirMeter_DrawOxygenLow(Panel_Messages); TextWindow_Update(globs::textGlobs.textImageWindow,0,elapsedAbs,NULL); lego::image::Image_DisplayScaled(image,NULL,&local_208,NULL); return; } Panel_SetPosition(Panel_Messages,globs::textGlobs.MsgPanel_Float42,globs::textGlobs.float_4b8); Panel_Draw(Panel_Messages,0.0); Panel_AirMeter_DrawJuice(Panel_Messages,(globs::legoGlobs.currLevel)->oxygenLevel); Panel_AirMeter_DrawOxygenLow(Panel_Messages); BVar4 = TextWindow_Update(globs::textGlobs.textOnlyWindow,0,elapsedAbs,&local_20c); pTVar6 = globs::textGlobs.textOnlyWindow; if (BVar4 == 0) { if ((globs::textGlobs.TextPanelFlags & TEXT_GLOB_FLAG_UNK_1) != TEXT_GLOB_FLAG_NONE) { if (globs::textGlobs.float_4ac <= (float)local_20c) { globs::textGlobs.TextPanelFlags = globs::textGlobs.TextPanelFlags & ~TEXT_GLOB_FLAG_UNK_1; return; } fVar1 = (float)(ulonglong)(globs::textGlobs.textOnlyWindow)->font->fontHeight; globs::textGlobs.float_4b8 = fVar1 + globs::textGlobs.float_4b8; globs::textGlobs.MsgPanel_Rect2.y = fVar1 + globs::textGlobs.MsgPanel_Rect2.y; globs::textGlobs.MsgPanel_Rect2.height = globs::textGlobs.MsgPanel_Rect2.height - fVar1; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.y); iVar3 = (int)lVar8; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.x); TextWindow_ChangePosition(pTVar6,(int)lVar8,iVar3); lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.height); uVar5 = (uint)lVar8; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.width); TextWindow_ChangeSize(globs::textGlobs.textOnlyWindow,(uint)lVar8,uVar5); if ((float)(ulonglong)globs::textGlobs.uint_498 <= globs::textGlobs.float_4b8) { globs::textGlobs.float_4b8 = (float)(ulonglong)globs::textGlobs.uint_498; globs::textGlobs.TextPanelFlags &= ~TEXT_GLOB_FLAG_UNK_1; globs::textGlobs.MsgPanel_Rect2.x = globs::textGlobs.MsgPanel_Rect1.x; globs::textGlobs.MsgPanel_Rect2.y = globs::textGlobs.MsgPanel_Rect1.y; globs::textGlobs.MsgPanel_Rect2.width = globs::textGlobs.MsgPanel_Rect1.width; globs::textGlobs.MsgPanel_Rect2.height = globs::textGlobs.MsgPanel_Rect1.height; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect1.y); iVar3 = (int)lVar8; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect1.x); TextWindow_ChangePosition(globs::textGlobs.textOnlyWindow,(int)lVar8,iVar3); lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.height); uVar5 = (uint)lVar8; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.width); TextWindow_ChangeSize(globs::textGlobs.textOnlyWindow,(uint)lVar8,uVar5); return; } } return; } fVar1 = (float)(ulonglong)(globs::textGlobs.textOnlyWindow)->font->fontHeight; globs::textGlobs.float_4b8 = globs::textGlobs.float_4b8 - fVar1; globs::textGlobs.MsgPanel_Rect2.y = globs::textGlobs.MsgPanel_Rect2.y - fVar1; globs::textGlobs.MsgPanel_Rect2.height = fVar1 + globs::textGlobs.MsgPanel_Rect2.height; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.y); iVar3 = (int)lVar8; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.x); TextWindow_ChangePosition(pTVar6,(int)lVar8,iVar3); lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.height); uVar5 = (uint)lVar8; lVar8 = __ftol((float10)globs::textGlobs.MsgPanel_Rect2.width); TextWindow_ChangeSize(globs::textGlobs.textOnlyWindow,(uint)lVar8,uVar5); globs::textGlobs.TextPanelFlags = globs::textGlobs.TextPanelFlags & ~TEXT_GLOB_FLAG_UNK_1; return; } void __cdecl lego::front::ToolTip_Initialise (Font *font,uint borderThickness,uint paddingThickness,float delaySeconds,uint appWidth, uint appHeight,int offsetY,float red,float green,float blue) { float *pfVar1; int iVar2; ToolTip *pTVar3; globs::toolTipGlobs.toolTipName[1] = "ToolTip_RadarBlock"; globs::toolTipGlobs.toolTipName[2] = "ToolTip_UnitSelect"; globs::toolTipGlobs.toolTipName[3] = "ToolTip_Construction"; globs::toolTipGlobs.toolTipName[4] = "ToolTip_InterfaceMenu"; globs::toolTipGlobs.toolTipName[5] = "ToolTip_InterfaceMenuBackButton"; globs::toolTipGlobs.toolTipName[6] = "ToolTip_MapBlock"; globs::toolTipGlobs.toolTipName[7] = "ToolTip_Priority"; globs::toolTipGlobs.toolTipName[8] = "ToolTip_InfoMenuContinue"; globs::toolTipGlobs.toolTipName[9] = "ToolTip_InfoMenuDisableFuture"; globs::toolTipGlobs.toolTipName[10] = "ToolTip_RadarToggle"; globs::toolTipGlobs.toolTipName[11] = "ToolTip_RadarObjectView"; globs::toolTipGlobs.toolTipName[12] = "ToolTip_RadarZoomIn"; globs::toolTipGlobs.toolTipName[13] = "ToolTip_RadarZoomOut"; globs::toolTipGlobs.toolTipName[14] = "ToolTip_RadarMapView"; globs::toolTipGlobs.toolTipName[15] = "ToolTip_InfoDockGoto"; globs::toolTipGlobs.toolTipName[16] = "ToolTip_InfoDockClose"; globs::toolTipGlobs.toolTipName[17] = "ToolTip_TopPanelCallToArms"; globs::toolTipGlobs.toolTipName[18] = "ToolTip_TopPanelInfo"; globs::toolTipGlobs.toolTipName[19] = "ToolTip_TopPanelOptions"; globs::toolTipGlobs.toolTipName[20] = "ToolTip_TopPanelPriorities"; globs::toolTipGlobs.toolTipName[21] = "ToolTip_PriorityDisable"; globs::toolTipGlobs.toolTipName[22] = "ToolTip_PriorityUpOne"; globs::toolTipGlobs.toolTipName[23] = "ToolTip_PriorityReset"; globs::toolTipGlobs.toolTipName[24] = "ToolTip_CamControlZoomIn"; globs::toolTipGlobs.toolTipName[25] = "ToolTip_CamControlZoomOut"; globs::toolTipGlobs.toolTipName[26] = "ToolTip_CamControlCycle"; globs::toolTipGlobs.toolTipName[27] = "ToolTip_CamControlRotate"; globs::toolTipGlobs.toolTipName[28] = "ToolTip_SideBar_Ore"; globs::toolTipGlobs.toolTipName[29] = "ToolTip_SideBar_Crystals"; globs::toolTipGlobs.toolTipName[30] = "ToolTip_Close"; globs::toolTipGlobs.toolTipName[31] = "ToolTip_PreviousMessage"; globs::toolTipGlobs.toolTipName[32] = "ToolTip_NextMessage"; globs::toolTipGlobs.toolTipName[33] = "ToolTip_More"; globs::toolTipGlobs.toolTipName[34] = "ToolTip_Back"; globs::toolTipGlobs.toolTipName[35] = "ToolTip_CamControlCycleMinifigures"; globs::toolTipGlobs.toolTipName[36] = "ToolTip_Reward_Save"; globs::toolTipGlobs.toolTipName[37] = "ToolTip_Reward_Advance"; globs::toolTipGlobs.toolTipName[38] = "ToolTip_FrontEnd_Back"; globs::toolTipGlobs.font = font; globs::toolTipGlobs.fontHeight = lego::image::Font_GetHeight(font); globs::toolTipGlobs.hoverTime = delaySeconds * 25.0; globs::toolTipGlobs.borderThickness = borderThickness; globs::toolTipGlobs.paddingThickness = paddingThickness; globs::toolTipGlobs.rgbFloats[1] = red + red * 0.4; globs::toolTipGlobs.appWidth = appWidth; globs::toolTipGlobs.appHeight = appHeight; globs::toolTipGlobs.offsetY = offsetY; globs::toolTipGlobs.rgbFloats[0] = red; globs::toolTipGlobs.rgbFloats[3] = green; globs::toolTipGlobs.rgbFloats[6] = blue; globs::toolTipGlobs.rgbFloats[4] = green + green * 0.4; globs::toolTipGlobs.rgbFloats[7] = blue + blue * 0.4; globs::toolTipGlobs.rgbFloats[2] = red - red * 0.4; pfVar1 = globs::toolTipGlobs.rgbFloats + 3; globs::toolTipGlobs.rgbFloats[5] = green - green * 0.4; globs::toolTipGlobs.rgbFloats[8] = blue - blue * 0.4; do { // Do bounds checking for RGB values if ((ushort)((ushort)(pfVar1[-3] < 1.0) << 8 | (ushort)(pfVar1[-3] == 1.0) << 0xe) == 0) { pfVar1[-3] = 1.0; } if ((ushort)((ushort)(*pfVar1 < 1.0) << 8 | (ushort)(*pfVar1 == 1.0) << 0xe) == 0) { *pfVar1 = 1.0; } if ((ushort)((ushort)(pfVar1[3] < 1.0) << 8 | (ushort)(pfVar1[3] == 1.0) << 0xe) == 0) { pfVar1[3] = 1.0; } if (pfVar1[-3] < 0.0) { pfVar1[-3] = 0.0; } if (*pfVar1 < 0.0) { *pfVar1 = 0.0; } if (pfVar1[3] < 0.0) { pfVar1[3] = 0.0; } pfVar1 = pfVar1 + 1; } while (pfVar1 < globs::toolTipGlobs.rgbFloats + 6); pTVar3 = globs::toolTipGlobs.toolTips; for (iVar2 = 0x1839; iVar2 != 0; iVar2 += -1) { pTVar3->timer = 0.0; pTVar3 = (ToolTip *)pTVar3->textBuffer; } return; } BOOL __cdecl lego::front::ToolTip_GetType(char *toolTipName,ToolTip_Type *out_toolTipType) { int iVar1; char **pName; ToolTip_Type toolTipType; toolTipType = ToolTip_RadarBlock; pName = globs::toolTipGlobs.toolTipName + 1; do { iVar1 = std::_stricmp(toolTipName,*pName); if (iVar1 == 0) { *out_toolTipType = toolTipType; return TRUE; } pName = pName + 1; toolTipType += ToolTip_RadarBlock; } while (pName < globs::toolTipGlobs.toolTips); return 0; } void __cdecl lego::front::ToolTip_SetContent(ToolTip_Type toolTipType,char *msg,...) { char *msg_00; char *pcVar1; char cVar2; int iVar3; int iVar4; Image *pIVar5; char *pcVar6; char *pcVar7; char filename [260]; char buff [512]; ToolTipFlags ttflags; std::vsprintf(buff,msg,&stack0x0000000c); // Use @ to denote an image... if (buff[0] == '@') { iVar4 = 1; while (buff[1] != '\0') { filename[iVar4 + -1] = buff[1]; iVar3 = iVar4 + 1; iVar4 += 1; buff[1] = buff[iVar3]; } filename[iVar4 + -1] = '\0'; pIVar5 = lego::image::Image_LoadBMPScaled(filename,0,0); globs::toolTipGlobs.toolTips[toolTipType].image = pIVar5; globs::toolTipGlobs.toolTips[toolTipType].flags = globs::toolTipGlobs.toolTips[toolTipType].flags | TOOLTIP_FLAG_IMAGECONTENT; } else { msg_00 = globs::toolTipGlobs.toolTips[toolTipType].textBuffer; pcVar6 = buff; pcVar7 = msg_00; while (buff[0] != '\0') { cVar2 = *pcVar6; // an \n as a return character... if ((cVar2 == '\\') && (pcVar6[1] == 'n')) { *pcVar7 = '\n'; pcVar6 = pcVar6 + 1; } else { // Use underscores as spaces if (cVar2 == '_') { *pcVar7 = ' '; } else { *pcVar7 = cVar2; } } pcVar1 = pcVar6 + 1; pcVar7 = pcVar7 + 1; pcVar6 = pcVar6 + 1; buff[0] = *pcVar1; } *pcVar7 = '\0'; lego::image::Font_GetStringInfo (globs::toolTipGlobs.font,&globs::toolTipGlobs.toolTips[toolTipType].textWidth, &globs::toolTipGlobs.toolTips[toolTipType].textLineCount,msg_00); globs::toolTipGlobs.toolTips[toolTipType].flags = globs::toolTipGlobs.toolTips[toolTipType].flags & ~TOOLTIP_FLAG_IMAGECONTENT; } ttflags = globs::toolTipGlobs.toolTips[toolTipType].flags; globs::toolTipGlobs.toolTips[toolTipType].iconCount = 0; globs::toolTipGlobs.toolTips[toolTipType].iconsHeight = 0; globs::toolTipGlobs.toolTips[toolTipType].iconsY = 0; globs::toolTipGlobs.toolTips[toolTipType].iconsWidth = 0; globs::toolTipGlobs.toolTips[toolTipType].iconsX = 0; globs::toolTipGlobs.toolTips[toolTipType].flags = ttflags | (TOOLTIP_FLAG_ENABLED1|TOOLTIP_FLAG_ENABLED2); return; } void __cdecl lego::front::ToolTip_AddIcon(ToolTip_Type toolTipType,Image *opt_image) { uint uVar1; int iVar2; if (opt_image == NULL) { globs::toolTipGlobs.toolTips[toolTipType].iconsY = 0; globs::toolTipGlobs.toolTips[toolTipType].iconsX = 0; } else { iVar2 = globs::toolTipGlobs.toolTips[toolTipType].iconsY; if (iVar2 < (int)opt_image->height) { iVar2 = globs::toolTipGlobs.toolTips[toolTipType].iconsHeight - iVar2; globs::toolTipGlobs.toolTips[toolTipType].iconsHeight = iVar2; uVar1 = opt_image->height; globs::toolTipGlobs.toolTips[toolTipType].iconsY = uVar1; globs::toolTipGlobs.toolTips[toolTipType].iconsHeight = iVar2 + uVar1; } iVar2 = globs::toolTipGlobs.toolTips[toolTipType].iconsX + opt_image->width; globs::toolTipGlobs.toolTips[toolTipType].iconsX = iVar2; if (globs::toolTipGlobs.toolTips[toolTipType].iconsWidth < iVar2) { globs::toolTipGlobs.toolTips[toolTipType].iconsWidth = iVar2; } } // globs::toolTipGlobs.toolTipDatas[toolTipType].imageList[.imageCount] = image; *(Image **) (toolTipType * 0x27c + 0x54d20c + globs::toolTipGlobs.toolTips[toolTipType].iconCount * 4) = opt_image; globs::toolTipGlobs.toolTips[toolTipType].iconCount = globs::toolTipGlobs.toolTips[toolTipType].iconCount + 1; return; } void __cdecl lego::front::ToolTip_SetSFX(ToolTip_Type toolTipType,SFX_ID sfxType) { ToolTipFlags ttflags; ttflags = globs::toolTipGlobs.toolTips[toolTipType].flags; globs::toolTipGlobs.toolTips[toolTipType].sfxType = sfxType; globs::toolTipGlobs.toolTips[toolTipType].flags = ttflags | (TOOLTIP_FLAG_ENABLED1|TOOLTIP_FLAG_ENABLED2); return; } // This seems to be broken, but it's unclear how the alignment logic is failing... void __cdecl lego::front::ToolTip_SetRightAlign(ToolTip_Type toolTipType,BOOL on) { ToolTipFlags ttflags; ttflags = globs::toolTipGlobs.toolTips[toolTipType].flags; if (on != 0) { globs::toolTipGlobs.toolTips[toolTipType].flags = ttflags | TOOLTIP_FLAG_RIGHTALIGN; return; } globs::toolTipGlobs.toolTips[toolTipType].flags = ttflags & ~TOOLTIP_FLAG_RIGHTALIGN; return; } void __cdecl lego::front::ToolTip_Activate(ToolTip_Type toolTipType) { globs::toolTipGlobs.toolTips[toolTipType].flags = globs::toolTipGlobs.toolTips[toolTipType].flags | TOOLTIP_FLAG_ACTIVE; return; } void __cdecl lego::front::ToolTip_ShowInstant(ToolTip_Type toolTipType) { globs::toolTipGlobs.toolTips[toolTipType].timer = globs::toolTipGlobs.hoverTime; return; } void __cdecl lego::front::ToolTip_Update(uint mouseX,uint mouseY,float elapsedAbsMS) { ToolTip *toolTip; BOOL BVar1; uint s_ToolTip_sfxStopped_; bool hasShowing; ToolTipFlags *ppRVar5; bool hasActive; hasShowing = false; hasActive = false; ppRVar5 = &globs::toolTipGlobs.toolTips[1].flags; s_ToolTip_sfxStopped_ = globals::s_ToolTip_sfxStopped; do { if ((*ppRVar5 & (TOOLTIP_FLAG_ENABLED1|TOOLTIP_FLAG_ENABLED2)) != TOOLTIP_FLAG_NONE) { if (((*ppRVar5 & TOOLTIP_FLAG_ACTIVE) == TOOLTIP_FLAG_NONE) || (hasActive)) { ppRVar5[-0x9e] = TOOLTIP_FLAG_NONE; } else { toolTip = (ToolTip *)(ppRVar5 + -0x9e); // toolTip->timer if (((float)ppRVar5[-0x9e] < globs::toolTipGlobs.hoverTime) || (hasShowing)) { s_ToolTip_sfxStopped_ = TRUE; globals::s_ToolTip_sfxStopped = TRUE; hasActive = true; toolTip->timer = elapsedAbsMS + toolTip->timer; } else { // toolTip->sfxType if (((ppRVar5[-1] != TOOLTIP_FLAG_NONE) && (s_ToolTip_sfxStopped_ != 0)) && ((globs::legoGlobs.flags2 & GAME2_DISABLETOOLTIPSOUND) == GAME2_NONE)) { BVar1 = snd::SFX_Random_SetAndPlayGlobalSample(ppRVar5[-1],NULL); s_ToolTip_sfxStopped_ = (uint)(BVar1 == 0); globals::s_ToolTip_sfxStopped = s_ToolTip_sfxStopped_; } // COMPARING AGAINST TEXT BUFFER ARRAY ADDRESS!! // if (toolTip->textBuffer != '\0') if (ppRVar5 != (ToolTipFlags *)0x274) { ToolTip_Draw(toolTip,mouseX,mouseY); s_ToolTip_sfxStopped_ = globals::s_ToolTip_sfxStopped; } hasShowing = true; hasActive = true; toolTip->timer = elapsedAbsMS + toolTip->timer; } } *ppRVar5 = *ppRVar5 & ~TOOLTIP_FLAG_ACTIVE; } ppRVar5 = ppRVar5 + 0x9f; } while (ppRVar5 < globs::roofGlobs.visibleTable + 0x70); return; } void __cdecl lego::front::ToolTip_DrawBox (Area2F valueRect,float rcRed,float rcGreen,float rcBlue,float ln1Red,float ln1Green, float ln1Blue,float ln2Red,float ln2Green,float ln2Blue,BOOL halfTrans) { float fVar1; float fVar2; Point2F *ln1From; Point2F *ln2From; float *ln1From_y; float *ln1To_y; uint lineCount; Point2F *ln1To; float *ln2From_y; Point2F *ln2To; float *ln2To_y; uint local_160; uint local_15c; Point2F ln1ListTo [10]; Point2F ln2ListTo [10]; Point2F ln1ListFrom [10]; Point2F ln2ListFrom [10]; float endX; float endY; float startX; float startY; lineCount = 0; local_160 = 0; local_15c = 0; if (globs::toolTipGlobs.borderThickness != 0) { ln2To = ln2ListTo; ln2To_y = &ln2ListTo[0].y; ln2From = ln2ListFrom; ln2From_y = &ln2ListFrom[0].y; ln1To_y = &ln1ListTo[0].y; ln1To = ln1ListTo; ln1From_y = &ln1ListFrom[0].y; ln1From = ln1ListFrom; do { fVar2 = (float)(ulonglong)local_15c; startX = valueRect.x + fVar2; startY = valueRect.y + fVar2; endY = ((valueRect.y + valueRect.height) - 1.0) - fVar2; endX = ((valueRect.x + valueRect.width) - 1.0) - fVar2; ln1From->x = startX; *ln1From_y = startY; fVar1 = ln1From->x; ln2From->x = startX; *ln1To_y = ((valueRect.y + valueRect.height) - 2.0) - fVar2; *ln2From_y = endY; ln1From[1].x = endX; ln1To->x = fVar1; ln2To->x = ((valueRect.x + valueRect.width) - 2.0) - fVar2; ln1From_y[2] = startY; *ln2To_y = endY; ln2From[1].x = endX; ln1To[1].x = startX - -1.0; ln2From_y[2] = endY; fVar1 = ln2From[1].x; ln1To_y[2] = startY; ln1From = ln1From + 2; ln1From_y = ln1From_y + 4; ln1To = ln1To + 2; ln2From_y = ln2From_y + 4; ln2To_y[2] = startY - -1.0; ln2From = ln2From + 2; ln2To[1].x = fVar1; lineCount = local_160 + 2; ln2To = ln2To + 2; ln1To_y = ln1To_y + 4; ln2To_y = ln2To_y + 4; local_15c += 1; local_160 = lineCount; } while (local_15c < globs::toolTipGlobs.borderThickness); } if (halfTrans == 0) { draw::Draw_RectListEx(&valueRect,1,rcRed,rcGreen,rcBlue,DrawEffect_None); draw::Draw_LineListEx(ln1ListFrom,ln1ListTo,lineCount,ln1Red,ln1Green,ln1Blue,DrawEffect_None); draw::Draw_LineListEx(ln2ListFrom,ln2ListTo,lineCount,ln2Red,ln2Green,ln2Blue,DrawEffect_None); return; } draw::Draw_RectListEx(&valueRect,1,rcRed,rcGreen,rcBlue,DrawEffect_HalfTrans); draw::Draw_LineListEx(ln1ListFrom,ln1ListTo,lineCount,ln1Red,ln1Green,ln1Blue,DrawEffect_None); draw::Draw_LineListEx(ln2ListFrom,ln2ListTo,lineCount,ln2Red,ln2Green,ln2Blue,DrawEffect_None); return; } void __cdecl lego::front::ToolTip_Draw(ToolTip *toolTip,uint mouseX,uint mouseY) { uint uVar1; uint innerHeight; int y; int margin; uint uVar2; Image **ppIVar3; uint uVar4; float10 extraout_ST0; float10 extraout_ST1; longlong lVar5; char *msg; char *pcVar6; Point2F local_44; uint local_3c; undefined4 uStack56; float local_34; float fStack48; float local_2c; float local_28; float fStack36; float local_20; float local_1c; float fStack24; float local_14; Area2F area; uint innerWidth; float xRight; local_34 = globs::toolTipGlobs.rgbFloats[0]; fStack48 = globs::toolTipGlobs.rgbFloats[3]; local_28 = globs::toolTipGlobs.rgbFloats[1]; fStack36 = globs::toolTipGlobs.rgbFloats[4]; local_2c = globs::toolTipGlobs.rgbFloats[6]; local_1c = globs::toolTipGlobs.rgbFloats[2]; fStack24 = globs::toolTipGlobs.rgbFloats[5]; local_20 = globs::toolTipGlobs.rgbFloats[7]; margin = (globs::toolTipGlobs.paddingThickness + globs::toolTipGlobs.borderThickness) * 2; local_14 = globs::toolTipGlobs.rgbFloats[8]; if ((toolTip->flags & TOOLTIP_FLAG_IMAGECONTENT) == TOOLTIP_FLAG_NONE) { innerWidth = toolTip->textWidth; if (toolTip->textWidth <= (uint)toolTip->iconsWidth) { innerWidth = toolTip->iconsWidth; } innerHeight = toolTip->textLineCount * globs::toolTipGlobs.fontHeight + toolTip->iconsHeight; } else { innerWidth = toolTip->image->width; innerHeight = toolTip->image->height; } // totalWidth local_44.x = (float)(margin + innerWidth); if ((toolTip->flags & TOOLTIP_FLAG_RIGHTALIGN) == TOOLTIP_FLAG_NONE) { if (globs::toolTipGlobs.appWidth < (int)local_44.x + mouseX) { area.x = (float)(ulonglong)(globs::toolTipGlobs.appWidth - (int)local_44.x); } else { area.x = (float)(ulonglong)mouseX; } } else { // HARDCODED CURSOR WIDTH: x + 32.0f xRight = (float)(ulonglong)mouseX - -32.0; if ((ushort)((ushort)(xRight < (float)(ulonglong)globs::toolTipGlobs.appWidth) << 8 | (ushort)(xRight == (float)(ulonglong)globs::toolTipGlobs.appWidth) << 0xe) == 0) { area.x = (float)(ulonglong)(globs::toolTipGlobs.appWidth - (int)local_44.x); } else { area.x = xRight - (float)(ulonglong)(uint)local_44.x; } } area.y = (float)(ulonglong)(globs::toolTipGlobs.offsetY + mouseY); area.height = (float)(ulonglong)(margin + innerHeight); if ((float)(ulonglong)globs::toolTipGlobs.appHeight < area.y + area.height) { area.y = (float)(ulonglong)(mouseY - (margin + innerHeight)) - 1.0; } local_44.y = 0.0; area.width = (float)(ulonglong)(uint)local_44.x; ToolTip_DrawBox((Area2F)CONCAT412(area.height,CONCAT48(area.width,CONCAT44(area.y,area.x))), globs::toolTipGlobs.rgbFloats[0],globs::toolTipGlobs.rgbFloats[3], globs::toolTipGlobs.rgbFloats[6],globs::toolTipGlobs.rgbFloats[1], globs::toolTipGlobs.rgbFloats[4],globs::toolTipGlobs.rgbFloats[7], globs::toolTipGlobs.rgbFloats[2],globs::toolTipGlobs.rgbFloats[5], globs::toolTipGlobs.rgbFloats[8],0); if ((*(byte *)&toolTip->flags & TOOLTIP_FLAG_IMAGECONTENT) == 0) { mouseX = toolTip->textLineCount * globs::toolTipGlobs.fontHeight; local_3c = globs::toolTipGlobs.paddingThickness; uStack56 = 0; pcVar6 = toolTip->textBuffer; uVar2 = 0; uVar4 = 0; msg = "%s"; lVar5 = __ftol((float10)area.y + (float10)(ulonglong)globs::toolTipGlobs.paddingThickness + (float10)(ulonglong)globs::toolTipGlobs.borderThickness); y = (int)lVar5; lVar5 = __ftol((float10)area.x + extraout_ST0 + extraout_ST1); lego::image::Font_PrintF(globs::toolTipGlobs.font,(int)lVar5,y,msg,pcVar6); mouseY = 0; if (toolTip->iconCount != 0) { ppIVar3 = toolTip->iconList; do { if (*ppIVar3 == NULL) { mouseX += uVar4; uVar4 = 0; uVar2 = 0; } else { local_3c = globs::toolTipGlobs.borderThickness; uStack56 = 0; local_34 = (float)globs::toolTipGlobs.paddingThickness; fStack48 = 0.0; fStack36 = 0.0; fStack24 = 0.0; local_1c = (float)mouseX; local_44.x = (float)(ulonglong)uVar2 + area.x + (float)(ulonglong)globs::toolTipGlobs.paddingThickness + (float)(ulonglong)globs::toolTipGlobs.borderThickness; local_44.y = (float)(ulonglong)mouseX + area.y + (float)(ulonglong)globs::toolTipGlobs.paddingThickness + (float)(ulonglong)globs::toolTipGlobs.borderThickness; local_28 = (float)uVar2; lego::image::Image_DisplayScaled(*ppIVar3,NULL,&local_44,NULL); uVar1 = (*ppIVar3)->height; if ((int)uVar4 < (int)uVar1) { uVar4 = uVar1; } uVar2 += (*ppIVar3)->width; } mouseY += 1; ppIVar3 = ppIVar3 + 1; } while (mouseY < toolTip->iconCount); } return; } local_3c = globs::toolTipGlobs.paddingThickness; uStack56 = 0; local_44.x = area.x + (float)(ulonglong)globs::toolTipGlobs.paddingThickness + (float)(ulonglong)globs::toolTipGlobs.borderThickness; local_44.y = area.y + (float)(ulonglong)globs::toolTipGlobs.paddingThickness + (float)(ulonglong)globs::toolTipGlobs.borderThickness; lego::image::Image_DisplayScaled(toolTip->image,NULL,&local_44,NULL); return; } void __cdecl lego::gfx::Upgrade_Part_Load (Upgrade_PartModel *upgradePart,int objID,Container *root,char *filename) { Container *cont; upgradePart->objID = 0; upgradePart->cont = NULL; upgradePart->nextObject = NULL; upgradePart->partInfo = NULL; cont = Container_Load(root,filename,"LWO",TRUE); upgradePart->cont = cont; if (cont == NULL) { cont = Container_Load(root,filename,"ACT",TRUE); upgradePart->cont = cont; } if (upgradePart->cont == NULL) { cont = Container_Load(root,filename,"MESH",TRUE); upgradePart->cont = cont; } upgradePart->nextObject = NULL; upgradePart->objID = objID; return; } void __cdecl lego::gfx::Upgrade_Part_Clone(Upgrade_PartModel *srcUpgradePart,Upgrade_PartModel *destUpgradePart) { Container *cont; destUpgradePart->objID = srcUpgradePart->objID; destUpgradePart->cont = srcUpgradePart->cont; destUpgradePart->nextObject = srcUpgradePart->nextObject; destUpgradePart->partInfo = srcUpgradePart->partInfo; cont = Container_Clone(srcUpgradePart->cont); destUpgradePart->cont = cont; return; } void __cdecl lego::gfx::Upgrade_Part_Remove(Upgrade_PartModel *upgradePart) { Container_Remove(upgradePart->cont); return; } float10 __cdecl lego::gfx::Upgrade_Part_MoveAnimation (Upgrade_PartModel *upgradePart,float elapsed,uint unused_repeatCount) { Container_MoveAnimation(upgradePart->cont,elapsed); return (float10)0.0; } BOOL __cdecl lego::gfx::Upgrade_Part_SetActivity(Upgrade_PartModel *upgradePart,char *activityName) { BOOL success; success = Container_SetActivity(upgradePart->cont,activityName); if (success == FALSE) { success = Container_SetActivity(upgradePart->cont,globs::objectGlobs.activityName[0]); } return success; } void __cdecl lego::gfx::Upgrade_Load(UpgradesModel *upgrades,Config *act,char *gameName) { char cVar1; Upgrade_PartInfo *pUVar2; char *keyPath; Config *prop; undefined4 *puVar3; char *pcVar4; Upgrade_PartModel *pUVar5; int iVar6; uint uVar7; uint uVar8; undefined4 *puVar9; char *pcVar10; uint level; char *stringParts [3]; char buff [256]; upgrades->partCount = 0; pUVar2 = (Upgrade_PartInfo *)io::Mem_Alloc(4000); upgrades->parts = pUVar2; for (iVar6 = 1000; iVar6 != 0; iVar6 += -1) { pUVar2->level = 0; pUVar2 = (Upgrade_PartInfo *)&pUVar2->nullFrameNo; } level = 0; do { std::sprintf(buff,"Level%i%i%i%i",level >> 3 & 1,level >> 2 & 1,level >> 1 & 1,level & 1); keyPath = cfg::Config_BuildStringID(gameName,"Upgrades",buff,0); prop = cfg::Config_FindArray(act,keyPath); if (prop != NULL) { upgrades->levelFlags = upgrades->levelFlags | level; for (; prop != NULL; prop = cfg::Config_GetNextItem(prop)) { uVar7 = 0xffffffff; pUVar2 = upgrades->parts + upgrades->partCount; pcVar4 = prop->value; do { pcVar10 = pcVar4; if (uVar7 == 0) break; uVar7 -= 1; pcVar10 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar10; } while (cVar1 != '\0'); uVar7 = ~uVar7; puVar3 = (undefined4 *)(pcVar10 + -uVar7); puVar9 = (undefined4 *)buff; for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar9 = *puVar3; puVar3 = puVar3 + 1; puVar9 = puVar9 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar3; puVar3 = (undefined4 *)((int)puVar3 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } iVar6 = util::Util_Tokenise(buff,stringParts,","); if (iVar6 == 3) { uVar7 = 0xffffffff; pcVar4 = stringParts[2]; do { if (uVar7 == 0) break; uVar7 -= 1; cVar1 = *pcVar4; pcVar4 = pcVar4 + 1; } while (cVar1 != '\0'); puVar3 = (undefined4 *)io::Mem_Alloc(~uVar7); uVar7 = 0xffffffff; pUVar2->weaponName = (char *)puVar3; pcVar4 = stringParts[2]; do { pcVar10 = pcVar4; if (uVar7 == 0) break; uVar7 -= 1; pcVar10 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar10; } while (cVar1 != '\0'); uVar7 = ~uVar7; puVar9 = (undefined4 *)(pcVar10 + -uVar7); for (uVar8 = uVar7 >> 2; uVar8 != 0; uVar8 -= 1) { *puVar3 = *puVar9; puVar9 = puVar9 + 1; puVar3 = puVar3 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar3 = *(undefined *)puVar9; puVar9 = (undefined4 *)((int)puVar9 + 1); puVar3 = (undefined4 *)((int)puVar3 + 1); } } pcVar4 = util::Util_StrCpy(stringParts[0]); pUVar2->nullObjectName = pcVar4; pUVar2->level = level; iVar6 = std::atoi(stringParts[1]); pUVar2->nullFrameNo = iVar6 - 1; pUVar5 = lrr::Lego_GetUpgradePartModel(prop->key); pUVar2->upgradeData = pUVar5; upgrades->partCount = upgrades->partCount + 1; } } level += 1; if (0xf < level) { if (upgrades->partCount == 0) { io::Mem_Free(upgrades->parts); upgrades->parts = NULL; } return; } } while( true ); } void __cdecl lego::gfx::Upgrade_SetUpgradeLevel(UpgradesModel *upgrades,uint objLevel) { LegoObject *pLVar1; LegoObject *pLVar2; Upgrade_PartModel *pUVar3; int iVar4; LegoObject_ID upgradeID; iVar4 = 0; pLVar2 = upgrades->firstObject; pUVar3 = (Upgrade_PartModel *)objLevel; while (pLVar2 != NULL) { pUVar3 = pLVar2->upgradePart; pLVar1 = pUVar3->nextObject; game::LegoObject_Remove(pLVar2); pLVar2 = pLVar1; } upgradeID = 0; upgrades->currentLevel = objLevel; upgrades->firstObject = NULL; if (upgrades->partCount != 0) { do { if (*(uint *)((int)&upgrades->parts->level + iVar4) == objLevel) { pLVar2 = game::LegoObject_Create (*(int ***)((int)&upgrades->parts->upgradeData + iVar4), LegoObject_UpgradePart,upgradeID); if (upgrades->firstObject == NULL) { upgrades->firstObject = pLVar2; } else { pUVar3->nextObject = pLVar2; } pUVar3 = pLVar2->upgradePart; pUVar3->partInfo = (Upgrade_PartInfo *)((int)&upgrades->parts->level + iVar4); } upgradeID += 1; iVar4 += 0x14; } while (upgradeID < upgrades->partCount); } return; } BOOL __cdecl lego::gfx::Vehicle_IsCameraFlipDir(VehicleModel *vehicle) { return (uint)(vehicle->cameraFlipDir == BOOL3_TRUE); } BOOL __cdecl lego::gfx::Vehicle_SetActivity(VehicleModel *vehicle,char *activityName,float elapsed) { uint i; uint success; BOOL BVar1; uint success2; VehicleFlags flags; Container **pNull; MeshLOD_RemoveTargets(vehicle->polyMedium1); i = 0; vehicle->drillNull = NULL; vehicle->depositNull = NULL; vehicle->driverNull = NULL; if (vehicle->cameraNullFrames != 0) { pNull = vehicle->cameraNulls; do { *pNull = NULL; i += 1; pNull = pNull + 1; } while (i < vehicle->cameraNullFrames); } i = 0; if (vehicle->carryNullFrames != 0) { pNull = vehicle->carryNulls; do { *pNull = NULL; i += 1; pNull = pNull + 1; } while (i < vehicle->carryNullFrames); } success = Container_SetActivity(vehicle->contAct1,activityName); flags = vehicle->flags; vehicle->flags = flags & ~VEHICLE_FLAG_NOACTIVITY1; if ((success == 0) && ((flags & VEHICLE_FLAG_HOLDMISSING) != VEHICLE_FLAG_NONE)) { BVar1 = Container_IsCurrentActivity(vehicle->contAct1,activityName); if (BVar1 == 0) { vehicle->flags = vehicle->flags | VEHICLE_FLAG_NOACTIVITY1; } } if (vehicle->contAct2 != NULL) { success2 = Container_SetActivity(vehicle->contAct2,activityName); success |= success2; } // if (!(vehicle->flags & VEHICLE_FLAG_NOACTIVITY1)) if ((*(byte *)&vehicle->flags & 4) == 0) { Container_SetAnimationTime(vehicle->contAct1,elapsed); } if (vehicle->contAct2 != NULL) { Container_SetAnimationTime(vehicle->contAct2,elapsed); } Vehicle_PopulateWheelNulls(vehicle); Vehicle_SetUpgradeActivity(vehicle,activityName); return success; } void __cdecl lego::gfx::Vehicle_SetUpgradeActivity(VehicleModel *vehicle,char *activityName) { int *opt_instance; VehicleModel *vehicle_00; Container **ppCVar1; Container *child; char *partName; Container *cont; WeaponsModel *pWVar2; int i; Upgrade_PartModel *upgradePart; uint j; int zero; uint local_c; Upgrade_PartInfo *locPartInfo; Upgrade_PartModel *locUpgradePart; uint index; Upgrade_PartInfo *partInfo; LegoObject *upgradeObj; vehicle_00 = vehicle; i = 3; upgradeObj = (vehicle->upgrades).firstObject; ppCVar1 = (vehicle->weapons).yPivotNulls; pWVar2 = &vehicle->weapons; do { ppCVar1[0x1a] = NULL; *ppCVar1 = NULL; ppCVar1[-3] = NULL; pWVar2->fireNullPairs[0] = NULL; ppCVar1 = ppCVar1 + 1; i += -1; pWVar2->fireNullPairs[1] = NULL; pWVar2 = (WeaponsModel *)pWVar2->fireNullPairs[1]; } while (i != 0); (vehicle->weapons).count = 0; do { if (upgradeObj == NULL) { return; } upgradePart = upgradeObj->upgradePart; partInfo = upgradePart->partInfo; locPartInfo = partInfo; locUpgradePart = upgradePart; cont = Vehicle_FindNull(vehicle_00,partInfo->nullObjectName,partInfo->nullFrameNo); child = Object_GetActivityContainer((BasicObjectModel *)upgradePart); Container_SetParent(child,cont); Container_ClearTransform(child); if (activityName == NULL) { Container_SetActivity(upgradePart->cont,globs::objectGlobs.activityName[0]); } else { Upgrade_Part_SetActivity(upgradePart,activityName); } if (partInfo->weaponName != NULL) { index = (vehicle_00->weapons).count; zero = 0; (vehicle_00->weapons).fireNullPairFrames[index] = 0; j = 0; opt_instance = (vehicle_00->weapons).fireNullPairFrames + index; vehicle = (VehicleModel *)(vehicle_00->weapons).fireNullPairs[index]; local_c = index; do { vehicle->objID = 0; partName = Container_FormatPartName (vehicle_00->contAct1,vehicle_00->fireNullName,opt_instance); cont = Container_SearchTree(child,partName,Container_SearchMode_FirstMatch,NULL); (vehicle_00->weapons).fireNullPairs[index][*opt_instance] = cont; cont = (vehicle_00->weapons).fireNullPairs[index][*opt_instance]; *opt_instance = *opt_instance + 1; if (cont == NULL) break; j += 1; vehicle = (VehicleModel *)&vehicle->wheelNullName; } while (j < 2); partName = Container_FormatPartName(vehicle_00->contAct1,vehicle_00->xPivot,&zero); cont = Container_SearchTree(child,partName,Container_SearchMode_FirstMatch,NULL); index = local_c; (vehicle_00->weapons).xPivotNulls[local_c] = cont; partName = Container_FormatPartName(vehicle_00->contAct1,vehicle_00->yPivot,&zero); cont = Container_SearchTree(child,partName,Container_SearchMode_FirstMatch,NULL); (vehicle_00->weapons).yPivotNulls[index] = cont; (vehicle_00->weapons).parts[index] = locPartInfo; (vehicle_00->weapons).count = (vehicle_00->weapons).count + 1; upgradePart = locUpgradePart; } upgradeObj = upgradePart->nextObject; } while( true ); } // WARNING: Function: _alloca4k replaced with injection: alloca_probe // WARNING: Could not reconcile some variable overlaps BOOL __cdecl lego::gfx::Vehicle_Load (VehicleModel *vehicle,int objID,Container *root,char *aeFilename,char *gameName) { char cVar1; int iVar2; Container *pCVar3; Config *prop; char *pcVar4; BoolTri BVar5; MeshLOD *pMVar6; Config *act; int iVar7; uint uVar8; uint uVar9; int *piVar10; undefined4 *puVar11; VehicleModel *pVVar12; Container **ppCVar13; char *pcVar14; undefined4 *puVar15; float10 fVar16; char *pcStack4560; char *pcStack4556; Box3F BStack4520; char *pcStack4496; int aiStack4492 [99]; undefined4 auStack4096 [256]; char acStack3072 [1024]; char buff2 [1024]; char buff1 [1024]; buff1._1020_4_ = 0x46c9ba; pVVar12 = vehicle; for (iVar7 = 0x7b; iVar7 != 0; iVar7 += -1) { pVVar12->objID = 0; pVVar12 = (VehicleModel *)&pVVar12->wheelNullName; } uVar8 = 0xffffffff; do { pcVar4 = aeFilename; if (uVar8 == 0) break; uVar8 -= 1; pcVar4 = aeFilename + 1; cVar1 = *aeFilename; aeFilename = pcVar4; } while (cVar1 != '\0'); uVar8 = ~uVar8; puVar11 = (undefined4 *)(pcVar4 + -uVar8); puVar15 = (undefined4 *)buff2; for (uVar9 = uVar8 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar11; puVar11 = puVar11 + 1; puVar15 = puVar15 + 1; } for (uVar8 &= 3; uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar11; puVar11 = (undefined4 *)((int)puVar11 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } iVar7 = util::Util_Tokenise(buff2,&pcStack4560,","); pCVar3 = Container_Load(root,pcStack4560,"ACT",TRUE); vehicle->contAct1 = pCVar3; if (pCVar3 != NULL) { if (iVar7 == 2) { pCVar3 = Container_Load(pCVar3,pcStack4556,"ACT",TRUE); vehicle->contAct2 = pCVar3; } else { vehicle->contAct2 = NULL; } uVar8 = 0xffffffff; pcVar4 = pcStack4560; do { pcVar14 = pcVar4; if (uVar8 == 0) break; uVar8 -= 1; pcVar14 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar14; } while (cVar1 != '\0'); uVar8 = ~uVar8; puVar11 = (undefined4 *)(pcVar14 + -uVar8); puVar15 = auStack4096; for (uVar9 = uVar8 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar11; puVar11 = puVar11 + 1; puVar15 = puVar15 + 1; } for (uVar8 &= 3; uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar11; puVar11 = (undefined4 *)((int)puVar11 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } uVar8 = util::Util_Tokenise((char *)auStack4096,&pcStack4496,"\\"); if (1 < uVar8) { piVar10 = aiStack4492; iVar7 = uVar8 - 1; do { iVar2 = *piVar10; piVar10 = piVar10 + 1; iVar7 += -1; *(undefined *)(iVar2 + -1) = '\\'; } while (iVar7 != 0); } std::sprintf(acStack3072,"%s\\%s.%s",(char *)auStack4096,(char *)(&BStack4520.max.z)[uVar8],"ae" ); prop = cfg::Config_Load(acStack3072); if (prop != NULL) { pcVar4 = cfg::Config_BuildStringID(gameName,"CameraNullName",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->cameraNullName = pcVar4; if (pcVar4 == NULL) { vehicle->cameraNullFrames = 0; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"CameraNullFrames",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"CameraNullFrames",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); } uVar8 = std::atoi(pcVar4); vehicle->cameraNullFrames = uVar8; pcVar4 = cfg::Config_BuildStringID(gameName,"CameraFlipDir",0); BVar5 = cfg::Config_GetBoolValue(prop,pcVar4); vehicle->cameraFlipDir = BVar5; } pcVar4 = cfg::Config_BuildStringID(gameName,"CarryNullName",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->carryNullName = pcVar4; if (pcVar4 == NULL) { vehicle->carryNullFrames = 0; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"CarryNullFrames",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); if (pcVar4 == NULL) { uVar8 = std::atoi(____EMPTYSTR__); vehicle->carryNullFrames = uVar8; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"CarryNullFrames",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); uVar8 = std::atoi(pcVar4); vehicle->carryNullFrames = uVar8; } } pcVar4 = cfg::Config_BuildStringID(gameName,"DrillNullName",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->drillNullName = pcVar4; pcVar4 = cfg::Config_BuildStringID(gameName,"DepositNullName",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->depositNullName = pcVar4; pcVar4 = cfg::Config_BuildStringID(gameName,"DriverNullName",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->driverNullName = pcVar4; pcVar4 = cfg::Config_BuildStringID(gameName,"FireNullName",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->fireNullName = pcVar4; pcVar4 = cfg::Config_BuildStringID(gameName,"yPivot",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->yPivot = pcVar4; pcVar4 = cfg::Config_BuildStringID(gameName,"xPivot",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->xPivot = pcVar4; pcVar4 = cfg::Config_BuildStringID(gameName,"PivotMaxZ",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); if (pcVar4 == NULL) { (vehicle->weapons).pivotMaxZ = 1.0; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"PivotMaxZ",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); if (pcVar4 == NULL) { fVar16 = std::atof(____EMPTYSTR__); (vehicle->weapons).pivotMaxZ = (float)fVar16; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"PivotMaxZ",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); fVar16 = std::atof(pcVar4); (vehicle->weapons).pivotMaxZ = (float)fVar16; } } pcVar4 = cfg::Config_BuildStringID(gameName,"PivotMinZ",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); if (pcVar4 == NULL) { (vehicle->weapons).pivotMinZ = -1.0; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"PivotMinZ",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); if (pcVar4 == NULL) { fVar16 = std::atof(____EMPTYSTR__); (vehicle->weapons).pivotMinZ = (float)fVar16; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"PivotMinZ",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); fVar16 = std::atof(pcVar4); (vehicle->weapons).pivotMinZ = (float)fVar16; } } Upgrade_Load(&vehicle->upgrades,prop,gameName); pcVar4 = cfg::Config_BuildStringID(gameName,"WheelMesh",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); if (pcVar4 != NULL) { std::sprintf(buff1,"%s\\%s",(char *)auStack4096,pcVar4); io::Mem_Free(pcVar4); pcVar4 = cfg::Config_BuildStringID(gameName,"WheelNullName",0); pcVar4 = cfg::Config_GetStringValue(prop,pcVar4); vehicle->wheelNullName = pcVar4; if (pcVar4 != NULL) { ppCVar13 = vehicle->contWheels; for (iVar7 = 6; iVar7 != 0; iVar7 += -1) { *ppCVar13 = NULL; ppCVar13 = ppCVar13 + 1; } pCVar3 = Container_Load(vehicle->contAct1,buff1,"LWO",0); vehicle->contWheels[0] = pCVar3; vehicle->wheelNullFrames = 1; ppCVar13 = vehicle->wheelNulls; for (iVar7 = 6; iVar7 != 0; iVar7 += -1) { *ppCVar13 = NULL; ppCVar13 = ppCVar13 + 1; } if (vehicle->contWheels[0] == NULL) { vehicle->wheelRadius = 0.0; vehicle->contWheels[1] = NULL; vehicle->contWheels[2] = NULL; vehicle->contWheels[3] = NULL; vehicle->contWheels[4] = NULL; vehicle->contWheels[5] = NULL; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"WheelRadius",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_BuildStringID(gameName,"WheelRadius",0); pcVar4 = cfg::Config_GetTempStringValue(prop,pcVar4); } fVar16 = std::atof(pcVar4); vehicle->wheelRadius = (float)fVar16; if ((float)fVar16 == 0.0) { if (vehicle->contWheels[0]->type == Container_Type_Mesh) { Container_Mesh_GetBox(vehicle->contWheels[0],&BStack4520); vehicle->wheelRadius = (BStack4520.max.y - BStack4520.min.y) * 0.5; Container_Mesh_SetQuality(vehicle->contWheels[0],D3DRMGROUP_0,Gouraud); } else { vehicle->wheelRadius = 3.0; } } } pMVar6 = game::LegoObject_LoadMeshLOD(prop,gameName,pcStack4560,LOD_MediumPoly,1); vehicle->polyMedium1 = pMVar6; if (vehicle->contAct2 != NULL) { uVar8 = 0xffffffff; pcVar4 = pcStack4556; do { pcVar14 = pcVar4; if (uVar8 == 0) break; uVar8 -= 1; pcVar14 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar14; } while (cVar1 != '\0'); uVar8 = ~uVar8; puVar11 = (undefined4 *)(pcVar14 + -uVar8); puVar15 = auStack4096; for (uVar9 = uVar8 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar11; puVar11 = puVar11 + 1; puVar15 = puVar15 + 1; } for (uVar8 &= 3; uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar11; puVar11 = (undefined4 *)((int)puVar11 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } uVar8 = util::Util_Tokenise((char *)auStack4096,&pcStack4496,"\\"); if (1 < uVar8) { piVar10 = aiStack4492; iVar7 = uVar8 - 1; do { iVar2 = *piVar10; piVar10 = piVar10 + 1; iVar7 += -1; *(undefined *)(iVar2 + -1) = '\\'; } while (iVar7 != 0); } std::sprintf(acStack3072,"%s\\%s.%s",(char *)auStack4096, (char *)(&BStack4520.max.z)[uVar8],"ae"); act = cfg::Config_Load(acStack3072); if (act != NULL) { pMVar6 = game::LegoObject_LoadMeshLOD(act,gameName,pcStack4556,LOD_MediumPoly,1); vehicle->polyMedium2 = pMVar6; } } vehicle->flags = VEHICLE_FLAG_SOURCE; pcVar4 = cfg::Config_BuildStringID(gameName,"HoldMissing",0); BVar5 = cfg::Config_GetBoolValue(prop,pcVar4); if (BVar5 == BOOL3_TRUE) { vehicle->flags = vehicle->flags | VEHICLE_FLAG_HOLDMISSING; } (vehicle->wheelLastUp).y = 0.0; (vehicle->wheelLastUp).x = 0.0; (vehicle->wheelLastUp).z = -1.0; vehicle->objID = objID; cfg::Config_Free(prop); return TRUE; } } cfg::Config_Free(prop); } } return FALSE; } // Similar to `Vehicle_Load`, this does not free the passed pointer. void __cdecl lego::gfx::Vehicle_Remove(VehicleModel *vehicle) { int i; Container **pWheelRef; // Set level to -1 to forcefully remove all upgrade model parts. Vehicle_SetUpgradeLevel(vehicle,0xffffffff); // Only free string memory if this is the original if ((*(byte *)&vehicle->flags & 1) != 0) { if (vehicle->cameraNullName != NULL) { io::Mem_Free(vehicle->cameraNullName); } if (vehicle->wheelNullName != NULL) { io::Mem_Free(vehicle->wheelNullName); } if (vehicle->drillNullName != NULL) { io::Mem_Free(vehicle->drillNullName); } if (vehicle->fireNullName != NULL) { io::Mem_Free(vehicle->fireNullName); } } pWheelRef = vehicle->wheelNulls; i = 6; do { if (pWheelRef[-6] != NULL) { Container_Remove(pWheelRef[-6]); } if (*pWheelRef != NULL) { Container_Remove(*pWheelRef); } pWheelRef = pWheelRef + 1; i += -1; } while (i != 0); Container_Remove(vehicle->contAct1); if (vehicle->contAct2 != NULL) { Container_Remove(vehicle->contAct2); } return; } void __cdecl lego::gfx::Vehicle_SwapPolyMedium(VehicleModel *vehicle,BOOL swap) { MeshLOD_SwapTarget(vehicle->polyMedium1,vehicle->contAct1,(uint)(swap == 0),0); if ((vehicle->contAct2 != NULL) && (vehicle->polyMedium2 != NULL)) { MeshLOD_SwapTarget(vehicle->polyMedium2,vehicle->contAct2,(uint)(swap == 0),0); } return; } // There's no stored HighPoly data, this just calls `Vehicle_SwapPolyMedium` void __cdecl lego::gfx::Vehicle_SwapPolyHigh(VehicleModel *vehicle,BOOL swap) { Vehicle_SwapPolyMedium(vehicle,swap); return; } // When `current` is true, the function returns whether the object can currently get this upgrade. // (AKA, has the object not gotten the upgrade yet? And does it support the upgrade type?) // Otherwise the function returns whether the object type supports the upgrade at all. BOOL __cdecl lego::gfx::Vehicle_CanUpgradeType (VehicleModel *vehicle,LegoObject_UpgradeType upgradeType,BOOL current) { uint level; uint mask; mask = 1 << ((byte)upgradeType & 0x1f); if (current != 0) { level = Vehicle_GetUpgradeLevel(vehicle); if ((mask & level) != 0) { return 0; } } return (vehicle->upgrades).levelFlags & mask; } uint __cdecl lego::gfx::Vehicle_GetUpgradeLevel(VehicleModel *vehicle) { return (vehicle->upgrades).currentLevel; } void __cdecl lego::gfx::Vehicle_SetUpgradeLevel(VehicleModel *vehicle,uint objLevel) { Upgrade_SetUpgradeLevel(&vehicle->upgrades,objLevel); Vehicle_SetUpgradeActivity(vehicle,NULL); return; } void __cdecl lego::gfx::Vehicle_HideWheels(VehicleModel *vehicle,BOOL hide) { Container **pWheel; int i; pWheel = vehicle->contWheels; i = 6; do { if (*pWheel != NULL) { Container_Hide(*pWheel,hide); } pWheel = pWheel + 1; i += -1; } while (i != 0); return; } BOOL __cdecl lego::gfx::Vehicle_Clone(VehicleModel *srcVehicle,VehicleModel *destVehicle) { Container *cont; MeshLOD *pMVar1; int iVar2; VehicleModel *pVVar3; Container **ppCVar4; VehicleModel *pVVar5; uint uVar6; pVVar3 = srcVehicle; pVVar5 = destVehicle; for (iVar2 = 0x7b; iVar2 != 0; iVar2 += -1) { pVVar5->objID = pVVar3->objID; pVVar3 = (VehicleModel *)&pVVar3->wheelNullName; pVVar5 = (VehicleModel *)&pVVar5->wheelNullName; } destVehicle->flags = destVehicle->flags & ~VEHICLE_FLAG_SOURCE; cont = Container_Clone(srcVehicle->contAct1); destVehicle->contAct1 = cont; if (cont != NULL) { if (srcVehicle->contAct2 != NULL) { cont = Container_Clone(srcVehicle->contAct2); destVehicle->contAct2 = cont; Container_SetParent(cont,destVehicle->contAct1); Container_SetPosition(destVehicle->contAct2,destVehicle->contAct1,0.0,0.0,0.0); Container_SetOrientation(destVehicle->contAct2,destVehicle->contAct1,0.0,0.0,1.0,0.0,1.0,0.0); Container_SetPerspectiveCorrection(destVehicle->contAct2,TRUE); } pMVar1 = MeshLOD_Clone(srcVehicle->polyMedium1); destVehicle->polyMedium1 = pMVar1; if (srcVehicle->polyMedium2 != NULL) { pMVar1 = MeshLOD_Clone(srcVehicle->polyMedium2); destVehicle->polyMedium2 = pMVar1; } Container_SetPerspectiveCorrection(destVehicle->contAct1,TRUE); Vehicle_PopulateWheelNulls(destVehicle); if ((srcVehicle->contWheels[0] != NULL) && (uVar6 = 0, destVehicle->wheelNullFrames != 0)) { ppCVar4 = destVehicle->contWheels; do { cont = Container_Clone(srcVehicle->contWheels[0]); *ppCVar4 = cont; if (cont != NULL) { Container_SetParent(cont,destVehicle->contAct1); Container_SetPerspectiveCorrection(*ppCVar4,TRUE); } uVar6 += 1; ppCVar4 = ppCVar4 + 1; } while (uVar6 < destVehicle->wheelNullFrames); } return TRUE; } return FALSE; } void __cdecl lego::gfx::Vehicle_SetOwnerObject(VehicleModel *vehicle,LegoObject *liveObj) { Container **pWheel; uint i; Container_SetUserData(vehicle->contAct1,liveObj); if (vehicle->contAct2 != NULL) { Container_SetUserData(vehicle->contAct2,liveObj); } i = 0; if (vehicle->wheelNullFrames != 0) { pWheel = vehicle->contWheels; do { if (*pWheel != NULL) { Container_SetUserData(*pWheel,liveObj); } i += 1; pWheel = pWheel + 1; } while (i < vehicle->wheelNullFrames); } return; } float10 __cdecl lego::gfx::Vehicle_GetAnimationTime(VehicleModel *vehicle) { float10 fVar1; fVar1 = Container_GetAnimationTime(vehicle->contAct1); return fVar1; } float10 __cdecl lego::gfx::Vehicle_MoveAnimation (VehicleModel *vehicle,float elapsed1,float elapsed2,uint repeatCount) { float fVar1; uint uVar2; float10 fVar3; if ((*(byte *)&vehicle->flags & 4) == 0) { fVar3 = Container_MoveAnimation(vehicle->contAct1,elapsed1); } else { fVar3 = (float10)0.0; } if (vehicle->contAct2 != NULL) { fVar3 = Container_MoveAnimation(vehicle->contAct2,elapsed2); } fVar1 = (float)fVar3; if ((1 < repeatCount) && (fVar1 != 0.0)) { uVar2 = Container_GetAnimationFrames(vehicle->contAct1); return (float10)fVar1 - (float10)(ulonglong)(uVar2 * (repeatCount - 1)); } return (float10)fVar1; } void __cdecl lego::gfx::Vehicle_PopulateWheelNulls(VehicleModel *vehicle) { char *partName; Container *cont; VehicleModel *vehicle_00; vehicle_00 = vehicle; vehicle = NULL; vehicle_00->wheelNullFrames = 0; do { partName = Container_FormatPartName (vehicle_00->contAct1,vehicle_00->wheelNullName,(int *)&vehicle); cont = Container_SearchTree(vehicle_00->contAct1,partName,Container_SearchMode_FirstMatch,NULL); vehicle_00->wheelNulls[(int)vehicle] = cont; if (vehicle_00->wheelNulls[(int)vehicle] != NULL) { vehicle_00->wheelNullFrames = vehicle_00->wheelNullFrames + 1; } vehicle = (VehicleModel *)((int)&vehicle->objID + 1); } while (vehicle < (VehicleModel *)0x6); return; } void __cdecl lego::gfx::Vehicle_Hide(VehicleModel *vehicle,BOOL hide) { VehicleFlags VVar1; Container **pWheel; uint i; if (hide == 0) { VVar1 = vehicle->flags & ~VEHICLE_FLAG_HIDDEN; } else { VVar1 = vehicle->flags | VEHICLE_FLAG_HIDDEN; } vehicle->flags = VVar1; Container_Hide(vehicle->contAct1,hide); if (vehicle->contAct2 != NULL) { Container_Hide(vehicle->contAct2,hide); } i = 0; if (vehicle->wheelNullFrames != 0) { pWheel = vehicle->contWheels; do { if (*pWheel != NULL) { Container_Hide(*pWheel,hide); } i += 1; pWheel = pWheel + 1; } while (i < vehicle->wheelNullFrames); } return; } BOOL __cdecl lego::gfx::Vehicle_IsHidden(VehicleModel *vehicle) { return (vehicle->flags & 0xff) >> 1 & 1; } void __cdecl lego::gfx::Vehicle_SetOrientation(VehicleModel *vehicle,float xDir,float yDir,float zDir) { Container_SetOrientation(vehicle->contAct1,NULL,xDir,yDir,zDir,0.0,0.0,-1.0); return; } void __cdecl lego::gfx::Vehicle_SetPosition (VehicleModel *vehicle,float xPos,float yPos,GetWorldZCallback zCallback,Map3D *map) { float fVar1; int iVar2; uint i; float *pfVar3; Vector3F *pVVar4; float10 zPos; Vector3F up; Vector3F tempB; float angle; Vector3F direction; Vector3F local_7c; Vector3F crossA; Vector3F crossB; uint ii; Vector3F wheelPositions [6]; Vector3F unused_up; Container **pWheel; zPos = (*zCallback)(xPos,yPos,map); Container_SetPosition(vehicle->contAct1,NULL,xPos,yPos,(float)zPos); Container_GetOrientation(vehicle->contAct1,NULL,&direction,&unused_up); Container_SetOrientation(vehicle->contAct1,NULL,direction.x,direction.y,direction.z,0.0,0.0,-1.0); if (vehicle->wheelNullFrames != 0) { i = 0; if (vehicle->wheelNullFrames != 0) { pVVar4 = wheelPositions; pWheel = vehicle->wheelNulls; do { Container_GetPosition(*pWheel,NULL,pVVar4); zPos = (*zCallback)(pVVar4->x,pVVar4->y,map); pVVar4->z = (float)zPos; i += 1; pWheel = pWheel + 1; pVVar4 = pVVar4 + 1; } while (i < vehicle->wheelNullFrames); } tempB.x = wheelPositions[1].x - wheelPositions[2].x; tempB.y = wheelPositions[1].y - wheelPositions[2].y; tempB.z = wheelPositions[1].z - wheelPositions[2].z; crossA.x = tempB.z * (wheelPositions[1].y - wheelPositions[0].y) - tempB.y * (wheelPositions[1].z - wheelPositions[0].z); crossA.y = tempB.x * (wheelPositions[1].z - wheelPositions[0].z) - tempB.z * (wheelPositions[1].x - wheelPositions[0].x); crossA.z = tempB.y * (wheelPositions[1].x - wheelPositions[0].x) - tempB.x * (wheelPositions[1].y - wheelPositions[0].y); math::Maths_Vector3DScale (&crossA,&crossA, 1.0 / SQRT(crossA.z * crossA.z + crossA.y * crossA.y + crossA.x * crossA.x)); tempB.x = wheelPositions[3].x - wheelPositions[0].x; tempB.y = wheelPositions[3].y - wheelPositions[0].y; crossB.x = (wheelPositions[3].z - wheelPositions[0].z) * (wheelPositions[3].y - wheelPositions[2].y) - tempB.y * (wheelPositions[3].z - wheelPositions[2].z); crossB.y = tempB.x * (wheelPositions[3].z - wheelPositions[2].z) - (wheelPositions[3].z - wheelPositions[0].z) * (wheelPositions[3].x - wheelPositions[2].x); crossB.z = tempB.y * (wheelPositions[3].x - wheelPositions[2].x) - tempB.x * (wheelPositions[3].y - wheelPositions[2].y); math::Maths_Vector3DScale (&crossB,&crossB, 1.0 / SQRT(crossB.z * crossB.z + crossB.y * crossB.y + crossB.x * crossB.x)); up.x = crossB.x + crossA.x; up.y = crossB.y + crossA.y; up.z = crossB.z + crossA.z; math::Maths_Vector3DScale(&up,&up,1.0 / SQRT(up.z * up.z + up.y * up.y + up.x * up.x)); pVVar4 = &vehicle->wheelLastUp; iVar2 = std::_finite((double)(vehicle->wheelLastUp).x); if (((iVar2 == 0) || (iVar2 = std::_finite((double)(vehicle->wheelLastUp).y), iVar2 == 0)) || (iVar2 = std::_finite((double)(vehicle->wheelLastUp).y), iVar2 == 0)) { pVVar4->x = up.x; (vehicle->wheelLastUp).y = up.y; (vehicle->wheelLastUp).z = up.z; } up.x = pVVar4->x * 0.4 + up.x; up.y = (vehicle->wheelLastUp).y * 0.4 + up.y; up.z = (vehicle->wheelLastUp).z * 0.4 + up.z; fVar1 = 1.0 / SQRT(up.z * up.z + up.y * up.y + up.x * up.x); up.x = fVar1 * up.x; up.y = fVar1 * up.y; up.z = fVar1 * up.z; fVar1 = direction.z * up.z + direction.y * up.y + direction.x * up.x; pVVar4->x = up.x; direction.x = direction.x - fVar1 * up.x; direction.y = direction.y - fVar1 * up.y; direction.z = direction.z - fVar1 * up.z; (vehicle->wheelLastUp).y = up.y; (vehicle->wheelLastUp).z = up.z; Container_SetOrientation (vehicle->contAct1,NULL,direction.x,direction.y,direction.z,-up.x,-up.y,-up.z); i = 0; if (vehicle->wheelNullFrames != 0) { pVVar4 = wheelPositions; pWheel = vehicle->wheelNulls; do { Container_GetPosition(*pWheel,NULL,pVVar4); zPos = (*zCallback)(pVVar4->x,pVVar4->y,map); Container_AddTranslation (*pWheel,Container_Combine_After,0.0, (float)-((zPos - (float10)pVVar4->z) - (float10)vehicle->wheelRadius),0.0); i += 1; pWheel = pWheel + 1; pVVar4 = pVVar4 + 1; } while (i < vehicle->wheelNullFrames); } i = 0; if (vehicle->wheelNullFrames != 0) { pWheel = vehicle->contWheels; do { if (*pWheel != NULL) { Container_SetPosition(*pWheel,pWheel[6],0.0,0.0,0.0); } i += 1; pWheel = pWheel + 1; } while (i < vehicle->wheelNullFrames); } ii = 0; if (vehicle->wheelNullFrames != 0) { pVVar4 = wheelPositions; pWheel = vehicle->contWheels; pfVar3 = &vehicle->wheelLastPositions[0].z; do { if (*pWheel != NULL) { Container_GetPosition(*pWheel,NULL,pVVar4); tempB.x = pVVar4->x - pfVar3[-2]; tempB.y = pVVar4->y - pfVar3[-1]; tempB.z = pVVar4->z - *pfVar3; angle = SQRT(tempB.z * tempB.z + tempB.y * tempB.y + tempB.x * tempB.x) / vehicle->wheelRadius; if (tempB.z * direction.z + tempB.y * direction.y + tempB.x * direction.x < 0.0) { angle = -angle; } Container_AddRotation(*pWheel,Container_Combine_Before,1.0,0.0,0.0,angle); } ii += 1; pWheel = pWheel + 1; pfVar3 = pfVar3 + 3; pVVar4 = pVVar4 + 1; } while (ii < vehicle->wheelNullFrames); } i = 0; if (vehicle->wheelNullFrames != 0) { pWheel = vehicle->contWheels; pVVar4 = vehicle->wheelLastPositions; do { if (*pWheel != NULL) { Container_GetPosition(*pWheel,NULL,pVVar4); } i += 1; pVVar4 = pVVar4 + 1; pWheel = pWheel + 1; } while (i < vehicle->wheelNullFrames); } return; } return; } Container * __cdecl lego::gfx::Vehicle_GetActivityContainer(VehicleModel *vehicle) { return vehicle->contAct1; } Container * __cdecl lego::gfx::Vehicle_FindNull(VehicleModel *vehicle,char *nullName,uint nullFrameNo) { Container *cont; char *partName; cont = NULL; if (vehicle->contAct2 != NULL) { partName = Container_FormatPartName(vehicle->contAct2,nullName,(int *)&nullFrameNo); cont = Container_SearchTree(vehicle->contAct2,partName,Container_SearchMode_FirstMatch,NULL); } if (cont == NULL) { partName = Container_FormatPartName(vehicle->contAct1,nullName,(int *)&nullFrameNo); cont = Container_SearchTree(vehicle->contAct1,partName,Container_SearchMode_FirstMatch,NULL); } return cont; } Container * __cdecl lego::gfx::Vehicle_GetCameraNull(VehicleModel *vehicle,uint frameNo) { Container *cont; if (vehicle->cameraNullName == NULL) { return NULL; } if (vehicle->cameraNulls[frameNo] != NULL) { return vehicle->cameraNulls[frameNo]; } cont = Vehicle_FindNull(vehicle,vehicle->cameraNullName,frameNo); vehicle->cameraNulls[frameNo] = cont; return cont; } Container * __cdecl lego::gfx::Vehicle_GetDrillNull(VehicleModel *vehicle) { Container *cont; if (vehicle->drillNullName == NULL) { cont = NULL; } else { cont = vehicle->drillNull; if (cont == NULL) { cont = Vehicle_FindNull(vehicle,vehicle->drillNullName,0); vehicle->drillNull = cont; return cont; } } return cont; } Container * __cdecl lego::gfx::Vehicle_GetDepositNull(VehicleModel *vehicle) { Container *cont; if (vehicle->depositNullName == NULL) { cont = NULL; } else { cont = vehicle->depositNull; if (cont == NULL) { cont = Vehicle_FindNull(vehicle,vehicle->depositNullName,0); vehicle->depositNull = cont; return cont; } } return cont; } Container * __cdecl lego::gfx::Vehicle_GetDriverNull(VehicleModel *vehicle) { Container *cont; if (vehicle->driverNullName == NULL) { cont = NULL; } else { cont = vehicle->driverNull; if (cont == NULL) { cont = Vehicle_FindNull(vehicle,vehicle->driverNullName,0); vehicle->driverNull = cont; return cont; } } return cont; } Container * __cdecl lego::gfx::Vehicle_GetCarryNull(VehicleModel *vehicle,uint frameNo) { Container *cont; if (vehicle->carryNullName == NULL) { return NULL; } if (vehicle->carryNulls[frameNo] != NULL) { return vehicle->carryNulls[frameNo]; } cont = Vehicle_FindNull(vehicle,vehicle->carryNullName,frameNo); vehicle->carryNulls[frameNo] = cont; return cont; } uint __cdecl lego::gfx::Vehicle_GetCarryNullFrames(VehicleModel *vehicle) { return vehicle->carryNullFrames; } float10 __cdecl lego::gfx::Vehicle_GetTransCoef(VehicleModel *vehicle) { float10 fVar1; fVar1 = Container_GetTransCoef(vehicle->contAct1); return fVar1; } // Module for handling the unfinished "Flood water" feature. // This is designed for the block "SurfaceType_Water" (0x7), // which is unused. void __cdecl lego::game::Water_Initialise(Container *root,Lego_Level *level) { Water_Pool *pool; uint j; uint width; int iVar1; uint *pPointsCount; uint x; uint y; Water_Pool **pPairSecond; uint bxEnd; uint bxStart; Point2F *pPVar2; uint i; Water_Pool *first; Water_Pool *second; y = 0; globs::waterGlobs.poolCount = 0; globs::waterGlobs.mergeCount = 0; // Assigned, but never used, level->DigDepth is always used instead globs::waterGlobs.digDepth = level->DigDepth; // This is a flood-fill algorithm. if (level->height != 0) { do { bxEnd = 0; bxStart = 0; x = 0; width = level->width; if (width != 0) { do { if (level->blocks[y * width + x].terrain == Lego_SurfaceType8_Water) { if (bxStart == bxEnd) { bxStart = x; } bxEnd = x + 1; } else { if (bxStart != bxEnd) { pool = Water_FindPoolAndMergeRows(y,bxStart,bxEnd); if (pool == NULL) { Water_AddPool(y,bxStart,bxEnd); } else { Water_AddPoolRowBlocks(pool,y,bxStart,bxEnd); } } bxEnd = 0; bxStart = 0; } width = level->width; x += 1; } while (x < width); } y += 1; } while (y < level->height); } i = 0; if (globs::waterGlobs.mergeCount != 0) { pPairSecond = &globs::waterGlobs.mergeList[0].removedPool; do { second = *pPairSecond; first = pPairSecond[-1]; if (second->blockCount != 0) { // std::memcpy(&first->points[first->pointsCount], &second->points[0], // second->pointsCount * sizeof(uint)); // // first->pointsCount += second->pointsCount; // second->pointsCount = 0; pool = second; pPVar2 = first->blocks + first->blockCount; for (y = (second->blockCount << 3) >> 2; y != 0; y -= 1) { pPVar2->x = pool->blocks[0].x; pool = (Water_Pool *)&pool->blocks[0].y; pPVar2 = (Point2F *)&pPVar2->y; } for (iVar1 = 0; iVar1 != 0; iVar1 += -1) { *(undefined *)&pPVar2->x = *(undefined *)&pool->blocks[0].x; pool = (Water_Pool *)((int)&pool->blocks[0].x + 1); pPVar2 = (Point2F *)((int)&pPVar2->x + 1); } first->blockCount = first->blockCount + second->blockCount; second->blockCount = 0; } i += 1; pPairSecond = pPairSecond + 2; } while (i < globs::waterGlobs.mergeCount); } // Sort by pointsCount, highest to lowest std::qsort(&globs::waterGlobs,globs::waterGlobs.poolCount,0x428,Water_QsortComparePools); // Then cap entryCount to number of entries with non-zero pointsCount's j = 0; if (globs::waterGlobs.poolCount != 0) { pPointsCount = &globs::waterGlobs.poolList[0].blockCount; y = globs::waterGlobs.poolCount; do { if (*pPointsCount == 0) { y = j; globs::waterGlobs.poolCount = j; } j += 1; pPointsCount = pPointsCount + 0x10a; } while (j < y); } Water_InitPoolDrains(root,level); Water_InitVertices(root,level); return; } void __cdecl lego::game::Water_InitPoolDrains(Container *root,Lego_Level *level) { int iVar1; int iVar2; uint uVar3; float *pfVar4; longlong lVar5; Point2F *local_30; uint local_2c; uint *local_28; uint i; Point2F DIRECTIONS [4]; Lego_SurfaceType8 terrain; DIRECTIONS[0].x = 0.0; DIRECTIONS[0].y = -1.0; DIRECTIONS[1].x = 1.0; DIRECTIONS[1].y = 0.0; DIRECTIONS[2].x = 0.0; DIRECTIONS[2].y = 1.0; DIRECTIONS[3].x = -1.0; DIRECTIONS[3].y = 0.0; i = 0; if (globs::waterGlobs.poolCount != 0) { local_28 = &globs::waterGlobs.poolList[0].blockCount; do { local_30 = (Point2F *)(local_28 + -200); local_28[0x3d] = 0; local_2c = 0; if (*local_28 != 0) { do { uVar3 = 0; pfVar4 = &DIRECTIONS[0].y; do { lVar5 = __ftol((float10)pfVar4[-1] + (float10)local_30->x); iVar1 = (int)lVar5; lVar5 = __ftol((float10)local_30->y + (float10)*pfVar4); iVar2 = (int)lVar5; if ((((-1 < iVar1) && (iVar1 < (int)level->width)) && (-1 < iVar2)) && (((iVar2 < (int)level->height && (terrain = level->blocks[iVar2 * level->width + iVar1].terrain, terrain != Lego_SurfaceType8_Water)) && (terrain != Lego_SurfaceType8_Immovable)))) { local_28[local_28[0x3d] * 6 + 1] = local_2c; local_28[local_28[0x3d] * 6 + 2] = uVar3; local_28[0x3d] = local_28[0x3d] + 1; break; } uVar3 += 1; pfVar4 = pfVar4 + 2; } while (uVar3 < 4); local_30 = local_30 + 1; local_2c += 1; } while (local_2c < *local_28); } i += 1; local_28 = local_28 + 0x10a; } while (i < globs::waterGlobs.poolCount); } return; } void __cdecl lego::game::Water_InitVertices(Container *root,Lego_Level *level) { float fVar1; uint uVar2; Container *cont; D3DRMGroupIndex groupID; float *pfVar3; uint uVar4; float *pfVar5; Point2F *pPVar6; float *pfVar7; longlong lVar8; longlong lVar9; Vector3F *pVVar10; uint j; uint *pEntryOff320; float *local_130; int local_12c; uint i; float TU_COORDS [4]; float TV_COORDS [4]; uint FACEDATA [6]; Point2F DIRECTIONS [4]; Vector3F vertPoses [4]; Vertex vertices [4]; FACEDATA[1] = 1; FACEDATA[3] = 1; DIRECTIONS[0].x = 0.0; DIRECTIONS[0].y = 0.0; DIRECTIONS[1].x = 1.0; DIRECTIONS[1].y = 0.0; DIRECTIONS[2].x = 1.0; DIRECTIONS[2].y = 1.0; DIRECTIONS[3].x = 0.0; DIRECTIONS[3].y = 1.0; FACEDATA[0] = 0; FACEDATA[2] = 3; FACEDATA[4] = 2; FACEDATA[5] = 3; TU_COORDS[0] = 0.0; TU_COORDS[1] = 1.0; TU_COORDS[2] = 1.0; TU_COORDS[3] = 0.0; TV_COORDS[0] = 0.0; TV_COORDS[1] = 0.0; TV_COORDS[2] = 1.0; TV_COORDS[3] = 1.0; i = 0; if (globs::waterGlobs.poolCount != 0) { pEntryOff320 = &globs::waterGlobs.poolList[0].blockCount; do { pfVar7 = (float *)(pEntryOff320 + -200); // structTable[i].float_z_418 = -10000.0; pEntryOff320[0x3e] = 0xc61c4000; j = 0; pfVar5 = pfVar7; if (*pEntryOff320 != 0) { do { pVVar10 = vertPoses; lVar8 = __ftol((float10)pfVar5[1]); uVar2 = (uint)lVar8; lVar8 = __ftol((float10)*pfVar5); lego::map::Map3D_GetBlockVertexPositions(level->map,(uint)lVar8,uVar2,pVVar10); local_130 = &vertPoses[0].z; pPVar6 = DIRECTIONS; local_12c = 4; do { lVar8 = __ftol((float10)pPVar6->y + (float10)pfVar5[1]); uVar2 = level->width; lVar9 = __ftol((float10)*pfVar5 + (float10)pPVar6->x); if (level->blocks[(int)lVar8 * uVar2 + (int)lVar9].predug == Lego_PredugType_Wall) { if ((ushort)((ushort)(*local_130 < (float)pEntryOff320[0x3e]) << 8 | (ushort)(*local_130 == (float)pEntryOff320[0x3e]) << 0xe) == 0) { // structTable[i].dig_z_418 = vertPoses[k].z; pEntryOff320[0x3e] = (uint)*local_130; } } else { pEntryOff320[0x41] = pEntryOff320[0x41] | 1; } pPVar6 = pPVar6 + 1; local_130 = local_130 + 3; local_12c += -1; } while (local_12c != 0); j += 1; pfVar5 = pfVar5 + 2; } while (j < *pEntryOff320); } // structTable[i].float_z2_41c = structTable[i].float_z_418; pEntryOff320[0x3f] = pEntryOff320[0x3e]; cont = gfx::Container_MakeMesh2(root,Container_MeshType_Transparent); pEntryOff320[0x40] = (uint)cont; gfx::Container_Hide(cont,~pEntryOff320[0x41] & 1); j = 0; if (*pEntryOff320 != 0) { do { groupID = gfx::Container_Mesh_AddGroup((Container *)pEntryOff320[0x40],4,2,3,FACEDATA); gfx::Container_Mesh_SetColourAlpha ((Container *)pEntryOff320[0x40],groupID,0.0,0.3,0.8,0.6); pVVar10 = vertPoses; lVar8 = __ftol((float10)pfVar7[1]); uVar2 = (uint)lVar8; lVar8 = __ftol((float10)*pfVar7); lego::map::Map3D_GetBlockVertexPositions(level->map,(uint)lVar8,uVar2,pVVar10); pfVar5 = &vertPoses[0].y; pfVar3 = &vertices[0].position.y; uVar2 = 0; do { // vertices[k].position.x = vertPoses[k].x; // vertices[k].position.y = vertPoses[k].y; // vertices[k].position.z = structTable[i].float_z_418; // vertices[k].normal.x = 0.0f; // vertices[k].normal.y = 0.0f; // vertices[k].normal.z = -1.0f; // vertices[k].tu = TU_COORDS[k]; // vertices[k].tv = TV_COORDS[k]; // vertices[k].colour = 0; pfVar3[-1] = pfVar5[-1]; *pfVar3 = *pfVar5; pfVar3[1] = (float)pEntryOff320[0x3e]; uVar4 = uVar2 + 4; pfVar5 = pfVar5 + 3; pfVar3[2] = 0.0; pfVar3[3] = 0.0; pfVar3[4] = -1.0; fVar1 = *(float *)((int)TU_COORDS + uVar2); pfVar3[7] = 0.0; pfVar3[5] = fVar1; pfVar3[6] = *(float *)((int)TV_COORDS + uVar2); pfVar3 = pfVar3 + 9; uVar2 = uVar4; } while (uVar4 < 0x10); gfx::Container_Mesh_SetVertices((Container *)pEntryOff320[0x40],j,0,4,vertices); j += 1; pfVar7 = pfVar7 + 2; } while (j < *pEntryOff320); } i += 1; pEntryOff320 = pEntryOff320 + 0x10a; } while (i < globs::waterGlobs.poolCount); } return; } // This function can be completely ignored, since there's not actual information on what // logf_removed is doing. void __cdecl lego::debug::Water_ChangeViewMode_removed(BOOL isFPViewMode) { Container **pContMeshTrans; uint i; Container *message; float arg1; float arg2; i = 0; if (globs::waterGlobs.poolCount != 0) { pContMeshTrans = &globs::waterGlobs.poolList[0].contMeshTrans; do { if (isFPViewMode == 0) { // contMeshTrans (Container*), 0.0, 0.0 message = *pContMeshTrans; arg2 = 0.0; arg1 = 0.0; } else { message = *pContMeshTrans; // contMeshTrans (Container*), 0.12, 0.32 arg2 = 0.32; arg1 = 0.12; } util::logf_removed((char *)message,0,arg1,arg2); i += 1; pContMeshTrans = pContMeshTrans + 0x10a; } while (i < globs::waterGlobs.poolCount); } return; } void __cdecl lego::game::Water_DestroyWallComplete(Lego_Level *level,uint bx,uint by) { float fVar1; Water_Pool *pool; uint by_00; longlong lVar2; Vector3F *out_vertPoses; Point2I VERT_OFFSETS [4]; Vector3F vertPoses [4]; uint drainIndex; Water_PoolDrain *item; VERT_OFFSETS[1].y = 2; VERT_OFFSETS[2].x = 2; VERT_OFFSETS[2].y = 3; VERT_OFFSETS[3].x = 3; VERT_OFFSETS[0].x = 0; VERT_OFFSETS[0].y = 1; VERT_OFFSETS[1].x = 1; VERT_OFFSETS[3].y = 0; pool = Water_FindPoolDrain(bx,by,&by); if (pool != NULL) { pool->flags = pool->flags & ~WATER_FLAG_SETTLED | WATER_FLAG_VISIBLE; gfx::Container_Hide(pool->contMeshTrans,0); out_vertPoses = vertPoses; drainIndex = pool->drainList[by].blockIndex; item = pool->drainList + by; item->active = 1; item->elapsedUp_c = 0.0; item->elapsedDown_10 = 0.0; lVar2 = __ftol((float10)pool->blocks[drainIndex].y); by_00 = (uint)lVar2; lVar2 = __ftol((float10)pool->blocks[drainIndex].x); lego::map::Map3D_GetBlockVertexPositions(level->map,(uint)lVar2,by_00,out_vertPoses); fVar1 = -vertPoses[VERT_OFFSETS[item->direction].x].z; if (-vertPoses[VERT_OFFSETS[item->direction].y].z <= -vertPoses[VERT_OFFSETS[item->direction].x].z) { fVar1 = -vertPoses[VERT_OFFSETS[item->direction].y].z; } item->drainWaterLevel = -fVar1; } return; } // Dams up a drain block, causing a pool to start filling (as long as no other drains are undammed). void __cdecl lego::game::Water_DamBlock(uint bx,uint by) { Water_Pool *pool; pool = Water_FindPoolDrain(bx,by,&by); if (pool != NULL) { // &= ~0x2; // |= 0x1; pool->flags = pool->flags & ~WATER_FLAG_FULL | WATER_FLAG_VISIBLE; gfx::Container_Hide(pool->contMeshTrans,FALSE); pool->drainList[by].active = FALSE; } return; } void __cdecl lego::game::Water_Update(Lego_Level *level,float elapsedGame) { float fVar1; float *pVertPosZ; float *pGroupOff8; int k; uint j; uint *pEntryOff414; D3DRMGroupIndex groupID; bool rising; uint numActiveDrains; uint i; Vertex vertices [4]; uint flags; bool bElapseDown; bool lowering; float lowestWaterLevel; float waterLevelDiff; numActiveDrains = 0; i = 0; if (globs::waterGlobs.poolCount != 0) { pEntryOff414 = &globs::waterGlobs.poolList[0].drainCount; do { lowering = false; lowestWaterLevel = (float)pEntryOff414[1]; rising = (*(byte *)(pEntryOff414 + 4) & 2) == 0; j = 0; if (*pEntryOff414 != 0) { pGroupOff8 = (float *)(pEntryOff414 + -0x3a); do { bElapseDown = false; if ((pGroupOff8[3] == 0.0) || ((ushort)((ushort)((float)pEntryOff414[2] < *pGroupOff8) << 8 | (ushort)((float)pEntryOff414[2] == *pGroupOff8) << 0xe) == 0)) { LAB_0046e6eb: bElapseDown = true; } else { if (lowestWaterLevel < *pGroupOff8) { lowestWaterLevel = *pGroupOff8; } rising = false; numActiveDrains += 1; lowering = true; if ((float)pEntryOff414[2] == *pGroupOff8) goto LAB_0046e6eb; } waterLevelDiff = pGroupOff8[1] + elapsedGame * 1.5; pGroupOff8[1] = waterLevelDiff; if (bElapseDown) { pGroupOff8[2] = elapsedGame * 0.5 + pGroupOff8[2]; } if ((ushort)((ushort)(waterLevelDiff < 240.0) << 8 | (ushort)(waterLevelDiff == 240.0) << 0xe) == 0) { pGroupOff8[1] = 240.0; } if ((ushort)((ushort)(pGroupOff8[2] < 240.0) << 8 | (ushort)(pGroupOff8[2] == 240.0) << 0xe) == 0) { pGroupOff8[2] = 240.0; } j += 1; pGroupOff8 = pGroupOff8 + 6; } while (j < *pEntryOff414); } flags = pEntryOff414[4]; if ((flags & 4) != 0) { lowering = false; } if ((lowering) || (rising)) { waterLevelDiff = ((float)pEntryOff414[2] - (float)pEntryOff414[1]) / level->DigDepth; if (lowering) { pEntryOff414[4] = flags & 0xfffffffd; fVar1 = ((float)(ulonglong)numActiveDrains * elapsedGame * 0.3) / (waterLevelDiff - -1.0) + (float)pEntryOff414[2]; pEntryOff414[2] = (uint)fVar1; if (lowestWaterLevel <= fVar1) { pEntryOff414[2] = (uint)lowestWaterLevel; pEntryOff414[4] = flags & 0xfffffffd | 4; } } else { pEntryOff414[4] = flags & 0xfffffffb; fVar1 = (float)pEntryOff414[2] - elapsedGame * 0.05; pEntryOff414[2] = (uint)fVar1; if ((ushort)((ushort)(fVar1 < lowestWaterLevel) << 8 | (ushort)(fVar1 == lowestWaterLevel) << 0xe) != 0) { pEntryOff414[2] = (uint)lowestWaterLevel; pEntryOff414[4] = flags & 0xfffffffb | 2; } } // rgb( 0, 76,204) + alpha change "deep blue, desaturated" gfx::Container_SetColourAlpha ((Container *)pEntryOff414[3],0.0,0.3,0.8,0.6 - waterLevelDiff * 0.4); groupID = D3DRMGROUP_0; if (pEntryOff414[-0x3d] != 0) { do { gfx::Container_Mesh_GetVertices((Container *)pEntryOff414[3],groupID,0,4,vertices); pVertPosZ = &vertices[0].position.z; k = 4; do { *pVertPosZ = (float)pEntryOff414[2]; pVertPosZ = pVertPosZ + 9; k += -1; } while (k != 0); gfx::Container_Mesh_SetVertices((Container *)pEntryOff414[3],groupID,0,4,vertices); groupID += 1; } while (groupID < pEntryOff414[-0x3d]); } } i += 1; pEntryOff414 = pEntryOff414 + 0x10a; } while (i < globs::waterGlobs.poolCount); } Water_UpdateNotHotBlocks(level); return; } void __cdecl lego::game::Water_UpdateNotHotBlocks(Lego_Level *level) { uint uVar1; uint uVar2; uint *puVar3; uint *puVar4; longlong lVar5; Vector3F *pVVar6; uint by; uint bx; uint i; uint j; Point2F worldPos; Point2I VERT_OFFSETS [4]; Vector3F DIRECTIONS3 [4]; Vector3F vertPoses [4]; VERT_OFFSETS[0].y = 1; VERT_OFFSETS[1].x = 1; DIRECTIONS3[0].x = 0.0; VERT_OFFSETS[1].y = 2; VERT_OFFSETS[2].x = 2; DIRECTIONS3[0].y = 1.0; VERT_OFFSETS[2].y = 3; VERT_OFFSETS[3].x = 3; DIRECTIONS3[0].z = 0.0; DIRECTIONS3[1].x = 1.0; DIRECTIONS3[1].y = 0.0; DIRECTIONS3[1].z = 0.0; DIRECTIONS3[2].x = 0.0; DIRECTIONS3[2].y = -1.0; DIRECTIONS3[2].z = 0.0; DIRECTIONS3[3].x = -1.0; DIRECTIONS3[3].y = 0.0; DIRECTIONS3[3].z = 0.0; VERT_OFFSETS[0].x = 0; VERT_OFFSETS[3].y = 0; i = 0; if (globs::waterGlobs.poolCount != 0) { puVar3 = &globs::waterGlobs.poolList[0].drainCount; do { j = 0; if (*puVar3 != 0) { puVar4 = puVar3 + -0x3b; do { uVar1 = puVar4[-1]; pVVar6 = vertPoses; lVar5 = __ftol((float10)(float)puVar3[uVar1 * 2 + -0x104]); uVar2 = (uint)lVar5; lVar5 = __ftol((float10)(float)puVar3[uVar1 * 2 + -0x105]); lego::map::Map3D_GetBlockVertexPositions(level->map,(uint)lVar5,uVar2,pVVar6); uVar1 = *puVar4; worldPos.x = (vertPoses[VERT_OFFSETS[uVar1].y].x + vertPoses[VERT_OFFSETS[uVar1].x].x) * 0.5 + DIRECTIONS3[uVar1].x * (float)puVar4[2]; worldPos.y = DIRECTIONS3[uVar1].y * (float)puVar4[2] + (vertPoses[VERT_OFFSETS[uVar1].x].y + vertPoses[VERT_OFFSETS[uVar1].y].y) * 0.5; lego::map::Map3D_WorldToBlockPos_NoZ (level->map,worldPos.x,worldPos.y,(int *)&bx,(int *)&by); Level_Block_SetNotHot(level,bx,by,TRUE); uVar1 = puVar4[-1]; pVVar6 = vertPoses; lVar5 = __ftol((float10)(float)puVar3[uVar1 * 2 + -0x104]); uVar2 = (uint)lVar5; lVar5 = __ftol((float10)(float)puVar3[uVar1 * 2 + -0x105]); lego::map::Map3D_GetBlockVertexPositions(level->map,(uint)lVar5,uVar2,pVVar6); uVar1 = *puVar4; worldPos.x = (vertPoses[VERT_OFFSETS[uVar1].y].x + vertPoses[VERT_OFFSETS[uVar1].x].x) * 0.5 + DIRECTIONS3[uVar1].x * (float)puVar4[3]; worldPos.y = DIRECTIONS3[uVar1].y * (float)puVar4[3] + (vertPoses[VERT_OFFSETS[uVar1].x].y + vertPoses[VERT_OFFSETS[uVar1].y].y) * 0.5; lego::map::Map3D_WorldToBlockPos_NoZ (level->map,worldPos.x,worldPos.y,(int *)&bx,(int *)&by); Level_Block_SetNotHot(level,bx,by,FALSE); j += 1; puVar4 = puVar4 + 6; } while (j < *puVar3); } i += 1; puVar3 = puVar3 + 0x10a; } while (i < globs::waterGlobs.poolCount); } return; } Water_Pool * __cdecl lego::game::Water_FindPoolDrain(uint bx,uint by,uint *optout_drainIndex) { uint j; Water_PoolDrain *pWVar1; Water_PoolDrain *pGroup; float10 extraout_ST0; longlong lVar2; uint i; Point2F DIRECTIONS [4]; DIRECTIONS[0].x = 0.0; DIRECTIONS[0].y = -1.0; DIRECTIONS[1].x = 1.0; DIRECTIONS[1].y = 0.0; DIRECTIONS[2].x = 0.0; DIRECTIONS[2].y = 1.0; DIRECTIONS[3].x = -1.0; DIRECTIONS[3].y = 0.0; i = 0; if (globs::waterGlobs.poolCount == 0) { return NULL; } // pVar1 ~= &globs::levelstruct428Globs.structTable[i]; pWVar1 = globs::waterGlobs.poolList[0].drainList; do { // pItem = &globs::levelstruct428Globs.structTable[i].items[0]; j = 0; pGroup = pWVar1; // if (globs::levelstruct428Globs.structTable[i].count != 0) if (pWVar1[10].blockIndex != 0) { do { // if ((bx == (uint)__ftol(structTable[i].points[j].x + // DIRECTIONS_F[structTable[i].items[j]->direction].x) && // (by == (uint)__ftol(structTable[i].points[j].y + // DIRECTIONS_F[structTable[i].items[j]->direction].y)) lVar2 = __ftol((float10)((Water_Pool *)&pWVar1[-0x22].elapsedUp_c)->blocks [pGroup->blockIndex].x + (float10)DIRECTIONS[pGroup->direction].x); if ((bx == (uint)lVar2) && (lVar2 = __ftol(extraout_ST0), by == (uint)lVar2)) { if (optout_drainIndex != NULL) { // This may also be a count up to the matching point *optout_drainIndex = j; } // return &globs::levelstruct428Globs.structTable[i]; return (Water_Pool *)&pWVar1[-0x22].elapsedUp_c; } j += 1; pGroup = pGroup + 1; // while (j < globs::levelstruct428Globs.structTable[i].count); } while (j < pWVar1[10].blockIndex); } i += 1; // pVar1 ~= &globs::levelstruct428Globs.structTable[++i]; pWVar1 = (Water_PoolDrain *)&pWVar1[0x2c].drainWaterLevel; if (globs::waterGlobs.poolCount <= i) { return NULL; } } while( true ); } // Qsort comparison for ordering by pointsCount, from highest to lowest. int __cdecl lego::game::Water_QsortComparePools(Water_Pool *a,Water_Pool *b) { if (b->blockCount < a->blockCount) { return 0xffffffff; } return (uint)(a->blockCount < b->blockCount); } // At this point I don't believe these x and y values are really // just coordinates. They don't seem to be used like that, and the // only reason they're labaled as such is due to creation from the // map dimensions 2D loop. Water_Pool * __cdecl lego::game::Water_FindPoolAndMergeRows(uint by,uint bxRowStart,uint bxRowEnd) { Water_Pool *pool; Point2F *pBlock; uint i; Water_Pool *mainPool; Water_Pool *mainPoolNext; uint j; mainPool = NULL; if ((by != 0) && (bxRowStart < bxRowEnd)) { do { i = 0; if (globs::waterGlobs.poolCount != 0) { pool = (Water_Pool *)&globs::waterGlobs; do { j = 0; if (pool->blockCount != 0) { // mainPoolNext is just an extra register used for mainPool, and can be eliminted with a // little bit of logic rework. pBlock = pool->blocks; mainPoolNext = mainPool; do { mainPool = mainPoolNext; if (((((float)(ulonglong)bxRowStart == pBlock->x) && ((float)(ulonglong)(by - 1) == pBlock->y)) && (mainPool = pool, mainPoolNext != NULL)) && (mainPool = mainPoolNext, mainPoolNext != pool)) { // Register this pool to be merged with mainPool at the end of Initialise. globs::waterGlobs.mergeList[globs::waterGlobs.mergeCount].mainPool = mainPoolNext; globs::waterGlobs.mergeList[globs::waterGlobs.mergeCount].removedPool = pool; globs::waterGlobs.mergeCount += 1; } j += 1; pBlock = pBlock + 1; mainPoolNext = mainPool; } while (j < pool->blockCount); } i += 1; pool = pool + 1; } while (i < globs::waterGlobs.poolCount); } bxRowStart += 1; } while (bxRowStart < bxRowEnd); } return mainPool; } void __cdecl lego::game::Water_AddPoolRowBlocks(Water_Pool *pool,uint by,uint bxRowStart,uint bxRowEnd) { if (bxRowStart < bxRowEnd) { do { pool->blocks[pool->blockCount].x = (float)(ulonglong)bxRowStart; pool->blocks[pool->blockCount].y = (float)(ulonglong)by; bxRowStart += 1; pool->blockCount = pool->blockCount + 1; } while (bxRowStart < bxRowEnd); } return; } void __cdecl lego::game::Water_AddPool(uint by,uint bxRowStart,uint bxRowEnd) { Water_Pool *pool; pool = globs::waterGlobs.poolList + globs::waterGlobs.poolCount; globs::waterGlobs.poolList[globs::waterGlobs.poolCount].blockCount = 0; Water_AddPoolRowBlocks(pool,by,bxRowStart,bxRowEnd); globs::waterGlobs.poolCount = globs::waterGlobs.poolCount + 1; return; } BOOL __cdecl lego::tools::Weapon_Initialise(Config *config,char *gameName) { char cVar1; Config *prop; char *pcVar2; Config *pCVar3; int iVar4; BOOL BVar5; void *pvVar6; uint uVar7; int iVar8; uint uVar9; int iVar10; char **ppcVar11; int iVar12; undefined4 *puVar13; uint uVar14; undefined4 *puVar15; float10 fVar16; LegoObject_Type local_d8; uint local_d4; Config *local_d0; int local_cc; int local_c8; int local_c4; char *local_c0 [16]; char local_80 [128]; uVar14 = 0; globs::weaponGlobs.config = config; globs::weaponGlobs.weaponCount = 0; pcVar2 = cfg::Config_BuildStringID(gameName,"WeaponTypes",0); pCVar3 = cfg::Config_FindArray(config,pcVar2); if (pCVar3 != NULL) { do { globs::weaponGlobs.weaponCount += 1; pCVar3 = cfg::Config_GetNextItem(pCVar3); } while (pCVar3 != NULL); globs::weaponGlobs.weaponStatsList = (WeaponStats *)io::Mem_Alloc(globs::weaponGlobs.weaponCount * 0x4b68); if (globs::weaponGlobs.weaponStatsList != NULL) { if (globs::weaponGlobs.weaponCount != 0) { iVar12 = 0; iVar10 = 0; do { local_d8 = LegoObject_None; do { local_d4 = 0; do { uVar9 = 0; do { uVar7 = uVar9 + 1; (globs::weaponGlobs.weaponStatsList)->objectCoefs[local_d8][local_d4] [uVar9 + iVar10] = -1.0; uVar9 = uVar7; } while (uVar7 < 0x10); local_d4 += 1; } while (local_d4 < 0xf); local_d8 += LegoObject_Vehicle; } while (local_d8 < LegoObject_Type_Count); *(undefined4 *) ((int)(globs::weaponGlobs.weaponStatsList)->wallDestroyTimes + iVar12 + -0x20) = 0; *(undefined4 *) ((int)(globs::weaponGlobs.weaponStatsList)->wallDestroyTimes + iVar12 + -0x14) = 0; *(undefined4 *) ((int)(globs::weaponGlobs.weaponStatsList)->wallDestroyTimes + iVar12 + -0x10) = 0; iVar8 = 0x12; // 150.0 *(undefined4 *)((int)(globs::weaponGlobs.weaponStatsList)->wallDestroyTimes + iVar12 + -4) = 0x43160000; iVar4 = iVar12 + 0x4b20; do { iVar8 += -1; // 5.0 *(undefined4 *)((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar4) = 1084227584; iVar4 = iVar4 + 4; } while (iVar8 != 0); uVar14 += 1; iVar10 += 0x12da; iVar12 += 0x4b68; } while (uVar14 < globs::weaponGlobs.weaponCount); } globs::weaponGlobs.weaponNameList = (char **)io::Mem_Alloc(globs::weaponGlobs.weaponCount * 4) ; if (globs::weaponGlobs.weaponNameList != NULL) { pcVar2 = cfg::Config_BuildStringID(gameName,"WeaponTypes",0); local_d0 = cfg::Config_FindArray(config,pcVar2); if (local_d0 != NULL) { iVar10 = 0x4b04; local_c8 = 0; local_cc = 0; local_c4 = 0x4b04; LAB_0046f010: prop = local_d0; pcVar2 = cfg::Config_BuildStringID(gameName,"WeaponTypes",local_d0->key,0); pCVar3 = cfg::Config_FindArray(config,pcVar2); joined_r0x0046f044: do { if (pCVar3 == NULL) goto LAB_0046f2cb; iVar12 = std::_stricmp(pCVar3->key,"SlowDeath"); if (iVar12 == 0) { util::Util_Tokenise(pCVar3->value,local_c0,":"); *(undefined4 *) ((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs[-1][0xe] + iVar10 + 0x3c) = 1 ; fVar16 = std::atof(local_c0[0]); *(float *)((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar10) = (float)fVar16; fVar16 = std::atof(local_c0[1]); *(float *)((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar10 + 4) = (float)fVar16; goto LAB_0046f2b4; } iVar12 = std::_stricmp(pCVar3->key,"RechargeTime"); if (iVar12 == 0) { fVar16 = std::atof(pCVar3->value); *(float *)((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar10 + 8) = (float)fVar16; goto LAB_0046f2b4; } iVar12 = std::_stricmp(pCVar3->key,"DefaultDamage"); if (iVar12 == 0) { fVar16 = std::atof(pCVar3->value); *(float *)((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar10 + 0xc) = (float)fVar16; goto LAB_0046f2b4; } iVar12 = std::_stricmp(pCVar3->key,"DischargeRate"); if (iVar12 == 0) { fVar16 = std::atof(pCVar3->value); *(float *)((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar10 + 0x10) = (float)fVar16; goto LAB_0046f2b4; } iVar12 = std::_stricmp(pCVar3->key,"WeaponRange"); if (iVar12 == 0) { fVar16 = std::atof(pCVar3->value); *(float *)((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar10 + 0x18) = (float)fVar16; goto LAB_0046f2b4; } iVar12 = 0; ppcVar11 = globs::legoGlobs.surfaceName; do { std::sprintf(local_80,"WallDestroyTime_%s",*ppcVar11 + 0x11); iVar4 = std::_stricmp(pCVar3->key,local_80); if (iVar4 == 0) { fVar16 = std::atof(pCVar3->value); (globs::weaponGlobs.weaponStatsList)->wallDestroyTimes[iVar12 + local_cc] = (float)fVar16; pCVar3 = cfg::Config_GetNextItem(pCVar3); break; } ppcVar11 = ppcVar11 + 1; iVar12 += 1; } while (ppcVar11 < globs::legoGlobs.langSurface_name); prop = local_d0; if (iVar12 == 0x12) { iVar12 = std::_stricmp(pCVar3->key,"Ammo"); if (iVar12 == 0) { iVar12 = std::atoi(pCVar3->value); *(int *)((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar10 + 0x14) = iVar12; } else { *(undefined4 *) ((int)(globs::weaponGlobs.weaponStatsList)->objectCoefs + iVar10 + 0x14) = 0; BVar5 = lrr::Lego_GetObjectByName(pCVar3->key,&local_d8,&local_d4,NULL); prop = local_d0; if (BVar5 == 0) goto joined_r0x0046f044; uVar14 = stats::Stats_GetLevels(local_d8,local_d4); util::Util_Tokenise(pCVar3->value,local_c0,":"); if (uVar14 != 0) { ppcVar11 = local_c0; uVar9 = 0; do { fVar16 = std::atof(*ppcVar11); ppcVar11 = ppcVar11 + 1; uVar7 = uVar9 + 1; (globs::weaponGlobs.weaponStatsList)->objectCoefs[local_d8][local_d4] [uVar9 + local_cc] = (float)fVar16; iVar10 = local_c4; uVar9 = uVar7; } while (uVar7 < uVar14); } } LAB_0046f2b4: pCVar3 = cfg::Config_GetNextItem(pCVar3); prop = local_d0; } } while( true ); } LAB_0046f345: if (local_d0 == NULL) { return 1; } io::Mem_Free(globs::weaponGlobs.weaponNameList); } io::Mem_Free(globs::weaponGlobs.weaponStatsList); } } return 0; LAB_0046f2cb: uVar14 = 0xffffffff; pcVar2 = prop->key; do { if (uVar14 == 0) break; uVar14 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); pvVar6 = io::Mem_Alloc(~uVar14); iVar10 += 0x4b68; *(void **)((int)globs::weaponGlobs.weaponNameList + local_c8) = pvVar6; uVar14 = 0xffffffff; puVar13 = (undefined4 *)prop->key; do { if (uVar14 == 0) break; uVar14 -= 1; cVar1 = *(char *)puVar13; puVar13 = (undefined4 *)((int)puVar13 + 1); } while (cVar1 != '\0'); puVar13 = (undefined4 *)prop->key; puVar15 = *(undefined4 **)((int)globs::weaponGlobs.weaponNameList + local_c8); for (uVar9 = ~uVar14 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar13; puVar13 = puVar13 + 1; puVar15 = puVar15 + 1; } local_cc += 0x12da; for (uVar14 = ~uVar14 & 3; uVar14 != 0; uVar14 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar13; puVar13 = (undefined4 *)((int)puVar13 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } local_c8 = local_c8 + 4; local_c4 = iVar10; local_d0 = cfg::Config_GetNextItem(prop); if (local_d0 == NULL) goto LAB_0046f345; goto LAB_0046f010; } // On failure, returns g_WeaponTypes_COUNT // Weapon IDs are 1-indexed it seems... uint __cdecl lego::tools::Weapon_GetWeaponIDByName(char *weaponName) { int cmp; uint i; i = 0; if (globs::weaponGlobs.weaponCount == 0) { return 1; } do { cmp = std::_stricmp(globs::weaponGlobs.weaponNameList[i],weaponName); if (cmp == 0) { return i; } i += 1; } while (i < globs::weaponGlobs.weaponCount); return globs::weaponGlobs.weaponCount + 1; } float10 __cdecl lego::tools::Weapon_GetRechargeTime(uint weaponID) { return (float10)globs::weaponGlobs.weaponStatsList[weaponID].rechargeTime; } float10 __cdecl lego::tools::Weapon_GetDischargeRate(uint weaponID) { return (float10)globs::weaponGlobs.weaponStatsList[weaponID].dischargeRate; } float10 __cdecl lego::tools::Weapon_GetWeaponRange(uint weaponID) { return (float10)globs::weaponGlobs.weaponStatsList[weaponID].weaponRange; } float10 __cdecl lego::tools::Weapon_GetWallDestroyTime(uint weaponID,Lego_SurfaceType surfaceType) { return (float10)globs::weaponGlobs.weaponStatsList[weaponID].wallDestroyTimes[surfaceType]; } float10 __cdecl lego::tools::Weapon_GetDamageForObject(uint weaponID,LegoObject *liveObj) { LegoObject_Type objType; objType = liveObj->type; if (globs::weaponGlobs.weaponStatsList[weaponID].objectCoefs [objType * 3 + liveObj->id + objType * 0xc][liveObj->objLevel] == -1.0) { return (float10)globs::weaponGlobs.weaponStatsList[weaponID].damage; } return (float10)globs::weaponGlobs.weaponStatsList[weaponID].objectCoefs[objType][liveObj->id] [liveObj->objLevel]; } // elapsed is only passed a non-zero value when unkSlowDeathBool is FALSE. But this may be // coincidence. void __cdecl lego::tools::Weapon_GenericDamageObject (LegoObject *liveObj,uint weaponID,BOOL hit,float elapsed,Point2F *dir) { float damage; BOOL BVar1; float10 fVar2; float slowDeathDuration; fVar2 = Weapon_GetDamageForObject(weaponID,liveObj); damage = (float)fVar2; if ((liveObj->flags3 & LIVEOBJ3_CANDAMAGE) != LIVEOBJ3_NONE) { BVar1 = game::LegoObject_IsActive(liveObj,TRUE); if (BVar1 != 0) { if (globs::weaponGlobs.weaponStatsList[weaponID].isSlowDeath != 0) { if (hit != 0) { game::LegoObject_AddDamage2 (liveObj,globs::weaponGlobs.weaponStatsList[weaponID].slowDeathInitialCoef * damage,TRUE,elapsed); slowDeathDuration = globs::weaponGlobs.weaponStatsList[weaponID].slowDeathDuration; liveObj->weaponID = weaponID; liveObj->weaponSlowDeath = slowDeathDuration; game::LegoObject_Hit(liveObj,dir,TRUE); return; } game::LegoObject_AddDamage2(liveObj,damage * elapsed,TRUE,elapsed); return; } if (liveObj->type == LegoObject_RockMonster) { reward::RewardQuota_RockMonsterAttacked(); } game::LegoObject_AddDamage2(liveObj,damage,TRUE,elapsed); if (hit != 0) { game::LegoObject_Hit(liveObj,dir,TRUE); } } } return; } void __cdecl lego::tools::Weapon_GunDamageObject(LegoObject *liveObj,float damage,BOOL reactToHit) { game::LegoObject_AddDamage2(liveObj,damage,TRUE,1.0); game::LegoObject_Hit(liveObj,NULL,reactToHit); return; } // Probably projectile hitting an object and the projectile object being removed. // Along with effects of weapon hitting. void __cdecl lego::tools::Weapon_Projectile_FUN_0046f670(Weapon_Projectile *projectile) { float10 weaponRange; float10 fVar1; float10 fVar2; float10 fVar3; Vector3F local_30; Vector3F local_24; SearchWeapons18_2 local_18; if (projectile->projectileObject != NULL) { local_18.ignoreObject = projectile->shooterObject; local_18.fromToDistance = &local_24; local_18.foundObject = NULL; local_18.ref_float_4 = 1.0; local_18.success = 0; local_18.fromPos = &projectile->lastPos; weaponRange = Weapon_GetWeaponRange(projectile->weaponID); if (weaponRange != (float10)0.0) { fVar1 = (float10)(projectile->initialPos).x - (float10)(projectile->currPos).x; fVar2 = (float10)(projectile->initialPos).y - (float10)(projectile->currPos).y; fVar3 = (float10)(projectile->initialPos).z - (float10)(projectile->currPos).z; local_30.y = (float)fVar2; local_30.z = (float)fVar3; if (weaponRange <= SQRT(fVar3 * (float10)local_30.z + fVar2 * (float10)local_30.y + fVar1 * fVar1)) { game::LegoObject_Remove(projectile->projectileObject); projectile->projectileObject = NULL; return; } } local_24.x = (projectile->currPos).x - (projectile->lastPos).x; local_24.y = (projectile->currPos).y - (projectile->lastPos).y; local_24.z = (projectile->currPos).z - (projectile->lastPos).z; game::LegoObject_RunThroughListsSkipUpgradeParts (Weapon_LegoObject_Callback_FUN_00471630,&local_18); Weapon_LegoObject_FUN_004718f0(&local_18); if (local_18.success != 0) { game::LegoObject_Remove(projectile->projectileObject); projectile->projectileObject = NULL; if (local_18.foundObject != NULL) { local_30.x = (local_18.fromToDistance)->x * local_18.ref_float_4 + (local_18.fromPos)->x; local_30.y = (local_18.fromPos)->y + (local_18.fromToDistance)->y * local_18.ref_float_4; local_30.z = (local_18.fromPos)->z + (local_18.fromToDistance)->z * local_18.ref_float_4; Weapon_GunHitObject(local_18.foundObject,&projectile->dir,&local_30,projectile->weaponID, projectile->knownWeapon); } } } return; } // Update Projectile and Lazer shots. void __cdecl lego::tools::Weapon_Update(float elapsedGame) { Weapon_Projectile *projectile; Weapon_Lazer *lazer; projectile = globs::weaponGlobs.projectileList; do { if (projectile->projectileObject != NULL) { Weapon_Projectile_UpdatePath(projectile,elapsedGame); } projectile = projectile + 1; } while (projectile < (Weapon_Projectile *)&globs::weaponGlobs.config); game::LegoObject_RunThroughListsSkipUpgradeParts (Weapon_LegoObject_Callback_UpdateObject,&elapsedGame); projectile = globs::weaponGlobs.projectileList; do { Weapon_Projectile_FUN_0046f670(projectile); projectile = projectile + 1; } while (projectile < (Weapon_Projectile *)&globs::weaponGlobs.config); lazer = globs::weaponGlobs.lazerList; do { if (lazer->innerMesh != NULL) { if (lazer->timer < 0.0) { gfx::Mesh_Remove(lazer->innerMesh,lazer->cont->activityFrame); gfx::Mesh_Remove(lazer->outerMesh,lazer->cont->activityFrame); lazer->innerMesh = NULL; } lazer->timer = lazer->timer - elapsedGame; } lazer = lazer + 1; } while (lazer < globs::weaponGlobs.projectileList); return; } BOOL __cdecl lego::tools::Weapon_LegoObject_Callback_UpdateObject(LegoObject *liveObj,float *pElapsed) { float fVar1; WeaponsModel *weapons; Container *cont; uint frameNo; float10 fVar2; float10 fVar3; Container *opt_ref; uint frameNo_00; Vector3F *out_pos; Vector3F local_c; if ((ushort)((ushort)(liveObj->weaponRechargeTimer < 0.0) << 8 | (ushort)(liveObj->weaponRechargeTimer == 0.0) << 0xe) == 0) { liveObj->weaponRechargeTimer = liveObj->weaponRechargeTimer - *pElapsed; } weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); if (weapons != NULL) { frameNo = 0; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); if (weapons->count != 0) { do { fVar2 = Weapon_LegoObject_GetWeaponTimer(liveObj,frameNo); // if (fVar2 > 0.0f) if ((ushort)((ushort)(fVar2 < (float10)0.0) << 8 | (ushort)(fVar2 == (float10)0.0) << 0xe) == 0) { frameNo_00 = frameNo; fVar3 = Weapon_LegoObject_GetWeaponTimer(liveObj,frameNo); Weapon_LegoObject_SetWeaponTimer(liveObj,(float)(fVar3 - (float10)*pElapsed),frameNo_00); fVar3 = snd::SFX_Random_GetSamplePlayTime(SFX_LazerRecharge); fVar1 = (float)(fVar3 * (float10)25.0 * (float10)globs::legoGlobs.gameSpeed); fVar3 = Weapon_LegoObject_GetWeaponTimer(liveObj,frameNo); if ((fVar3 < (float10)fVar1) && ((ushort)((ushort)((float)fVar2 < fVar1) << 8 | (ushort)((float)fVar2 == fVar1) << 0xe) == 0)) { out_pos = &local_c; opt_ref = NULL; cont = game::LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(cont,opt_ref,out_pos); snd::SFX_Random_PlaySound3DOnContainer(NULL,SFX_LazerRecharge,FALSE,FALSE,&local_c); } } frameNo += 1; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); } while (frameNo < weapons->count); } } if ((ushort)((ushort)(liveObj->weaponSlowDeath < 0.0) << 8 | (ushort)(liveObj->weaponSlowDeath == 0.0) << 0xe) == 0) { Weapon_GenericDamageObject(liveObj,liveObj->weaponID,FALSE,*pElapsed,NULL); liveObj->weaponSlowDeath = liveObj->weaponSlowDeath - *pElapsed; } return 0; } // effectSpawnPos is required if LegoObject_IsRockMonsterCanGather(liveObj). void __cdecl lego::tools::Weapon_GunHitObject (LegoObject *liveObj,Vector3F *dir,Vector3F *opt_effectSpawnPos,uint weaponID, Weapon_KnownType knownWeapon) { BOOL BVar1; StatsFlags2 sflags2; float10 freezerTime; float10 damage; float10 pusherDist; Point2F dirVec_; dirVec_.x = dir->x; dirVec_.y = dir->y; BVar1 = game::LegoObject_IsRockMonsterCanGather(liveObj); if (BVar1 != 0) { effect::Effect_Spawn_BoulderExplode(opt_effectSpawnPos); } if (knownWeapon == Weapon_KnownType_Laser) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_CANLASER) != STATS2_NONE) { damage = stats::StatsObject_GetLaserDamage(liveObj); Weapon_GunDamageObject(liveObj,(float)damage,TRUE); } if (opt_effectSpawnPos != NULL) { effect::Effect_Spawn_Particle(MISCOBJECT_LAZERHIT,opt_effectSpawnPos,NULL); } } else { if (knownWeapon == Weapon_KnownType_Pusher) { sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_CANPUSH) != STATS2_NONE) { pusherDist = stats::StatsObject_GetPusherDist(liveObj); damage = stats::StatsObject_GetPusherDamage(liveObj); dirVec_.x = dirVec_.x * 1.5; dirVec_.y = dirVec_.y * 1.5; Weapon_GunDamageObject(liveObj,(float)damage,TRUE); game::LegoObject_Push(liveObj,&dirVec_,(float)pusherDist); } if (opt_effectSpawnPos != NULL) { effect::Effect_Spawn_Particle(MISCOBJECT_PUSHERHIT,opt_effectSpawnPos,NULL); return; } } else { if (knownWeapon != Weapon_KnownType_Freezer) { Weapon_GenericDamageObject(liveObj,weaponID,TRUE,0.0,&dirVec_); return; } // 10.0f dir = (Vector3F *)0x41200000; sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_CANFREEZE) != STATS2_NONE) { freezerTime = stats::StatsObject_GetFreezerTime(liveObj); // if (freezerTime > 0.0f) if ((ushort)((ushort)(freezerTime < (float10)0.0) << 8 | (ushort)(freezerTime == (float10)0.0) << 0xe) == 0) { dir = (Vector3F *)(float)freezerTime; } damage = stats::StatsObject_GetFreezerDamage(liveObj); Weapon_GunDamageObject(liveObj,(float)damage,FALSE); game::LegoObject_Freeze(liveObj,(float)dir); } if (opt_effectSpawnPos != NULL) { effect::Effect_Spawn_Particle(MISCOBJECT_FREEZERHIT,opt_effectSpawnPos,NULL); return; } } } return; } void __cdecl lego::tools::Weapon_Projectile_UpdatePath(Weapon_Projectile *projectile,float elapsed) { float fVar1; float dirx; Container *cont; float fVar2; Point2F local_14; float local_8; cont = game::LegoObject_GetActivityContainer(projectile->projectileObject); gfx::Container_GetPosition(cont,NULL,&projectile->lastPos); fVar2 = projectile->speed * elapsed; if (projectile->isCurvedPath == 0) { local_8 = (projectile->dir).y * fVar2; fVar1 = (projectile->dir).z; (projectile->currPos).x = (projectile->dir).x * fVar2 + (projectile->currPos).x; (projectile->currPos).y = (projectile->currPos).y + local_8; (projectile->currPos).z = (projectile->currPos).z + fVar1 * fVar2; gfx::Container_SetPosition (cont,NULL,(projectile->currPos).x,(projectile->currPos).y,(projectile->currPos).z); fVar2 = (projectile->dir).z; fVar1 = (projectile->dir).y; dirx = (projectile->dir).x; } else { fVar2 = fVar2 + projectile->currDistance; projectile->currDistance = fVar2; math::BezierCurve_Interpolate(&projectile->curve,fVar2,&local_14); fVar2 = (projectile->dir).y; (projectile->currPos).x = (projectile->dir).x * local_14.x + (projectile->initialPos).x; (projectile->currPos).y = (projectile->initialPos).y + fVar2 * local_14.x; (projectile->currPos).z = (projectile->initialPos).z + local_14.y; gfx::Container_SetPosition (cont,NULL,(projectile->currPos).x,(projectile->currPos).y,(projectile->currPos).z); fVar2 = ((projectile->currPos).z - (projectile->lastPos).z) * 0.25; fVar1 = (projectile->currPos).y - (projectile->lastPos).y; dirx = (projectile->currPos).x - (projectile->lastPos).x; } gfx::Container_SetOrientation(cont,NULL,dirx,fVar1,fVar2,0.0,0.0,-1.0); return; } BOOL __cdecl lego::tools::Weapon_Projectile_AddStraightPath (LegoObject *liveObj,Vector3F *fromPos,Vector3F *fromToDistance,int weaponID, Weapon_KnownType knownWeapon) { Vector3F *pVVar1; float fVar2; float fVar3; BOOL BVar4; int handle; Weapon_KnownType knownWeapon_00; LegoObject *liveObj_00; int weaponID_00; knownWeapon_00 = knownWeapon; weaponID_00 = weaponID; liveObj_00 = liveObj; if (knownWeapon == Weapon_KnownType_Laser) { game::LegoObject_Weapon_FUN_004375c0(liveObj,weaponID,1.0); } Weapon_GetObjectTypeAndID_ByKnownWeaponType (knownWeapon_00,(LegoObject_Type *)&weaponID,&knownWeapon); BVar4 = lrr::Lego_GetObjectTypeModel(weaponID,knownWeapon,(Container **)&liveObj); if (BVar4 != 0) { handle = Weapon_Projectile_GetNextAvailable(); if (handle != -1) { globs::weaponGlobs.projectileList[handle].isCurvedPath = FALSE; globs::weaponGlobs.projectileList[handle].weaponID = weaponID_00; globs::weaponGlobs.projectileList[handle].knownWeapon = knownWeapon_00; globs::weaponGlobs.projectileList[handle].currPos.x = fromPos->x; globs::weaponGlobs.projectileList[handle].currPos.y = fromPos->y; globs::weaponGlobs.projectileList[handle].currPos.z = fromPos->z; globs::weaponGlobs.projectileList[handle].initialPos.x = fromPos->x; globs::weaponGlobs.projectileList[handle].initialPos.y = fromPos->y; fVar3 = fromPos->z; globs::weaponGlobs.projectileList[handle].speed = 5.0; globs::weaponGlobs.projectileList[handle].initialPos.z = fVar3; pVVar1 = &globs::weaponGlobs.projectileList[handle].dir; pVVar1->x = fromToDistance->x; globs::weaponGlobs.projectileList[handle].dir.y = fromToDistance->y; globs::weaponGlobs.projectileList[handle].dir.z = fromToDistance->z; fVar3 = globs::weaponGlobs.projectileList[handle].dir.y; fVar2 = globs::weaponGlobs.projectileList[handle].dir.z; fVar3 = 1.0 / SQRT(pVVar1->x * pVVar1->x + fVar2 * fVar2 + fVar3 * fVar3); pVVar1->x = pVVar1->x * fVar3; globs::weaponGlobs.projectileList[handle].dir.y = fVar3 * globs::weaponGlobs.projectileList[handle].dir.y; globs::weaponGlobs.projectileList[handle].dir.z = fVar3 * globs::weaponGlobs.projectileList[handle].dir.z; globs::weaponGlobs.projectileList[handle].shooterObject = liveObj_00; globs::weaponGlobs.projectileList[handle].unused_29c = 0; liveObj_00 = game::LegoObject_CreateInWorld (liveObj,weaponID,knownWeapon,0,fromPos->x,fromPos->y,0.0); globs::weaponGlobs.projectileList[handle].projectileObject = liveObj_00; Weapon_Projectile_UpdatePath(globs::weaponGlobs.projectileList + handle,0.0); return TRUE; } } return FALSE; } BOOL __cdecl lego::tools::Weapon_Projectile_AddCurvedPath (LegoObject *liveObj,Vector3F *fromPos,Vector3F *toPos,int weaponID, Weapon_KnownType knownWeapon) { BezierCurve *curve; float fVar1; float fVar2; float fVar3; BOOL BVar4; int handle; LegoObject *pLVar5; float10 fVar6; LegoObject_ID objID; LegoObject_Type objType; Container *objModel; Point2F local_20; Point2F local_18; Point2F local_10; Point2F local_8; local_8.x = 0.0; local_8.y = 0.0; local_18.x = 1.0; local_18.y = -1.3; local_20.x = 0.3; local_20.y = 1.0; Weapon_GetObjectTypeAndID_ByKnownWeaponType(knownWeapon,&objType,&objID); BVar4 = lrr::Lego_GetObjectTypeModel(objType,objID,&objModel); if (BVar4 != 0) { handle = Weapon_Projectile_GetNextAvailable(); if (handle != -1) { globs::weaponGlobs.projectileList[handle].knownWeapon = knownWeapon; globs::weaponGlobs.projectileList[handle].weaponID = weaponID; globs::weaponGlobs.projectileList[handle].isCurvedPath = TRUE; globs::weaponGlobs.projectileList[handle].initialPos.x = fromPos->x; globs::weaponGlobs.projectileList[handle].initialPos.y = fromPos->y; globs::weaponGlobs.projectileList[handle].initialPos.z = fromPos->z; globs::weaponGlobs.projectileList[handle].currPos.x = fromPos->x; globs::weaponGlobs.projectileList[handle].currPos.y = fromPos->y; globs::weaponGlobs.projectileList[handle].currPos.z = fromPos->z; globs::weaponGlobs.projectileList[handle].dir.x = toPos->x - fromPos->x; globs::weaponGlobs.projectileList[handle].dir.y = toPos->y - fromPos->y; globs::weaponGlobs.projectileList[handle].dir.z = toPos->z - fromPos->z; fVar1 = globs::weaponGlobs.projectileList[handle].dir.y; fVar2 = globs::weaponGlobs.projectileList[handle].dir.z; fVar3 = globs::weaponGlobs.projectileList[handle].dir.x; fVar2 = 1.0 / SQRT(fVar3 * fVar3 + fVar2 * fVar2 + fVar1 * fVar1); globs::weaponGlobs.projectileList[handle].dir.x = globs::weaponGlobs.projectileList[handle].dir.x * fVar2; fVar1 = globs::weaponGlobs.projectileList[handle].dir.z; globs::weaponGlobs.projectileList[handle].dir.y = fVar2 * globs::weaponGlobs.projectileList[handle].dir.y; globs::weaponGlobs.projectileList[handle].dir.z = fVar2 * fVar1; globs::weaponGlobs.projectileList[handle].speed = 4.0; fVar3 = fromPos->y - toPos->y; fVar1 = fromPos->z - toPos->z; fVar2 = fromPos->x - toPos->x; local_10.y = toPos->z - fromPos->z; fVar1 = SQRT(fVar2 * fVar2 + fVar1 * fVar1 + fVar3 * fVar3); local_10.x = fVar1; math::BezierCurve_Vector2DChangeLength(&local_18,fVar1 * 0.2); math::BezierCurve_Vector2DChangeLength(&local_20,fVar1 * 0.3333333); curve = &globs::weaponGlobs.projectileList[handle].curve; math::BezierCurve_BuildPoints(curve,&local_8,&local_18,&local_10,&local_20,50); fVar6 = math::BezierCurve_UpdateDistances(curve); globs::weaponGlobs.projectileList[handle].totalDistance = (float)fVar6; globs::weaponGlobs.projectileList[handle].currDistance = 0.0; globs::weaponGlobs.projectileList[handle].shooterObject = liveObj; globs::weaponGlobs.projectileList[handle].unused_29c = 0; pLVar5 = game::LegoObject_CreateInWorld(objModel,objType,objID,0,fromPos->x,fromPos->y,0.0); globs::weaponGlobs.projectileList[handle].projectileObject = pLVar5; Weapon_Projectile_UpdatePath(globs::weaponGlobs.projectileList + handle,0.0); return TRUE; } } return FALSE; } void __cdecl lego::tools::Weapon_GetObjectTypeAndID_ByKnownWeaponType (Weapon_KnownType knownWeapon,LegoObject_Type *out_objType,LegoObject_ID *out_objID) { switch(knownWeapon) { case Weapon_KnownType_Laser: *out_objType = LegoObject_LaserShot; *out_objID = 0; return; case Weapon_KnownType_Pusher: *out_objType = LegoObject_Pusher; *out_objID = 0; return; case Weapon_KnownType_Freezer: *out_objType = LegoObject_Freezer; *out_objID = 0; return; case Weapon_KnownType_Boulder: *out_objType = LegoObject_Boulder; *out_objID = 0; } return; } int __cdecl lego::tools::Weapon_Projectile_GetNextAvailable(void) { int i; LegoObject **ppLVar1; i = 0; ppLVar1 = &globs::weaponGlobs.projectileList[0].projectileObject; do { if (*ppLVar1 == NULL) { return i; } ppLVar1 = ppLVar1 + 0xac; i += 1; } while (ppLVar1 < globs::s_FormatPartName_name + 0x2a0); return -1; } int __cdecl lego::tools::Weapon_Lazer_GetNextAvailable(void) { int i; Weapon_Lazer *pSVar2; i = 0; pSVar2 = globs::weaponGlobs.lazerList; do { if (pSVar2->innerMesh == NULL) { return i; } pSVar2 = pSVar2 + 1; i += 1; } while (pSVar2 < globs::weaponGlobs.projectileList); return -1; } LegoObject * __cdecl lego::tools::Weapon_FireLazer (Vector3F *fromPos,Vector3F *dir,LegoObject *liveObj,float elapsed,float weaponRange, int weaponID,float coef) { Vector3F *pVVar1; int weaponID_00; Container *cont; Map3D *map; BOOL BVar2; Lego_Level *level; float10 fVar3; float fVar4; float fVar5; LegoObject *opt_wPos; Point2F *pPVar6; Vector3F *toPos; float *out_by; float local_24; Point2F local_20; Vector3F local_18; Vector3F local_c; LegoObject *liveObj_00; Lego_SurfaceType8 terrain; opt_wPos = (LegoObject *)fromPos; local_24 = 1.0; fromPos = NULL; snd::SFX_Random_PlaySound3DOnContainer(NULL,SFX_Laser,FALSE,FALSE,(Vector3F *)opt_wPos); liveObj_00 = liveObj; pVVar1 = dir; local_18.x = weaponRange * dir->x; local_18.y = weaponRange * dir->y; local_18.z = dir->z * weaponRange; Weapon_DoCallbacksSearch_FUN_00471b20 ((Vector3F *)opt_wPos,&local_18,(LegoObject **)&fromPos,&local_24,liveObj); local_18.x = local_24 * local_18.x; local_18.y = local_24 * local_18.y; local_18.z = local_24 * local_18.z; local_c.x = local_18.x + ((Vector3F *)opt_wPos)->x; local_c.y = ((Vector3F *)opt_wPos)->y + local_18.y; local_c.z = (float)((Vector3F *)opt_wPos)->z + local_18.z; toPos = &local_c; cont = game::LegoObject_GetActivityContainer(liveObj_00); Weapon_Lazer_Add(cont,(Vector3F *)opt_wPos,toPos); weaponID_00 = weaponID; if (((LegoObject *)fromPos != NULL) || (1.0 <= local_24)) { if ((LegoObject *)fromPos != NULL) { effect::Effect_Spawn_Particle(MISCOBJECT_LAZERHIT,&local_c,NULL); snd::SFX_Random_PlaySound3DOnContainer(NULL,SFX_LaserHit,FALSE,FALSE,&local_c); if ((LegoObject *)fromPos != NULL) { if ((liveObj_00 == NULL) || (liveObj_00->type != LegoObject_MiniFigure)) { pPVar6 = NULL; } else { local_20.x = pVVar1->x; local_20.y = pVVar1->y; pPVar6 = &local_20; } game::LegoObject_Hit((LegoObject *)fromPos,pPVar6,1); } } } else { effect::Effect_Spawn_BoulderExplode(&local_c); snd::SFX_Random_PlaySound3DOnContainer(NULL,SFX_LaserHit,FALSE,FALSE,&local_c); out_by = &local_20.y; pPVar6 = &local_20; fVar4 = local_c.x; fVar5 = local_c.y; map = lrr::Lego_GetMap(); lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar4,fVar5,(int *)pPVar6,(int *)out_by); BVar2 = game::Level_Block_IsWall((uint)local_20.x,(uint)local_20.y); if (BVar2 != 0) { BVar2 = game::Level_Block_IsImmovable((Point2I *)&local_20); if ((BVar2 == 0) && (terrain = (globs::legoGlobs.currLevel)->blocks [(globs::legoGlobs.currLevel)->width * (int)local_20.y + (int)local_20.x]. terrain, terrain != Lego_SurfaceType8_RechargeSeam)) { fVar3 = Weapon_GetWallDestroyTime(weaponID_00,(uint)terrain); weaponRange = (float)fVar3; BVar2 = game::Level_Block_Damage((uint)local_20.x,(uint)local_20.y,weaponRange,elapsed); if (BVar2 != 0) { BVar2 = 0; fVar4 = local_20.x; fVar5 = local_20.y; level = lrr::Lego_GetLevel(); game::Level_DestroyWall(level,(uint)fVar4,(uint)fVar5,BVar2); } goto LAB_004704fa; } } BVar2 = game::Level_Block_IsPath((Point2I *)&local_20); if (BVar2 != 0) { ai::AITask_DoClearTypeAction((Point2I *)&local_20,Message_ClearRemovePathComplete); game::Level_BlockUpdateSurface(globs::legoGlobs.currLevel,(int)local_20.x,(int)local_20.y,0); } } LAB_004704fa: game::LegoObject_Weapon_FUN_004375c0(liveObj_00,weaponID_00,coef); return (LegoObject *)fromPos; } BOOL __cdecl lego::tools::Weapon_LegoObject_Collision_FUN_00470520 (LegoObject *liveObj,Point2F *fromPos,Point2F *faceDir,BOOL doTestCollision) { StatsFlags1 sflags1; BOOL BVar1; sflags1 = stats::StatsObject_GetStatsFlags1(liveObj); if ((sflags1 & STATS1_COLLBOX) != STATS1_NONE) { BVar1 = Weapon_LegoObject_CollisionBox_FUN_00470570 (liveObj,fromPos,faceDir,NULL,doTestCollision); return BVar1; } BVar1 = Weapon_LegoObject_CollisionRadius_FUN_00470800(liveObj,fromPos,faceDir,doTestCollision); return BVar1; } BOOL __cdecl lego::tools::Weapon_LegoObject_CollisionBox_FUN_00470570 (LegoObject *liveObj,Point2F *fromPos,Point2F *faceDir,Point2F *optout_intersection, BOOL doTestCollision) { float fVar1; ushort uVar2; Container *cont; BOOL BVar3; Size2F *pSVar4; Point2F *pPVar5; int iVar6; Vector3F *out_vector; Point2F *pPVar7; uint uVar8; Point2F intersection; Point2F testFaceDir; Point2F testFromPos; Point2F local_60; Point2F local_58 [5]; Vector3F local_30 [4]; cont = game::LegoObject_GetActivityContainer(liveObj); testFromPos.x = fromPos->x; testFromPos.y = fromPos->y; testFaceDir.x = faceDir->x; testFaceDir.y = faceDir->y; if ((doTestCollision != 0) && (BVar3 = Weapon_LegoObject_TestCollision_FUN_004708f0(liveObj,&testFromPos,&testFaceDir), BVar3 != 0)) { return 0; } pSVar4 = stats::StatsObject_GetCollBox(liveObj); local_30[0].x = pSVar4->width * -0.5; pSVar4 = stats::StatsObject_GetCollBox(liveObj); local_30[0].z = pSVar4->height * 0.5; pSVar4 = stats::StatsObject_GetCollBox(liveObj); local_30[1].x = pSVar4->width * 0.5; pSVar4 = stats::StatsObject_GetCollBox(liveObj); local_30[1].z = pSVar4->height * 0.5; pSVar4 = stats::StatsObject_GetCollBox(liveObj); local_30[2].x = pSVar4->width * 0.5; pSVar4 = stats::StatsObject_GetCollBox(liveObj); local_30[2].z = pSVar4->height * -0.5; pSVar4 = stats::StatsObject_GetCollBox(liveObj); local_30[3].x = pSVar4->width * -0.5; pSVar4 = stats::StatsObject_GetCollBox(liveObj); local_30[3].z = pSVar4->height * -0.5; local_30[3].y = 0.0; local_30[2].y = 0.0; local_30[1].y = 0.0; local_30[0].y = 0.0; pPVar7 = local_58; out_vector = local_30; iVar6 = 4; do { gfx::Container_Transform(cont,out_vector,out_vector); fVar1 = out_vector->y; pPVar7->x = out_vector->x; pPVar7->y = fVar1; out_vector = out_vector + 1; pPVar7 = pPVar7 + 1; iVar6 += -1; } while (iVar6 != 0); local_58[4].x = local_58[0].x; local_58[4].y = local_58[0].y; uVar8 = 0; pPVar7 = local_58; do { local_60.x = pPVar7->x - pPVar7[1].x; local_60.y = pPVar7->y - pPVar7[1].y; pPVar5 = math::Maths_Vector2DIntersection (&intersection,&testFromPos,&testFaceDir,pPVar7,&local_60); if (pPVar5 != NULL) { if (ABS(pPVar7->x - pPVar7[1].x) <= ABS(pPVar7->y - pPVar7[1].y)) { if (((ushort)((ushort)(intersection.y < pPVar7->y) << 8 | (ushort)(intersection.y == pPVar7->y) << 0xe) == 0) && (intersection.y < pPVar7[1].y)) goto LAB_004707ca; if (intersection.y < pPVar7->y) { uVar2 = (ushort)(intersection.y < pPVar7[1].y) << 8 | (ushort)(intersection.y == pPVar7[1].y) << 0xe; goto joined_r0x004707b1; } } else { if (((ushort)((ushort)(intersection.x < pPVar7->x) << 8 | (ushort)(intersection.x == pPVar7->x) << 0xe) == 0) && (intersection.x < pPVar7[1].x)) goto LAB_004707ca; if (intersection.x < pPVar7->x) { uVar2 = (ushort)(intersection.x < pPVar7[1].x) << 8 | (ushort)(intersection.x == pPVar7[1].x) << 0xe; joined_r0x004707b1: if (uVar2 == 0) { LAB_004707ca: if (optout_intersection != NULL) { optout_intersection->x = intersection.x; optout_intersection->y = intersection.y; } return TRUE; } } } } uVar8 += 1; pPVar7 = pPVar7 + 1; if (3 < uVar8) { return 0; } } while( true ); } BOOL __cdecl lego::tools::Weapon_LegoObject_CollisionRadius_FUN_00470800 (LegoObject *liveObj,Point2F *fromPos,Point2F *faceDir,BOOL doTestCollision) { BOOL BVar1; float10 collRadius; Point2F testFromPos; Point2F testFaceDir; Point2F thisPos; Point2F testFromFacePos; Point2F collPos; testFromPos.x = fromPos->x; testFromPos.y = fromPos->y; testFaceDir.x = faceDir->x; testFaceDir.y = faceDir->y; if ((doTestCollision != 0) && (BVar1 = Weapon_LegoObject_TestCollision_FUN_004708f0(liveObj,&testFromPos,&testFaceDir), BVar1 != 0)) { return 0; } testFromFacePos.x = testFaceDir.x + testFromPos.x; testFromFacePos.y = testFaceDir.y + testFromPos.y; game::LegoObject_GetPosition(liveObj,&thisPos.x,&thisPos.y); math::Collision_PointOnLine(&testFromPos,&testFromFacePos,&thisPos,&collPos); collRadius = stats::StatsObject_GetCollRadius(liveObj); if (collRadius <= (float10)SQRT((collPos.y - thisPos.y) * (collPos.y - thisPos.y) + (collPos.x - thisPos.x) * (collPos.x - thisPos.x))) { return FALSE; } return TRUE; } BOOL __cdecl lego::tools::Weapon_LegoObject_TestCollision_FUN_004708f0 (LegoObject *liveObj,Point2F *fromPos,Point2F *faceDir) { Point2F toPos; game::LegoObject_GetPosition(liveObj,&toPos.x,&toPos.y); // Maths_Vector2DSubtract(&toPos, &toPos, fromPos); // if (Maths_Vector2DDotProduct(&toPos, faceDir) < 0.0f) if ((toPos.x - fromPos->x) * faceDir->x + (toPos.y - fromPos->y) * faceDir->y < 0.0) { return TRUE; } return FALSE; } void __cdecl lego::tools::Weapon_Lazer_Add(Container *cont,Vector3F *fromPos,Vector3F *toPos) { int handle; Mesh *innerBeam; Mesh *outerBeam; handle = Weapon_Lazer_GetNextAvailable(); if (handle != -1) { // (MESH_TRANSFORM_FLAG_IDENTITY|MESH_RENDER_FLAG_ALPHA11) (0x4400) innerBeam = gfx::Mesh_CreateOnFrame(cont->activityFrame,NULL,0x4400,NULL,Mesh_Type_Norm); globs::weaponGlobs.lazerList[handle].innerMesh = innerBeam; outerBeam = gfx::Mesh_CreateOnFrame(cont->activityFrame,NULL,0x4400,NULL,Mesh_Type_Norm); globs::weaponGlobs.lazerList[handle].outerMesh = outerBeam; Weapon_Lazer_InitMesh (globs::weaponGlobs.lazerList[handle].innerMesh,0.3,fromPos,toPos,0.6,0.6,0.6,1.0); Weapon_Lazer_InitMesh (globs::weaponGlobs.lazerList[handle].outerMesh,1.0,fromPos,toPos,0.1,0.2,0.5,1.0); globs::weaponGlobs.lazerList[handle].cont = cont; // Lasts for 5 frames. globs::weaponGlobs.lazerList[handle].timer = 5.0; } return; } void __cdecl lego::tools::Weapon_Lazer_InitMesh (Mesh *mesh,float thickness,Vector3F *fromPos,Vector3F *toPos,float red,float green, float blue,float alpha) { float *pfVar1; float *pfVar2; float *pfVar3; float fVar4; float fVar5; float fVar6; float fVar7; float fVar8; float fVar9; float fVar10; float fVar11; float fVar12; float fVar13; Vector3F *pVVar14; D3DRMGroupIndex groupID; uint uVar15; uint uVar16; float local_404; float local_400; uint faceData [48]; Point2F textCoords [16]; Vector3F vertPoses [16]; Vector3F normal [8]; textCoords[0].y = 1.0; textCoords[2].x = 1.0; textCoords[3].x = 1.0; textCoords[3].y = 1.0; textCoords[4].y = 1.0; textCoords[6].x = 1.0; textCoords[7].x = 1.0; textCoords[7].y = 1.0; textCoords[8].y = 1.0; textCoords[10].x = 1.0; textCoords[11].x = 1.0; textCoords[11].y = 1.0; textCoords[12].y = 1.0; textCoords[14].x = 1.0; textCoords[15].x = 1.0; textCoords[15].y = 1.0; textCoords[0].x = 0.0; textCoords[1].x = 0.0; textCoords[1].y = 0.0; textCoords[2].y = 0.0; textCoords[4].x = 0.0; textCoords[5].x = 0.0; textCoords[5].y = 0.0; textCoords[6].y = 0.0; textCoords[8].x = 0.0; textCoords[9].x = 0.0; textCoords[9].y = 0.0; textCoords[10].y = 0.0; textCoords[12].x = 0.0; textCoords[13].x = 0.0; textCoords[13].y = 0.0; textCoords[14].y = 0.0; faceData[1] = 1; faceData[2] = 9; faceData[3] = 9; faceData[6] = 1; faceData[8] = 10; faceData[9] = 10; faceData[10] = 9; faceData[11] = 1; faceData[16] = 10; faceData[0] = 0; faceData[4] = 8; faceData[5] = 0; faceData[7] = 2; faceData[12] = 2; faceData[13] = 3; faceData[14] = 0xb; faceData[15] = 0xb; faceData[17] = 2; faceData[18] = 3; faceData[19] = 4; faceData[23] = 3; faceData[20] = 0xc; faceData[21] = 0xc; faceData[28] = 0xc; faceData[26] = 0xd; faceData[27] = 0xd; faceData[34] = 0xd; faceData[32] = 0xe; faceData[33] = 0xe; faceData[40] = 0xe; faceData[38] = 0xf; faceData[39] = 0xf; faceData[46] = 0xf; faceData[22] = 0xb; fVar6 = toPos->x - fromPos->x; fVar7 = toPos->y - fromPos->y; fVar5 = toPos->z - fromPos->z; faceData[24] = 4; faceData[29] = 4; faceData[25] = 5; faceData[30] = 5; faceData[31] = 6; faceData[35] = 5; faceData[36] = 6; faceData[37] = 7; faceData[41] = 6; faceData[42] = 7; faceData[43] = 0; faceData[44] = 8; faceData[45] = 8; faceData[47] = 7; fVar4 = 1.0 / SQRT(fVar5 * fVar5 + fVar7 * fVar7 + fVar6 * fVar6); fVar7 = fVar4 * fVar7; fVar5 = fVar4 * fVar5; if ((fVar7 == 0.0) && (fVar5 == 0.0)) { local_400 = 1.0; local_404 = 0.0; } else { if (fVar7 == 0.0) { local_404 = 1.0; local_400 = 0.0; } else { local_400 = SQRT(1.0 / ((fVar5 * fVar5) / (fVar7 * fVar7) - -1.0)); local_404 = -((fVar5 / fVar7) * local_400); } } fVar8 = local_404 * thickness; fVar9 = local_400 * thickness; fVar5 = (local_400 * fVar7 - local_404 * fVar5) * thickness; fVar7 = -(local_400 * fVar4 * fVar6) * thickness; fVar6 = local_404 * fVar4 * fVar6 * thickness; fVar12 = fVar8 * 0.4142136; fVar4 = fVar5 * 0.4142136; fVar10 = fVar7 * 0.4142136; fVar11 = fVar6 * 0.4142136; fVar13 = fVar9 * 0.4142136; vertPoses[0].x = fVar4 + 0.0; vertPoses[0].y = fVar8 + fVar10; vertPoses[0].z = fVar9 + fVar11; vertPoses[1].x = fVar5 + 0.0; vertPoses[1].y = fVar7 + fVar12; vertPoses[1].z = fVar6 + fVar13; vertPoses[2].x = fVar5 + -0.0; vertPoses[2].y = fVar7 + -fVar12; vertPoses[2].z = fVar6 + -fVar13; vertPoses[3].x = fVar4 - 0.0; vertPoses[3].y = fVar10 - fVar8; vertPoses[3].z = fVar11 - fVar9; vertPoses[4].x = -0.0 - fVar4; vertPoses[4].y = -fVar8 - fVar10; vertPoses[4].z = -fVar9 - fVar11; vertPoses[5].x = -0.0 - fVar5; vertPoses[5].y = -fVar12 - fVar7; vertPoses[5].z = -fVar13 - fVar6; vertPoses[6].x = 0.0 - fVar5; vertPoses[6].y = fVar12 - fVar7; vertPoses[6].z = fVar13 - fVar6; vertPoses[7].x = 0.0 - fVar4; vertPoses[7].y = fVar8 - fVar10; vertPoses[7].z = fVar9 - fVar11; pVVar14 = vertPoses; uVar15 = 0; do { fVar4 = toPos->x; pfVar3 = (float *)((int)&normal[0].z + uVar15); fVar5 = pVVar14->x; fVar6 = pVVar14->y; *(float *)((int)&normal[0].x + uVar15) = pVVar14->x; pfVar1 = &pVVar14->y; fVar7 = pVVar14->z; uVar16 = uVar15 + 0xc; *(float *)((int)&normal[0].y + uVar15) = fVar6; pfVar2 = &pVVar14->z; *pfVar3 = fVar7; fVar7 = *(float *)((int)&normal[0].y + uVar15); fVar6 = *(float *)((int)&normal[0].x + uVar15); fVar8 = *pfVar3; *(float *)((int)&vertPoses[8].x + uVar15) = fVar4 + fVar5; fVar9 = 1.0 / SQRT(fVar6 * fVar6 + fVar8 * fVar8 + fVar7 * fVar7); *(float *)((int)&vertPoses[8].y + uVar15) = *pfVar1 + toPos->y; fVar4 = fromPos->x; pVVar14[8].z = *pfVar2 + toPos->z; fVar5 = *(float *)((int)&normal[0].x + uVar15); pVVar14->x = fVar4 + pVVar14->x; fVar4 = *(float *)((int)&normal[0].y + uVar15); fVar6 = *pfVar3; *pfVar1 = *pfVar1 + fromPos->y; fVar7 = *pfVar2; fVar8 = fromPos->z; *(float *)((int)&normal[0].x + uVar15) = fVar9 * fVar5; *(float *)((int)&normal[0].y + uVar15) = fVar9 * fVar4; *pfVar3 = fVar9 * fVar6; *pfVar2 = fVar7 + fVar8; pVVar14 = pVVar14 + 1; uVar15 = uVar16; } while (uVar16 < 0x60); groupID = gfx::Mesh_AddGroup(mesh,0x10,0x10,3,faceData); gfx::Mesh_SetGroupColour(mesh,groupID,red,green,blue,Mesh_Colour_Emissive); gfx::Mesh_SetGroupMaterialValues(mesh,groupID,alpha,Mesh_Colour_Alpha); gfx::Mesh_SetVertices_SameNormal(mesh,groupID,0,0x10,vertPoses,normal,textCoords); return; } WeaponsModel * __cdecl lego::tools::Weapon_LegoObject_GetWeaponsModel(LegoObject *liveObj) { if (liveObj->type == LegoObject_Vehicle) { return &liveObj->vehicle->weapons; } if (liveObj->type != LegoObject_Building) { return NULL; } return &liveObj->building->weapons; } float10 __cdecl lego::tools::Weapon_LegoObject_GetWeaponTimer(LegoObject *liveObj,uint frameNo) { WeaponsModel *weapons; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); return (float10)weapons->timers[frameNo]; } void __cdecl lego::tools::Weapon_LegoObject_SetWeaponTimer(LegoObject *liveObj,float timer,uint frameNo) { WeaponsModel *weapons; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); weapons->timers[frameNo] = timer; return; } // Only Z value of the two vector parameters is used. BOOL __cdecl lego::tools::Weapon_MathUnk_CheckVectorsZScalar_InRange (Vector3F *vectorPos,Vector3F *vectorScaled,float minZ,float maxZ,float scalar) { float fVar1; fVar1 = vectorScaled->z * scalar + vectorPos->z; if (((ushort)((ushort)(fVar1 < maxZ) << 8 | (ushort)(fVar1 == maxZ) << 0xe) != 0) && (maxZ - minZ <= fVar1)) { return TRUE; } return FALSE; } BOOL __cdecl lego::tools::Weapon_LegoObject_Callback_FUN_00471630(LegoObject *liveObj,SearchWeapons18_2 *search) { float fVar1; SearchWeapons18_2 *pSVar2; Map3D *map; BOOL BVar3; float10 fVar4; float fVar5; float maxZ; float fVar6; float scalar; SearchWeapons18_2 *scalar_00; Point2F local_28; Point2F local_20; Point2F local_18; Point2F local_10; Point2F local_8; pSVar2 = search; local_8.x = search->fromPos->x; local_8.y = search->fromPos->y; local_28.x = search->fromToDistance->x; local_28.y = search->fromToDistance->y; fVar1 = SQRT(local_28.y * local_28.y + local_28.x * local_28.x); if ((liveObj != search->ignoreObject) && (((ushort)((ushort)(fVar1 < -1e-05) << 8 | (ushort)(fVar1 == -1e-05) << 0xe) != 0 || (1e-05 <= fVar1)))) { game::LegoObject_GetPosition(liveObj,&local_18.x,&local_18.y); fVar5 = local_18.x; fVar6 = local_18.y; map = lrr::Lego_GetMap(); fVar4 = lego::map::Map3D_GetWorldZ(map,fVar5,fVar6); fVar5 = (float)fVar4; math::Collision_PointOnLineRay(&local_8,&local_28,&local_18,&local_10); local_18.x = local_10.x - local_18.x; local_18.y = local_10.y - local_18.y; fVar4 = stats::StatsObject_GetCollRadius(liveObj); if ((float10)SQRT(local_18.y * local_18.y + local_18.x * local_18.x) <= fVar4) { local_20.x = local_10.x - local_8.x; local_20.y = local_10.y - local_8.y; fVar6 = SQRT(local_20.y * local_20.y + local_20.x * local_20.x); if (((ushort)((ushort)(fVar6 < -1e-05) << 8 | (ushort)(fVar6 == -1e-05) << 0xe) == 0) && (fVar6 < 1e-05)) { scalar = 0.0; maxZ = fVar5; fVar4 = stats::StatsObject_GetCollHeight(liveObj); BVar3 = Weapon_MathUnk_CheckVectorsZScalar_InRange (search->fromPos,search->fromToDistance,(float)fVar4,maxZ,scalar); if (BVar3 != 0) { search->foundObject = liveObj; search->ref_float_4 = 0.0; search->success = 1; return 0; } } search = (SearchWeapons18_2 *)(fVar6 / fVar1); if (((((ushort)((ushort)(local_28.x < -1e-05) << 8 | (ushort)(local_28.x == -1e-05) << 0xe) != 0) || (1e-05 <= local_28.x)) || ((ushort)((ushort)(local_20.x < -1e-05) << 8 | (ushort)(local_20.x == -1e-05) << 0xe) != 0 )) || (1e-05 <= local_20.x)) { fVar1 = local_28.x / local_20.x; } else { if ((((ushort)((ushort)(local_28.y < -1e-05) << 8 | (ushort)(local_28.y == -1e-05) << 0xe) == 0) && (local_28.y < 1e-05)) && (((ushort)((ushort)(local_20.y < -1e-05) << 8 | (ushort)(local_20.y == -1e-05) << 0xe) == 0 && (local_20.y < 1e-05)))) { return 0; } fVar1 = local_28.y / local_20.y; } if (fVar1 < 0.0) { search = (SearchWeapons18_2 *)((float)search * -1.0); } if (((ushort)((ushort)((float)search < 0.0) << 8 | (ushort)((float)search == 0.0) << 0xe) == 0 ) && ((float)search < pSVar2->ref_float_4)) { scalar_00 = search; fVar4 = stats::StatsObject_GetCollHeight(liveObj); BVar3 = Weapon_MathUnk_CheckVectorsZScalar_InRange (pSVar2->fromPos,pSVar2->fromToDistance,(float)fVar4,fVar5, (float)scalar_00); if (BVar3 != 0) { pSVar2->foundObject = liveObj; pSVar2->ref_float_4 = (float)search; pSVar2->success = TRUE; } } } } return 0; } void __cdecl lego::tools::Weapon_LegoObject_FUN_004718f0(SearchWeapons18_2 *search) { Map3D *map; BOOL BVar1; uint uVar2; uint uVar3; uint uVar4; uint uVar5; uint uVar6; float fVar7; float fVar8; Vector3F *rayOrigin; uint *puVar9; uint *puVar10; Vector3F *pVVar11; Vector3F *pVVar12; uint by2; uint by1; uint bx2; uint bx1; float local_24; float local_20; float local_1c; Vector3F local_18; float local_8; float local_4; lrr::Lego_GetMap(); lrr::Lego_GetMap(); puVar9 = &bx1; pVVar12 = search->fromToDistance; pVVar11 = search->fromPos; local_18.x = pVVar12->x + pVVar11->x; local_18.y = pVVar11->y + pVVar12->y; local_18.z = pVVar11->z + pVVar12->z; puVar10 = &by1; fVar8 = pVVar11->y; fVar7 = pVVar11->x; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar7,fVar8,(int *)puVar9,(int *)puVar10); if (BVar1 == 0) { map = lrr::Lego_GetMap(); if (map->blockWidth <= bx1) { map = lrr::Lego_GetMap(); bx1 = map->blockWidth - 1; } map = lrr::Lego_GetMap(); if (map->blockHeight <= by1) { map = lrr::Lego_GetMap(); by1 = map->blockHeight - 1; } } puVar9 = &by2; puVar10 = &bx2; fVar8 = local_18.x; fVar7 = local_18.y; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_WorldToBlockPos_NoZ(map,fVar8,fVar7,(int *)puVar10,(int *)puVar9); if (BVar1 == 0) { map = lrr::Lego_GetMap(); if (map->blockWidth <= bx2) { map = lrr::Lego_GetMap(); bx2 = map->blockWidth - 1; } map = lrr::Lego_GetMap(); if (map->blockHeight <= by2) { map = lrr::Lego_GetMap(); by2 = map->blockHeight - 1; } } uVar3 = bx2; uVar2 = by2; if (bx2 < bx1) { bx2 = bx1; bx1 = uVar3; } if (by2 < by1) { by2 = by1; by1 = uVar2; } uVar2 = by2; uVar3 = bx2; uVar4 = bx1; uVar5 = by1; if (bx1 <= bx2) { do { uVar6 = uVar5; if (uVar5 <= uVar2) { do { pVVar11 = search->fromToDistance; rayOrigin = search->fromPos; pVVar12 = &local_18; uVar2 = uVar4; uVar3 = uVar5; map = lrr::Lego_GetMap(); BVar1 = lego::map::Map3D_Intersections_Sub2_FUN_004518a0 (map,uVar2,uVar3,rayOrigin,pVVar11,pVVar12); if (BVar1 != 0) { pVVar12 = search->fromPos; pVVar11 = search->fromToDistance; fVar8 = local_18.x - pVVar12->x; local_8 = local_18.y - pVVar12->y; local_4 = local_18.z - pVVar12->z; local_24 = pVVar11->z; local_20 = pVVar11->x; local_1c = SQRT(local_20 * local_20 + local_24 * local_24 + pVVar11->y * pVVar11->y); fVar8 = SQRT(local_4 * local_4 + local_8 * local_8 + fVar8 * fVar8) / local_1c; if (fVar8 < search->ref_float_4) { search->ref_float_4 = fVar8; search->success = 1; search->foundObject = NULL; } } uVar5 += 1; uVar2 = by2; uVar3 = bx2; uVar6 = by1; } while (uVar5 <= by2); } uVar4 += 1; uVar5 = uVar6; } while (uVar4 <= uVar3); } return; } BOOL __cdecl lego::tools::Weapon_DoCallbacksSearch_FUN_00471b20 (Vector3F *vecCector,Vector3F *vecDistance,LegoObject **out_liveObj,float *ref_float_4, LegoObject *opt_ignoreObj) { SearchWeapons18_2 search; search.foundObject = NULL; search.success = 0; search.ref_float_4 = *ref_float_4; search.fromPos = vecCector; search.fromToDistance = vecDistance; search.ignoreObject = opt_ignoreObj; game::LegoObject_RunThroughListsSkipUpgradeParts(Weapon_LegoObject_Callback_FUN_00471630,&search); Weapon_LegoObject_FUN_004718f0(&search); *ref_float_4 = search.ref_float_4; *out_liveObj = search.foundObject; return search.success; } BOOL __cdecl lego::tools::Weapon_LegoObject_DoCallbacksSearch_FUN_00471b90 (LegoObject *liveObj,LegoObject *otherObj) { BOOL BVar1; float local_28; Vector3F collCenter1; Vector3F collCenter2; Vector3F collDiff; LegoObject *liveObj1_00; LegoObject *liveObj2_00; liveObj1_00 = liveObj; local_28 = 1.0; Weapon_LegoObject_GetCollCenterPosition(liveObj,&collCenter1); liveObj2_00 = otherObj; Weapon_LegoObject_GetCollCenterPosition(otherObj,&collCenter2); collDiff.x = collCenter2.x - collCenter1.x; collDiff.y = collCenter2.y - collCenter1.y; collDiff.z = collCenter2.z - collCenter1.z; BVar1 = Weapon_DoCallbacksSearch_FUN_00471b20 (&collCenter1,&collDiff,&liveObj,&local_28,liveObj1_00); if ((BVar1 != 0) && (liveObj != liveObj2_00)) { return TRUE; } return FALSE; } BOOL __cdecl lego::tools::Weapon_LegoObject_SeeThroughWalls_FUN_00471c20 (LegoObject *liveObj,LegoObject *otherObj) { Lego_Level *pLVar1; BoolTri BVar2; char *pcVar3; undefined4 uVar4; Vector3F local_3c; Vector3F local_30; Vector3F local_24; SearchWeapons18_2 search; search.fromPos = &local_3c; search.fromToDistance = &local_24; uVar4 = 0; pcVar3 = "SeeThroughWalls"; search.foundObject = NULL; search.ref_float_4 = 1.0; search.success = 0; search.ignoreObject = NULL; pLVar1 = lrr::Lego_GetLevel(); pcVar3 = cfg::Config_BuildStringID(globs::legoGlobs.gameName,pLVar1->name,pcVar3,uVar4); BVar2 = cfg::Config_GetBoolValue(globs::weaponGlobs.config,pcVar3); if (BVar2 != BOOL3_FALSE) { return FALSE; } Weapon_LegoObject_GetCollCenterPosition(liveObj,&local_3c); Weapon_LegoObject_GetCollCenterPosition(otherObj,&local_30); local_24.x = local_30.x - local_3c.x; local_24.y = local_30.y - local_3c.y; local_24.z = local_30.z - local_3c.z; Weapon_LegoObject_FUN_004718f0(&search); return search.success; } Container * __cdecl lego::tools::Weapon_GetFireNull(WeaponsModel *weapons,uint frameNo,uint pairNo) { return weapons->fireNullPairs[frameNo][pairNo]; } Container * __cdecl lego::tools::Weapon_GetXPivotNull(WeaponsModel *weapons,uint frameNo) { return weapons->xPivotNulls[frameNo]; } Container * __cdecl lego::tools::Weapon_GetYPivotNull(WeaponsModel *weapons,uint frameNo) { return weapons->yPivotNulls[frameNo]; } void __cdecl lego::tools::Weapon_PivotTracker (WeaponsModel *weapons,Vector3F *targetWorldPos,float elapsed,BOOL assignTarget, uint frameNo) { int iVar1; Vector3F *pVVar2; float fVar3; Container *xPivotNull; Container *yPivotNull; Vector3F pivotPos; float timeScalar; if (assignTarget != 0) { pVVar2 = weapons->targetWorldPoses + frameNo; pVVar2->x = targetWorldPos->x; pVVar2->y = targetWorldPos->y; pVVar2->z = targetWorldPos->z; } xPivotNull = Weapon_GetXPivotNull(weapons,frameNo); // if (elapsed > 0.00001f) if ((xPivotNull != NULL) && ((ushort)((ushort)(elapsed < 1e-05) << 8 | (ushort)(elapsed == 1e-05) << 0xe) == 0)) { gfx::Container_GetPosition(xPivotNull,NULL,&pivotPos); timeScalar = 5.0 / elapsed; iVar1 = (int)weapons->fireNullPairs + frameNo * 0xc; pivotPos.x = *(float *)(iVar1 + 0x68) - pivotPos.x; pivotPos.y = *(float *)(iVar1 + 0x6c) - pivotPos.y; pivotPos.z = *(float *)(iVar1 + 0x70) - pivotPos.z; fVar3 = 1.0 / SQRT(pivotPos.z * pivotPos.z + pivotPos.y * pivotPos.y + pivotPos.x * pivotPos.x); *(float *)(iVar1 + 0x44) = *(float *)(iVar1 + 0x44) * timeScalar; *(float *)(iVar1 + 0x48) = *(float *)(iVar1 + 0x48) * timeScalar; *(float *)(iVar1 + 0x4c) = *(float *)(iVar1 + 0x4c) * timeScalar; *(float *)(iVar1 + 0x44) = fVar3 * pivotPos.x + *(float *)(iVar1 + 0x44); *(float *)(iVar1 + 0x48) = fVar3 * pivotPos.y + *(float *)(iVar1 + 0x48); *(float *)(iVar1 + 0x4c) = fVar3 * pivotPos.z + *(float *)(iVar1 + 0x4c); fVar3 = 1.0 / SQRT(*(float *)(iVar1 + 0x44) * *(float *)(iVar1 + 0x44) + *(float *)(iVar1 + 0x4c) * *(float *)(iVar1 + 0x4c) + *(float *)(iVar1 + 0x48) * *(float *)(iVar1 + 0x48)); *(float *)(iVar1 + 0x44) = *(float *)(iVar1 + 0x44) * fVar3; *(float *)(iVar1 + 0x48) = fVar3 * *(float *)(iVar1 + 0x48); *(float *)(iVar1 + 0x4c) = fVar3 * *(float *)(iVar1 + 0x4c); // if (weapons->vectors3_44[frameNo].z > weapons->pivotMaxZ) { // weapons->vectors3_44[frameNo].z = weapons->pivotMaxZ; // } if ((ushort)((ushort)(*(float *)(iVar1 + 0x4c) < weapons->pivotMaxZ) << 8 | (ushort)(*(float *)(iVar1 + 0x4c) == weapons->pivotMaxZ) << 0xe) == 0) { *(float *)(iVar1 + 0x4c) = weapons->pivotMaxZ; } yPivotNull = Weapon_GetYPivotNull(weapons,frameNo); if (yPivotNull != NULL) { gfx::Container_SetOrientation (yPivotNull,NULL,*(float *)(iVar1 + 0x44),weapons->fireDirections[frameNo].y,0.0,0.0 ,0.0,-1.0); } gfx::Container_SetOrientation (xPivotNull,NULL,*(float *)(iVar1 + 0x44),weapons->fireDirections[frameNo].y, *(float *)(iVar1 + 0x4c),0.0,0.0,-1.0); } return; } // May return out_vector44 (param_2) void __cdecl lego::tools::Weapon_GetFireDirection(WeaponsModel *weapons,Vector3F *out_dir,uint frameNo) { Vector3F *pVVar1; pVVar1 = weapons->fireDirections + frameNo; out_dir->x = pVVar1->x; out_dir->y = pVVar1->y; out_dir->z = pVVar1->z; return; } BOOL __cdecl lego::tools::Weapon_LegoObject_GetCollCenterPosition(LegoObject *liveObj,Vector3F *out_vector) { Container *cont; float10 fVar1; cont = game::LegoObject_GetActivityContainer(liveObj); gfx::Container_GetPosition(cont,NULL,out_vector); fVar1 = stats::StatsObject_GetCollHeight(liveObj); out_vector->z = (float)((float10)out_vector->z - fVar1 * (float10)0.5); return TRUE; } // Returns true if the object is active, and if the object stats specifies it has a tracker (not if // the tracker itself is active). BOOL __cdecl lego::tools::Weapon_LegoObject_IsActiveWithTracker(LegoObject *liveObj) { StatsFlags2 sflags2; BOOL BVar1; sflags2 = stats::StatsObject_GetStatsFlags2(liveObj); if ((sflags2 & STATS2_TRACKER) != STATS2_NONE) { BVar1 = game::LegoObject_IsActive(liveObj,(uint)(liveObj->type != LegoObject_Building)); if (BVar1 != 0) { return TRUE; } } return FALSE; } // Updates the mounted laser tracker on an object when in tracker mode. // The tracker will pivot towards the direction of the mouse, and fire when mslb is down. BOOL __cdecl lego::tools::Weapon_LegoObject_UpdateSelectedTracker(LegoObject *liveObj,float elapsed,uint frameNo) { LegoObject *liveObj_00; WeaponsModel *weapon; uint mouseY; uint mouseX; int iVar1; Container *fireNull; uint weaponID; LegoObject *projectileObj; float10 fVar2; Vector3F *pVVar3; float elapsed_00; BOOL BVar4; uint uVar5; LegoObject **selectedObj; LegoObject *pairNo; LegoObject *local_34; float weaponRange; Point2F local_2c; Vector3F local_24; Vector3F local_18; Vector3F firePos; uint frameNo_00; frameNo_00 = frameNo; liveObj_00 = liveObj; lrr::Lego_GetMouseWorldPosition(&local_18); pVVar3 = &local_18; BVar4 = TRUE; elapsed_00 = elapsed; uVar5 = frameNo; weapon = Weapon_LegoObject_GetWeaponsModel(liveObj); Weapon_PivotTracker(weapon,pVVar3,elapsed_00,BVar4,uVar5); BVar4 = input::mslb(); if (((BVar4 != 0) && ((globs::legoGlobs.flags2 & GAME2_MOUSE_INSIDEGAMEVIEW) != GAME2_NONE)) && (fVar2 = Weapon_LegoObject_GetWeaponTimer(liveObj,frameNo), (ushort)((ushort)(fVar2 < (float10)0.0) << 8 | (ushort)(fVar2 == (float10)0.0) << 0xe) != 0)) { selectedObj = &local_34; mouseY = input::msy(); mouseX = input::msx(); BVar4 = game::LegoObject_DoPickSphereSelection(mouseX,mouseY,selectedObj); if ((BVar4 == 0) || (local_34 != liveObj)) { liveObj = NULL; do { iVar1 = game::Level_GetCrystalCount(TRUE); if (iVar1 != 0) { uVar5 = frameNo_00; pairNo = liveObj; weapon = Weapon_LegoObject_GetWeaponsModel(liveObj_00); fireNull = Weapon_GetFireNull(weapon,uVar5,(uint)pairNo); // This is what handles returning after 1 loop instead of 2. if (fireNull == NULL) { return 1; } weapon = Weapon_LegoObject_GetWeaponsModel(liveObj_00); weaponID = Weapon_GetWeaponIDByName(weapon->parts[frameNo_00]->weaponName); fVar2 = Weapon_GetWeaponRange(weaponID); weaponRange = (float)fVar2; fVar2 = stats::StatsObject_GetFunctionCoef(liveObj_00); frameNo = (uint)(float)fVar2; if (fVar2 == (float10)0.0) { // = 1.0f; frameNo = 0x3f800000; } if (liveObj == NULL) { uVar5 = frameNo_00; fVar2 = Weapon_GetRechargeTime(weaponID); Weapon_LegoObject_SetWeaponTimer(liveObj_00,(float)fVar2,uVar5); pVVar3 = &local_24; uVar5 = frameNo_00; weapon = Weapon_LegoObject_GetWeaponsModel(liveObj_00); Weapon_GetFireDirection(weapon,pVVar3,uVar5); lrr::Lego_SetPointerSFX(PointerSFX_Okay); } gfx::Container_GetPosition(fireNull,NULL,&firePos); projectileObj = Weapon_FireLazer(&firePos,&local_24,liveObj_00,elapsed,weaponRange,weaponID, (float)frameNo); if (projectileObj != NULL) { local_2c.x = local_24.x; local_2c.y = local_24.y; Weapon_GenericDamageObject(projectileObj,weaponID,TRUE,0.0,&local_2c); liveObj_00->projectileObject = projectileObj; } } liveObj = (LegoObject *)((int)&liveObj->type + 1); } while (liveObj < (LegoObject *)0x2); } } return TRUE; } // Updates the mounted laser tracker on an object when not in tracker mode. // The tracker will pivot towards the direction of the vehicle/building. BOOL __cdecl lego::tools::Weapon_LegoObject_UpdateUnselectedTracker (LegoObject *liveObj,float elapsed,uint frameNo) { Container *cont; WeaponsModel *weapons; Vector3F *targetWorldPos; BOOL assignTarget; Vector3F dir; Vector3F wPos; Vector3F newVector68; Vector3F up; cont = game::LegoObject_GetActivityContainer(liveObj); if (cont != NULL) { gfx::Container_GetOrientation(cont,NULL,&dir,&up); gfx::Container_GetPosition(cont,NULL,&wPos); dir.x = dir.x * 10000.0; targetWorldPos = &newVector68; dir.y = dir.y * 10000.0; assignTarget = TRUE; dir.z = dir.z * 10000.0; newVector68.x = dir.x + wPos.x; newVector68.y = dir.y + wPos.y; newVector68.z = dir.z + wPos.z; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); Weapon_PivotTracker(weapons,targetWorldPos,elapsed,assignTarget,frameNo); } return TRUE; } BOOL __cdecl lego::tools::Weapon_LegoObject_UpdateTracker(LegoObject *liveObj,float elapsed) { WeaponsModel *weapons; uint frameNo; if ((*(byte *)&liveObj->flags4 & LIVEOBJ4_LASERTRACKERMODE) == 0) { frameNo = 0; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); if (weapons->count != 0) { do { Weapon_LegoObject_UpdateUnselectedTracker(liveObj,elapsed,frameNo); frameNo += 1; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); } while (frameNo < weapons->count); } } else { frameNo = 0; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); if (weapons->count != 0) { do { Weapon_LegoObject_UpdateSelectedTracker(liveObj,elapsed,frameNo); frameNo += 1; weapons = Weapon_LegoObject_GetWeaponsModel(liveObj); } while (frameNo < weapons->count); return TRUE; } } return TRUE; } // Clears projectile object if it matches the passed object. BOOL __cdecl lego::tools::Weapon_Callback_RemoveProjectileReference (LegoObject *liveObj,LegoObject *projectileObj) { if (liveObj->projectileObject == projectileObj) { liveObj->projectileObject = NULL; } return 0; } BOOL __cdecl lego::tools::Weapon_LegoObject_WithinWeaponRange(LegoObject *liveObj,LegoObject *otherObj) { Weapon_KnownType weaponID; float10 weaponRange; Vector3F otherPos; Vector3F thisPos; weaponID = game::LegoObject_GetEquippedBeam(liveObj); if (((liveObj != NULL) && (otherObj != NULL)) && (weaponID != Weapon_KnownType_None)) { weaponRange = Weapon_GetWeaponRange(weaponID); Weapon_LegoObject_GetCollCenterPosition(liveObj,&thisPos); Weapon_LegoObject_GetCollCenterPosition(otherObj,&otherPos); if (SQRT((otherPos.z - thisPos.z) * (otherPos.z - thisPos.z) + (otherPos.y - thisPos.y) * (otherPos.y - thisPos.y) + (otherPos.x - thisPos.x) * (otherPos.x - thisPos.x)) < (float)weaponRange) { return TRUE; } } return FALSE; } BOOL __cdecl lego::tools::Weapon_LegoObject_WithinAwarenessRange(LegoObject *liveObj,LegoObject *otherObj) { Weapon_KnownType weaponType; float10 awarenessRange; Vector3F otherPos; Vector3F thisPos; weaponType = game::LegoObject_GetEquippedBeam(liveObj); if (((liveObj != NULL) && (otherObj != NULL)) && (weaponType != Weapon_KnownType_None)) { awarenessRange = stats::StatsObject_GetAwarenessRange(liveObj); Weapon_LegoObject_GetCollCenterPosition(liveObj,&thisPos); Weapon_LegoObject_GetCollCenterPosition(otherObj,&otherPos); if (SQRT((otherPos.z - thisPos.z) * (otherPos.z - thisPos.z) + (otherPos.y - thisPos.y) * (otherPos.y - thisPos.y) + (otherPos.x - thisPos.x) * (otherPos.x - thisPos.x)) < (float)awarenessRange) { return TRUE; } } return FALSE; } bool __thiscall lego::video::G98CMovie__InitSample(G98CMovie *this,IAMMultiMediaStream *lpAMMMStream) { IMediaStream **ppIVar1; IAMMultiMediaStreamVtbl *pIVar2; IDirectDrawMediaStream *This; IDirectDrawStreamSample *This_00; IDirectDrawSurface *This_01; HRESULT HVar3; pIVar2 = lpAMMMStream->lpVtbl; ppIVar1 = &this->m_sampleBaseStream; HVar3 = (*pIVar2->GetMediaStream)(lpAMMMStream,&idl::MSPID_PrimaryVideo,ppIVar1); this->m_err = HVar3; if (-1 < HVar3) { HVar3 = (*(*ppIVar1)->lpVtbl->QueryInterface) (*ppIVar1,&idl::IID_IDirectDrawMediaStream,&this->m_sampleStream); this->m_err = HVar3; if (-1 < HVar3) { This = this->m_sampleStream; // IDirectDrawMediaStream->CreateSample(this, IDirectDrawSurface* pSurface, const RECT* // pRect, DWORD dwFlags, IDirectDrawStreamSample** ppSample) HVar3 = (*(code *)This->lpVtbl->CreateSample)(This,NULL,NULL,0,&this->m_sample); this->m_err = HVar3; if (-1 < HVar3) { This_00 = this->m_sample; // IDirectDrawStreamSample->GetSurface(this, IDirectDrawSurface** ppDirectDrawSurface, // RECT* pRect) HVar3 = (*(code *)This_00->lpVtbl->GetSurface)(This_00,&this->m_baseSurf,&this->m_movieRect) ; this->m_err = HVar3; if (-1 < HVar3) { This_01 = this->m_baseSurf; HVar3 = (*This_01->lpVtbl->QueryInterface) (This_01,&idl::IID_IDirectDrawSurface3,(IUnknown **)&this->m_surf); this->m_err = HVar3; if (-1 < HVar3) { // STREAMSTATE_RUN (0x1) HVar3 = (*pIVar2->SetState)(lpAMMMStream,STREAMSTATE_RUN); this->m_err = HVar3; if (-1 < HVar3) { return true; } } } } } } (*(*ppIVar1)->lpVtbl->Release)(*ppIVar1); (*this->m_sampleStream->lpVtbl->Release)(this->m_sampleStream); (*this->m_sample->lpVtbl->Release)(this->m_sample); (*this->m_baseSurf->lpVtbl->Release)(this->m_baseSurf); return -1 < this->m_err; } bool __thiscall lego::video::G98CMovie__OpenAMStream (G98CMovie *this,char *fName,IAMMultiMediaStream **lplpAMMMStream,IDirectDraw2 *ddraw2) { IAMMultiMediaStreamVtbl *pIVar1; HRESULT HVar2; IAMMultiMediaStream *amMMStream; WCHAR wfilenameBuffer [260]; // CLSCTX_INPROC_SERVER (0x1) HVar2 = CoCreateInstance((IID *)&idl::CLSID_AMMultiMediaStream,NULL,1, (IID *)&idl::IID_IAMMultiMediaStream,&amMMStream); if (-1 < HVar2) { // STREAMTYPE_READ (0x0) HVar2 = (*amMMStream->lpVtbl->Initialize)(amMMStream,STREAMTYPE_READ,0,NULL); if (-1 < HVar2) { HVar2 = (*amMMStream->lpVtbl->AddMediaStream) (amMMStream,(IUnknown *)ddraw2,&idl::MSPID_PrimaryVideo,0,NULL); if (-1 < HVar2) { // AMMSF_ADDDEFAULTRENDERER (0x1) HVar2 = (*amMMStream->lpVtbl->AddMediaStream) (amMMStream,NULL,&idl::MSPID_PrimaryAudio,1,NULL); if (HVar2 < 0) { // failure is just outright ignored here? HVar2 = 0; } // The IAMMultiMediaStream::OpenFile function only supports unicode, // so convert our filename to wide chars. MultiByteToWideChar(CP_ACP,0,fName,-1,wfilenameBuffer,0x104); (*amMMStream->lpVtbl->OpenFile)(amMMStream,wfilenameBuffer,0); pIVar1 = amMMStream->lpVtbl; *lplpAMMMStream = amMMStream; (*pIVar1->AddRef)(amMMStream); } } } (*amMMStream->lpVtbl->Release)(amMMStream); return -1 < HVar2; } G98CMovie * __thiscall lego::video::G98CMovie___ctor (G98CMovie *this,char *fName,IDirectDrawSurface3 *bSurf3,IDirectDraw2 *ddraw2) { char cVar1; bool bVar2; undefined4 *puVar3; int iVar4; uint uVar5; uint uVar6; undefined4 *puVar7; char *pcVar8; char *pcVar9; this->m_sampleBaseStream = NULL; this->m_sampleStream = NULL; this->m_baseSurf = NULL; this->m_surf = NULL; this->m_sample = NULL; this->m_bSurf = bSurf3; this->m_ddraw2 = ddraw2; CoInitialize(NULL); if (fName != NULL) { // *(char **)((int)this + 0x30) = std::_strdup(filename); iVar4 = -1; pcVar8 = fName; do { if (iVar4 == 0) break; iVar4 += -1; cVar1 = *pcVar8; pcVar8 = pcVar8 + 1; } while (cVar1 != '\0'); // if (std::strlen(filename) != 0) if (iVar4 != -2) { uVar5 = 0xffffffff; pcVar8 = fName; do { if (uVar5 == 0) break; uVar5 -= 1; cVar1 = *pcVar8; pcVar8 = pcVar8 + 1; } while (cVar1 != '\0'); puVar3 = (undefined4 *)io::Mem_Alloc(~uVar5); uVar5 = 0xffffffff; this->m_filename = (char *)puVar3; pcVar8 = fName; do { pcVar9 = pcVar8; if (uVar5 == 0) break; uVar5 -= 1; pcVar9 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar9; } while (cVar1 != '\0'); uVar5 = ~uVar5; puVar7 = (undefined4 *)(pcVar9 + -uVar5); for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar3 = *puVar7; puVar7 = puVar7 + 1; puVar3 = puVar3 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar3 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar3 = (undefined4 *)((int)puVar3 + 1); } // end of std::_strdup bVar2 = G98CMovie__OpenAMStream(this,fName,&this->m_amStream,ddraw2); if (bVar2 != false) { G98CMovie__InitSample(this,this->m_amStream); } } } return this; } void __thiscall lego::video::G98CMovie___dtor(G98CMovie *this) { IMediaStream *This; IDirectDrawMediaStream *This_00; IDirectDrawStreamSample *This_01; IDirectDrawSurface *This_02; IDirectDrawSurface3 *This_03; IDirectDraw2 *This_04; IAMMultiMediaStream *This_05; This = this->m_sampleBaseStream; if (This != NULL) { (*This->lpVtbl->Release)((IUnknown *)This); } This_00 = this->m_sampleStream; if (This_00 != NULL) { (*This_00->lpVtbl->Release)((IUnknown *)This_00); } This_01 = this->m_sample; if (This_01 != NULL) { (*This_01->lpVtbl->Release)((IUnknown *)This_01); } This_02 = this->m_baseSurf; if (This_02 != NULL) { (*This_02->lpVtbl->Release)((IUnknown *)This_02); } This_03 = this->m_bSurf; if (This_03 != NULL) { (*This_03->lpVtbl->Release)((IUnknown *)This_03); } This_04 = this->m_ddraw2; if (This_04 != NULL) { (*This_04->lpVtbl->Release)((IUnknown *)This_04); } This_05 = this->m_amStream; if (This_05 != NULL) { (*This_05->lpVtbl->Release)((IUnknown *)This_05); } if (this->m_filename != NULL) { io::Mem_Free(this->m_filename); } return; } bool __thiscall lego::video::G98CMovie__Update(G98CMovie *this,float speed,RECT *destRect) { IDirectDrawStreamSample *pIVar1; IAMMultiMediaStream *pIVar2; HRESULT HVar3; pIVar1 = this->m_sample; if (pIVar1 != NULL) { HVar3 = (*(code *)pIVar1->lpVtbl->Update)(pIVar1,0,NULL,NULL,NULL); if (HVar3 == 0) { // DDBLT_WAIT (0x1000000) HVar3 = (*(code *)this->m_bSurf->lpVtbl->Blt) (this->m_bSurf,destRect,this->m_surf,NULL,0x1000000,NULL); return HVar3 == 0; } // On failure... SHUTDOWN EVERYTHING! (*this->m_sampleBaseStream->lpVtbl->Release)(this->m_sampleBaseStream); this->m_sampleBaseStream = NULL; (*this->m_sampleStream->lpVtbl->Release)(this->m_sampleStream); this->m_sampleStream = NULL; (*this->m_sample->lpVtbl->Release)(this->m_sample); this->m_sample = NULL; (*this->m_baseSurf->lpVtbl->Release)(this->m_baseSurf); pIVar2 = this->m_amStream; this->m_baseSurf = NULL; if (pIVar2 != NULL) { (*pIVar2->lpVtbl->Release)(pIVar2); this->m_amStream = NULL; return false; } } return false; } // WARNING: Could not reconcile some variable overlaps longlong __thiscall lego::video::G98CMovie__GetDuration(G98CMovie *this) { longlong lVar1; longlong duration; (*this->m_amStream->lpVtbl->GetDuration)(this->m_amStream,&duration); // __alldiv - 64-bit integer division in 32-bit environments // // return duration / 10000LL; // 100-nanosecond units -> milliseconds lVar1 = __alldiv(CONCAT44(duration._4_4_,(undefined4)duration),10000); return lVar1; } Movie_t * __cdecl lego::video::Movie_Load(char *fName) { char *filename; IDirectDraw4 *pIVar1; IDirectDrawSurface4 *pIVar2; FILE *stream; BOOL BVar3; G98CMovie *videoPlayer; undefined4 *in_FS_OFFSET; IDirectDrawSurface3 *ddSurface3; IDirectDraw2 *ddraw2; G98CMovie *This; char cdFileBuffer [512]; undefined4 local_c; undefined *puStack8; undefined4 local_4; // C++ function start guards (ignore these) local_c = *in_FS_OFFSET; local_4 = 0xffffffff; puStack8 = &LAB_0049e06c; *in_FS_OFFSET = &local_c; // actual start of C++ function filename = io::File_VerifyFilename(fName); videoPlayer = NULL; pIVar1 = ddraw::DirectDraw(); (*pIVar1->lpVtbl->QueryInterface)(pIVar1,&idl::IID_IDirectDraw2,(IUnknown **)&ddraw2); pIVar2 = ddraw::DirectDraw_bSurf(); (*pIVar2->lpVtbl->QueryInterface)(pIVar2,&idl::IID_IDirectDrawSurface3,(IUnknown **)&ddSurface3); stream = std::fopen(filename,"r"); if (stream == NULL) { // File not found in local Data folder, Try open in CDROM/Data folder BVar3 = io::File_GetCDFilePath(cdFileBuffer,fName); if (BVar3 == 0) goto LAB_0047290d; This = (G98CMovie *)std::operator_new(0x38); local_4 = 1; if (This != NULL) { videoPlayer = G98CMovie___ctor(This,cdFileBuffer,ddSurface3,ddraw2); goto LAB_0047290d; } } else { // Open file in local Data folder std::fclose(stream); This = (G98CMovie *)std::operator_new(0x38); local_4 = 0; if (This != NULL) { videoPlayer = G98CMovie___ctor(This,filename,ddSurface3,ddraw2); goto LAB_0047290d; } } videoPlayer = NULL; LAB_0047290d: // C++ function end guard (ignore this) *in_FS_OFFSET = local_c; return (Movie_t *)videoPlayer; } void __cdecl lego::video::Movie_GetSize(Movie_t *mov,uint *out_width,uint *out_height) { DDSURFACEDESC *pDVar1; int iVar2; DDSURFACEDESC surfDesc; pDVar1 = &surfDesc; for (iVar2 = 0x1b; iVar2 != 0; iVar2 += -1) { pDVar1->dwSize = 0; pDVar1 = (DDSURFACEDESC *)((int)pDVar1 + 4); } surfDesc.dwSize = 0x6c; (*(code *)mov->m_surf->lpVtbl->GetSurfaceDesc)(mov->m_surf,&surfDesc); *out_width = surfDesc.dwWidth; *out_height = surfDesc.dwHeight; return; } // Gets the movie duration in milliseconds. longlong __cdecl lego::video::Movie_GetDuration(Movie_t *mov) { longlong lVar1; lVar1 = G98CMovie__GetDuration((G98CMovie *)mov); return lVar1; } BOOL __cdecl lego::video::Movie_Update(Movie_t *mov,float speed,RECT *destRect) { bool bVar1; bVar1 = G98CMovie__Update((G98CMovie *)mov,speed,destRect); return (uint)(bVar1 != false); } void __cdecl lego::video::Movie_Free(Movie_t *mov) { if (mov != NULL) { G98CMovie___dtor((G98CMovie *)mov); // This function is multi-purpose (the linker assigned functions with the same // functionality to different areas). So distinguishing is annoying game::RadarMap_Free_UnwindMultiUse((RadarMap *)mov); } return; } Container * __cdecl lego::gfx::Container_Initialise(char *gameName) { Container *pCVar1; int iVar2; Container_Globs *pCVar3; pCVar3 = &globs::containerGlobs; for (iVar2 = 0x806; iVar2 != 0; iVar2 += -1) { pCVar3->listSet[0] = NULL; pCVar3 = (Container_Globs *)(pCVar3->listSet + 1); } pCVar3 = &globs::containerGlobs; for (iVar2 = 0x14; iVar2 != 0; iVar2 += -1) { pCVar3->listSet[0] = NULL; pCVar3 = (Container_Globs *)(pCVar3->listSet + 1); } globs::containerGlobs.extensionName[1] = "x"; globs::containerGlobs.extensionName[2] = "x"; globs::containerGlobs.extensionName[3] = "x"; globs::containerGlobs.typeName[0] = "NULL"; globs::containerGlobs.typeName[1] = "MESH"; globs::containerGlobs.typeName[2] = "FRAME"; globs::containerGlobs.typeName[3] = "ANIM"; globs::containerGlobs.typeName[7] = "LWS"; globs::containerGlobs.typeName[8] = "LWO"; globs::containerGlobs.typeName[4] = "ACT"; globs::containerGlobs.typeName[5] = NULL; globs::containerGlobs.extensionName[0] = ____EMPTYSTR__; globs::containerGlobs.extensionName[4] = "ae"; globs::containerGlobs.extensionName[5] = ____EMPTYSTR__; globs::containerGlobs.gameName = gameName; globs::containerGlobs.freeList = NULL; globs::containerGlobs.listCount = 0; globs::containerGlobs.flags = CONTAINER_FLAG_INITIALISED; globs::containerGlobs.textureCount = 0; globs::containerGlobs.sharedDir = NULL; pCVar1 = Container_Create(NULL); // D3DRMSORT_NONE (0x1) globs::containerGlobs.rootContainer = pCVar1; (*pCVar1->masterFrame->lpVtbl->SetSortMode)(pCVar1->masterFrame,D3DRMSORT_NONE); return pCVar1; } void __cdecl lego::gfx::Container_Shutdown(void) { int iVar1; Container *in_cont; byte bVar2; int iVar3; Container_TextureRef *pCVar4; Container_Globs *pCVar5; uint uVar6; bVar2 = 0; pCVar5 = &globs::containerGlobs; do { if (pCVar5->listSet[0] != NULL) { iVar1 = 1 << (bVar2 & 0x1f); if (iVar1 != 0) { iVar3 = 0; do { in_cont = (Container *)((int)&pCVar5->listSet[0]->masterFrame + iVar3); if ((in_cont != NULL) && (in_cont->nextFree == in_cont)) { Container_Remove2(in_cont,TRUE); } iVar3 += 0x2c; iVar1 += -1; } while (iVar1 != 0); } io::Mem_Free(pCVar5->listSet[0]); } pCVar5 = (Container_Globs *)(pCVar5->listSet + 1); bVar2 += 1; } while (pCVar5 < (Container_Globs *)&globs::containerGlobs.freeList); uVar6 = 0; globs::containerGlobs.freeList = NULL; globs::containerGlobs.flags = CONTAINER_FLAG_NONE; if (globs::containerGlobs.textureCount != 0) { pCVar4 = globs::containerGlobs.textureSet; do { if (pCVar4->filename != NULL) { io::Mem_Free(pCVar4->filename); } uVar6 += 1; pCVar4 = pCVar4 + 1; } while (uVar6 < globs::containerGlobs.textureCount); } if (globs::containerGlobs.sharedDir != NULL) { io::Mem_Free(globs::containerGlobs.sharedDir); } return; } void __cdecl lego::gfx::Container_SetSharedTextureDirectory(char *path) { globs::containerGlobs.sharedDir = util::Util_StrCpy(path); return; } void __cdecl lego::gfx::Container_EnableSoundTriggers(BOOL on) { if (on != 0) { globs::containerGlobs.flags = globs::containerGlobs.flags | CONTAINER_FLAG_TRIGGERENABLED; return; } globs::containerGlobs.flags = globs::containerGlobs.flags & ~CONTAINER_FLAG_TRIGGERENABLED; return; } void __cdecl lego::gfx::Container_SetTriggerFrameCallback(ContainerTriggerFrameCallback callback,void *data) { globs::containerGlobs.triggerFrameCallback = callback; globs::containerGlobs.triggerFrameData = data; return; } void __cdecl lego::gfx::Container_SetSoundTriggerCallback(ContainerSoundTriggerCallback callback,void *data) { globs::containerGlobs.soundTriggerCallback = callback; globs::containerGlobs.soundTriggerData = data; globs::containerGlobs.flags = globs::containerGlobs.flags | CONTAINER_FLAG_TRIGGERENABLED; return; } // OFFICIAL: Container_GetRoot(void) Container * __cdecl lego::gfx::Container_GetRoot(void) { return globs::containerGlobs.rootContainer; } Container * __cdecl lego::gfx::Container_Create(Container *opt_parent) { Container *cont; HRESULT HVar1; int iVar2; IDirect3DRMFrame3 *parentFrame1; IDirect3DRMFrame3 *parentFrame3; Container *pCVar3; parentFrame1 = NULL; parentFrame3 = NULL; if (opt_parent != NULL) { parentFrame1 = opt_parent->masterFrame; parentFrame3 = opt_parent->hiddenFrame; } if (globs::containerGlobs.freeList == NULL) { Container_AddList(); } cont = globs::containerGlobs.freeList; pCVar3 = globs::containerGlobs.freeList; globs::containerGlobs.freeList = (globs::containerGlobs.freeList)->nextFree; for (iVar2 = 0xb; iVar2 != 0; iVar2 += -1) { pCVar3->masterFrame = NULL; pCVar3 = (Container *)&pCVar3->activityFrame; } cont->nextFree = cont; HVar1 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateFrame) (globs::mainGlobs.lpD3DRM,parentFrame1,&cont->masterFrame); if (HVar1 == 0) { HVar1 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateFrame) (globs::mainGlobs.lpD3DRM,cont->masterFrame,&cont->activityFrame); if (HVar1 == 0) { HVar1 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateFrame) (globs::mainGlobs.lpD3DRM,parentFrame3,&cont->hiddenFrame); if (HVar1 == 0) { Container_Frame_SetAppData (cont->masterFrame,cont,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); Container_Frame_SetAppData (cont->activityFrame,cont,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); Container_Frame_SetAppData (cont->hiddenFrame,cont,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); return cont; } } } Container_Remove(cont); return NULL; } void __cdecl lego::gfx::Container_Remove(Container *cont) { Container_Remove2(cont,FALSE); return; } void __cdecl lego::gfx::Container_Remove2(Container *in_cont,BOOL kill) { Container_CloneData *pCVar1; Container_Type CVar2; Container_TypeData *pCVar3; IDirect3DRMVisual *pIVar4; Container *cont; uint uVar5; AnimClone **out_acList; IDirect3DRMFrame3 **out_frameList; void **buffer; AnimClone *actFrameRes; void *pvVar6; AnimClone **buffer_00; IDirect3DRMFrame3 **ppIVar7; cont = in_cont; if (in_cont->type != Container_Type_Reference) { Container_SetParent(in_cont,NULL); } if (((cont->type == Container_Type_FromActivity) || (cont->type == Container_Type_Anim)) && (pCVar1 = cont->cloneData, pCVar1 != NULL)) { if (kill == 0) { pCVar1->used = 0; return; } if (pCVar1->cloneTable != NULL) { io::Mem_Free(pCVar1->cloneTable); } io::Mem_Free(cont->cloneData); } CVar2 = cont->type; if (CVar2 == Container_Type_FromActivity) { uVar5 = Container_GetActivities(cont,NULL,NULL,NULL); out_acList = (AnimClone **)io::Mem_Alloc(uVar5 * 4); kill = (BOOL)out_acList; out_frameList = (IDirect3DRMFrame3 **)io::Mem_Alloc(uVar5 * 4); Container_GetActivities(cont,out_frameList,out_acList,NULL); buffer_00 = out_acList; if (uVar5 != 0) { ppIVar7 = out_frameList; do { AnimClone_Remove(*(AnimClone **)(((int)out_acList - (int)out_frameList) + (int)ppIVar7)); Container_Frame_FreeName(*ppIVar7); Container_Frame_RemoveAppData(*ppIVar7); (*(*ppIVar7)->lpVtbl->Release)((IUnknown *)*ppIVar7); ppIVar7 = ppIVar7 + 1; uVar5 -= 1; buffer_00 = (AnimClone **)kill; } while (uVar5 != 0); } io::Mem_Free(buffer_00); io::Mem_Free(out_frameList); } else { if (CVar2 == Container_Type_Mesh) { pCVar3 = cont->typeData; if (pCVar3 != NULL) { if (pCVar3->transMesh == NULL) { buffer = (*pCVar3->mesh->lpVtbl->GetAppData)(pCVar3->mesh); if (buffer != NULL) { pvVar6 = NULL; if (buffer[1] != NULL) { do { pIVar4 = *(IDirect3DRMVisual **)((int)*buffer + (int)pvVar6 * 4); (*cont->activityFrame->lpVtbl->DeleteVisual)(cont->activityFrame,pIVar4); (*pIVar4->lpVtbl->Release)(pIVar4); pvVar6 = (void *)((int)pvVar6 + 1); } while (pvVar6 < buffer[1]); } io::Mem_Free(*buffer); io::Mem_Free(buffer); } } else { Mesh_Remove(pCVar3->transMesh,cont->activityFrame); } } } else { if ((CVar2 == Container_Type_Anim) && (actFrameRes = Container_Frame_GetAnimClone(cont->activityFrame), actFrameRes != NULL)) { AnimClone_Remove(actFrameRes); } } } Container_FreeTypeData(cont); if ((cont->type != Container_Type_Reference) || ((*(byte *)&cont->flags & CONTAINER_FLAG_DEADREFERENCE) == 0)) { Container_Frame_RemoveAppData(cont->masterFrame); } if (cont->type != Container_Type_Reference) { Container_Frame_RemoveAppData(cont->activityFrame); } Container_Frame_RemoveAppData(cont->hiddenFrame); if (cont->type == Container_Type_Reference) { (*cont->hiddenFrame->lpVtbl->Release)(cont->hiddenFrame); } else { (*cont->masterFrame->lpVtbl->GetParent)(cont->masterFrame,(IDirect3DRMFrame3 **)&in_cont); if (in_cont != NULL) { // IDirect3DRMFrame3->DeleteChild(this, IDirect3DRMFrame3* lpChild) // (this = resData->frame1->GetParent, lpChild = resData->frame1) (*(code *)in_cont->masterFrame[0x25].lpVtbl)((IDirect3DRMFrame3 *)in_cont,cont->masterFrame); // IDirect3DRMFrame3->Release(this) // (this = resData->frame1->GetParent) (*(code *)in_cont->masterFrame[2].lpVtbl)((IDirect3DRMFrame3 *)in_cont); } (*cont->masterFrame->lpVtbl->Release)(cont->masterFrame); (*cont->activityFrame->lpVtbl->Release)(cont->activityFrame); (*cont->hiddenFrame->lpVtbl->GetParent)(cont->hiddenFrame,(IDirect3DRMFrame3 **)&in_cont); if (in_cont != NULL) { // IDirect3DRMFrame3->DeleteChild(this, IDirect3DRMFrame3* lpChild) // (this = resData->frame3->GetParent, lpChild = resData->frame3) (*(code *)in_cont->masterFrame[0x25].lpVtbl)((IDirect3DRMFrame3 *)in_cont,cont->hiddenFrame); // IDirect3DRMFrame3->Release(this) // (this = resData->frame3->GetParent) (*(code *)in_cont->masterFrame[2].lpVtbl)((IDirect3DRMFrame3 *)in_cont); } (*cont->hiddenFrame->lpVtbl->Release)(cont->hiddenFrame); } cont->nextFree = globs::containerGlobs.freeList; globs::containerGlobs.freeList = cont; return; } Container * __cdecl lego::gfx::Container_Load(Container *parent,char *filename,char *typestr,BOOL looping) { char cVar1; Container_Type CVar2; int iVar3; Config *prop; Config *prop_00; char *pcVar4; BoolTri BVar5; BoolTri BVar6; char *pcVar7; BOOL BVar8; Container *pCVar9; byte *file_data; IDirect3DRMMesh *mesh; Mesh *transMesh; AnimClone *animClone; uint uVar10; uint uVar11; undefined4 *puVar12; undefined4 *puVar13; float10 fVar14; Container *local_864; float local_860; char *local_85c; BOOL isNoTexture; uint local_854; char filenameBuffer [512]; char local_650 [508]; char *apcStack1108 [21]; char filenameBuffer2 [512]; char local_200 [512]; local_864 = NULL; CVar2 = Container_ParseTypeString(typestr,&isNoTexture); uVar10 = 0xffffffff; do { pcVar4 = filename; if (uVar10 == 0) break; uVar10 -= 1; pcVar4 = filename + 1; cVar1 = *filename; filename = pcVar4; } while (cVar1 != '\0'); uVar10 = ~uVar10; puVar12 = (undefined4 *)(pcVar4 + -uVar10); puVar13 = (undefined4 *)filenameBuffer2; for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar13 = *puVar12; puVar12 = puVar12 + 1; puVar13 = puVar13 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar13 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar13 = (undefined4 *)((int)puVar13 + 1); } if (CVar2 == Container_Type_FromActivity) { uVar10 = 0xffffffff; pcVar4 = filenameBuffer2; do { pcVar7 = pcVar4; if (uVar10 == 0) break; uVar10 -= 1; pcVar7 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar7; } while (cVar1 != '\0'); uVar10 = ~uVar10; puVar12 = (undefined4 *)(pcVar7 + -uVar10); puVar13 = (undefined4 *)local_200; for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar13 = *puVar12; puVar12 = puVar12 + 1; puVar13 = puVar13 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar13 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar13 = (undefined4 *)((int)puVar13 + 1); } iVar3 = util::Util_Tokenise(filenameBuffer2,apcStack1108 + 1,"\\"); std::sprintf(filenameBuffer,"%s\\%s.%s",local_200,apcStack1108[iVar3], globs::containerGlobs.extensionName[4]); prop = cfg::Config_Load(filenameBuffer); if (prop != NULL) { std::sprintf(filenameBuffer,"%s%s%s",globs::containerGlobs.gameName,"::","Activities"); prop_00 = cfg::Config_FindArray(prop,filenameBuffer); if (prop_00 != NULL) { local_864 = Container_Create(parent); local_864->type = Container_Type_FromActivity; do { local_85c = prop_00->key; if (*local_85c == '!') { if ((globs::mainGlobs.flags & MAIN_FLAG_REDUCEANIMATION) == MAIN_FLAG_NONE) { if (true) { local_85c = local_85c + 1; } goto LAB_004730ee; } } else { LAB_004730ee: std::sprintf(local_650,"%s%s%s%s%s",globs::containerGlobs.gameName,"::",prop_00->value, "::","FILE"); pcVar4 = cfg::Config_GetTempStringValue(prop,local_650); if (pcVar4 != NULL) { std::sprintf(filenameBuffer,"%s\\%s",local_200,pcVar4); std::sprintf(local_650,"%s%s%s%s%s",globs::containerGlobs.gameName,"::",prop_00->value ,"::","TRANSCOEF"); pcVar4 = cfg::Config_GetTempStringValue(prop,local_650); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_GetTempStringValue(prop,local_650); } fVar14 = std::atof(pcVar4); local_860 = (float)fVar14; std::sprintf(local_650,"%s%s%s%s%s",globs::containerGlobs.gameName,"::",prop_00->value ,"::","TRIGGER"); pcVar4 = cfg::Config_GetTempStringValue(prop,local_650); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_GetTempStringValue(prop,local_650); } local_854 = std::atoi(pcVar4); std::sprintf(local_650,"%s%s%s%s%s",globs::containerGlobs.gameName,"::",prop_00->value ,"::","LWSFILE"); BVar5 = cfg::Config_GetBoolValue(prop,local_650); std::sprintf(local_650,"%s%s%s%s%s",globs::containerGlobs.gameName,"::",prop_00->value ,"::","LOOPING"); BVar6 = cfg::Config_GetBoolValue(prop,local_650); std::sprintf(local_650,"%s%s%s%s%s",globs::containerGlobs.gameName,"::",prop_00->value ,"::","SAMPLE"); pcVar7 = cfg::Config_GetStringValue(prop,local_650); pcVar4 = local_85c; BVar8 = Container_AddActivity2 (local_864,filenameBuffer,local_85c,local_860,local_854,pcVar7,NULL, (uint)(BVar5 == BOOL3_TRUE),(uint)(BVar6 != BOOL3_FALSE)); if ((BVar8 != 0) && (local_864->typeData == NULL)) { Container_SetActivity(local_864,pcVar4); } } } prop_00 = cfg::Config_GetNextItem(prop_00); } while (prop_00 != NULL); } std::sprintf(filenameBuffer,"%s%s%s",globs::containerGlobs.gameName,"::","SCALE"); pcVar4 = cfg::Config_GetTempStringValue(prop,filenameBuffer); if (pcVar4 == NULL) { pcVar4 = ____EMPTYSTR__; } else { pcVar4 = cfg::Config_GetTempStringValue(prop,filenameBuffer); } fVar14 = std::atof(pcVar4); local_85c = (char *)(float)fVar14; if ((float)local_85c != 0.0) { (*local_864->activityFrame->lpVtbl->AddScale) (local_864->activityFrame,D3DRMCOMBINE_REPLACE,(float)local_85c,(float)local_85c, (float)local_85c); } cfg::Config_Free(prop); return local_864; } } else { if (CVar2 == Container_Type_Frame) { pCVar9 = Container_Create(parent); pCVar9->type = Container_Type_Frame; std::sprintf(filenameBuffer,"%s.%s",filenameBuffer2,globs::containerGlobs.extensionName[2]); Container_FrameLoad(filenameBuffer,pCVar9->activityFrame); return pCVar9; } if (CVar2 == Container_Type_Mesh) { std::sprintf(filenameBuffer,"%s.%s",filenameBuffer2,globs::containerGlobs.extensionName[1]); file_data = io::File_LoadBinary(filenameBuffer,(uint *)&local_860); if (file_data != NULL) { pCVar9 = Container_Create(parent); pCVar9->type = Container_Type_Mesh; mesh = Container_MeshLoad(file_data,(uint)local_860,filenameBuffer,pCVar9->activityFrame, isNoTexture); if (mesh != NULL) { Container_SetTypeData(pCVar9,NULL,NULL,mesh,NULL); } io::Mem_Free(file_data); return pCVar9; } } else { if ((CVar2 == Container_Type_Anim) || (CVar2 == Container_Type_LWS)) { pCVar9 = Container_Create(parent); pCVar9->type = Container_Type_Anim; std::sprintf(filenameBuffer,"%s.%s",filenameBuffer2,globs::containerGlobs.extensionName[3]); animClone = Container_LoadAnimSet (filenameBuffer,pCVar9->activityFrame,(uint *)&local_860, (uint)(CVar2 == Container_Type_LWS),looping); if (animClone != NULL) { Container_Frame_SetAppData (pCVar9->activityFrame,pCVar9,animClone,filenameBuffer2,(uint *)&local_860,NULL, NULL,NULL,NULL,NULL,NULL); return pCVar9; } } else { if (CVar2 != Container_Type_LWO) { return NULL; } pCVar9 = Container_Create(parent); pCVar9->type = Container_Type_LWO; transMesh = Mesh_Load(filenameBuffer2,pCVar9->activityFrame,isNoTexture); if (transMesh != NULL) { Container_SetTypeData(pCVar9,NULL,NULL,NULL,transMesh); return pCVar9; } } Container_Remove(pCVar9); } } return NULL; } BOOL __cdecl lego::gfx::Container_IsCurrentActivity(Container *cont,char *actname) { IDirect3DRMFrame3 *frame; if (cont->type == Container_Type_FromActivity) { frame = Container_Frame_Find(cont,actname,0); if (frame != NULL) { return TRUE; } } return 0; } BOOL __cdecl lego::gfx::Container_SetActivity(Container *cont,char *actname) { char cVar1; IDirect3DRMFrame3 *child; IDirect3DRMFrame3 *child_00; undefined4 *name; uint uVar2; uint uVar3; char *buffer; BOOL BVar4; undefined4 *puVar5; char *pcVar6; undefined4 *puVar7; BVar4 = 0; if (cont->type == Container_Type_FromActivity) { child = Container_Frame_Find(cont,actname,1); if (child == NULL) { BVar4 = 0; } else { buffer = NULL; if (((cont->typeData != NULL) && (pcVar6 = cont->typeData->name, pcVar6 != NULL)) && (child_00 = Container_Frame_Find(cont,pcVar6,0), buffer = pcVar6, child_00 != NULL)) { Container_Frame_SafeAddChild(cont->hiddenFrame,child_00); } Container_Frame_SafeAddChild(cont->activityFrame,child); uVar2 = 0xffffffff; pcVar6 = actname; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); name = (undefined4 *)io::Mem_Alloc(~uVar2); uVar2 = 0xffffffff; do { pcVar6 = actname; if (uVar2 == 0) break; uVar2 -= 1; pcVar6 = actname + 1; cVar1 = *actname; actname = pcVar6; } while (cVar1 != '\0'); uVar2 = ~uVar2; puVar5 = (undefined4 *)(pcVar6 + -uVar2); puVar7 = name; for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar7 = *puVar5; puVar5 = puVar5 + 1; puVar7 = puVar7 + 1; } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } Container_SetTypeData(cont,(char *)name,NULL,NULL,NULL); BVar4 = 1; cont->flags = cont->flags | CONTAINER_FLAG_TRIGGERSAMPLE; if (buffer != NULL) { io::Mem_Free(buffer); } } if (cont->activityCallback != NULL) { (*cont->activityCallback)(cont,cont->activityCallbackData); } } return BVar4; } BOOL __cdecl lego::gfx::Container_Light_SetSpotPenumbra(Container *spotlight,float angle) { IDirect3DRMLight *This; HRESULT HVar1; This = spotlight->typeData->light; HVar1 = (*This->lpVtbl->SetPenumbra)(This,angle); return (uint)(HVar1 == 0); } BOOL __cdecl lego::gfx::Container_Light_SetSpotUmbra(Container *spotlight,float angle) { IDirect3DRMLight *This; HRESULT HVar1; This = spotlight->typeData->light; HVar1 = (*This->lpVtbl->SetUmbra)(This,angle); return (uint)(HVar1 == 0); } BOOL __cdecl lego::gfx::Container_Light_SetSpotRange(Container *spotlight,float dist) { IDirect3DRMLight *This; HRESULT HVar1; This = spotlight->typeData->light; HVar1 = (*This->lpVtbl->SetRange)(This,dist); return (uint)(HVar1 == 0); } void __cdecl lego::gfx::Container_Light_SetEnableContainer(Container *light,Container *enable) { IDirect3DRMLight *This; // IDirect3DRMFrame3->QueryInterface(this, IID_IDirect3DRMFrame, IDirect3DRMFrame** // lplpOut) // (downcast: IDirect3DRMFrame3 -> IDirect3DRMFrame) (*enable->masterFrame->lpVtbl->QueryInterface) ((IUnknown *)enable->masterFrame,(IID *)&idl::IID_IDirect3DRMFrame, (IDirect3DRMFrame **)&enable); This = light->typeData->light; // IDirect3DRMLight->SetEnableFrame(this, IDirect3DRMFrame* lpEnableFrame) (*This->lpVtbl->SetEnableFrame)(This,(IDirect3DRMFrame *)enable); return; } Container * __cdecl lego::gfx::Container_MakeLight(Container *parent,D3DRMLightType type,float r,float g,float b) { Container *cont; HRESULT HVar1; IDirect3DRM3 *light; IDirect3DRMLight *lpD3DRMLight; cont = Container_Create(parent); if (cont != NULL) { cont->type = Container_Type_Light; // IDirect3DRM3->CreateLightRGB(this, TD3DRMLightType ltLightType, float vRed, float // vGreen, float vBlue, IDirect3DRMLight** lplpD3DRMLight) light = globs::mainGlobs.lpD3DRM; lpD3DRMLight = (IDirect3DRMLight *)r; HVar1 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateLightRGB) (globs::mainGlobs.lpD3DRM,type,r,g,b,(IDirect3DRMLight **)&parent); if (HVar1 == 0) { // IDirect3DRMFrame3->AddLight(this, IDirect3DRMLight* lpD3DRMLight) (*cont->activityFrame->lpVtbl->AddLight)(cont->activityFrame,lpD3DRMLight); Container_SetTypeData(cont,NULL,(IDirect3DRMLight *)light,NULL,NULL); } } return cont; } Container * __cdecl lego::gfx::Container_MakeMesh2(Container *parent,Container_MeshType type) { Container_MeshType CVar1; Container *cont; HRESULT HVar2; void **data; void *pvVar3; uint renderFlags; Mesh *transMesh; IDirect3DRMMesh *unaff_ESI; cont = Container_Create(parent); CVar1 = type; if (cont != NULL) { cont->type = Container_Type_Mesh; if (((type == Container_MeshType_Transparent) || (type == Container_MeshType_Immediate)) || (type == Container_MeshType_Additive)) { renderFlags = 0x2000; if (type == Container_MeshType_Transparent) { renderFlags = 0x3000; } else { if (type == Container_MeshType_Additive) { renderFlags = 0x2800; } } transMesh = Mesh_CreateOnFrame(cont->activityFrame,NULL,renderFlags,NULL,Mesh_Type_Norm); Container_SetTypeData(cont,NULL,NULL,NULL,transMesh); } else { HVar2 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateMesh) (globs::mainGlobs.lpD3DRM,(IDirect3DRMMesh **)&parent); if (HVar2 == 0) { (*cont->activityFrame->lpVtbl->AddVisual)(cont->activityFrame,(IDirect3DRMVisual *)parent); Container_SetTypeData(cont,NULL,NULL,unaff_ESI,NULL); if (CVar1 == Container_MeshType_SeperateMeshes) { data = (void **)io::Mem_Alloc(0x14); data[2] = &DAT_00000014; data[1] = NULL; pvVar3 = io::Mem_Alloc(0x50); *data = pvVar3; data[3] = NULL; data[4] = (void *)0x1; (*unaff_ESI->lpVtbl->SetAppData)((IUnknown *)unaff_ESI,(DWORD)data); return cont; } (*unaff_ESI->lpVtbl->SetAppData)((IUnknown *)unaff_ESI,0); return cont; } } } return cont; } IDirect3DRMFrame3 * __cdecl lego::gfx::Container_GetMasterFrame(Container *cont) { return cont->masterFrame; } // WARNING: Type propagation algorithm not settling Container * __cdecl lego::gfx::Container_Clone(Container *orig) { char cVar1; IDirect3DRMMesh *pIVar2; Container_TypeData *pCVar3; Container_Type CVar4; Container *pCVar5; Container *parent; Container **ppCVar6; Container_TypeData *pCVar7; char *pcVar8; Container_CloneData *pCVar9; float fVar10; IDirect3DRMFrame3 **out_frameList; char **out_nameList; char *pcVar11; AnimClone *pAVar12; Mesh *pMVar13; uint uVar14; uint uVar15; Container *cont; undefined4 *puVar16; IDirect3DRMFrame3 **ppIVar17; Container *pCVar18; undefined4 *puVar19; float10 fVar20; IDirect3DRMFrame3 *This; float fVar21; int iVar22; int iVar23; char **ppcVar24; IDirect3DRMFrame3 **ppIVar25; undefined local_54 [52]; float fStack32; int *piStack28; IDirect3DRMFrame3 *pIStack4; cont = orig; pCVar18 = NULL; if (orig->type == Container_Type_Mesh) { pIVar2 = orig->typeData->mesh; (*pIVar2->lpVtbl->GetAppData)((IUnknown *)pIVar2); } if ((cont->type == Container_Type_FromActivity) || (cont->type == Container_Type_Anim)) { if ((cont->cloneData != NULL) && (pCVar5 = cont->cloneData->clonedFrom, pCVar5 != NULL)) { cont = pCVar5; } pCVar9 = cont->cloneData; if (pCVar9 == NULL) { pCVar5 = Container_GetParent(cont); pCVar5 = Container_Create(pCVar5); pCVar9 = (Container_CloneData *)io::Mem_Alloc(0x14); cont->cloneData = pCVar9; pCVar9->cloneCount = 1; ppCVar6 = (Container **)io::Mem_Alloc(4); cont->cloneData->cloneTable = ppCVar6; ((Container *)cont->cloneData->cloneTable)->masterFrame = (IDirect3DRMFrame3 *)pCVar5; cont->cloneData->clonedFrom = NULL; cont->cloneData->cloneNumber = NULL; cont->cloneData->used = 1; } else { pCVar5 = cont; if (pCVar9->used != 0) { uVar14 = 0; pCVar5 = pCVar18; if (pCVar9->cloneCount != 0) { ppCVar6 = pCVar9->cloneTable; do { pCVar5 = *ppCVar6; if ((pCVar5 != NULL) && (pCVar5->cloneData->used == 0)) break; uVar14 += 1; ppCVar6 = ppCVar6 + 1; pCVar5 = pCVar18; } while (uVar14 < pCVar9->cloneCount); } } pCVar18 = pCVar5; if (pCVar5 == NULL) { pCVar5 = Container_GetParent(cont); pCVar5 = Container_Create(pCVar5); uVar14 = cont->cloneData->cloneCount; cont->cloneData->cloneCount = uVar14 + 1; ppCVar6 = (Container **) io::Mem_ReAlloc(cont->cloneData->cloneTable,cont->cloneData->cloneCount << 2); cont->cloneData->cloneTable = ppCVar6; cont->cloneData->cloneTable[uVar14] = pCVar5; } else { pCVar5->cloneData->used = 1; parent = Container_GetParent(cont); Container_SetParent(pCVar5,parent); Container_SetAnimationTime(pCVar5,0.0); } } } else { pCVar5 = Container_GetParent(cont); pCVar5 = Container_Create(pCVar5); } (*cont->activityFrame->lpVtbl->GetParent)(cont->activityFrame,(IDirect3DRMFrame3 **)&orig); This = cont->activityFrame; (*This->lpVtbl->GetTransform)(This,pIStack4,(Matrix4F *)(local_54 + 0xc)); (*pCVar5->activityFrame->lpVtbl->AddTransform) (pCVar5->activityFrame,D3DRMCOMBINE_REPLACE,(Matrix4F *)local_54); (**(code **)(*piStack28 + 8))(piStack28); if (pCVar18 == NULL) { pCVar5->type = cont->type; if (cont->typeData == NULL) { pCVar5->typeData = NULL; } else { pCVar7 = (Container_TypeData *)io::Mem_Alloc(0x10); pCVar5->typeData = pCVar7; pCVar3 = cont->typeData; pCVar7->name = pCVar3->name; pCVar7->light = pCVar3->light; pCVar7->mesh = pCVar3->mesh; pCVar7->transMesh = pCVar3->transMesh; pcVar8 = cont->typeData->name; if (pcVar8 != NULL) { uVar14 = 0xffffffff; do { if (uVar14 == 0) break; uVar14 -= 1; cVar1 = *pcVar8; pcVar8 = pcVar8 + 1; } while (cVar1 != '\0'); pcVar8 = (char *)io::Mem_Alloc(~uVar14); pCVar5->typeData->name = pcVar8; uVar14 = 0xffffffff; pcVar8 = cont->typeData->name; do { pcVar11 = pcVar8; if (uVar14 == 0) break; uVar14 -= 1; pcVar11 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar11; } while (cVar1 != '\0'); uVar14 = ~uVar14; puVar16 = (undefined4 *)(pcVar11 + -uVar14); puVar19 = (undefined4 *)pCVar5->typeData->name; for (uVar15 = uVar14 >> 2; uVar15 != 0; uVar15 -= 1) { *puVar19 = *puVar16; puVar16 = puVar16 + 1; puVar19 = puVar19 + 1; } for (uVar14 &= 3; uVar14 != 0; uVar14 -= 1) { *(undefined *)puVar19 = *(undefined *)puVar16; puVar16 = (undefined4 *)((int)puVar16 + 1); puVar19 = (undefined4 *)((int)puVar19 + 1); } } } if ((cont->type == Container_Type_FromActivity) || (cont->type == Container_Type_Anim)) { pCVar9 = (Container_CloneData *)io::Mem_Alloc(0x14); pCVar5->cloneData = pCVar9; pCVar9->cloneTable = NULL; pCVar5->cloneData->cloneCount = 0; pCVar5->cloneData->clonedFrom = cont; pCVar5->cloneData->cloneNumber = This; pCVar5->cloneData->used = 1; } CVar4 = pCVar5->type; if (CVar4 == Container_Type_Mesh) { pIVar2 = pCVar5->typeData->mesh; (*pCVar5->activityFrame->lpVtbl->AddVisual)(pCVar5->activityFrame,(IDirect3DRMVisual *)pIVar2) ; (*pIVar2->lpVtbl->AddRef)((IUnknown *)pIVar2); return pCVar5; } if (CVar4 == Container_Type_FromActivity) { fVar10 = (float)Container_GetActivities(cont,NULL,NULL,NULL); uVar14 = (int)fVar10 * 4; out_frameList = (IDirect3DRMFrame3 **)io::Mem_Alloc(uVar14); ppIVar25 = out_frameList; out_nameList = (char **)io::Mem_Alloc(uVar14); ppcVar24 = out_nameList; Container_GetActivities(cont,out_frameList,NULL,out_nameList); fStack32 = 0.0; if (fVar10 != 0.0) { ppIVar17 = out_frameList; iVar22 = (int)out_nameList - (int)out_frameList; out_nameList = ppcVar24; out_frameList = ppIVar25; do { pcVar8 = Container_Frame_GetAnimSetFileName(*ppIVar17); fVar20 = Container_Frame_GetTransCo(*ppIVar17); fVar21 = (float)fVar20; pcVar11 = Container_Frame_GetSample(*ppIVar17); pAVar12 = Container_Frame_GetAnimClone(*ppIVar17); uVar14 = Container_Frame_GetTrigger(*ppIVar17); Container_Frame_SetAppData(*ppIVar17,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); iVar23 = iVar22; Container_AddActivity2 (pCVar5,pcVar8,(char *)(*(int *)(iVar22 + (int)ppIVar17) + 9),fVar21,uVar14, pcVar11,pAVar12,0,0); io::Mem_Free(*(void **)(iVar22 + (int)ppIVar17)); fVar21 = fStack32; if ((uint)fStack32 % 0x19 == 0) { snd::Sound3D_Update(); } fStack32 = (float)((int)fVar21 + 1); ppIVar17 = ppIVar17 + 1; iVar22 = iVar23; } while ((uint)fStack32 < (uint)fVar10); } io::Mem_Free(out_frameList); io::Mem_Free(out_nameList); if (pCVar5->typeData != NULL) { Container_SetActivity(pCVar5,pCVar5->typeData->name); return pCVar5; } } else { if (CVar4 == Container_Type_Anim) { pcVar8 = Container_Frame_GetAnimSetFileName(cont->activityFrame); pAVar12 = Container_Frame_GetAnimClone(cont->activityFrame); pAVar12 = AnimClone_Make(pAVar12,pCVar5->activityFrame,(uint *)&fStack32); Container_Frame_SetAppData (pCVar5->activityFrame,pCVar5,pAVar12,pcVar8,(uint *)&fStack32,NULL,NULL,NULL,NULL ,NULL,NULL); return pCVar5; } if (CVar4 == Container_Type_LWO) { pMVar13 = Mesh_Clone(pCVar5->typeData->transMesh,pCVar5->activityFrame); pCVar5->typeData->transMesh = pMVar13; } } } return pCVar5; } void __cdecl lego::gfx::Container_Hide2(Container *cont,BOOL hide) { if (hide != 0) { cont->flags = cont->flags | CONTAINER_FLAG_HIDDEN2; return; } cont->flags = cont->flags & ~CONTAINER_FLAG_HIDDEN2; return; } void __cdecl lego::gfx::Container_Hide(Container *cont,BOOL hide) { ContainerFlags CVar1; CVar1 = cont->flags & CONTAINER_FLAG_HIDDEN; if (hide != 0) { if (CVar1 == CONTAINER_FLAG_NONE) { Container_Frame_SafeAddChild(cont->hiddenFrame,cont->activityFrame); cont->flags = cont->flags | CONTAINER_FLAG_HIDDEN; return; } if (hide != 0) { return; } } if (CVar1 != CONTAINER_FLAG_NONE) { Container_Frame_SafeAddChild(cont->masterFrame,cont->activityFrame); cont->flags = cont->flags & ~CONTAINER_FLAG_HIDDEN; } return; } BOOL __cdecl lego::gfx::Container_IsHidden(Container *cont) { return (cont->flags & 0xff) >> 3 & 1; } Container * __cdecl lego::gfx::Container_SearchTree (Container *root,char *name,Container_SearchMode mode,uint *ref_count) { char cVar1; Container *pCVar2; uint uVar3; Container_SearchData search; uVar3 = 0xffffffff; search.string = name; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *name; name = name + 1; } while (cVar1 != '\0'); search.stringLen = ~uVar3 - 1; search.caseSensitive = 0; search.resultFrame = NULL; search.count = 0; search.mode = mode; if (ref_count == NULL) { search.matchNumber = 0; } else { search.matchNumber = *ref_count; } Container_Frame_WalkTree(root->masterFrame,0,Container_Frame_SearchCallback,&search); if ((mode == Container_SearchMode_FirstMatch) || (mode == Container_SearchMode_NthMatch)) { if (search.resultFrame != NULL) { pCVar2 = Container_Frame_GetContainer(search.resultFrame); return pCVar2; } } else { if (mode == Container_SearchMode_MatchCount) { *ref_count = search.count; return NULL; } } return NULL; } // Returns a temporary buffer that must be used immediately before the next call to this function. char * __cdecl lego::gfx::Container_FormatPartName(Container *cont,char *partname,int *opt_instance) { char *pcVar1; AnimClone *clone; BOOL BVar2; char *pcVar3; char *pcVar4; IDirect3DRMFrame3 *frame; char tempString [1024]; if (cont->type == Container_Type_FromActivity) { frame = Container_Frame_Find(cont,cont->typeData->name,0); } else { if (cont->type == Container_Type_Anim) { frame = cont->activityFrame; } } clone = Container_Frame_GetAnimClone(frame); BVar2 = AnimClone_IsLws__Flic_GetWidth(clone); if (BVar2 == 0) { pcVar3 = Container_Frame_GetAnimSetFileName(frame); std::sprintf(tempString,"%s",pcVar3); std::_strlwr(tempString); pcVar4 = tempString; pcVar3 = tempString; while (tempString[0] != '\0') { if (tempString[0] == '\\') { pcVar3 = pcVar4 + 1; } pcVar1 = pcVar4 + 1; pcVar4 = pcVar4 + 1; tempString[0] = *pcVar1; } if (opt_instance != NULL) { std::sprintf(globs::s_FormatPartName_name,"xf_????????_%s_%s_%0.2d_DDc_00",partname,pcVar3, *opt_instance); return globs::s_FormatPartName_name; } pcVar4 = "xf_????????_%s_%s_??_DDc_00"; } else { if (opt_instance == NULL) { std::sprintf(globs::s_FormatPartName_name,"%s_??",partname); return globs::s_FormatPartName_name; } pcVar3 = (char *)*opt_instance; pcVar4 = "%s_%0.2i"; } std::sprintf(globs::s_FormatPartName_name,pcVar4,partname,(int)pcVar3); return globs::s_FormatPartName_name; } void __cdecl lego::gfx::Container_SetUserData(Container *cont,void *data) { cont->userData = data; return; } void * __cdecl lego::gfx::Container_GetUserData(Container *cont) { return cont->userData; } void __cdecl lego::gfx::Container_EnableFog(BOOL on) { (*(globs::containerGlobs.rootContainer)->masterFrame->lpVtbl->SetSceneFogEnable) ((globs::containerGlobs.rootContainer)->masterFrame,on); if (on != 0) { (*(globs::containerGlobs.rootContainer)->masterFrame->lpVtbl->SetSceneBackground) ((globs::containerGlobs.rootContainer)->masterFrame,globs::containerGlobs.fogColour); return; } (*(globs::containerGlobs.rootContainer)->masterFrame->lpVtbl->SetSceneBackground) ((globs::containerGlobs.rootContainer)->masterFrame,0); return; } void __cdecl lego::gfx::Container_SetFogColour(float r,float g,float b) { longlong lVar1; longlong lVar2; longlong lVar3; lVar1 = __ftol((float10)g * (float10)255.0); lVar2 = __ftol((float10)r * (float10)255.0); lVar3 = __ftol((float10)b * (float10)255.0); globs::containerGlobs.fogColour = ((uint)lVar1 | ((uint)lVar2 | 0xffffff00) << 8) << 8 | (uint)lVar3; (*(globs::containerGlobs.rootContainer)->masterFrame->lpVtbl->SetSceneFogColor) ((globs::containerGlobs.rootContainer)->masterFrame,globs::containerGlobs.fogColour); return; } void __cdecl lego::gfx::Container_SetFogMode(D3DRMSceneFogMethod mode) { (*(globs::containerGlobs.rootContainer)->masterFrame->lpVtbl->SetSceneFogMode) ((globs::containerGlobs.rootContainer)->masterFrame,mode); (*(globs::containerGlobs.rootContainer)->masterFrame->lpVtbl->SetSceneFogMethod) ((globs::containerGlobs.rootContainer)->masterFrame,globs::mainGlobs.fogMethod); return; } void __cdecl lego::gfx::Container_SetFogParams(float start,float end,float density) { (*(globs::containerGlobs.rootContainer)->masterFrame->lpVtbl->SetSceneFogParams) ((globs::containerGlobs.rootContainer)->masterFrame,start,end,density); return; } void __cdecl lego::gfx::Container_SetPerspectiveCorrection(Container *cont,BOOL on) { uint uVar1; IDirect3DRMFrame3 **out_frameList; D3DRMGroupIndex DVar2; IDirect3DRMFrame3 **ppIVar3; D3DRMGroupIndex groupID; if (cont->type == Container_Type_FromActivity) { uVar1 = Container_GetActivities(cont,NULL,NULL,NULL); out_frameList = (IDirect3DRMFrame3 **)io::Mem_Alloc(uVar1 * 4); Container_GetActivities(cont,out_frameList,NULL,NULL); ppIVar3 = out_frameList; for (; uVar1 != 0; uVar1 -= 1) { Container_Frame_WalkTree(*ppIVar3,0,Container_SetPerspectiveCorrectionCallback,&on); ppIVar3 = ppIVar3 + 1; } io::Mem_Free(out_frameList); return; } if (cont->type == Container_Type_Mesh) { DVar2 = Container_Mesh_GetGroupCount(cont); groupID = D3DRMGROUP_0; if (DVar2 != D3DRMGROUP_0) { do { Container_Mesh_SetPerspectiveCorrection(cont,groupID,on); groupID += 1; } while (groupID < DVar2); } } return; } BOOL __cdecl lego::gfx::Container_SetPerspectiveCorrectionCallback(IDirect3DRMFrame3 *frame,BOOL *lpArg_on) { BOOL BVar1; HRESULT HVar2; IDirect3DRMVisual *pIVar3; IDirect3DRMVisual **ppIVar4; int *unaff_ESI; IDirect3DRMVisual *lpD3DRMVisual; BOOL *local_8; LPVOID local_4; BVar1 = *lpArg_on; // IDirect3DRMFrame3->GetVisuals(this, DWORD* lpdwCount, IDirect3DRMVisualArray** // lplpVisuals) // // First get count of array, to confirm its non-zero (*frame->lpVtbl->GetVisuals)(frame,(DWORD *)&lpArg_on,NULL); if (lpArg_on != NULL) { // IDirect3DRMFrame3->GetVisuals(this, DWORD* lpdwCount, IDirect3DRMVisualArray** // lplpVisuals) // // Then get the actual array (*frame->lpVtbl->GetVisuals) (frame,(DWORD *)&lpArg_on,(IDirect3DRMVisualArray **)globs::containerGlobs.visualArray ); local_8 = NULL; if (lpArg_on != NULL) { ppIVar4 = globs::containerGlobs.visualArray; do { pIVar3 = *ppIVar4; HVar2 = (*pIVar3->lpVtbl->QueryInterface) ((IUnknown *)pIVar3,(IID *)&idl::IID_IDirect3DRMMeshBuilder2,&local_4); if (HVar2 == 0) { (**(code **)(*unaff_ESI + 0x7c))(unaff_ESI,BVar1); } else { HVar2 = (*pIVar3->lpVtbl->QueryInterface) ((IUnknown *)pIVar3,(IID *)&idl::IID_IDirect3DRMMesh,&local_8); if (HVar2 == 0) { pIVar3 = (IDirect3DRMVisual *)(*frame->lpVtbl->GetMaterialMode)(frame); lpD3DRMVisual = NULL; if (pIVar3 != NULL) { do { (*frame->lpVtbl->AddVisual)(frame,lpD3DRMVisual); lpD3DRMVisual = (IDirect3DRMVisual *)((int)&lpD3DRMVisual->lpVtbl + D3DRMMATERIAL_FROMPARENT); } while (lpD3DRMVisual < pIVar3); } } } local_8 = (BOOL *)((int)local_8 + 1); ppIVar4 = ppIVar4 + 1; } while (local_8 < lpArg_on); } } return 0; } // WARNING: Type propagation algorithm not settling IDirectDrawSurface4 * __cdecl lego::gfx::Container_LoadTextureSurface (char *fname,BOOL managed,uint *out_width,uint *out_height,BOOL *out_trans) { BITMAP_FILE_INFO_STRUCT *data; HRESULT HVar1; BOOL BVar2; IDirectDrawSurface4 *pIVar3; int iVar4; uint uVar5; DDSURFACEDESC2 *pDVar6; undefined4 *puVar7; DDSURFACEDESC2 *pDVar8; undefined4 *puVar9; DDPIXELFORMAT *pDVar10; IDirectDrawSurface4 *ddSurface4; uint local_14c; DDCOLORKEY local_148; IDirectDrawPalette *ddPal2; uint length; D3DRMImage d3dImage; DDSURFACEDESC2 surfDesc; DDSURFACEDESC2 local_7c; ddSurface4 = NULL; local_148.dwColorSpaceLowValue = 0; data = (BITMAP_FILE_INFO_STRUCT *)io::File_LoadBinary(fname,&length); if (data != NULL) { lego::image::BMP_Parse(data,length,&d3dImage); if ((d3dImage.rgb == 0) && (d3dImage.depth == 8)) { pDVar6 = &surfDesc; for (iVar4 = 0x1f; iVar4 != 0; iVar4 += -1) { pDVar6->dwSize = 0; pDVar6 = (DDSURFACEDESC2 *)&pDVar6->dwFlags; } surfDesc.dwSize = 0x7c; // CMD_NM 0x20 surfDesc.dwFlags = 0x1007; surfDesc.dwWidth = d3dImage.width; surfDesc.dwHeight = d3dImage.height; surfDesc.ddsCaps.dwCaps = 0x1000; if ((((byte)globs::mainGlobs.flags & 0x20) == 0) && (managed != 0)) { surfDesc.ddsCaps.dwCaps2 = 0x10; } else { surfDesc.ddsCaps.dwCaps = 0x5000; } surfDesc.ddpfPixelFormat.dwSize = 0x20; HVar1 = (*(globs::mainGlobs.device)->lpVtbl->FindPreferredTextureFormat) (globs::mainGlobs.device,0x800,4,&surfDesc.ddpfPixelFormat); if (HVar1 != 0) { pDVar6 = &surfDesc; pDVar8 = &local_7c; for (iVar4 = 0x1f; iVar4 != 0; iVar4 += -1) { pDVar8->dwSize = pDVar6->dwSize; pDVar6 = (DDSURFACEDESC2 *)&pDVar6->dwFlags; pDVar8 = (DDSURFACEDESC2 *)&pDVar8->dwFlags; } pDVar10 = &surfDesc.ddpfPixelFormat; for (iVar4 = 8; iVar4 != 0; iVar4 += -1) { pDVar10->dwSize = 0; pDVar10 = (DDPIXELFORMAT *)&pDVar10->dwFlags; } surfDesc.ddsCaps.dwCaps2 &= 0xffffffef; surfDesc.ddsCaps.dwCaps = surfDesc.ddsCaps.dwCaps & 0xffffafff | 0x840; surfDesc.ddpfPixelFormat.dwSize = 0x20; surfDesc.ddpfPixelFormat.dwFlags = 0x60; surfDesc.ddpfPixelFormat.dwRGBBitCount = 8; local_148.dwColorSpaceLowValue = 1; } HVar1 = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreateSurface) (globs::directDrawGlobs.lpDirectDraw,&surfDesc,&ddSurface4,NULL); if (HVar1 == 0) { pDVar6 = &surfDesc; for (iVar4 = 0x1f; iVar4 != 0; iVar4 += -1) { pDVar6->dwSize = 0; pDVar6 = (DDSURFACEDESC2 *)&pDVar6->dwFlags; } surfDesc.dwSize = 0x7c; HVar1 = (*ddSurface4->lpVtbl->Lock)(ddSurface4,NULL,&surfDesc,1,NULL); if (HVar1 == 0) { iVar4 = 0; if (0 < d3dImage.height) { do { puVar7 = (undefined4 *)d3dImage.buffer1; puVar9 = (undefined4 *)surfDesc.lpSurface; for (uVar5 = (uint)d3dImage.bytes_per_line >> 2; uVar5 != 0; uVar5 -= 1) { *puVar9 = *puVar7; puVar7 = puVar7 + 1; puVar9 = puVar9 + 1; } for (uVar5 = d3dImage.bytes_per_line & 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } surfDesc.lpSurface = (LPVOID)((int)surfDesc.lpSurface + surfDesc.lPitch); d3dImage.buffer1 = (byte *)((int)d3dImage.buffer1 + d3dImage.bytes_per_line); iVar4 += 1; } while (iVar4 < d3dImage.height); } (*ddSurface4->lpVtbl->Unlock)(ddSurface4,NULL); HVar1 = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreatePalette) (globs::directDrawGlobs.lpDirectDraw,0x4c, (D3DRMPaletteEntry *)d3dImage.alpha_mask, (IDirectDrawPalette **)&local_148.dwColorSpaceHighValue,NULL); if (HVar1 == 0) { HVar1 = (*ddSurface4->lpVtbl->SetPalette)(ddSurface4,ddPal2); if (HVar1 == 0) { if (local_148.dwColorSpaceLowValue != 0) { pDVar10 = &local_7c.ddpfPixelFormat; for (iVar4 = 8; iVar4 != 0; iVar4 += -1) { pDVar10->dwSize = 0; pDVar10 = (DDPIXELFORMAT *)&pDVar10->dwFlags; } local_7c.ddpfPixelFormat.dwSize = 0x20; HVar1 = (*(globs::mainGlobs.device)->lpVtbl->FindPreferredTextureFormat) (globs::mainGlobs.device,0x400,0,&local_7c.ddpfPixelFormat); pIVar3 = ddSurface4; if ((HVar1 == 0) && (HVar1 = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreateSurface) (globs::directDrawGlobs.lpDirectDraw,&local_7c,&ddSurface4, NULL), HVar1 == 0)) { if (local_7c.ddpfPixelFormat.dwRGBBitCount == 0x10) { ddraw::DirectDraw_Blt8ToSurface(ddSurface4,pIVar3,d3dImage.palette); } (*pIVar3->lpVtbl->Release)(pIVar3); } } if (out_trans != NULL) { BVar2 = Container_GetDecalColour(fname,&local_14c); if (BVar2 == 0) { *out_trans = 0; } else { if (local_148.dwColorSpaceLowValue != 0) { local_14c = ddraw::DirectDraw_GetColour (ddSurface4, (uint)CONCAT21(CONCAT11(d3dImage.palette[local_14c].red, d3dImage.palette[local_14c].green ),d3dImage.palette[local_14c].blue )); } local_148.dwColorSpaceLowValue = local_14c; local_148.dwColorSpaceHighValue = local_14c; (*ddSurface4->lpVtbl->SetColorKey)(ddSurface4,8,&local_148); *out_trans = 1; } } if (out_width != NULL) { *out_width = d3dImage.width; } if (out_height != NULL) { *out_height = d3dImage.height; } (*ddSurface4->lpVtbl->AddRef)((IUnknown *)ddSurface4); } (*ddPal2->lpVtbl->Release)(ddPal2); } } pIVar3 = (IDirectDrawSurface4 *)(*ddSurface4->lpVtbl->Release)(ddSurface4); if (pIVar3 == NULL) { ddSurface4 = pIVar3; } } } lego::image::BMP_Cleanup(&d3dImage); io::Mem_Free(data); } return ddSurface4; } BOOL __cdecl lego::gfx::Container_GetDecalColour(char *fname,uint *out_colour) { char *pcVar1; byte *str; char cVar2; uint uVar3; char *pcVar4; cVar2 = *fname; pcVar4 = fname; while (cVar2 != '\0') { if (cVar2 == '\\') { pcVar4 = fname + 1; } pcVar1 = fname + 1; fname = fname + 1; cVar2 = *pcVar1; } if ((*pcVar4 == 'a') || (*pcVar4 == 'A')) { str = (byte *)(pcVar4 + 1); // std::isdigit(c) if (std::globals::_pcharwidth < 2) { uVar3 = *(byte *)(std::globals::_pctype + *str) & C1_DIGIT; } else { uVar3 = std::_isctype((uint)*str,4); } if (uVar3 != 0) { // std::isdigit(c) if (std::globals::_pcharwidth < 2) { uVar3 = *(byte *)(std::globals::_pctype + (byte)pcVar4[2]) & C1_DIGIT; } else { uVar3 = std::_isctype((uint)(byte)pcVar4[2],4); } if (uVar3 != 0) { // std::isdigit(c) if (std::globals::_pcharwidth < 2) { uVar3 = *(byte *)(std::globals::_pctype + (byte)pcVar4[3]) & C1_DIGIT; } else { uVar3 = std::_isctype((uint)(byte)pcVar4[3],4); } if ((uVar3 != 0) && (pcVar4[4] == '_')) { uVar3 = std::atoi((char *)str); *out_colour = uVar3; return TRUE; } } } } return 0; } // WARNING: Type propagation algorithm not settling Container_Texture * __cdecl lego::gfx::Container_LoadTexture2(char *fname,BOOL immediate,uint *out_width,uint *out_height) { byte bVar1; byte bVar2; D3DRMPaletteEntry *pDVar3; int *piVar4; char *lpFileName; Container_Texture *buffer; IDirectDrawSurface4 *This; HRESULT HVar5; BOOL BVar6; D3DRMImage *pDVar7; int *piVar8; byte bVar9; undefined uVar10; ushort uVar11; undefined uVar12; undefined uVar13; undefined2 uVar14; IDirect3DRMTexture3 *local_c; Container_Texture *local_8; undefined4 uStack4; local_c = NULL; lpFileName = io::File_VerifyFilename(fname); buffer = (Container_Texture *)io::Mem_Alloc(0xc); if (buffer != NULL) { local_8 = buffer; if (immediate == 0) { HVar5 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->LoadTexture) (globs::mainGlobs.lpD3DRM,lpFileName,&local_c); if (HVar5 == 0) { pDVar7 = (*local_c->lpVtbl->GetImage)(local_c); if (pDVar7 != NULL) { BVar6 = Container_GetDecalColour(fname,(uint *)&fname); if (BVar6 != 0) { pDVar3 = pDVar7->palette; bVar9 = pDVar3[(int)fname].red; bVar1 = pDVar3[(int)fname].blue; bVar2 = pDVar3[(int)fname].green; (*local_c->lpVtbl->SetDecalTransparency)(local_c,1); (*local_c->lpVtbl->SetDecalTransparentColor) (local_c,(uint)CONCAT21(CONCAT11(bVar9,bVar2),bVar1)); buffer = local_8; } if (out_width != NULL) { *out_width = pDVar7->width; } if ((IDirectDrawPalette *)out_height != NULL) { *out_height = (uint)((IDirectDrawPalette *)&pDVar7->height)->lpVtbl; } } buffer->surface = NULL; buffer->texture = local_c; (*local_c->lpVtbl->SetAppData)((IUnknown *)local_c,(DWORD)buffer); return buffer; } } else { This = Container_LoadTextureSurface(fname,immediate,out_width,out_height,NULL); if (This != NULL) { HVar5 = (*This->lpVtbl->QueryInterface) ((IUnknown *)This,(IID *)&idl::IID_IDirectDrawSurface,&out_width); if (HVar5 == 0) { HVar5 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateTextureFromSurface) (globs::mainGlobs.lpD3DRM,(IDirectDrawSurface4 *)out_width,&local_c); if (HVar5 == 0) { (**(code **)(*out_width + 8))((IUnknown *)out_width); BVar6 = Container_GetDecalColour(fname,(uint *)&fname); if (BVar6 != 0) { (*This->lpVtbl->GetPalette)(This,(IDirectDrawPalette **)&out_height); uVar12 = 1; uVar13 = 0; uVar14 = 0; bVar9 = (byte)uStack4; uVar10 = (undefined)((uint)uStack4 >> 8); uVar11 = (ushort)((uint)uStack4 >> 0x10); piVar8 = NULL; // IDirectDrawPalette::GetEntries(THIS_ DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, // D3DRMPALETTEENTRY* lpEntries) (**(code **)(*(int *)immediate + 0x10))(immediate,0,bVar9,1,&stack0xfffffff0); (*local_c->lpVtbl->Release)((IUnknown *)local_c); piVar4 = (int *)CONCAT22(uVar14,CONCAT11(uVar13,uVar12)); (**(code **)(*piVar4 + 0x50))(piVar4,1); (**(code **)(*piVar8 + 0x54)) (piVar8,((uint)bVar9 << 8 | CONCAT21(uVar11,uVar10) & 0xff) << 8 | uVar11 & 0xff); } buffer->surface = This; buffer->texture = local_c; (*local_c->lpVtbl->SetAppData)((IUnknown *)local_c,(DWORD)buffer); return buffer; } (**(code **)(*out_width + 8))(); } (*This->lpVtbl->Release)((IUnknown *)This); io::Mem_Free(buffer); return NULL; } } io::Mem_Free(buffer); } return NULL; } void __cdecl lego::gfx::Container_FreeTexture(Container_Texture *text) { IDirectDrawSurface4 *pIVar1; IDirect3DRMTexture3 *pIVar2; ULONG UVar3; if (text != NULL) { pIVar1 = text->surface; if (pIVar1 != NULL) { UVar3 = (*pIVar1->lpVtbl->Release)(pIVar1); while (UVar3 != 0) { UVar3 = (*text->surface->lpVtbl->Release)(text->surface); } } pIVar2 = text->texture; if (pIVar2 != NULL) { UVar3 = (*pIVar2->lpVtbl->Release)(pIVar2); while (UVar3 != 0) { UVar3 = (*text->texture->lpVtbl->Release)(text->texture); } } } return; } void __cdecl lego::gfx::Container_Mesh_Swap(Container *target,Container *origin,BOOL restore) { IDirect3DRMVisual *pIVar1; IDirect3DRMMesh *lpD3DRMVisual; int unaff_EBX; uint uVar2; IDirect3DRMVisual **ppIVar3; IDirect3DRMFrame3 *This; if (target->type == Container_Type_Reference) { This = target->masterFrame; } else { This = target->activityFrame; } if (restore != 0) { // IDirect3DRMFrame3->GetVisuals(this, DWORD* lpdwCount, IDirect3DRMVisualArray** // lplpVisuals) // // First get count of array, to confirm its non-zero (*This->lpVtbl->GetVisuals)(This,(DWORD *)&restore,NULL); if (restore != 0) { // IDirect3DRMFrame3->GetVisuals(this, DWORD* lpdwCount, IDirect3DRMVisualArray** // lplpVisuals) // // Then get the actual array (*This->lpVtbl->GetVisuals)(This,(DWORD *)&restore,globs::containerGlobs.visualArray); uVar2 = 0; if (restore != 0) { ppIVar3 = globs::containerGlobs.visualArray; do { (*This->lpVtbl->DeleteVisual)(This,*ppIVar3); uVar2 += 1; ppIVar3 = ppIVar3 + 1; } while (uVar2 < (uint)restore); } } (*target->hiddenFrame->lpVtbl->GetVisuals)(target->hiddenFrame,(DWORD *)&restore,NULL); if (restore != 0) { (*target->hiddenFrame->lpVtbl->GetVisuals) (target->hiddenFrame,(DWORD *)&restore,globs::containerGlobs.visualArray); uVar2 = 0; if (restore != 0) { ppIVar3 = globs::containerGlobs.visualArray; do { pIVar1 = *ppIVar3; (*This->lpVtbl->AddVisual)(This,pIVar1); (**(code **)(**(int **)(unaff_EBX + 8) + 0xa0))(*(int **)(unaff_EBX + 8),pIVar1); uVar2 += 1; ppIVar3 = ppIVar3 + 1; } while (uVar2 < (uint)restore); } } target->flags = target->flags & ~CONTAINER_FLAG_MESHSWAPPED; return; } (*This->lpVtbl->GetVisuals)(This,(DWORD *)&restore,NULL); if (restore != 0) { (*This->lpVtbl->GetVisuals)(This,(DWORD *)&restore,(IDirect3DRMVisual **)0x76be24); uVar2 = 0; if (restore != 0) { ppIVar3 = globs::containerGlobs.visualArray; do { pIVar1 = *ppIVar3; (*target->hiddenFrame->lpVtbl->AddVisual)(target->hiddenFrame,pIVar1); (*This->lpVtbl->DeleteVisual)(This,pIVar1); uVar2 += 1; ppIVar3 = ppIVar3 + 1; } while (uVar2 < (uint)restore); } } if (origin != NULL) { lpD3DRMVisual = origin->typeData->mesh; if (lpD3DRMVisual == NULL) { (*This->lpVtbl->AddVisual)(This,(IDirect3DRMVisual *)origin->typeData->transMesh->uv); target->flags = target->flags | CONTAINER_FLAG_MESHSWAPPED; return; } (*This->lpVtbl->AddVisual)(This,(IDirect3DRMVisual *)lpD3DRMVisual); } target->flags = target->flags | CONTAINER_FLAG_MESHSWAPPED; return; } uint __cdecl lego::gfx::Container_Mesh_AddGroup (Container *cont,uint vertexCount,uint faceCount,uint vPerFace,uint *faceData) { Mesh *mesh; IDirect3DRMMesh *This; void *pvVar1; void **ppvVar2; HRESULT HVar3; int *unaff_EDI; IDirect3DRMVisual *local_4; mesh = cont->typeData->transMesh; if (mesh != NULL) { pvVar1 = (void *)Mesh_AddGroup(mesh,vertexCount,faceCount,vPerFace,faceData); return (uint)pvVar1; } This = cont->typeData->mesh; ppvVar2 = (void **)(*This->lpVtbl->GetAppData)((IUnknown *)This); if (ppvVar2 != NULL) { if (ppvVar2[4] == NULL) { if (ppvVar2[1] == ppvVar2[2]) { return (uint)(void *)0xffffffff; } HVar3 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateMesh) (globs::mainGlobs.lpD3DRM,(IDirect3DRMMesh **)&cont); if (HVar3 != 0) { return (uint)(void *)0xffffffff; } *(IDirect3DRMVisual **)((int)*ppvVar2 + (int)ppvVar2[1] * 4) = local_4; ppvVar2[1] = (void *)((int)ppvVar2[1] + 1); (*cont->activityFrame->lpVtbl->AddVisual)(cont->activityFrame,local_4); (**(code **)(*unaff_EDI + 0x18))(unaff_EDI,(uint)ppvVar2[1] | 0x80000000); if ((ppvVar2[1] == ppvVar2[2]) && (pvVar1 = io::Mem_ReAlloc(*ppvVar2,(int)ppvVar2[2] * 4 + 0x50), pvVar1 != NULL)) { *ppvVar2 = pvVar1; ppvVar2[2] = (void *)((int)ppvVar2[2] + 0x14); } } else { ppvVar2[4] = NULL; } } HVar3 = (*This->lpVtbl->AddGroup) (This,vertexCount,faceCount,vPerFace,faceData,(D3DRMGroupIndex *)&local_4); if (HVar3 != 0) { return (uint)(void *)0xffffffff; } if (ppvVar2 == NULL) { return (uint)(void *)faceCount; } return (uint)ppvVar2[1]; } uint __cdecl lego::gfx::Container_Mesh_GetGroupCount(Container *cont) { Mesh *mesh; IDirect3DRMMesh *pIVar1; uint uVar2; DWORD DVar3; mesh = cont->typeData->transMesh; if (mesh != NULL) { uVar2 = Mesh_GetGroupCount(mesh); return uVar2; } pIVar1 = cont->typeData->mesh; DVar3 = (*pIVar1->lpVtbl->GetAppData)((IUnknown *)pIVar1); if (DVar3 != 0) { return *(int *)(DVar3 + 4) + 1; } pIVar1 = cont->typeData->mesh; uVar2 = (*pIVar1->lpVtbl->GetGroupCount)(pIVar1); return uVar2; } void __cdecl lego::gfx::Container_Mesh_SetQuality (Container *cont,D3DRMGroupIndex groupID,Graphics_Quality quality) { D3DRMRenderQuality d3drmQuality; Container *cont_00; cont_00 = cont; if (cont->typeData->transMesh == NULL) { // d3drmQuality = D3DRMRENDER_WIREFRAME; d3drmQuality = 0x40; if (quality != Wireframe) { d3drmQuality = groupID; } if (quality == UnlitFlat) { d3drmQuality = D3DRMRENDER_UNLITFLAT; } if (quality == Flat) { // d3drmQuality = D3DRMRENDER_FLAT; d3drmQuality = 0x88; } if (quality == Gouraud) { // d3drmQuality = D3DRMRENDER_GROURAUD; d3drmQuality = 0x89; } cont = (Container *)cont->typeData->mesh; Container_Mesh_HandleSeperateMeshGroups((IDirect3DRMMesh **)&cont,&groupID); (*cont_00->typeData->mesh->lpVtbl->SetGroupQuality) ((IDirect3DRMMesh *)cont,groupID,d3drmQuality); } return; } BOOL __cdecl lego::gfx::Container_Mesh_IsGroupHidden(Container *cont,D3DRMGroupIndex group) { Mesh *mesh; IDirect3DRMMesh *This; Container *pCVar1; int *piVar2; uint uVar3; mesh = cont->typeData->transMesh; if (mesh != NULL) { pCVar1 = (Container *)Mesh_IsGroupHidden(mesh,group); return (BOOL)pCVar1; } This = cont->typeData->mesh; piVar2 = (int *)(*This->lpVtbl->GetAppData)((IUnknown *)This); if (piVar2 != NULL) { if (cont != NULL) { piVar2 = *(int **)(*piVar2 + -4 + (int)cont * 4); uVar3 = (**(code **)(*piVar2 + 0x1c))(piVar2); return (BOOL)(~uVar3 >> 0x1f); } return (BOOL)(Container *)piVar2[3]; } return (BOOL)cont; } void __cdecl lego::gfx::Container_Mesh_HideGroup(Container *cont,D3DRMGroupIndex group,BOOL hide) { Mesh *mesh; int *piVar1; DWORD DVar2; uint uVar3; IDirect3DRMMesh *This; IDirect3DRMMesh *This_00; int unaff_retaddr; mesh = cont->typeData->transMesh; if (mesh != NULL) { Mesh_HideGroup(mesh,group,hide); return; } This_00 = cont->typeData->mesh; piVar1 = (int *)(*This_00->lpVtbl->GetAppData)((IUnknown *)This_00); if (piVar1 == NULL) { return; } if (cont == NULL) { uVar3 = piVar1[3]; This = NULL; } else { This = *(IDirect3DRMMesh **)(*piVar1 + -4 + (int)cont * 4); DVar2 = (*This->lpVtbl->GetAppData)((IUnknown *)This); uVar3 = ~DVar2 >> 0x1f; This_00 = This; } if (group != D3DRMGROUP_0) { if (uVar3 == 0) { (**(code **)(**(int **)(unaff_retaddr + 4) + 0xa0))(*(int **)(unaff_retaddr + 4),This_00); goto LAB_00474e84; } if (group != D3DRMGROUP_0) goto LAB_00474e84; } if (uVar3 != 0) { (**(code **)(**(int **)(unaff_retaddr + 4) + 0x48))(*(int **)(unaff_retaddr + 4),This_00); } LAB_00474e84: if (This == NULL) { piVar1[3] = group; return; } DVar2 = (*This->lpVtbl->GetAppData)((IUnknown *)This); if (group == D3DRMGROUP_0) { (*This->lpVtbl->SetAppData)((IUnknown *)This,DVar2 & 0x7fffffff | 0x80000000); return; } (*This->lpVtbl->SetAppData)((IUnknown *)This,DVar2 & 0x7fffffff); return; } BOOL __cdecl lego::gfx::Container_Mesh_HandleSeperateMeshGroups (IDirect3DRMMesh **ref_mesh,D3DRMGroupIndex *ref_groupID) { int *piVar1; piVar1 = (int *)(*(*ref_mesh)->lpVtbl->GetAppData)(*ref_mesh); if (piVar1 != NULL) { if (*ref_groupID != D3DRMGROUP_0) { *ref_mesh = *(IDirect3DRMMesh **)(*piVar1 + -4 + *ref_groupID * 4); } *ref_groupID = D3DRMGROUP_0; return TRUE; } return 0; } BOOL __cdecl lego::gfx::Container_Mesh_GetGroup (Container *cont,D3DRMGroupIndex groupID,uint *out_vertexCount,uint *out_faceCount, uint *out_vPerFace,uint *out_faceDataSize,uint *out_faceData) { Mesh *mesh; Mesh_Group *pMVar1; int iVar2; mesh = cont->typeData->transMesh; if (mesh != NULL) { pMVar1 = Mesh_GetGroup(mesh,groupID,out_vertexCount,out_faceCount,out_vPerFace,out_faceDataSize, out_faceData); return (BOOL)pMVar1; } cont = (Container *)cont->typeData->mesh; Container_Mesh_HandleSeperateMeshGroups((IDirect3DRMMesh **)&cont,&groupID); iVar2 = (*(code *)cont->masterFrame[0x17].lpVtbl) (cont,groupID,out_vertexCount,out_faceCount,out_vPerFace,out_faceDataSize, out_faceData); return (BOOL)(Mesh_Group *)(uint)(iVar2 == 0); } // Returns -1 on failure, and 0 on success uint __cdecl lego::gfx::Container_Mesh_GetVertices (Container *cont,D3DRMGroupIndex groupID,uint index,uint count,Vertex *out_retArray) { Mesh *mesh; D3DRMGroupIndex DVar1; mesh = cont->typeData->transMesh; if (mesh != NULL) { Mesh_GetVertices(mesh,groupID,index,count,out_retArray); return groupID; } cont = (Container *)cont->typeData->mesh; Container_Mesh_HandleSeperateMeshGroups((IDirect3DRMMesh **)&cont,&groupID); DVar1 = (*(code *)cont->masterFrame[0x18].lpVtbl)(cont,groupID,index,count,out_retArray); if (DVar1 != D3DRMGROUP_0) { DVar1 = D3DRMGROUP_ALLGROUPS; } return DVar1; } uint __cdecl lego::gfx::Container_Mesh_SetVertices (Container *cont,D3DRMGroupIndex groupID,uint index,uint count,Vertex *values) { Mesh *mesh; D3DRMGroupIndex DVar1; // Returns 0 on success and -1 on failure mesh = cont->typeData->transMesh; if (mesh != NULL) { Mesh_SetVertices(mesh,groupID,index,count,values); return groupID; } cont = (Container *)cont->typeData->mesh; Container_Mesh_HandleSeperateMeshGroups((IDirect3DRMMesh **)&cont,&groupID); DVar1 = (*(code *)cont->masterFrame[0xf].lpVtbl)(cont,groupID,index,count,values); if (DVar1 != D3DRMGROUP_0) { DVar1 = D3DRMGROUP_ALLGROUPS; } return DVar1; } void __cdecl lego::gfx::Container_Mesh_SetTexture (Container *cont,D3DRMGroupIndex groupID,Container_Texture *ref_itext) { Mesh *mesh; IDirect3DRMTexture3 *This; int *unaff_retaddr; if (ref_itext == NULL) { This = NULL; } else { This = ref_itext->texture; } mesh = cont->typeData->transMesh; if (mesh != NULL) { Mesh_SetGroupTexture(mesh,groupID,ref_itext); return; } cont = (Container *)cont->typeData->mesh; Container_Mesh_HandleSeperateMeshGroups((IDirect3DRMMesh **)&cont,&groupID); if (This == NULL) { ref_itext = NULL; } else { (*This->lpVtbl->QueryInterface)((IUnknown *)This,(IID *)&idl::IID_IDirect3DRMTexture,&ref_itext) ; } // IDirect3DRMMesh->SetGroupTexture(this, D3DRMGroupIndex id, IDirect3DRMTexture* // lpTexture) (*(code *)cont->masterFrame[0x15].lpVtbl)(cont,groupID,ref_itext); if (unaff_retaddr != NULL) { (**(code **)(*unaff_retaddr + 8))(unaff_retaddr); } return; } void __cdecl lego::gfx::Container_Mesh_SetPerspectiveCorrection(Container *cont,D3DRMGroupIndex groupID,BOOL on) { if (cont->typeData->transMesh == NULL) { cont = (Container *)cont->typeData->mesh; Container_Mesh_HandleSeperateMeshGroups((IDirect3DRMMesh **)&cont,&groupID); // IDirect3DRMMesh->SetGroupMapping(this, int id, D3DRMMapping value) // D3DRMMAP_WRAPU = 0x1, // D3DRMMAP_WRAPV = 0x2, // D3DRMMAP_PERSPCORRECT = 0x4, if (on != 0) { (*(code *)cont->masterFrame[0x12].lpVtbl)((IDirect3DRMMesh *)cont,groupID,4); return; } (*(code *)cont->masterFrame[0x12].lpVtbl)((IDirect3DRMMesh *)cont,groupID,0); } return; } BOOL __cdecl lego::gfx::Container_Mesh_Scale(Container *cont,float x,float y,float z) { Mesh *mesh; IDirect3DRMMesh *This; int *piVar1; int *piVar2; undefined4 unaff_ESI; uint uVar3; mesh = cont->typeData->transMesh; if (mesh != NULL) { Mesh_Scale(mesh,x,y,z); return 0; } This = cont->typeData->mesh; (*This->lpVtbl->Scale)(This,x,y,z); piVar2 = (int *)(*This->lpVtbl->GetAppData)((IUnknown *)This); if ((piVar2 != NULL) && (uVar3 = 0, piVar2[1] != 0)) { do { piVar1 = *(int **)(*piVar2 + uVar3 * 4); (**(code **)(*piVar1 + 0x2c))(piVar1,unaff_ESI,y,z); uVar3 += 1; } while (uVar3 < (uint)piVar2[1]); } return 0; } BOOL __cdecl lego::gfx::Container_Mesh_GetBox(Container *cont,Box3F *out_box) { float fVar1; IDirect3DRMMesh *This; int *piVar2; int *piVar3; float unaff_EBX; float unaff_ESI; float unaff_EDI; uint uVar4; float local_18; float local_14; float local_10; This = cont->typeData->mesh; (*This->lpVtbl->GetBox)(This,out_box); piVar3 = (int *)(*This->lpVtbl->GetAppData)((IUnknown *)This); if ((piVar3 != NULL) && (uVar4 = 0, piVar3[1] != 0)) { do { piVar2 = *(int **)(*piVar3 + uVar4 * 4); (**(code **)(*piVar2 + 0x34))(piVar2,&stack0xffffffdc); if (unaff_EDI < (out_box->min).x) { (out_box->min).x = unaff_EDI; } if (unaff_ESI < (out_box->min).y) { (out_box->min).y = unaff_ESI; } if (unaff_EBX < (out_box->min).z) { (out_box->min).z = unaff_EBX; } fVar1 = (out_box->max).x; if ((ushort)((ushort)(local_18 < fVar1) << 8 | (ushort)(local_18 == fVar1) << 0xe) == 0) { (out_box->max).x = local_18; } fVar1 = (out_box->max).y; if ((ushort)((ushort)(local_14 < fVar1) << 8 | (ushort)(local_14 == fVar1) << 0xe) == 0) { (out_box->max).y = local_14; } fVar1 = (out_box->max).z; if ((ushort)((ushort)(local_10 < fVar1) << 8 | (ushort)(local_10 == fVar1) << 0xe) == 0) { (out_box->max).z = local_10; } uVar4 += 1; } while (uVar4 < (uint)piVar3[1]); } return 0; } void __cdecl lego::gfx::Container_Mesh_SetEmissive (Container *cont,D3DRMGroupIndex groupID,float r,float g,float b) { Mesh *mesh; mesh = cont->typeData->transMesh; if (mesh != NULL) { Mesh_SetGroupColour(mesh,groupID,r,g,b,Mesh_Colour_Emissive); } return; } void __cdecl lego::gfx::Container_Mesh_SetColourAlpha (Container *cont,D3DRMGroupIndex groupID,float r,float g,float b,float a) { Mesh *mesh; mesh = cont->typeData->transMesh; if (mesh != NULL) { Mesh_SetGroupColour(mesh,groupID,r,g,b,Mesh_Colour_Diffuse); Mesh_SetGroupMaterialValues(mesh,groupID,a,Mesh_Colour_Alpha); } return; } void __cdecl lego::gfx::Container_Transform(Container *cont,Vector3F *out_vector,Vector3F *in_vector) { (*(code *)cont->masterFrame->lpVtbl->Transform)(cont->masterFrame,out_vector,in_vector); return; } void __cdecl lego::gfx::Container_InverseTransform(Container *cont,Vector3F *out_vector,Vector3F *in_vector) { (*cont->masterFrame->lpVtbl->InverseTransform)(cont->masterFrame,out_vector,in_vector); return; } void __cdecl lego::gfx::Container_SetColourAlpha(Container *cont,float r,float g,float b,float a) { IDirect3DRMLight *This; longlong lVar1; longlong lVar2; longlong lVar3; longlong lVar4; lVar1 = __ftol((float10)r * (float10)255.0); lVar2 = __ftol((float10)a * (float10)255.0); lVar3 = __ftol((float10)g * (float10)255.0); lVar4 = __ftol((float10)b * (float10)255.0); if (cont->type == Container_Type_Light) { This = cont->typeData->light; (*This->lpVtbl->SetColor) (This,(((uint)lVar1 | (int)lVar2 << 8) << 8 | (uint)lVar3) << 8 | (uint)lVar4); } return; } float10 __cdecl lego::gfx::Container_MoveAnimation(Container *cont,float delta) { float10 fVar1; fVar1 = Container_GetAnimationTime(cont); fVar1 = Container_SetAnimationTime(cont,(float)(fVar1 + (float10)delta)); return fVar1; } float10 __cdecl lego::gfx::Container_SetAnimationTime(Container *cont,float time) { float fVar1; IDirect3DRMFrame3 *frame; char *sampleName; uint uVar2; uint uVar3; ContainerFlags CVar4; float10 fVar5; AnimClone *local_14; float local_10; local_14 = NULL; local_10 = 0.0; if (cont->type == Container_Type_FromActivity) { frame = Container_Frame_Find(cont,cont->typeData->name,0); if ((frame != NULL) && (local_14 = Container_Frame_GetAnimClone(frame), (*(byte *)&cont->flags & CONTAINER_FLAG_TRIGGERSAMPLE) != 0)) { sampleName = Container_Frame_GetSample(frame); if ((sampleName != NULL) && ((globs::containerGlobs.soundTriggerCallback != NULL && (((byte)globs::containerGlobs.flags & CONTAINER_FLAG_TRIGGERENABLED) != 0)))) { (*globs::containerGlobs.soundTriggerCallback) (sampleName,cont,globs::containerGlobs.soundTriggerData); } cont->flags = cont->flags & ~CONTAINER_FLAG_TRIGGERSAMPLE; } } else { frame = (IDirect3DRMFrame3 *)time; if (cont->type == Container_Type_Anim) { local_14 = Container_Frame_GetAnimClone(cont->activityFrame); frame = cont->activityFrame; } } if (local_14 != NULL) { CVar4 = cont->flags & CONTAINER_FLAG_HIDDEN; fVar5 = Container_GetAnimationTime(cont); uVar2 = Container_Frame_GetFrameCount(frame); Container_Frame_SetAppData(frame,NULL,NULL,NULL,NULL,NULL,&time,NULL,NULL,NULL,NULL); if (uVar2 != 0) { uVar2 -= 1; fVar1 = (float)(ulonglong)uVar2; if ((ushort)((ushort)(time < fVar1) << 8 | (ushort)(time == fVar1) << 0xe) == 0) { local_10 = time - fVar1; CVar4 = CONTAINER_FLAG_NONE; } } if (CVar4 == CONTAINER_FLAG_NONE) { uVar3 = Container_Frame_GetTrigger(frame); fVar1 = (float)(ulonglong)uVar3; if ((((uVar2 != 1) && (AnimClone_SetTime(local_14,time,NULL), globs::containerGlobs.triggerFrameCallback != NULL)) && (fVar1 != 0.0)) && (((float)fVar5 < fVar1 && (fVar1 <= time)))) { (*globs::containerGlobs.triggerFrameCallback)(cont,globs::containerGlobs.triggerFrameData); return (float10)local_10; } } else { cont->flags = cont->flags | CONTAINER_FLAG_ANIMATIONSKIPPED; } } return (float10)local_10; } void __cdecl lego::gfx::Container_ForceAnimationUpdate(Container *cont) { IDirect3DRMFrame3 *frame; Container *pCVar1; float10 fVar2; if ((*(byte *)&cont->flags & CONTAINER_FLAG_ANIMATIONSKIPPED) != 0) { pCVar1 = cont; if (cont->type == Container_Type_FromActivity) { frame = Container_Frame_Find(cont,cont->typeData->name,0); if (frame != NULL) { pCVar1 = (Container *)Container_Frame_GetAnimClone(frame); fVar2 = Container_Frame_GetCurrTime(frame); cont = (Container *)(float)fVar2; } } else { if (cont->type == Container_Type_Anim) { pCVar1 = (Container *)Container_Frame_GetAnimClone(cont->activityFrame); fVar2 = Container_Frame_GetCurrTime(cont->activityFrame); cont = (Container *)(float)fVar2; } } if (pCVar1 != NULL) { AnimClone_SetTime((AnimClone *)pCVar1,(float)cont,NULL); } } return; } float10 __cdecl lego::gfx::Container_GetAnimationTime(Container *cont) { IDirect3DRMFrame3 *frame; float10 fVar1; fVar1 = (float10)0.0; if (cont->type == Container_Type_FromActivity) { frame = Container_Frame_Find(cont,cont->typeData->name,0); if (frame != NULL) { fVar1 = Container_Frame_GetCurrTime(frame); return fVar1; } fVar1 = (float10)(float)fVar1; } else { if (cont->type == Container_Type_Anim) { fVar1 = Container_Frame_GetCurrTime(cont->activityFrame); return fVar1; } } return fVar1; } uint __cdecl lego::gfx::Container_GetAnimationFrames(Container *cont) { IDirect3DRMFrame3 *frame; uint uVar1; frame = NULL; if (cont->type == Container_Type_FromActivity) { frame = Container_Frame_Find(cont,cont->typeData->name,0); } else { if (cont->type == Container_Type_Anim) { frame = cont->activityFrame; } } if (frame != NULL) { uVar1 = Container_Frame_GetFrameCount(frame); return uVar1; } return 0; } void __cdecl lego::gfx::Container_SetPosition(Container *cont,Container *opt_ref,float x,float y,float z) { // IDirect3DRMFrame3->SetPosition(this, IDirect3DRMFrame3* lpRef, float rvX, float rvY, // float rvZ) Container_GetFrames(cont,opt_ref,(IDirect3DRMFrame3 **)&opt_ref,(IDirect3DRMFrame3 **)&cont); (*(code *)opt_ref->masterFrame[0x3c].lpVtbl)(opt_ref,cont,x,y,z); return; } void __cdecl lego::gfx::Container_SetOrientation (Container *cont,Container *opt_ref,float dirx,float diry,float dirz,float upx,float upy, float upz) { Container_GetFrames(cont,opt_ref,(IDirect3DRMFrame3 **)&opt_ref,(IDirect3DRMFrame3 **)&cont); // IDirect3DRMFrame3->SetOrientation(this, IDirect3DRMFrame3* lpRef, float rvDx, float // rvDy, float rvDz, float rvUx, float rvUy, float rvUz) (*(code *)opt_ref->masterFrame[0x3b].lpVtbl)(opt_ref,cont,dirx,diry,dirz,upx,upy,upz); return; } void __cdecl lego::gfx::Container_GetPosition(Container *cont,Container *opt_ref,Vector3F *out_pos) { Container_GetFrames(cont,opt_ref,(IDirect3DRMFrame3 **)&opt_ref,(IDirect3DRMFrame3 **)&cont); // IDirect3DRMFrame3->GetPosition(this, IDirect3DRMFrame3* lpRef, Vector3F* lprvPos) (*(code *)opt_ref->masterFrame[0x18].lpVtbl)(opt_ref,cont,out_pos); return; } void __cdecl lego::gfx::Container_GetOrientation (Container *cont,Container *opt_ref,Vector3F *out_dir,Vector3F *out_up) { Vector3F **unaff_retaddr; Vector3F *pVVar1; Vector3F *pVVar2; Vector3F dvector; Vector3F uvector; Container_GetFrames(cont,opt_ref,(IDirect3DRMFrame3 **)&opt_ref,(IDirect3DRMFrame3 **)&cont); pVVar1 = &dvector; pVVar2 = &uvector; // IDirect3DRMFrame3->GetOrientation(this, IDirect3DRMFrame3* lpRef, Vector3F* lprvDir, // Vector3F* lprvUp) (*(code *)opt_ref->masterFrame[0x1f].lpVtbl)(); if (uvector.z != 0.0) { *(Container **)uvector.z = opt_ref; *(Container **)((int)uvector.z + 4) = cont; *(Vector3F **)((int)uvector.z + 8) = pVVar1; } if (unaff_retaddr != NULL) { *unaff_retaddr = pVVar2; unaff_retaddr[1] = (Vector3F *)dvector.x; unaff_retaddr[2] = (Vector3F *)dvector.y; } return; } void __cdecl lego::gfx::Container_AddRotation (Container *cont,Container_Combine combine,float x,float y,float z,float angle) { // enum D3DRMCombineType // D3DRMCOMBINE_REPLACE = 0, // D3DRMCOMBINE_BEFORE = 1, // D3DRMCOMBINE_AFTER = 2, // // IDirect3DRMFrame3->AddRotation(this, D3DRMCombineType rctCombine, float rvX, float // rvY, float rvZ, float rvTheta) (*cont->masterFrame->lpVtbl->AddRotation)(cont->masterFrame,combine,x,y,z,angle); return; } void __cdecl lego::gfx::Container_AddScale(Container *cont,Container_Combine combine,float x,float y,float z) { // enum D3DRMCombineType // D3DRMCOMBINE_REPLACE = 0, // D3DRMCOMBINE_BEFORE = 1, // D3DRMCOMBINE_AFTER = 2, // // IDirect3DRMFrame3->AddScale(this, D3DRMCombineType rctCombine, float rvX, float rvY, // float rvZ) (*cont->masterFrame->lpVtbl->AddScale)(cont->masterFrame,combine,x,y,z); return; } void __cdecl lego::gfx::Container_AddTranslation (Container *cont,Container_Combine combine,float x,float y,float z) { // enum D3DRMCombineType // D3DRMCOMBINE_REPLACE = 0, // D3DRMCOMBINE_BEFORE = 1, // D3DRMCOMBINE_AFTER = 2, // // IDirect3DRMFrame3->AddTranslation(this, D3DRMCombineType rctCombine, float rvX, float // rvY, float rvZ) (*cont->masterFrame->lpVtbl->AddTranslation)(cont->masterFrame,combine,x,y,z); return; } void __cdecl lego::gfx::Container_ClearTransform(Container *cont) { Matrix4F identity; identity.values[0][0] = 1.0; identity.values[1][0] = 0.0; identity.values[2][0] = 0.0; identity.values[3][0] = 0.0; identity.values[0][1] = 0.0; identity.values[1][1] = 1.0; identity.values[2][1] = 0.0; identity.values[3][1] = 0.0; identity.values[0][2] = 0.0; identity.values[1][2] = 0.0; identity.values[2][2] = 1.0; identity.values[3][2] = 0.0; identity.values[0][3] = 0.0; identity.values[1][3] = 0.0; identity.values[2][3] = 0.0; identity.values[3][3] = 1.0; Container_AddTransform(cont,Container_Combine_Replace,&identity); return; } void __cdecl lego::gfx::Container_AddTransform(Container *cont,Container_Combine combine,Matrix4F *mat) { // IDirect3DRMFrame3->AddTransform(this, D3DRMCombineType rctCombine, D3DRMMatrix4D* // rmMatrix) (*cont->masterFrame->lpVtbl->AddTransform)(cont->masterFrame,combine,mat); return; } float10 __cdecl lego::gfx::Container_GetZXRatio(Container *cont) { IDirect3DRMFrame3 *pIVar1; float unaff_ESI; Matrix4F mat; pIVar1 = cont->masterFrame; (*pIVar1->lpVtbl->GetParent)(pIVar1,(IDirect3DRMFrame3 **)&cont); (*pIVar1->lpVtbl->GetTransform)(pIVar1,(IDirect3DRMFrame3 *)cont,&mat); (*(code *)cont->masterFrame[2].lpVtbl)(cont); // Decompile is wrong. This is correct: mat[2][2] / mat[0][0]; return (float10)mat.values[2][1] / (float10)unaff_ESI; } // When resParent is NULL, resChild's current parent will be removed instead. void __cdecl lego::gfx::Container_SetParent(Container *child,Container *parent) { IDirect3DRMFrame3 *childHidden; IDirect3DRMFrame3 *childMaster; Container *parent_00; parent_00 = parent; childMaster = child->masterFrame; childHidden = child->hiddenFrame; if (parent == NULL) { // IDirect3DRMFrame3->GetParent(this, IDirect3DRMFrame3** lplpParent) // (for resData1->frame1) (*childMaster->lpVtbl->GetParent)(childMaster,(IDirect3DRMFrame3 **)&child); if (child != NULL) { // IDirect3DRMFrame3->DeleteChild(this, IDIrect3DRMFrame3* lpChild) (*(code *)child->masterFrame[0x25].lpVtbl)((IDirect3DRMFrame3 *)child,childMaster); // IDirect3DRMFrame3->Release(this) // (releasing GetParent frame) (*(code *)child->masterFrame[2].lpVtbl)((IDirect3DRMFrame3 *)child); } // IDirect3DRMFrame3->GetParent(this, IDirect3DRMFrame3** lplpParent) // (for resData1->frame3) (*childMaster->lpVtbl->GetParent)(childHidden,(IDirect3DRMFrame3 **)&child); if (child != NULL) { (*(code *)child->masterFrame[0x25].lpVtbl)((IDirect3DRMFrame3 *)child,childHidden); (*(code *)child->masterFrame[2].lpVtbl)((IDirect3DRMFrame3 *)child); return; } } else { child = (Container *)parent->masterFrame; Container_Frame_SafeAddChild((IDirect3DRMFrame3 *)child,childMaster); child = (Container *)parent_00->hiddenFrame; Container_Frame_SafeAddChild((IDirect3DRMFrame3 *)child,childHidden); } return; } Container * __cdecl lego::gfx::Container_GetParent(Container *cont) { Container *pCVar1; if (cont == globs::containerGlobs.rootContainer) { return NULL; } (*cont->masterFrame->lpVtbl->GetParent)(cont->masterFrame,(IDirect3DRMFrame3 **)&cont); if (cont != NULL) { pCVar1 = Container_Frame_GetContainer((IDirect3DRMFrame3 *)cont); (*(code *)cont->masterFrame[2].lpVtbl)((IDirect3DRMFrame3 *)cont); return pCVar1; } return NULL; } float10 __cdecl lego::gfx::Container_GetTransCoef(Container *cont) { char *findName; IDirect3DRMFrame3 *frame; float10 fVar1; if (((cont->type == Container_Type_FromActivity) && (cont->typeData != NULL)) && (findName = cont->typeData->name, findName != NULL)) { frame = Container_Frame_Find(cont,findName,0); if (frame != NULL) { fVar1 = Container_Frame_GetTransCo(frame); return fVar1; } } return (float10)0.0; } Container * __cdecl lego::gfx::Container_SearchOwner(IDirect3DRMFrame3 *in_frame) { Container *pCVar1; IDirect3DRMFrame3 *frame; Container *pCVar2; pCVar2 = NULL; frame = in_frame; do { if (frame == NULL) { return pCVar2; } pCVar1 = Container_Frame_GetOwner(frame); if ((pCVar1 != NULL) && (pCVar1->type != Container_Type_Reference)) { pCVar2 = pCVar1; } (*frame->lpVtbl->GetParent)(frame,&in_frame); frame = in_frame; if (in_frame == NULL) { frame = NULL; } else { (*in_frame->lpVtbl->Release)(in_frame); } } while (pCVar2 == NULL); return pCVar2; } Container * __cdecl lego::gfx::Container_Frame_GetContainer(IDirect3DRMFrame3 *frame) { Container *owner; owner = Container_Frame_GetOwner(frame); if (owner == NULL) { owner = Container_Create(NULL); if (owner != NULL) { (*owner->masterFrame->lpVtbl->Release)((IUnknown *)owner->masterFrame); (*owner->activityFrame->lpVtbl->Release)((IUnknown *)owner->activityFrame); owner->masterFrame = frame; owner->activityFrame = NULL; owner->type = Container_Type_Reference; (*frame->lpVtbl->AddDestroyCallback) ((IUnknown *)frame,Container_Frame_ReferenceDestroyCallback,NULL); Container_Frame_SetAppData(frame,owner,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); } } return owner; } // #ifndef CONTAINER_MATCHHIDDENHIERARCHY void __cdecl lego::gfx::Container_GetFrames (Container *cont,Container *opt_ref,IDirect3DRMFrame3 **out_contFrame, IDirect3DRMFrame3 **out_refFrame) { *out_contFrame = cont->masterFrame; if (opt_ref == NULL) { *out_refFrame = (globs::containerGlobs.rootContainer)->masterFrame; return; } *out_refFrame = opt_ref->masterFrame; return; } Container_Type __cdecl lego::gfx::Container_ParseTypeString(char *str,BOOL *out_noTexture) { char cVar1; int iVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char **ppcVar6; char *pcVar7; undefined4 *puVar8; Container_Type CVar9; undefined4 local_50 [10]; char *local_28; char *local_24; if (str == NULL) { return Container_Type_Invalid; } uVar3 = 0xffffffff; do { pcVar7 = str; if (uVar3 == 0) break; uVar3 -= 1; pcVar7 = str + 1; cVar1 = *str; str = pcVar7; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar7 + -uVar3); puVar8 = local_50; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar8 = *puVar5; puVar5 = puVar5 + 1; puVar8 = puVar8 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } uVar3 = util::Util_Tokenise((char *)local_50,&local_28,":"); if (1 < uVar3) { iVar2 = std::_stricmp(local_24,"NOTEXTURE"); if (iVar2 == 0) { *out_noTexture = 1; goto LAB_00475c6a; } } *out_noTexture = 0; LAB_00475c6a: CVar9 = Container_Type_Null; ppcVar6 = globs::containerGlobs.typeName; do { if (*ppcVar6 != NULL) { iVar2 = std::_stricmp(*ppcVar6,(char *)local_50); if (iVar2 == 0) { return CVar9; } } ppcVar6 = ppcVar6 + 1; CVar9 += Container_Type_Mesh; } while (ppcVar6 < globs::containerGlobs.extensionName); return Container_Type_Invalid; } void __cdecl lego::gfx::Container_AddList(void) { Container *pCVar1; Container *pCVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::containerGlobs.listCount & 0x1f); pCVar2 = (Container *)io::Mem_Alloc(uVar4 * 0x2c); globs::containerGlobs.listSet[globs::containerGlobs.listCount] = pCVar2; pCVar2 = globs::containerGlobs.listSet[globs::containerGlobs.listCount]; if (pCVar2 != NULL) { globs::containerGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pCVar1 = pCVar2; do { pCVar1->nextFree = pCVar1 + 1; iVar3 += -1; pCVar1 = pCVar1 + 1; } while (iVar3 != 0); } pCVar2[uVar4 - 1].nextFree = globs::containerGlobs.freeList; globs::containerGlobs.freeList = pCVar2; } return; } // WARNING: Exceeded maximum restarts with more pending uint __cdecl lego::gfx::Container_GetActivities (Container *cont,IDirect3DRMFrame3 **out_frameList,AnimClone **out_acList, char **out_nameList) { HRESULT HVar1; char *_Str1; int iVar2; AnimClone *pAVar3; int unaff_EBX; uint uVar4; Container *pCVar5; int *unaff_ESI; uint uVar6; AnimClone **ppAVar7; Container *unaff_retaddr; GUID *pGStack76; undefined *puStack72; int *piStack68; uint uStack64; int local_24; IDirect3DRMFrameArray *local_18; IDirect3DRMFrame3 *local_14; uint local_10; uint local_c; DWORD local_8; if (cont->type == Container_Type_FromActivity) { local_c = 0; pCVar5 = cont; do { uVar6 = local_c; if (local_c == 0) { local_14 = pCVar5->activityFrame; } if (local_c == 1) { local_14 = pCVar5->hiddenFrame; } uStack64 = 0x475d7d; HVar1 = (*local_14->lpVtbl->GetChildren)(local_14,&local_18); if (HVar1 == 0) { local_8 = (*local_18->lpVtbl->GetSize)(); uVar4 = 0; if (local_8 != 0) { local_c = (int)out_acList - (int)out_frameList; ppAVar7 = (AnimClone **)out_frameList; pCVar5 = unaff_retaddr; do { piStack68 = NULL; puStack72 = (undefined *)0x475dc4; uStack64 = uVar4; (*ppcRam00000000[4])(); puStack72 = &stack0xffffffcc; pGStack76 = &idl::IID_IDirect3DRMFrame3; (**ppcRam00000000)(); (**(code **)(*unaff_ESI + 8))(unaff_ESI); (**(code **)(*piStack68 + 0x24))(piStack68,&uStack64,0); if (pGStack76 != NULL) { _Str1 = (char *)io::Mem_Alloc((uint)pGStack76); (*ppcRam00000000[9])(0,&pGStack76,_Str1); iVar2 = std::_strnicmp(_Str1,"ActFrame",8); if (iVar2 == 0) { if (local_24 != 0) { *(undefined4 *)(((int)cont - (int)out_frameList) + (int)ppAVar7) = 0; } if (false) { pAVar3 = Container_Frame_GetAnimClone(NULL); *ppAVar7 = pAVar3; } if (false) { *(char **)(unaff_EBX + (int)ppAVar7) = _Str1; } ppAVar7 = ppAVar7 + 1; puStack72 = puStack72 + 1; if (false) goto LAB_00475e74; } io::Mem_Free(_Str1); } LAB_00475e74: (*ppcRam00000000[2])(0); uVar4 += 1; uVar6 = local_10; unaff_retaddr = pCVar5; } while (uVar4 < local_8); } uStack64 = 0x475ea1; (*ppcRam00000000[2])(); } local_c = uVar6 + 1; } while (local_c < 2); } return 0; } // If non-null, `name` will be owned by this Resource. void __cdecl lego::gfx::Container_SetTypeData (Container *cont,char *name,IDirect3DRMLight *light,IDirect3DRMMesh *mesh,Mesh *transMesh) { Container_TypeData *pCVar1; if (cont->typeData == NULL) { pCVar1 = (Container_TypeData *)io::Mem_Alloc(0x10); cont->typeData = pCVar1; pCVar1->name = name; cont->typeData->light = light; cont->typeData->mesh = mesh; cont->typeData->transMesh = transMesh; } else { if (name != NULL) { cont->typeData->name = name; } if (light != NULL) { cont->typeData->light = light; } if (mesh != NULL) { cont->typeData->mesh = mesh; } if (transMesh != NULL) { cont->typeData->transMesh = transMesh; return; } } return; } void __cdecl lego::gfx::Container_FreeTypeData(Container *cont) { Container_TypeData *pCVar1; Container_Type CVar2; IDirect3DRMMesh *This; pCVar1 = cont->typeData; if (pCVar1 != NULL) { CVar2 = cont->type; if (CVar2 == Container_Type_FromActivity) { io::Mem_Free(pCVar1->name); } else { if (CVar2 == Container_Type_Light) { (*pCVar1->light->lpVtbl->Release)((IUnknown *)pCVar1->light); } else { if (CVar2 == Container_Type_Mesh) { if (pCVar1->mesh != NULL) { (*cont->activityFrame->lpVtbl->DeleteVisual) (cont->activityFrame,(IDirect3DRMVisual *)pCVar1->mesh); This = cont->typeData->mesh; (*This->lpVtbl->Release)((IUnknown *)This); } } else { if ((CVar2 == Container_Type_LWO) && (pCVar1->transMesh != NULL)) { Mesh_Remove(pCVar1->transMesh,cont->activityFrame); } } } } io::Mem_Free(cont->typeData); cont->typeData = NULL; } return; } // ALSO: Container_AddActivity() BOOL __cdecl lego::gfx::Container_AddActivity2 (Container *cont,char *filename,char *actname,float transCo,uint trigger,char *sample, AnimClone *origClone,BOOL lws,BOOL looping) { HRESULT HVar1; AnimClone *animClone; IDirect3DRMFrame3 *local_208; uint local_204; char local_200 [512]; std::sprintf(local_200,"%s.%s",filename,globs::containerGlobs.extensionName[3]); HVar1 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateFrame) (globs::mainGlobs.lpD3DRM,cont->hiddenFrame,&local_208); if (HVar1 == 0) { Container_Frame_FormatName(local_208,"%s_%s","ActFrame",actname); if (origClone == NULL) { animClone = Container_LoadAnimSet(local_200,local_208,&local_204,lws,looping); } else { animClone = AnimClone_Make(origClone,local_208,&local_204); } Container_Frame_SetAppData (local_208,cont,animClone,filename,&local_204,NULL,NULL,&transCo,sample,NULL,&trigger) ; return TRUE; } return 0; } void __cdecl lego::gfx::Container_Frame_ReferenceDestroyCallback(IDirect3DRMFrame3 *lpD3DRMobj,void *lpArg) { Container *pCVar1; pCVar1 = Container_Frame_GetOwner(lpD3DRMobj); if (pCVar1 != NULL) { pCVar1->flags = pCVar1->flags | CONTAINER_FLAG_DEADREFERENCE; Container_Frame_RemoveAppData(lpD3DRMobj); } return; } // WARNING: Exceeded maximum restarts with more pending IDirect3DRMFrame3 * __cdecl lego::gfx::Container_Frame_Find(Container *cont,char *findName,BOOL hidden) { IDirect3DRMFrame3 *pIVar1; HRESULT HVar2; uint uVar3; char *lpName; int iVar4; IDirect3DRMFrame3 *unaff_EBP; IDirect3DRMFrame3 *pIVar5; uint uVar6; uint uVar7; IDirect3DRMFrame3 *pIVar8; IDirect3DRMFrame3 *rmFrame3; IDirect3DRMFrameArray *rmArray; IUnknown *rmFrameBase; uint dwNameSize; uint dwSize; char nameBuffer [512]; pIVar5 = NULL; if (hidden == 0) { pIVar1 = cont->activityFrame; } else { pIVar1 = cont->hiddenFrame; } // IDirect3DRMFrame3->GetChildren(this, IDirect3DRMFrameArray** lplpChildren) HVar2 = (*pIVar1->lpVtbl->GetChildren)(pIVar1,&rmArray); if (HVar2 == 0) { // DWORD IDirect3DRMFrameArray->GetSize(this) uVar3 = (*rmArray->lpVtbl->GetSize)(); uVar6 = 0; if (uVar3 != 0) { do { // IDirect3DRMFrameArray->GetElement(this, DWORD index, IDirect3DRMFrame** // lplpD3DRMFrame) pIVar1 = rmFrame3; uVar7 = uVar6; (*rmFrame3->lpVtbl->AddDestroyCallback)(); // IDirect3DRMFrame->QueryInterface(this, IID_IDirect3DRMFrame3, IDirect3DRMFrame3** // lplpOut) pIVar8 = unaff_EBP; (*unaff_EBP->lpVtbl->QueryInterface) ((IUnknown *)unaff_EBP,(IID *)&idl::IID_IDirect3DRMFrame3, (LPVOID *)&stack0xfffffddc); // IDirect3DRMFrame->Release(this) (*rmArray->lpVtbl->Release)((IUnknown *)rmArray); // IDirect3DRMFrame3->GetName(this, DWORD* lpdwSize, LPSTR lpName) (*pIVar1->lpVtbl->GetName)((IUnknown *)pIVar1,(LPDWORD)&stack0xfffffdd8,NULL); if (pIVar1 != NULL) { lpName = (char *)io::Mem_Alloc((int)&pIVar1->lpVtbl + 1); // IDirect3DRMFrame3->GetName(this, DWORD* lpdwSize, LPSTR lpName) (*unaff_EBP->lpVtbl->GetName)((IUnknown *)unaff_EBP,(LPDWORD)&stack0xfffffdcc,lpName); std::sprintf(&stack0xfffffdd4,"%s_%s","ActFrame",cont); iVar4 = std::_stricmp(lpName,&stack0xfffffdd4); if (iVar4 == 0) { pIVar5 = unaff_EBP; } uVar3 = uVar7; io::Mem_Free(lpName); } // IDirect3DRMFrame3->Release(this) (*unaff_EBP->lpVtbl->Release)((IUnknown *)unaff_EBP); } while ((pIVar5 == NULL) && (uVar6 += 1, unaff_EBP = pIVar8, uVar6 < uVar3)); } // IDirect3DRMFrameArray->Release(this) (*rmFrame3->lpVtbl->Release)(); } return pIVar5; } void __cdecl lego::gfx::Container_Frame_SetAppData (IDirect3DRMFrame3 *frame,Container *owner,AnimClone *animClone,char *asfname, uint *frameCount,char *frameName,float *currTime,float *transCo,char *actSample, Sound3D_SoundFrameRecord *soundRecord,uint *trigger) { char cVar1; Container_AppData *appData; undefined4 *puVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData == NULL) { appData = (Container_AppData *)io::Mem_Alloc(0x28); appData->animClone = animClone; appData->ownerContainer = owner; appData->animSetFileName = NULL; if (frameCount == NULL) { appData->frameCount = 0; } else { appData->frameCount = *frameCount; } appData->frameName = frameName; if (currTime == NULL) { appData->currTime = 0.0; } else { appData->currTime = *currTime; } if (transCo == NULL) { appData->transCo = 0.0; } else { appData->transCo = *transCo; } if (trigger == NULL) { appData->trigger = 0; } else { appData->trigger = *trigger; } appData->activitySample = actSample; appData->soundList = soundRecord; (*frame->lpVtbl->SetAppData)(frame,appData); } else { if (owner != NULL) { appData->ownerContainer = owner; } if (animClone != NULL) { appData->animClone = animClone; } if ((asfname != NULL) && (appData->animSetFileName != NULL)) { io::Mem_Free(appData->animSetFileName); } if (frameCount != NULL) { appData->frameCount = *frameCount; } if (frameName != NULL) { appData->frameName = frameName; } if (currTime != NULL) { appData->currTime = *currTime; } if (transCo != NULL) { appData->transCo = *transCo; } if (actSample != NULL) { appData->activitySample = actSample; } if (soundRecord != NULL) { appData->soundList = soundRecord; } if (trigger != NULL) { appData->trigger = *trigger; } } if (asfname != NULL) { uVar3 = 0xffffffff; pcVar6 = asfname; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); puVar2 = (undefined4 *)io::Mem_Alloc(~uVar3); uVar3 = 0xffffffff; appData->animSetFileName = (char *)puVar2; do { pcVar6 = asfname; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = asfname + 1; cVar1 = *asfname; asfname = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar2 = *puVar5; puVar5 = puVar5 + 1; puVar2 = puVar2 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar2 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar2 = (undefined4 *)((int)puVar2 + 1); } } return; } void __cdecl lego::gfx::Container_Frame_RemoveAppData(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { if (appData->animSetFileName != NULL) { io::Mem_Free(appData->animSetFileName); } io::Mem_Free(appData); } (*frame->lpVtbl->SetAppData)(frame,NULL); return; } // ACCESSOR: ResourceAppData->resData (field_0) Container * __cdecl lego::gfx::Container_Frame_GetOwner(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { return appData->ownerContainer; } return NULL; } // ACCESSOR: ResourceAppData->filename (field_4) char * __cdecl lego::gfx::Container_Frame_GetAnimSetFileName(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { return appData->animSetFileName; } return NULL; } // ACCESSOR: ResourceAppData->actFrameRes (field_1c) AnimClone * __cdecl lego::gfx::Container_Frame_GetAnimClone(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { return appData->animClone; } return NULL; } // ACCESSOR: ResourceAppData->field_c (field_c) uint __cdecl lego::gfx::Container_Frame_GetFrameCount(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { return appData->frameCount; } return 0; } // ACCESSOR: ResourceAppData->float_10 (field_10) float10 __cdecl lego::gfx::Container_Frame_GetCurrTime(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { return (float10)appData->currTime; } return (float10)0.0; } // ACCESSOR: ResourceAppData->float_14 (field_14) float10 __cdecl lego::gfx::Container_Frame_GetTransCo(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { return (float10)appData->transCo; } return (float10)0.0; } // ACCESSOR: ResourceAppData->sampleName (field_18) char * __cdecl lego::gfx::Container_Frame_GetSample(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { return appData->activitySample; } return NULL; } // ACCESSOR: ResourceAppData->field_20 (field_20) uint __cdecl lego::gfx::Container_Frame_GetTrigger(IDirect3DRMFrame3 *frame) { Container_AppData *appData; appData = (*frame->lpVtbl->GetAppData)(frame); if (appData != NULL) { return appData->trigger; } return 0; } void __cdecl lego::gfx::Container_Frame_SafeAddChild(IDirect3DRMFrame3 *parent,IDirect3DRMFrame3 *child) { IDirect3DRMFrame3 *lpD3DRMFrameChild; Matrix4F matrix; lpD3DRMFrameChild = child; // IDirect3DRMFrame3->GetParent(this, IDirect3DRMFrame3** lplpParent) (*child->lpVtbl->GetParent)(child,&child); // IDirect3DRMFrame3->GetTransform(this, IDirect3DRMFrame3* lpRefFrame, Matrix4F** // rmMatrix) // (this = frame2, lpRefFrame = GetParent) (*lpD3DRMFrameChild->lpVtbl->GetTransform)(lpD3DRMFrameChild,child,&matrix); if (child != NULL) { // IDirect3DRMFrame3->Release(this) // (this = GetParent) (*child->lpVtbl->Release)(child); } // IDirect3DRMFrame3->AddChild(this, IDirect3DRMFrame3* lpD3DRMFrameChild) // (this = frame1, lpChild = frame2) (*parent->lpVtbl->AddChild)(parent,lpD3DRMFrameChild); // IDirect3DRMFrame3->AddTransform(this, TD3DRMCombineType rctCombine, Matrix4F* // rmMatrix) // (this = frame2) (*lpD3DRMFrameChild->lpVtbl->AddTransform)(lpD3DRMFrameChild,D3DRMCOMBINE_REPLACE,&matrix); return; } void __cdecl lego::gfx::Container_Frame_FormatName(IDirect3DRMFrame3 *frame,char *msg,...) { int iVar1; char *buffer; char local_400 [1024]; iVar1 = std::vsprintf(local_400,msg,&stack0x0000000c); buffer = (char *)io::Mem_Alloc(iVar1 + 1); std::vsprintf(buffer,msg,&stack0x0000000c); (*frame->lpVtbl->SetName)((IUnknown *)frame,buffer); Container_Frame_SetAppData(frame,NULL,NULL,NULL,NULL,buffer,NULL,NULL,NULL,NULL,NULL); return; } void __cdecl lego::gfx::Container_Frame_FreeName(IDirect3DRMFrame3 *frame) { char *buffer; buffer = Container_Frame_GetName(frame); if (buffer != NULL) { io::Mem_Free(buffer); } return; } char * __cdecl lego::gfx::Container_Frame_GetName(IDirect3DRMFrame3 *frame) { DWORD DVar1; DVar1 = (*frame->lpVtbl->GetAppData)((IUnknown *)frame); if (DVar1 != 0) { return *(char **)(DVar1 + 8); } return NULL; } BOOL __cdecl lego::gfx::Container_Frame_WalkTree (IDirect3DRMFrame3 *frame,uint level,ContainerWalkTreeCallback Callback,void *data) { IDirect3DRMFrame3 *This; ContainerWalkTreeCallback Callback_00; void *data_00; BOOL BVar1; uint uVar2; code **unaff_EBX; uint uVar3; IDirect3DRMFrame3 *unaff_EDI; int *local_8; int *local_4; data_00 = data; Callback_00 = Callback; This = frame; local_8 = NULL; BVar1 = (*Callback)(frame,data); if (BVar1 != 0) { return (BOOL)(IDirect3DRMFrame3 *)TRUE; } (*This->lpVtbl->GetChildren)(This,(IDirect3DRMFrameArray **)&frame); uVar2 = (**(code **)(*local_4 + 0xc))(local_4); uVar3 = 0; if (uVar2 != 0) { do { (**(code **)(*local_8 + 0x10))(local_8,uVar3,register0x00000010); (**(code **)*unaff_EBX)(unaff_EBX,&idl::IID_IDirect3DRMFrame3,&local_8); (*unaff_EDI->lpVtbl->Release)((IUnknown *)unaff_EDI); BVar1 = Container_Frame_WalkTree(unaff_EDI,(int)local_4 + 1,Callback_00,data_00); if (BVar1 != 0) { (*unaff_EDI->lpVtbl->Release)((IUnknown *)unaff_EDI); break; } (*unaff_EDI->lpVtbl->Release)((IUnknown *)unaff_EDI); uVar3 += 1; } while (uVar3 < uVar2); } (**(code **)(*local_8 + 8))(local_8); return (BOOL)unaff_EDI; } BOOL __cdecl lego::gfx::Container_Frame_SearchCallback(IDirect3DRMFrame3 *frame,Container_SearchData *search) { byte bVar1; Container_SearchMode CVar2; IDirect3DRMFrame3 *This; Container_SearchData *pCVar3; byte *lpName; uint uVar4; byte *pbVar5; int iVar6; uint unaff_EBP; byte *pbVar7; bool bVar8; This = frame; (*frame->lpVtbl->GetName)((IUnknown *)frame,(LPDWORD)&frame,NULL); pCVar3 = search; if ((int)&frame[-1].lpVtbl + 3U != search->stringLen) { return 0; } lpName = (byte *)io::Mem_Alloc((uint)frame); *lpName = 0; (*This->lpVtbl->GetName)((IUnknown *)This,(LPDWORD)&frame,(LPSTR)lpName); uVar4 = 0; if (unaff_EBP != 0) { do { if (pCVar3->string[uVar4] == '?') { lpName[uVar4] = 0x3f; } uVar4 += 1; } while (uVar4 < unaff_EBP); } CVar2 = pCVar3->mode; if (CVar2 == Container_SearchMode_FirstMatch) { pCVar3->resultFrame = NULL; if (pCVar3->caseSensitive == 0) { iVar6 = std::_stricmp((char *)lpName,pCVar3->string); } else { pbVar7 = (byte *)pCVar3->string; pbVar5 = lpName; do { bVar1 = *pbVar5; bVar8 = bVar1 < *pbVar7; if (bVar1 != *pbVar7) { LAB_0047676f: if (1 - bVar8 != (uint)(bVar8 != 0)) goto LAB_00476856; goto LAB_00476853; } if (bVar1 == 0) break; bVar1 = pbVar5[1]; bVar8 = bVar1 < pbVar7[1]; if (bVar1 != pbVar7[1]) goto LAB_0047676f; pbVar5 = pbVar5 + 2; pbVar7 = pbVar7 + 2; } while (bVar1 != 0); iVar6 = 0; } if (iVar6 != 0) goto LAB_00476856; } else { if (CVar2 == Container_SearchMode_MatchCount) { if (pCVar3->caseSensitive == 0) { iVar6 = std::_stricmp((char *)lpName,pCVar3->string); } else { pbVar7 = (byte *)pCVar3->string; pbVar5 = lpName; do { bVar1 = *pbVar5; bVar8 = bVar1 < *pbVar7; if (bVar1 != *pbVar7) { LAB_004767d0: if (1 - bVar8 == (uint)(bVar8 != 0)) { pCVar3->count = pCVar3->count + 1; } goto LAB_00476856; } if (bVar1 == 0) break; bVar1 = pbVar5[1]; bVar8 = bVar1 < pbVar7[1]; if (bVar1 != pbVar7[1]) goto LAB_004767d0; pbVar5 = pbVar5 + 2; pbVar7 = pbVar7 + 2; } while (bVar1 != 0); iVar6 = 0; } if (iVar6 == 0) { pCVar3->count = pCVar3->count + 1; } goto LAB_00476856; } if (CVar2 != Container_SearchMode_NthMatch) goto LAB_00476856; pCVar3->resultFrame = NULL; if (pCVar3->caseSensitive == 0) { iVar6 = std::_stricmp((char *)lpName,pCVar3->string); } else { pbVar7 = (byte *)pCVar3->string; pbVar5 = lpName; do { bVar1 = *pbVar5; bVar8 = bVar1 < *pbVar7; if (bVar1 != *pbVar7) { LAB_0047682a: iVar6 = (1 - (uint)bVar8) - (uint)(bVar8 != 0); goto joined_r0x00476843; } if (bVar1 == 0) break; bVar1 = pbVar5[1]; bVar8 = bVar1 < pbVar7[1]; if (bVar1 != pbVar7[1]) goto LAB_0047682a; pbVar5 = pbVar5 + 2; pbVar7 = pbVar7 + 2; } while (bVar1 != 0); iVar6 = 0; } joined_r0x00476843: if (iVar6 == 0) { pCVar3->count = pCVar3->count + 1; } if (pCVar3->count != pCVar3->matchNumber + 1) goto LAB_00476856; } LAB_00476853: pCVar3->resultFrame = This; LAB_00476856: io::Mem_Free(lpName); if (pCVar3->resultFrame == NULL) { return 0; } return TRUE; } AnimClone * __cdecl lego::gfx::Container_LoadAnimSet (char *fname,IDirect3DRMFrame3 *frame,uint *out_frameCount,BOOL lws,BOOL looping) { char cVar1; Lws_Info *scene; HRESULT HVar2; int iVar3; uint uVar4; uint uVar5; IDirect3DRMFrame3 *unaff_EBX; AnimClone *pAVar6; IDirect3DRMAnimationSet2 *unaff_EBP; undefined4 *puVar7; undefined4 *puVar8; char *pcVar9; IDirect3DRMAnimationSet2 *local_11c; IDirect3DRMFrame3 *local_118; byte *local_114; uint local_110 [2]; char acStack263 [3]; char local_104 [260]; pAVar6 = NULL; local_11c = NULL; if (lws == 0) { local_114 = io::File_LoadBinary(fname,local_110); if (local_114 != NULL) { // IDirect3DRM3->CreateFrame(this, IDirect3DRMFrame3* lpD3DRMFrame, IDirect3DRMFrame3** // lplpD3DRMFrame) HVar2 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateFrame) (globs::mainGlobs.lpD3DRM,frame,&local_118); if (HVar2 == 0) { // IDirect3DRM3->CreateAnimationSet(this, IDirect3DRMAnimationSet2** // lplpD3DRMAnimationSet) HVar2 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateAnimationSet) (globs::mainGlobs.lpD3DRM,&local_11c); if (HVar2 == 0) { local_114 = (byte *)fname; local_110[0] = 0; // IDirect3DRMAnimationSet2->Load(this, void* lpvObjSource, void* lpvObjID, // TD3DRMLoadOptions drd3mLOFlags, TD3DRMLoadTexture3Callback d3drmLoadTextureProc, // void* lpArgLTP, IDirect3DRMFrame3* lpParentFrame) iVar3 = (*(code *)unaff_EBP->lpVtbl->Load) (unaff_EBP,&local_11c,0,2,Container_TextureLoadCallback,&local_114, unaff_EBX); if (iVar3 == 0) { // IDirect3DRMAnimationSet2->SetTime(this, float rvTime) (*(code *)unaff_EBP->lpVtbl->SetTime)(unaff_EBP,0); uVar4 = Container_GetAnimFileFrameCount((char *)local_11c); if (fname != NULL) { *(uint *)fname = uVar4; } pAVar6 = AnimClone_Register(unaff_EBP,unaff_EBX,uVar4); } io::Mem_Free(local_11c); } // IDirect3DRMFrame3->Release(this) (*unaff_EBX->lpVtbl->Release)((IUnknown *)unaff_EBX); } } } else { uVar4 = 0xffffffff; do { pcVar9 = fname; if (uVar4 == 0) break; uVar4 -= 1; pcVar9 = fname + 1; cVar1 = *fname; fname = pcVar9; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar7 = (undefined4 *)(pcVar9 + -uVar4); puVar8 = (undefined4 *)local_104; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = *puVar7; puVar7 = puVar7 + 1; puVar8 = puVar8 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } uVar4 = 0xffffffff; pcVar9 = local_104; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar9; pcVar9 = pcVar9 + 1; } while (cVar1 != '\0'); acStack263[~uVar4] = '\0'; scene = Lws_Parse(local_104,looping); if (scene != NULL) { Lws_LoadMeshes(scene,frame); Lws_SetTime(scene,0.0); if (out_frameCount != NULL) { uVar4 = Lws_GetFrameCount(scene); *out_frameCount = uVar4; } pAVar6 = AnimClone_RegisterLws(scene,frame,*out_frameCount); return pAVar6; } } return pAVar6; } uint __cdecl lego::gfx::Container_GetAnimFileFrameCount(char *fileData) { byte *str; uint uVar1; uVar1 = 0; str = (byte *)std::strstr(fileData,"DDiScene"); if (str != NULL) { while( true ) { // int std::isdigit(int c) if (std::globals::_pcharwidth < 2) { // C1_DIGIT (0x4) uVar1 = *(byte *)(std::globals::_pctype + *str) & C1_DIGIT; } else { // C1_DIGIT (0x4) uVar1 = std::_isctype((uint)*str,C1_DIGIT); } if (uVar1 != 0) break; str = str + 1; } uVar1 = std::atoi((char *)str); } if (uVar1 == 0) { uVar1 = 1; } return uVar1; } BOOL __cdecl lego::gfx::Container_FrameLoad(char *fname,IDirect3DRMFrame3 *frame) { int iVar1; uint uVar2; void *buffer; byte *local_10; uint fileSize; char *local_8; undefined4 local_4; uVar2 = 0; local_10 = io::File_LoadBinary(fname,&fileSize); if (local_10 != NULL) { buffer = NULL; local_8 = fname; local_4 = 0; iVar1 = (*(code *)frame->lpVtbl->Load) (frame,&local_10,0,2,Container_TextureLoadCallback,&local_8); uVar2 = (uint)(iVar1 == 0); io::Mem_Free(buffer); } return uVar2; } // WARNING: Restarted to delay deadcode elimination for space: stack IDirect3DRMMesh * __cdecl lego::gfx::Container_MeshLoad (void *file_data,uint file_size,char *file_name,IDirect3DRMFrame3 *frame,BOOL noTexture) { int iVar1; int *piVar2; IDirect3DRMMesh **ppIVar3; IDirect3DRMMesh *local_10; HRESULT local_c; IDirect3DRMMeshBuilder3 *local_8; uint local_4; local_8 = (IDirect3DRMMeshBuilder3 *)file_data; local_4 = file_size; // IDirect3DRM3->CreateMeshBuilder(this, IDirect3DRMMeshBuilder3** lplpD3DRMMeshBuilder) local_c = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateMeshBuilder) (globs::mainGlobs.lpD3DRM,(IDirect3DRMMeshBuilder3 **)&file_data); ppIVar3 = &local_10; if (local_c == 0) { local_10 = (IDirect3DRMMesh *)file_name; if (noTexture != 0) { local_c = 1; } // WARNING: Load size is inaccurate piVar2 = (int *)0x2; // IDirect3DRMMeshBuilder3->Load(this, void* lpvObjSource, void* lpvObjID, // TD3DRMLoadOptions d3drmLOFlags, TD3DRMLoadTexture3Callback d3drmLoadTextureProc, // void* lpvArg) // D3DRMLOAD_FROMMEMORY (0x2) iVar1 = (**(code **)((int)*file_data + 0x2c)) (file_data,&local_8,0,2,Container_TextureLoadCallback); if (iVar1 == 0) { // IDirect3DRMMeshBuilder3->CreateMesh(this, IDirect3DRMMesh** lplpD3DRMMesh) (**(code **)((int)*ppIVar3 + 0xc0))(ppIVar3,&local_10); (**(code **)(*piVar2 + 8))(piVar2); // IDirect3DRMFrame3->AddVisual(this, IDirect3DRMVisual* lpD3DRMVisual) iVar1 = (**(code **)((int)*ppIVar3 + 0x48))(ppIVar3,piVar2); if (iVar1 == 0) { return local_10; } } (**(code **)((int)*ppIVar3 + 8))(ppIVar3); } return NULL; } HRESULT __cdecl lego::gfx::Container_TextureLoadCallback (char *name,Container_TextureData *textureData,IDirect3DRMTexture3 **texture) { byte bVar1; IDirect3DRMTexture3 *pIVar2; char cVar3; byte *pbVar4; Container_Texture *pCVar5; undefined4 *puVar6; uint uVar7; int iVar8; uint uVar9; uint uVar10; char *pcVar11; char *pcVar12; Container_TextureRef *pCVar13; byte *pbVar14; undefined4 *puVar15; char *pcVar16; char *pcVar17; char *pcVar18; char **ppcVar19; char **ppcVar20; bool bVar21; char *local_410; char *local_40c; int local_408; char *local_404; char local_400 [1024]; if ((*(byte *)&textureData->flags & 1) == 0) { pcVar12 = textureData->xFileName; pcVar11 = local_400; local_410 = NULL; local_40c = pcVar12; local_404 = pcVar11; local_408 = 0; if ((globs::containerGlobs.sharedDir != NULL) != 0xffffffff) { LAB_00476c0f: if (local_408 == 0) { cVar3 = *pcVar12; if (cVar3 != '\0') { do { if (cVar3 == '\\') { if (local_410 != NULL) { *local_410 = '\\'; } *pcVar11 = '\0'; local_410 = pcVar11; } else { *pcVar11 = cVar3; } cVar3 = pcVar12[1]; pcVar12 = pcVar12 + 1; pcVar11 = pcVar11 + 1; } while (cVar3 != '\0'); local_404 = pcVar11; local_40c = pcVar12; } if (local_410 == NULL) { uVar7 = 0xffffffff; pcVar17 = name; do { pcVar16 = pcVar17; if (uVar7 == 0) break; uVar7 -= 1; pcVar16 = pcVar17 + 1; cVar3 = *pcVar17; pcVar17 = pcVar16; } while (cVar3 != '\0'); uVar7 = ~uVar7; puVar6 = (undefined4 *)(pcVar16 + -uVar7); puVar15 = (undefined4 *)local_400; for (uVar9 = uVar7 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar6; puVar6 = puVar6 + 1; puVar15 = puVar15 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } } else { uVar7 = 0xffffffff; pcVar17 = "\\"; do { pcVar16 = pcVar17; if (uVar7 == 0) break; uVar7 -= 1; pcVar16 = pcVar17 + 1; cVar3 = *pcVar17; pcVar17 = pcVar16; } while (cVar3 != '\0'); uVar7 = ~uVar7; iVar8 = -1; puVar6 = (undefined4 *)local_400; do { puVar15 = puVar6; if (iVar8 == 0) break; iVar8 += -1; puVar15 = (undefined4 *)((int)puVar6 + 1); cVar3 = *(char *)puVar6; puVar6 = puVar15; } while (cVar3 != '\0'); puVar6 = (undefined4 *)(pcVar16 + -uVar7); puVar15 = (undefined4 *)((int)puVar15 + -1); for (uVar9 = uVar7 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar6; puVar6 = puVar6 + 1; puVar15 = puVar15 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } uVar7 = 0xffffffff; pcVar17 = name; do { pcVar16 = pcVar17; if (uVar7 == 0) break; uVar7 -= 1; pcVar16 = pcVar17 + 1; cVar3 = *pcVar17; pcVar17 = pcVar16; } while (cVar3 != '\0'); uVar7 = ~uVar7; iVar8 = -1; pcVar17 = local_400; do { pcVar18 = pcVar17; if (iVar8 == 0) break; iVar8 += -1; pcVar18 = pcVar17 + 1; cVar3 = *pcVar17; pcVar17 = pcVar18; } while (cVar3 != '\0'); puVar6 = (undefined4 *)(pcVar16 + -uVar7); puVar15 = (undefined4 *)(pcVar18 + -1); for (uVar9 = uVar7 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar15 = *puVar6; puVar6 = puVar6 + 1; puVar15 = puVar15 + 1; } for (uVar7 &= 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } } } else { std::sprintf(local_400,"%s\\%s",globs::containerGlobs.sharedDir,name); } uVar7 = 0; *texture = NULL; if (globs::containerGlobs.textureCount != 0) { pCVar13 = globs::containerGlobs.textureSet; do { pbVar4 = (byte *)pCVar13->filename; if (pbVar4 != NULL) { pbVar14 = (byte *)local_400; do { bVar1 = *pbVar4; bVar21 = bVar1 < *pbVar14; if (bVar1 != *pbVar14) { LAB_00476d3e: iVar8 = (1 - (uint)bVar21) - (uint)(bVar21 != 0); goto LAB_00476d43; } if (bVar1 == 0) break; bVar1 = pbVar4[1]; bVar21 = bVar1 < pbVar14[1]; if (bVar1 != pbVar14[1]) goto LAB_00476d3e; pbVar4 = pbVar4 + 2; pbVar14 = pbVar14 + 2; } while (bVar1 != 0); iVar8 = 0; LAB_00476d43: pcVar11 = local_404; if (iVar8 == 0) { pIVar2 = globs::containerGlobs.textureSet[uVar7].texture; *texture = pIVar2; (*pIVar2->lpVtbl->AddRef)((IUnknown *)pIVar2); return 0; } } uVar7 += 1; pCVar13 = pCVar13 + 1; pcVar12 = local_40c; } while (uVar7 < globs::containerGlobs.textureCount); } pCVar5 = Container_LoadTexture2(local_400,0,NULL,NULL); if (pCVar5 == NULL) { local_408 += 1; if ((int)((globs::containerGlobs.sharedDir != NULL) + 1) <= local_408) { return -0x7789fcef; } goto LAB_00476c0f; } pIVar2 = pCVar5->texture; *texture = pIVar2; Container_YFlipTexture(pIVar2); if (((byte)globs::mainGlobs.flags & MAIN_FLAG_MIPMAPENABLED) != 0) { (*(code *)(*texture)->lpVtbl->GenerateMIPMap)(*texture,0); } if (globs::containerGlobs.textureCount == 1000) { std::qsort(globs::containerGlobs.textureSet,1000,8,Container_TextureSetSort); while (globs::containerGlobs.visualArray[globs::containerGlobs.textureCount * 2 + 2] == NULL ) { globs::containerGlobs.textureCount -= 1; } } uVar7 = globs::containerGlobs.textureCount; if (globs::containerGlobs.textureCount < 1000) { pCVar13 = globs::containerGlobs.textureSet + globs::containerGlobs.textureCount; (*(*texture)->lpVtbl->AddDestroyCallback) ((IUnknown *)*texture,Container_TextureDestroyCallback,pCVar13); uVar9 = 0xffffffff; ppcVar19 = &local_40c; do { if (uVar9 == 0) break; uVar9 -= 1; cVar3 = *(char *)ppcVar19; ppcVar19 = (char **)((int)ppcVar19 + 1); } while (cVar3 != '\0'); puVar6 = (undefined4 *)io::Mem_Alloc(~uVar9); uVar9 = 0xffffffff; pCVar13->filename = (char *)puVar6; ppcVar19 = &local_40c; do { ppcVar20 = ppcVar19; if (uVar9 == 0) break; uVar9 -= 1; ppcVar20 = (char **)((int)ppcVar19 + 1); cVar3 = *(char *)ppcVar19; ppcVar19 = ppcVar20; } while (cVar3 != '\0'); uVar9 = ~uVar9; puVar15 = (undefined4 *)((int)ppcVar20 - uVar9); for (uVar10 = uVar9 >> 2; uVar10 != 0; uVar10 -= 1) { *puVar6 = *puVar15; puVar15 = puVar15 + 1; puVar6 = puVar6 + 1; } for (uVar9 &= 3; uVar9 != 0; uVar9 -= 1) { *(undefined *)puVar6 = *(undefined *)puVar15; puVar15 = (undefined4 *)((int)puVar15 + 1); puVar6 = (undefined4 *)((int)puVar6 + 1); } globs::containerGlobs.textureSet[uVar7].texture = *texture; globs::containerGlobs.textureCount += 1; } return 0; } } return -0x7789fcef; } void __cdecl lego::gfx::Container_YFlipTexture(IDirect3DRMTexture3 *texture) { D3DRMImage *pDVar1; int iVar2; undefined4 *buffer; uint uVar3; undefined4 *puVar4; undefined4 *puVar5; uint size; undefined4 *puVar6; undefined4 *puVar7; int local_c; pDVar1 = (*texture->lpVtbl->GetImage)(texture); if (pDVar1 != NULL) { iVar2 = pDVar1->depth * pDVar1->width; size = (int)(iVar2 + (iVar2 >> 0x1f & 7U)) >> 3; buffer = (undefined4 *)io::Mem_Alloc(size); if (buffer != NULL) { puVar4 = (undefined4 *)pDVar1->buffer1; local_c = 0; puVar5 = (undefined4 *)((pDVar1->height + -1) * pDVar1->bytes_per_line + (int)puVar4); if (0 < pDVar1->height / 2) { do { puVar6 = puVar5; puVar7 = buffer; for (uVar3 = size >> 2; uVar3 != 0; uVar3 -= 1) { *puVar7 = *puVar6; puVar6 = puVar6 + 1; puVar7 = puVar7 + 1; } for (uVar3 = size & 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } puVar6 = puVar4; puVar7 = puVar5; for (uVar3 = size >> 2; uVar3 != 0; uVar3 -= 1) { *puVar7 = *puVar6; puVar6 = puVar6 + 1; puVar7 = puVar7 + 1; } for (uVar3 = size & 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } puVar6 = buffer; puVar7 = puVar4; for (uVar3 = size >> 2; uVar3 != 0; uVar3 -= 1) { *puVar7 = *puVar6; puVar6 = puVar6 + 1; puVar7 = puVar7 + 1; } for (uVar3 = size & 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } puVar4 = (undefined4 *)((int)puVar4 + pDVar1->bytes_per_line); puVar5 = (undefined4 *)((int)puVar5 - pDVar1->bytes_per_line); local_c += 1; } while (local_c < pDVar1->height / 2); } io::Mem_Free(buffer); } } return; } // if (*param_1 && !*param_2) return -1; // if (!*param_1 && *param_2) return 1; // else return 0; int __cdecl lego::gfx::Container_TextureSetSort(Container_TextureRef *a,Container_TextureRef *b) { if ((a->filename != NULL) && (b->filename == NULL)) { return -1; } if ((a->filename == NULL) && (b->filename != NULL)) { return 1; } return 0; } void __cdecl lego::gfx::Container_TextureDestroyCallback (IDirect3DRMTexture3 *lpD3DRMobj,Container_TextureRef *textRef) { void *buffer; buffer = (*textRef->texture->lpVtbl->GetAppData)(textRef->texture); io::Mem_Free(buffer); io::Mem_Free(textRef->filename); textRef->filename = NULL; textRef->texture = NULL; return; } void __cdecl lego::view::Viewport_Initialise(void) { int iVar1; Viewport_Globs *pVVar2; pVVar2 = &globs::viewportGlobs; for (iVar1 = 0x20; iVar1 != 0; iVar1 += -1) { pVVar2->listSet[0] = NULL; pVVar2 = (Viewport_Globs *)(pVVar2->listSet + 1); } globs::viewportGlobs.freeList = NULL; globs::viewportGlobs.listCount = 0; globs::viewportGlobs.flags = 1; return; } void __cdecl lego::view::Viewport_Shutdown(void) { Viewport_Globs *pVVar1; Viewport_RemoveAll(); pVVar1 = &globs::viewportGlobs; do { if (pVVar1->listSet[0] != NULL) { io::Mem_Free(pVVar1->listSet[0]); } pVVar1 = (Viewport_Globs *)(pVVar1->listSet + 1); } while (pVVar1 < (Viewport_Globs *)&globs::viewportGlobs.freeList); globs::viewportGlobs.freeList = NULL; globs::viewportGlobs.flags = 0; return; } // Creates a viewport, where the float arguments are positions between 0.0 and 1.0 // (rather than between 0,0 and rmWidth,rmHeight) Viewport * __cdecl lego::view::Viewport_Create (float xposf,float yposf,float widthf,float heightf,Container *contCamera) { uint uVar1; uint uVar2; int yPos; Viewport *pVVar3; float10 extraout_ST0; longlong lVar4; float unaff_retaddr; float fVar5; float fStack4; uVar1 = (*(code *)(globs::mainGlobs.device)->lpVtbl->GetWidth)(globs::mainGlobs.device); uVar2 = (*(code *)(globs::mainGlobs.device)->lpVtbl->GetHeight)(globs::mainGlobs.device); fVar5 = (float)(ulonglong)uVar1; lVar4 = __ftol((float10)yposf * (float10)(ulonglong)uVar2); uVar1 = (uint)lVar4; lVar4 = __ftol((float10)xposf * (float10)fVar5); uVar2 = (uint)lVar4; lVar4 = __ftol((float10)unaff_retaddr * extraout_ST0); yPos = (int)lVar4; lVar4 = __ftol((float10)fStack4 * (float10)fVar5); pVVar3 = Viewport_CreatePixel((int)lVar4,yPos,uVar2,uVar1,(Container *)widthf); return pVVar3; } Viewport * __cdecl lego::view::Viewport_CreatePixel(int xPos,int yPos,uint width,uint height,Container *contCamera) { IDirect3DRMViewport2 **lplpD3DRMViewport; Viewport **ppVVar1; IDirect3DRMViewport2 *This; Viewport *appData; uint uVar2; uint uVar3; HRESULT HVar4; uint unaff_EBX; uint unaff_retaddr; uVar2 = (*(code *)(globs::mainGlobs.device)->lpVtbl->GetWidth)(globs::mainGlobs.device); uVar3 = (*(code *)(globs::mainGlobs.device)->lpVtbl->GetHeight)(globs::mainGlobs.device); if ((int)unaff_EBX < 0) { unaff_EBX += uVar2; } if ((int)unaff_retaddr < 0) { unaff_retaddr += uVar3; } if ((xPos + unaff_EBX <= uVar2) && (yPos + unaff_retaddr <= uVar3)) { if (globs::viewportGlobs.freeList == NULL) { Viewport_AddList(); } appData = globs::viewportGlobs.freeList; lplpD3DRMViewport = &(globs::viewportGlobs.freeList)->lpVP; ppVVar1 = &(globs::viewportGlobs.freeList)->nextFree; globs::viewportGlobs.freeList = (globs::viewportGlobs.freeList)->nextFree; *ppVVar1 = NULL; // IDirect3DRM3->CreateViewport(this, IDirect3DRMDevice3* lpDev, IDirect3DRMFrame3* // lpCamera, DWORD dwXPos, DWORD dwYPos, DWORD dwWidth, DWORD dwHeight, // IDirect3DRMViewport2** lplpD3DRMViewport) HVar4 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateViewport) (globs::mainGlobs.lpD3DRM,globs::mainGlobs.device,*(IDirect3DRMFrame3 **)width ,unaff_EBX,unaff_retaddr,xPos,yPos,lplpD3DRMViewport); if (HVar4 == 0) { This = *lplpD3DRMViewport; // IDirect3DRMViewport2->SetAppData(this, ViewportData* appData) (*This->lpVtbl->SetAppData)(This,appData); appData->smoothFOV = 0.0; return appData; } } return NULL; } void __cdecl lego::view::Viewport_GetSize(Viewport *view,uint *out_width,uint *out_height) { DWORD DVar1; if (out_width != NULL) { DVar1 = (*view->lpVP->lpVtbl->GetWidth)(view->lpVP); *out_width = DVar1; } if (out_height != NULL) { DVar1 = (*view->lpVP->lpVtbl->GetHeight)(view->lpVP); *out_height = DVar1; } return; } void __cdecl lego::view::Viewport_SetCamera(Viewport *view,Container *contCamera) { (*view->lpVP->lpVtbl->SetCamera)(view->lpVP,contCamera->masterFrame); return; } Container * __cdecl lego::view::Viewport_GetCamera(Viewport *view) { HRESULT HVar1; Container *pCVar2; Container *pCVar3; pCVar3 = NULL; // IDirect3DRMViewport2->GetCamera(this, IDirect3DRMFrame3** lplpCamera) HVar1 = (*view->lpVP->lpVtbl->GetCamera)(view->lpVP,(IDirect3DRMFrame3 **)&view); if (HVar1 == 0) { // ResourceData* IDirect3DRMFrame3->GetAppData(this) pCVar2 = (**(code **)((int)view->xoffset + 0x1c))((IDirect3DRMFrame3 *)view); if (pCVar2 != NULL) { pCVar3 = (Container *)pCVar2->masterFrame; } // IDirect3DRMFrame3->Release(this) (**(code **)((int)view->xoffset + 8))(view); } return pCVar3; } void __cdecl lego::view::Viewport_SetBackClip(Viewport *view,float dist) { (*view->lpVP->lpVtbl->SetBack)(view->lpVP,dist); return; } float10 __cdecl lego::view::Viewport_GetBackClip(Viewport *view) { float10 fVar1; // float IDirect3DRMViewport2->GetBack(this) fVar1 = (*view->lpVP->lpVtbl->GetBack)(view->lpVP); return fVar1; } float10 __cdecl lego::view::Viewport_GetFrontClip(Viewport *view) { float10 fVar1; // float IDirect3DRMViewport2->GetFront(this) fVar1 = (*view->lpVP->lpVtbl->GetFront)(view->lpVP); return fVar1; } void __cdecl lego::view::Viewport_Clear(Viewport *view,BOOL full) { Viewport *pVVar1; IDirect3DRMFrame3 *pIVar2; DWORD DVar3; longlong lVar4; RECT local_20; float local_10; float local_c; float local_8; float local_4; pVVar1 = view; if ((IDirect3DViewport3 *)full != NULL) { pIVar2 = Viewport_GetScene(view); DVar3 = 0; view = (Viewport *)(*pVVar1->lpVP->lpVtbl->GetX)(pVVar1->lpVP); local_10 = (float)(int)view; view = (Viewport *)(*pVVar1->lpVP->lpVtbl->GetY)(pVVar1->lpVP); local_c = (float)(int)view; local_20.left = (*pVVar1->lpVP->lpVtbl->GetWidth)(pVVar1->lpVP); local_20.top = 0; local_8 = (float)(ulonglong)(uint)local_20.left; local_20.left = (*pVVar1->lpVP->lpVtbl->GetHeight)(pVVar1->lpVP); local_20.top = 0; local_4 = (float)(ulonglong)(uint)local_20.left; if (pIVar2 != NULL) { DVar3 = (*pIVar2->lpVtbl->GetSceneBackground)(pIVar2); } lVar4 = __ftol((float10)local_10); local_20.left = (LONG)lVar4; lVar4 = __ftol((float10)local_c); local_20.top = (LONG)lVar4; lVar4 = __ftol((float10)local_10 + (float10)local_8); local_20.right = (LONG)lVar4; lVar4 = __ftol((float10)local_c + (float10)local_4); local_20.bottom = (LONG)lVar4; (*pVVar1->lpVP->lpVtbl->GetDirect3DViewport)(pVVar1->lpVP,(IDirect3DViewport **)&view); (**(code **)view->xoffset) ((IDirect3DViewport *)view,&idl::IID_IDirect3DViewport3,(IDirect3DViewport3 **)&full); (**(code **)((int)view->xoffset + 8))((IDirect3DViewport *)view); (**(code **)((int)*(IDirect3DViewport3 *)full + 0x50)) ((IDirect3DViewport3 *)full,1,&local_20,3,DVar3,1.0,0); (**(code **)((int)*(IDirect3DViewport3 *)full + 8))((IDirect3DViewport3 *)full); return; } (*view->lpVP->lpVtbl->Clear)(view->lpVP,D3DRMCLEAR_ALL); return; } void __cdecl lego::view::Viewport_Render(Viewport *view,Container *root,float delta) { float fVar1; HRESULT err; float10 fVar2; view->rendering = 1; if (view->smoothFOV != 0.0) { // float IDirect3DRMViewport2->GetField(this) fVar2 = (*view->lpVP->lpVtbl->GetField)(view->lpVP); fVar1 = (1.0 / delta) * 4.0; fVar1 = (1.0 / (fVar1 - -1.0)) * (float)(fVar2 * (float10)fVar1 + (float10)view->smoothFOV); // IDirect3DRMViewport2->SetField(this, float rvField) (*view->lpVP->lpVtbl->SetField)(view->lpVP,fVar1); if (fVar1 == view->smoothFOV) { view->smoothFOV = 0.0; } } // IDirect3DRMViewport2->Render(this, IDirect3DRMFrame3* lpD3DRMFrame) err = (*view->lpVP->lpVtbl->Render)(view->lpVP,root->masterFrame); if (err == 0) { gfx::Mesh_PostRenderAll(view); view->rendering = 0; return; } debug::Error_SetDXError(err,1,"C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Viewports.c",286); view->rendering = 0; return; } void __cdecl lego::view::Viewport_Remove(Viewport *view) { view->nextFree = globs::viewportGlobs.freeList; globs::viewportGlobs.freeList = view; (*view->lpVP->lpVtbl->Release)(view->lpVP); return; } void __cdecl lego::view::Viewport_SmoothSetField(Viewport *view,float fov) { view->smoothFOV = fov; return; } void __cdecl lego::view::Viewport_SetField(Viewport *view,float fov) { (*view->lpVP->lpVtbl->SetField)(view->lpVP,fov); view->smoothFOV = 0.0; return; } float10 __cdecl lego::view::Viewport_GetField(Viewport *view) { float10 fVar1; fVar1 = (*view->lpVP->lpVtbl->GetField)(view->lpVP); return fVar1; } void __cdecl lego::view::Viewport_InverseTransform(Viewport *view,Vector3F *out_vector,Vector4F *transform4d) { // IDirect3DRMViewport2->InverseTransform(this, Vector3F* out_lprvDst, const Vector4F* // lprvSrc) (*view->lpVP->lpVtbl->InverseTransform)(view->lpVP,out_vector,transform4d); return; } void __cdecl lego::view::Viewport_Transform(Viewport *view,Vector4F *out_transform4d,Vector3F *vector) { // IDirect3DRMViewport2->Transform(this, Vector4F** lplprvDst, Vector3F* lprvSrc) (*view->lpVP->lpVtbl->Transform)(view->lpVP,out_transform4d,vector); return; } Point2F * __cdecl lego::view::Viewport_WorldToScreen(Viewport *view,Point2F *out_screenPt,Vector3F *in_worldVec) { Vector4F transform4d; // IDirect3DRMViewport2->Transform(this, Vector4F** lplprvDst, Vector3F* lprvSrc) (*view->lpVP->lpVtbl->Transform)(view->lpVP,&transform4d,in_worldVec); // out_point.x = (transform4d.x / transform4d.w) // out_point.y = (transform4d.y / transform4d.w) out_screenPt->x = transform4d.x / transform4d.w; out_screenPt->y = transform4d.y / transform4d.w; return out_screenPt; } // WARNING: Restarted to delay deadcode elimination for space: stack IDirect3DRMFrame3 * __cdecl lego::view::Viewport_GetScene(Viewport *view) { IDirect3DRMFrame3 *local_8; IDirect3DRMFrame3 *local_4; local_8 = NULL; local_4 = NULL; (*view->lpVP->lpVtbl->GetCamera)(view->lpVP,&local_8); if (local_8 != NULL) { (*local_8->lpVtbl->Release)((IUnknown *)local_8); (*local_8->lpVtbl->GetScene)((IDirect3DRMViewport2 *)local_8,(IDirect3DRMDevice3 **)&local_4); (*local_4->lpVtbl->Release)((IUnknown *)local_4); } return local_4; } void __cdecl lego::view::Viewport_AddList(void) { Viewport *pVVar1; Viewport *pVVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::viewportGlobs.listCount & 0x1f); pVVar2 = (Viewport *)io::Mem_Alloc(uVar4 * 0x20); globs::viewportGlobs.listSet[globs::viewportGlobs.listCount] = pVVar2; pVVar2 = globs::viewportGlobs.listSet[globs::viewportGlobs.listCount]; if (pVVar2 != NULL) { globs::viewportGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pVVar1 = pVVar2; do { pVVar1->nextFree = pVVar1 + 1; iVar3 += -1; pVVar1 = pVVar1 + 1; } while (iVar3 != 0); } pVVar2[uVar4 - 1].nextFree = globs::viewportGlobs.freeList; globs::viewportGlobs.freeList = pVVar2; } return; } void __cdecl lego::view::Viewport_RemoveAll(void) { int iVar1; int iVar2; Viewport_Globs *pVVar3; uint uVar4; int iVar5; uVar4 = 0; if (globs::viewportGlobs.listCount != 0) { pVVar3 = &globs::viewportGlobs; do { if ((pVVar3->listSet[0] != NULL) && (iVar1 = 1 << ((byte)uVar4 & 0x1f), iVar1 != 0)) { iVar5 = 0; do { iVar2 = (int)&pVVar3->listSet[0]->xoffset + iVar5; if ((iVar2 != 0) && (*(int *)(iVar2 + 0x1c) == iVar2)) { // IDirect3DRMViewport2->Release(this) (*(*(IDirect3DRMViewport2 **)(iVar2 + 0x10))->lpVtbl->Release) (*(IDirect3DRMViewport2 **)(iVar2 + 0x10)); } iVar5 += 0x20; iVar1 += -1; } while (iVar1 != 0); } uVar4 += 1; pVVar3 = (Viewport_Globs *)(pVVar3->listSet + 1); } while (uVar4 < globs::viewportGlobs.listCount); } return; } int __cdecl lego::util::Util_Tokenise(char *input,char **out_parts,char *delimiter) { char cVar1; int iVar2; uint uVar3; int numParts; char *pcVar4; char **ppcVar5; uVar3 = 0xffffffff; pcVar4 = delimiter; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar4; pcVar4 = pcVar4 + 1; } while (cVar1 != '\0'); if (*input == '\0') { return 0; } numParts = 1; *out_parts = input; if (*input != '\0') { ppcVar5 = out_parts + 1; do { iVar2 = std::strncmp(delimiter,input,~uVar3 - 1); if (iVar2 == 0) { *input = '\0'; *ppcVar5 = input + (~uVar3 - 1); numParts += 1; ppcVar5 = ppcVar5 + 1; } pcVar4 = input + 1; input = input + 1; } while (*pcVar4 != '\0'); } return numParts; } int __cdecl lego::util::Util_WSTokenise(char *input,char **out_parts) { uint uVar1; int iVar2; byte **ppbVar3; if (*input != '\0') { *out_parts = input; iVar2 = 1; if (*input != '\0') { ppbVar3 = (byte **)(out_parts + 1); do { // int std::isspace(int c) if (std::globals::_pcharwidth < 2) { // C1_SPACE (0x8) uVar1 = *(byte *)(std::globals::_pctype + (byte)*input) & C1_SPACE; } else { // C1_SPACE (0x8) uVar1 = std::_isctype((uint)(byte)*input,C1_SPACE); } if (uVar1 == 0) { input = (char *)((byte *)input + 1); } else { *input = 0; do { input = (char *)((byte *)input + 1); // int std::isspace(int c) if (std::globals::_pcharwidth < 2) { // C1_SPACE (0x8) uVar1 = *(byte *)(std::globals::_pctype + (byte)*input) & C1_SPACE; } else { // C1_SPACE (0x8) uVar1 = std::_isctype((uint)(byte)*input,C1_SPACE); } } while (uVar1 != 0); *ppbVar3 = (byte *)input; iVar2 += 1; ppbVar3 = ppbVar3 + 1; } } while (*input != 0); } return iVar2; } return 0; } // OFFICIAL: Util_StrCpy // C RUNTIME: ::_strdup char * __cdecl lego::util::Util_StrCpy(char *strSource) { char cVar1; undefined4 *puVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; undefined4 *puVar7; uVar3 = 0xffffffff; pcVar6 = strSource; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); puVar2 = (undefined4 *)io::Mem_Alloc(~uVar3); uVar3 = 0xffffffff; do { pcVar6 = strSource; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = strSource + 1; cVar1 = *strSource; strSource = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); puVar7 = puVar2; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar7 = *puVar5; puVar5 = puVar5 + 1; puVar7 = puVar7 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } return (char *)puVar2; } char * __cdecl lego::util::Util_RemoveUnderscores(char *text,...) { char *pcVar1; char cVar2; char *pcVar3; char *pcVar4; char fmtBuffer [256]; char replBuffer [256]; std::vsprintf(fmtBuffer,text,&stack0x00000008); pcVar3 = fmtBuffer; pcVar4 = replBuffer; while (fmtBuffer[0] != '\0') { cVar2 = *pcVar3; if ((cVar2 == '\\') && (pcVar3[1] == 'n')) { *pcVar4 = '\n'; pcVar3 = pcVar3 + 1; } else { if (cVar2 == '_') { *pcVar4 = ' '; } else { *pcVar4 = cVar2; } } pcVar1 = pcVar3 + 1; pcVar4 = pcVar4 + 1; pcVar3 = pcVar3 + 1; fmtBuffer[0] = *pcVar1; } *pcVar4 = '\0'; pcVar4 = Util_StrCpy(replBuffer); return pcVar4; } char * __cdecl lego::util::Util_StrIStr(char *str,char *strSearch) { char cVar1; int iVar2; uint uVar3; uint uVar4; char *pcVar5; uint uVar6; uVar3 = 0xffffffff; pcVar5 = str; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); uVar3 = ~uVar3; uVar4 = 0xffffffff; pcVar5 = strSearch; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); if (((uVar3 != 1) && (~uVar4 - 1 != 0)) && (uVar6 = 0, uVar3 != 1)) { do { iVar2 = std::_strnicmp(str,strSearch,~uVar4 - 1); if (iVar2 == 0) { return str; } uVar6 += 1; str = str + 1; } while (uVar6 < uVar3 - 1); return NULL; } return NULL; } // https://github.com/microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/begin/sdkdiff/utils.cpp // // hash_string() uint __cdecl lego::util::Util_HashString(char *str,BOOL bIgnoreBlanks,BOOL upperCase) { byte bVar1; uint uVar2; int iVar3; int iVar4; uint uVar5; byte *pbVar6; int iVar7; uVar5 = 0; iVar7 = 0x600937; iVar4 = 1; bVar1 = *str; pbVar6 = (byte *)str; while (bVar1 != 0) { if (bIgnoreBlanks != 0) { while( true ) { // int std::isspace(int c) if (std::globals::_pcharwidth < 2) { // C1_SPACE (0x8) uVar2 = *(byte *)(std::globals::_pctype + *pbVar6) & C1_SPACE; } else { // C1_SPACE (0x8) uVar2 = std::_isctype((uint)*pbVar6,C1_SPACE); } if (uVar2 == 0) break; pbVar6 = pbVar6 + 1; } } bVar1 = *pbVar6; pbVar6 = pbVar6 + 1; str = (char *)(uint)bVar1; if (upperCase != 0) { uVar2 = std::toupper((int)str); str = (char *)(uVar2 & 0xff); } iVar3 = iVar4 * iVar7; iVar7 *= 0x600937; uVar5 += iVar3 * (int)str; iVar4 += 1; bVar1 = *pbVar6; } return uVar5; } BoolTri __cdecl lego::util::Util_GetBoolFromString(char *str) { int iVar1; iVar1 = std::_stricmp(str,"YES"); if (iVar1 == 0) { return BOOL3_TRUE; } iVar1 = std::_stricmp(str,"TRUE"); if (iVar1 == 0) { return BOOL3_TRUE; } iVar1 = std::_stricmp(str,"ON"); if (iVar1 == 0) { return BOOL3_TRUE; } iVar1 = std::_stricmp(str,"NO"); if (iVar1 == 0) { return BOOL3_FALSE; } iVar1 = std::_stricmp(str,"FALSE"); if (iVar1 == 0) { return BOOL3_FALSE; } iVar1 = std::_stricmp(str,"OFF"); return -(uint)(iVar1 != 0) & BOOL3_ERROR; } int lego::WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { char cVar1; DWORD DVar2; LPSTR pCVar3; char *pcVar4; BOOL BVar5; MainFlags MVar6; DWORD DVar7; uint uVar8; uint uVar9; int iVar10; undefined4 *puVar11; char *pcVar12; undefined4 *puVar13; float fpsSync; BOOL insistOnCD; BOOL nosound; uint local_c88; undefined4 uStack3204; char mutexName [128]; char fullCmdLine [1024]; char errorMessage [1024]; char standardParameters [1024]; nosound = 0; insistOnCD = 0; if (true) { std::sprintf(mutexName,"%s Mutex","Lego Rock Raiders"); CreateMutexA(NULL,TRUE,mutexName); DVar2 = GetLastError(); if (DVar2 == ERROR_ALREADY_EXISTS) { return 0; } } pCVar3 = GetCommandLineA(); cVar1 = *pCVar3; pcVar4 = pCVar3; while (cVar1 != '\0') { if (cVar1 == '\\') { pcVar4 = pCVar3 + 1; } pcVar12 = pCVar3 + 1; pCVar3 = pCVar3 + 1; cVar1 = *pcVar12; } uVar8 = 0xffffffff; do { pcVar12 = pcVar4; if (uVar8 == 0) break; uVar8 -= 1; pcVar12 = pcVar4 + 1; cVar1 = *pcVar4; pcVar4 = pcVar12; } while (cVar1 != '\0'); uVar8 = ~uVar8; puVar11 = (undefined4 *)(pcVar12 + -uVar8); puVar13 = (undefined4 *)globs::mainGlobs.programName; for (uVar9 = uVar8 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar13 = *puVar11; puVar11 = puVar11 + 1; puVar13 = puVar13 + 1; } pcVar4 = globs::mainGlobs.programName; for (uVar8 &= 3; cVar1 = globs::mainGlobs.programName[0], uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar13 = *(undefined *)puVar11; puVar11 = (undefined4 *)((int)puVar11 + 1); puVar13 = (undefined4 *)((int)puVar13 + 1); } while (cVar1 != '\0') { if (*pcVar4 == '\"') { *pcVar4 = '\0'; } pcVar12 = pcVar4 + 1; pcVar4 = pcVar4 + 1; cVar1 = *pcVar12; } iVar10 = 0x506814; pcVar4 = globs::mainGlobs.programName; cVar1 = globs::mainGlobs.programName[0]; while (cVar1 != '\0') { if (cVar1 == '.') { pcVar4 = (char *)(iVar10 + 1); } pcVar12 = (char *)(iVar10 + 1); iVar10 += 1; cVar1 = *pcVar12; } if (pcVar4 != globs::mainGlobs.programName) { // to upper std::_strupr(pcVar4); pcVar4 = std::strstr(globs::mainGlobs.programName,".EXE"); if (pcVar4 != NULL) { *pcVar4 = '\0'; } } globs::mainGlobs.className = globs::mainGlobs.programName; globs::mainGlobs.active = FALSE; globs::mainGlobs.exit = FALSE; globs::mainGlobs.stateSet = FALSE; globs::mainGlobs.hInst = hInstance; globs::mainGlobs.fixedFrameTiming = 0.0; globs::mainGlobs.flags = MAIN_FLAG_NONE; BVar5 = registry::Registry_GetValue ("SOFTWARE\\LEGO Media\\Games\\Rock Raiders","StandardParameters", REGISTRY_STRING_VALUE,standardParameters,0x400); if (BVar5 == 0) { std::sprintf(fullCmdLine,"%s",lpCmdLine); } else { std::sprintf(fullCmdLine,"%s %s",lpCmdLine,standardParameters); } main::Main_ParseCommandLine(fullCmdLine,&nosound,&insistOnCD); BVar5 = registry::Registry_GetValue ("SOFTWARE\\LEGO Media\\Games\\Rock Raiders","NoHALMessage", REGISTRY_STRING_VALUE,errorMessage,0x400); if (BVar5 == 0) { std::sprintf(errorMessage,"No DirectX 3D accelerator could be found."); } debug::Error_Initialise(); io::Mem_Initialise(); io::File_Initialise(globs::mainGlobs.programName,insistOnCD, "SOFTWARE\\LEGO Media\\Games\\Rock Raiders"); cfg::Config_Initialise(); input::Input_InitKeysAndDI(); BVar5 = main::Main_InitApp(hInstance); if (BVar5 != 0) { ddraw::DirectDraw_Initialise(globs::mainGlobs.hWnd); BVar5 = snd::Sound_Initialise(nosound); if ((BVar5 != 0) && (BVar5 = setup::Init_Initialise (TRUE,globs::mainGlobs.flags & MAIN_FLAG_DEBUGMODE, globs::mainGlobs.flags & MAIN_FLAG_BEST, globs::mainGlobs.flags & MAIN_FLAG_WINDOW,errorMessage), BVar5 != 0)) { video::Animation_Initialise(globs::directDrawGlobs.lpDirectDraw); draw::Draw_Initialise(NULL); Gods_Go(globs::mainGlobs.programName); if (globs::mainGlobs.stateSet != 0) { if ((globs::mainGlobs.currState.Initialise != NULL) && (BVar5 = (*globs::mainGlobs.currState.Initialise)(), BVar5 == 0)) { globs::mainGlobs.currState.Initialise = NULL; globs::mainGlobs.currState.MainLoop = NULL; globs::mainGlobs.currState.Shutdown = NULL; } if (globs::mainGlobs.currState.MainLoop != NULL) { fpsSync = 1.0; DVar2 = timeGetTime(); while (globs::mainGlobs.exit == 0) { globs::INPUT.lClicked = 0; globs::INPUT.rClicked = 0; globs::INPUT.lDoubleClicked = 0; globs::INPUT.rDoubleClicked = 0; main::Main_HandleIO(); if ((globs::mainGlobs.flags & MAIN_FLAG_FULLSCREEN) != MAIN_FLAG_NONE) { globs::mainGlobs.active = TRUE; } input::Input_ReadKeys(); input::Input_ReadMouse2(); BVar5 = (*globs::mainGlobs.currState.MainLoop)(fpsSync); if (BVar5 == 0) { globs::mainGlobs.exit = TRUE; } main::Main_Finalise3D(); ddraw::DirectDraw_Flip(); MVar6 = globs::mainGlobs.flags & ~MAIN_FLAG_UPDATED; if ((globs::mainGlobs.flags & MAIN_FLAG_DUMPMODE) == MAIN_FLAG_NONE) { if ((globs::mainGlobs.flags & MAIN_FLAG_PAUSED) == MAIN_FLAG_NONE) { if (globs::mainGlobs.fixedFrameTiming != 0.0) { fpsSync = globs::mainGlobs.fixedFrameTiming; goto LAB_00477e2a; } globs::mainGlobs.flags = MVar6; DVar7 = timeGetTime(); uStack3204 = 0; local_c88 = DVar7 - DVar2; fpsSync = (float)(ulonglong)local_c88 * 0.025; DVar2 = DVar7; if ((ushort)((ushort)(fpsSync < 3.0) << 8 | (ushort)(fpsSync == 3.0) << 0xe) == 0) { fpsSync = 3.0; } } else { fpsSync = 0.0; LAB_00477e2a: globs::mainGlobs.flags = MVar6; DVar2 = timeGetTime(); } } else { fpsSync = 0.8333333; globs::mainGlobs.flags = MVar6; } } } if (globs::mainGlobs.currState.Shutdown != NULL) { (*globs::mainGlobs.currState.Shutdown)(); } } } ddraw::DirectDraw_Shutdown(); DestroyWindow(globs::mainGlobs.hWnd); } input::Input_ReleaseKeysAndDI(); cfg::Config_Shutdown(); util::logf_removed(NULL); debug::Error_CloseLog(); debug::Error_Shutdown(); return 0; } // Sets the "-nm" commandline option only if the "-ftm" option is not set. // (The "-ftm" option is intended to be set when running on Voodoo2-based graphics cards, as is // shown by CLGen.exe) // This is called when Lego.cfg/Lego*::Main::TextureUsage (units in pixels) is valid and <= // available video memory. void __cdecl lego::main::Main_DisableTextureManagement(void) { if ((globs::mainGlobs.flags & MAIN_FLAG_FORCETEXTUREMANAGEMENT) == MAIN_FLAG_NONE) { globs::mainGlobs.flags |= MAIN_FLAG_DONTMANAGETEXTURES; } return; } void __cdecl lego::main::Main_ParseCommandLine(char *lpszCmdLine,BOOL *out_nosound,BOOL *out_insistOnCD) { char *pcVar1; char cVar2; char *pcVar3; uint uVar4; int iVar5; pcVar3 = util::Util_StrIStr(lpszCmdLine,"-insistOnCD"); if (pcVar3 != NULL) { *out_insistOnCD = 1; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-nosound"); if (pcVar3 != NULL) { *out_nosound = 1; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-debug"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_DEBUGMODE; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-nm"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_DONTMANAGETEXTURES; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-ftm"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_FORCETEXTUREMANAGEMENT; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-fvf"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_FORCEVERTEXFOG; } // "best fit" for screen mode selection pcVar3 = util::Util_StrIStr(lpszCmdLine,"-best"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_BEST; } // Only used when "-best" is specified pcVar3 = util::Util_StrIStr(lpszCmdLine,"-window"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_WINDOW; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-dualmouse"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_DUALMOUSE; } // Automatically triggers "-debug" command line option as well pcVar3 = util::Util_StrIStr(lpszCmdLine,"-debugcomplete"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_DEBUGCOMPLETE; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-testercall"); if (pcVar3 != NULL) { globs::mainGlobs.programmerLevel = PROGRAMMER_MODE_2; globs::mainGlobs.flags |= MAIN_FLAG_TESTERCALL; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-testlevels"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_LEVELSOPEN; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-reducesamples"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_REDUCESAMPLES; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-showversion"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_SHOWVERSION; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-reduceanimation"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_REDUCEANIMATION; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-reducepromeshes"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_REDUCEPROMESHES; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-reduceflics"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_REDUCEFLICS; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-reduceimages"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_REDUCEIMAGES; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-startlevel"); if (pcVar3 != NULL) { pcVar3 = pcVar3 + 0xb; iVar5 = 0; cVar2 = *pcVar3; while ((cVar2 != '\0' && (cVar2 == ' '))) { pcVar1 = pcVar3 + 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } cVar2 = *pcVar3; while ((cVar2 != '\0' && (cVar2 != ' '))) { globs::mainGlobs.startLevel[iVar5] = cVar2; pcVar1 = pcVar3 + 1; iVar5 += 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } globs::mainGlobs.startLevel[iVar5] = '\0'; globs::mainGlobs.flags |= MAIN_FLAG_STARTLEVEL; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-flags"); if (pcVar3 != NULL) { globs::mainGlobs.clFlags = std::atoi(pcVar3 + 6); } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-fpslock"); if ((pcVar3 != NULL) && (uVar4 = std::atoi(pcVar3 + 8), uVar4 != 0)) { globs::mainGlobs.fixedFrameTiming = 25.0 / (float)(ulonglong)uVar4; } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-programmer"); if (pcVar3 == NULL) { globs::mainGlobs.programmerLevel = PROGRAMMER_OFF; } else { globs::mainGlobs.programmerLevel = std::atoi(pcVar3 + 0xb); if (globs::mainGlobs.programmerLevel == PROGRAMMER_OFF) { globs::mainGlobs.programmerLevel = PROGRAMMER_MODE_1; } } pcVar3 = util::Util_StrIStr(lpszCmdLine,"-cleansaves"); if (pcVar3 != NULL) { globs::mainGlobs.flags |= MAIN_FLAG_CLEANSAVES; } return; } void __cdecl lego::main::Main_LoopUpdate(BOOL clear) { Main_HandleIO(); input::Input_ReadKeys(); input::Input_ReadMouse2(); Main_Finalise3D(); ddraw::DirectDraw_Flip(); if (clear != 0) { ddraw::DirectDraw_Clear(NULL,0); } globs::mainGlobs.flags = globs::mainGlobs.flags & ~MAIN_FLAG_UPDATED; return; } MainCLFlags __cdecl lego::main::Main_GetCLFlags(void) { return globs::mainGlobs.clFlags; } int __cdecl lego::main::Main_GetWindowsBitDepth(void) { HDC hdc; int iVar1; iVar1 = BITSPIXEL; hdc = GetDC(globs::mainGlobs.hWnd); iVar1 = GetDeviceCaps(hdc,iVar1); return iVar1; } void __cdecl lego::main::Main_Finalise3D(void) { if ((globs::mainGlobs.flags & MAIN_FLAG_UPDATED) == MAIN_FLAG_NONE) { (*(code *)(globs::mainGlobs.device)->lpVtbl->Update)(globs::mainGlobs.device); globs::mainGlobs.flags |= MAIN_FLAG_UPDATED; } return; } BOOL __cdecl lego::main::Main_SetState(Main_State *state) { if (state != NULL) { globs::mainGlobs.currState.Initialise = state->Initialise; globs::mainGlobs.currState.MainLoop = state->MainLoop; globs::mainGlobs.currState.Shutdown = state->Shutdown; globs::mainGlobs.stateSet = TRUE; return TRUE; } return 0; } uint __cdecl lego::main::Main_GetTime(void) { DWORD DVar1; // WARNING: Could not recover jumptable at 0x004782c0. Too many branches // WARNING: Treating indirect jump as call DVar1 = timeGetTime(); return DVar1; } BOOL __cdecl lego::main::Main_DispatchMessage(MSG *msg) { UINT UVar1; if ((((byte)globs::mainGlobs.flags & MAIN_FLAG_FULLSCREEN) != 0) && (((UVar1 = msg->message, UVar1 == WM_ACTIVATEAPP || (UVar1 == WM_SYSKEYDOWN)) || (UVar1 == WM_SYSKEYUP)))) { return 0; } return 1; } void __cdecl lego::main::Main_HandleIO(void) { int iVar1; BOOL BVar2; MSG msg; iVar1 = PeekMessageA((LPMSG)&msg,NULL,0,0,1); while (iVar1 != 0) { BVar2 = Main_DispatchMessage(&msg); if (BVar2 != 0) { TranslateMessage(&msg); DispatchMessageA(&msg); } iVar1 = PeekMessageA((LPMSG)&msg,NULL,0,0,1); } return; } void __cdecl lego::main::Main_SetupDisplay(BOOL fullScreen,uint xPos,uint yPos,uint width,uint height) { HWND hWnd; RECT rect; globs::mainGlobs.appWidth = width; globs::mainGlobs.appHeight = height; if (fullScreen != 0) { globs::mainGlobs.flags |= MAIN_FLAG_FULLSCREEN; } debug::Error_FullScreen(fullScreen); if (fullScreen == 0) { rect.left = xPos; rect.right = width + xPos; rect.bottom = height + yPos; // WS_POPUPWINDOW | WS_CAPTION (0x80880000 | 0xc00000) // WS_POPUP | WS_BORDER | WS_DLGFRAME | WS_SYSMENU (0x80000000 | 0x800000 | 0x400000 | // 0x80000) globs::mainGlobs.style = 0x80c80000; rect.top = yPos; Main_AdjustWindowRect((LPRECT)&rect); SetWindowLongA(globs::mainGlobs.hWnd,-0x10,globs::mainGlobs.style); // HWND_TOP (0x0) and SWP_NOZORDER (0x4) // Then hide system cursor since game draws its own SetWindowPos(globs::mainGlobs.hWnd,NULL,rect.left,rect.top,rect.right - rect.left, rect.bottom - rect.top,SWP_NOZORDER); ShowCursor(FALSE); } else { hWnd = GetDesktopWindow(); GetWindowRect(hWnd,(LPRECT)&rect); // HWND_TOP (0x0) and SWP_NOZORDER (0x4) // Then hide system cursor since game draws its own SetWindowPos(globs::mainGlobs.hWnd,NULL,rect.left,rect.top,rect.right - rect.left, rect.bottom - rect.top,SWP_NOZORDER); SetCursor(NULL); } ShowWindow(globs::mainGlobs.hWnd,SW_SHOW); SetActiveWindow(globs::mainGlobs.hWnd); return; } BOOL __cdecl lego::main::Main_SetupDirect3D (Graphics_Device *dev,IDirectDraw *ddraw1,IDirectDrawSurface4 *backSurf, BOOL doubleBuffered) { HRESULT HVar1; Graphics_Device *err; Graphics_Device *pGVar2; code ***ppvObj; Graphics_Device **ppGVar3; IUnknown *local_8; code **local_4; pGVar2 = NULL; if ((dev != NULL) && (pGVar2 = dev, (dev->flags & GRAPHICS_DEVICE_FLAG_VIDEOTEXTURE) != GRAPHICS_DEVICE_FLAG_NONE)) { globs::mainGlobs.flags |= MAIN_FLAG_VIDEOTEXTURE; } // Direct3DRMFrame3::SetSceneFogMethod // D3DRMFOGMETHOD_VERTEX = 0x1 // D3DRMFOGMETHOD_TABLE = 0x2 // D3DRMFOGMETHOD_ANY = 0x4 if (((globs::mainGlobs.flags & MAIN_FLAG_FORCEVERTEXFOG) != MAIN_FLAG_NONE) || (globs::mainGlobs.fogMethod = D3DRMFOGMETHOD_TABLE, (dev->flags & GRAPHICS_DEVICE_FLAG_HARDWARE) == GRAPHICS_DEVICE_FLAG_NONE)) { globs::mainGlobs.fogMethod = D3DRMFOGMETHOD_VERTEX; } HVar1 = Direct3DRMCreate(&local_8); err = dev; if ((HVar1 == 0) && (HVar1 = (*local_8->lpVtbl->QueryInterface) (local_8,(IID *)&idl::IID_IDirect3DRM3,(void **)0x506914), err = dev, HVar1 == 0)) { ppvObj = &local_4; (*backSurf->lpVtbl->QueryInterface) ((IUnknown *)backSurf,(IID *)&idl::IID_IDirectDrawSurface,ppvObj); err = (Graphics_Device *) (*(code *)(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateDeviceFromSurface) (globs::mainGlobs.lpD3DRM,pGVar2,local_4,ppvObj,0,0x506918); if (err == NULL) { ppGVar3 = &dev; (*(code *)(globs::mainGlobs.device)->lpVtbl->GetDirect3DDevice2)(globs::mainGlobs.device); (**(code **)*local_4)(local_4,&idl::IID_IDirect3DDevice3,0x50691c); (**(code **)((*ppGVar3)->guid).Data4)(ppGVar3); if (local_8 != NULL) { (*(code *)(globs::mainGlobs.device)->lpVtbl->SetBufferCount)(globs::mainGlobs.device,2); } return TRUE; } debug::Error_SetDXError ((HRESULT)err,3,"C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Main.c",568); } if (err != NULL) { debug::Error_SetDXError ((HRESULT)err,1,"C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Main.c",576); } return 0; } void __cdecl lego::main::Main_AdjustWindowRect(LPRECT lpRect) { // Adjust rectangle to client coordinates only in windowed mode if (((byte)globs::mainGlobs.flags & MAIN_FLAG_FULLSCREEN) == 0) { AdjustWindowRect(lpRect,globs::mainGlobs.style,0); } return; } void __cdecl lego::main::Main_Setup3D (Graphics_Quality renderQuality,BOOL dither,BOOL linearFilter,BOOL mipMap, BOOL mipMapLinear,BOOL blendTransparency,BOOL sortTransparency) { char cVar1; DWORD quality; // D3DRMRENDER_WIREFRAME 0x40 (D3DRMSHADE_FLAT|D3DRMLIGHT_OFF|D3DRMFILL_WIREFRAME) quality = 0x40; if (renderQuality == Flat) { // D3DRMRENDER_FLAT 0x88 (D3DRMSHADE_FLAT|D3DRMLIGHT_ON|D3DRMFILL_SOLID) quality = 0x88; } if (renderQuality == UnlitFlat) { // D3DRMRENDER_UNLITFLAT 0x80 (D3DRMSHADE_FLAT|D3DRMLIGHT_OFF|D3DRMFILL_SOLID) quality = 0x80; } if (renderQuality == Gouraud) { // D3DRMRENDER_GOURAUD 0x89 (D3DRMSHADE_GOURAUD|D3DRMLIGHT_ON|D3DRMFILL_SOLID) quality = 0x89; } if (linearFilter == 0) { // D3DRMTEXTURE_NEAREST 0 cVar1 = '\0'; } else { if (mipMap == 0) { // D3DRMTEXTURE_LINEAR 1 cVar1 = '\x01'; } else { // D3DRMTEXTURE_MIPLINEAR 3 (!linearmipmap), D3DRMTEXTURE_LINEARMIPLINEAR 5 cVar1 = (-(mipMapLinear != 0) & 2U) + 3; globs::mainGlobs.flags |= MAIN_FLAG_MIPMAPENABLED; } } if (globs::mainGlobs.device != NULL) { // IDirect3DRMDevice3::SetDither(THIS_ BOOL) (*(globs::mainGlobs.device)->lpVtbl->SetDither)(globs::mainGlobs.device,dither); // IDirect3DRMDevice3::SetQuality(THIS_ D3DRMRENDERQUALITY) (*(globs::mainGlobs.device)->lpVtbl->SetQuality)(globs::mainGlobs.device,quality); // IDirect3DRMDevice3::SetTextureQuality(THIS_ D3DRMTEXTUREQUALITY) (*(globs::mainGlobs.device)->lpVtbl->SetTextureQuality)(globs::mainGlobs.device,(DWORD)cVar1); } return; } void __cdecl lego::main::Main_SetTitle(char *title) { SetWindowTextA(globs::mainGlobs.hWnd,title); return; } BOOL __cdecl lego::main::Main_InitApp(HINSTANCE hInstance) { ATOM AVar1; WNDCLASSA wndClass; wndClass.style = CS_DBLCLKS; wndClass.lpfnWndProc = Main_WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = NULL; wndClass.hCursor = NULL; wndClass.hbrBackground = NULL; wndClass.lpszMenuName = NULL; wndClass.lpszClassName = globs::mainGlobs.className; AVar1 = RegisterClassA(&wndClass); if (AVar1 == 0) { MessageBoxA(NULL,"Unable to register window class","Fatal Error",0); return 0; } // WS_POPUP | WS_SYSMENU globs::mainGlobs.hWnd = CreateWindowExA(WS_EX_APPWINDOW,globs::mainGlobs.className,____EMPTYSTR__,0x80080000,0,0,100, 100,NULL,NULL,hInstance,NULL); if (globs::mainGlobs.hWnd != NULL) { SetFocus(globs::mainGlobs.hWnd); return TRUE; } MessageBoxA(NULL,"Unable to Create Main Window","Fatal Error",0); return 0; } LRESULT __cdecl lego::main::Main_WndProc_Fullscreen(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { LRESULT LVar1; if (message < 0x11) { if (message != 0x10) { if (true) { switch(message) { default: break; case 2: goto switchD_00478794_caseD_2; case 3: case 5: case 6: goto switchD_00478830_caseD_200; } } goto switchD_00478830_caseD_207; } } else { if (WM_ACTIVATEAPP < message) { if (message < WM_NCACTIVATE + 1) { if (message == WM_NCACTIVATE) { switchD_00478830_caseD_200: return 0; } if (message == WM_WINDOWPOSCHANGING) { *(uint *)(lParam + 0x18) = *(uint *)(lParam + 0x18) & 0xfffffdff; return 0; } } else { if (message < WM_SYSKEYDOWN + 1) { if (message == WM_SYSKEYDOWN) { return 0; } if ((0xff < message) && (message < 0x102)) { return 0; } } else { if (true) { switch(message) { case 0x200: case 0x211: case 0x212: goto switchD_00478830_caseD_200; case 0x201: case 0x202: case 0x204: case 0x205: if ((globs::mainGlobs.flags & MAIN_FLAG_DUALMOUSE) == MAIN_FLAG_NONE) { if (true) { switch(message) { case 0x201: case 0x204: if (globs::INPUT.mslb == 0) { globs::INPUT.lClicked = 1; globs::INPUT.rClicked = 1; } globs::INPUT.mslb = 1; globs::INPUT.msrb = 1; globs::INPUT.lDoubleClicked = 1; return 0; case 0x202: case 0x205: globs::INPUT.lClicked = 0; globs::INPUT.rClicked = 0; globs::INPUT.msrb = 0; globs::INPUT.mslb = 0; } } } else { if (true) { switch(message) { case 0x201: globs::INPUT.mslb = 1; globs::INPUT.lClicked = 1; return 0; case 0x202: globs::INPUT.mslb = 0; globs::INPUT.lClicked = 0; return 0; case 0x204: globs::INPUT.msrb = 1; globs::INPUT.rClicked = 1; return 0; case 0x205: globs::INPUT.msrb = 0; globs::INPUT.rClicked = 0; return 0; } } } case 0x203: globs::INPUT.lDoubleClicked = 1; return 0; case 0x206: globs::INPUT.rDoubleClicked = 1; return 0; } } } } goto switchD_00478830_caseD_207; } if (message == WM_ACTIVATEAPP) { // True if this window is being activated globs::mainGlobs.active = wParam; return 0; } if (message != WM_QUIT) goto switchD_00478830_caseD_207; } switchD_00478794_caseD_2: globs::mainGlobs.exit = 1; switchD_00478830_caseD_207: LVar1 = DefWindowProcA(hWnd,message,wParam,lParam); return LVar1; } LRESULT __cdecl lego::main::Main_WndProc_Windowed(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { int iVar1; LRESULT LVar2; UINT UVar3; if (message < WM_ACTIVATE + 1) { UVar3 = message; if (message == WM_ACTIVATE) { return 0; } } else { if (WM_ACTIVATEAPP < message) { // Handle mouse button input (0x201 is WM_LBUTTONDOWN) iVar1 = message - 0x201; switch(iVar1) { case 0: case 1: case 3: case 4: // WM_LBUTTONDOWN (0x201) or WM_LBUTTONUP (0x202) or WM_RBUTTONDOWN (0x204) or // WM_RBUTTONUP (0x205) if ((globs::mainGlobs.flags & MAIN_FLAG_DUALMOUSE) == MAIN_FLAG_NONE) { if (true) { switch(iVar1) { case 0: case 3: // WM_LBUTTONDOWN (0x201) or WM_RBUTTONDOWN (0x204) SetCapture(hWnd); if (globs::INPUT.mslb == 0) { globs::INPUT.lClicked = 1; globs::INPUT.rClicked = 1; } globs::INPUT.mslb = 1; globs::INPUT.msrb = 1; globs::INPUT.lDoubleClicked = 1; return 0; case 1: case 4: // WM_LBUTTONUP (0x202) or WM_RBUTTONUP (0x205) ReleaseCapture(); globs::INPUT.lClicked = 0; globs::INPUT.rClicked = 0; globs::INPUT.msrb = 0; globs::INPUT.mslb = 0; } } } else { if (true) { switch(iVar1) { case 0: // WM_LBUTTONDOWN (0x201) SetCapture(hWnd); globs::INPUT.mslb = 1; globs::INPUT.lClicked = 1; globs::INPUT.lDoubleClicked = 1; return 0; case 1: // WM_LBUTTONUP (0x202) ReleaseCapture(); globs::INPUT.mslb = 0; globs::INPUT.lClicked = 0; globs::INPUT.lDoubleClicked = 1; return 0; case 3: globs::INPUT.msrb = 1; globs::INPUT.rClicked = 1; globs::INPUT.lDoubleClicked = 1; return 0; case 4: // WM_RBUTTONUP (0x205) globs::INPUT.msrb = 0; globs::INPUT.rClicked = 0; globs::INPUT.lDoubleClicked = 1; return 0; } } } case 2: // WM_LBUTTONDBLCLK (0x203) globs::INPUT.lDoubleClicked = 1; // WM_RBUTTONDBLCLK (0x206) return 0; case 5: globs::INPUT.rDoubleClicked = 1; return 0; } goto switchD_004789e8_caseD_6; } if (message == WM_ACTIVATEAPP) { // True if this window is being activated globs::mainGlobs.active = wParam; return 0; } // WM_CLOSE (0x10) -0x10, is closing UVar3 = message - 0x10; if (message - 0x10 == 0) { globs::mainGlobs.exit = 1; return 0; } } // WM_QUIT (0x12) if (UVar3 == WM_DESTROY) { globs::mainGlobs.exit = 1; return 0; } switchD_004789e8_caseD_6: LVar2 = DefWindowProcA(hWnd,message,wParam,lParam); return LVar2; } LRESULT lego::main::Main_WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { LRESULT LVar1; if (((byte)globs::mainGlobs.flags & MAIN_FLAG_FULLSCREEN) != 0) { LVar1 = Main_WndProc_Fullscreen(hWnd,message,wParam,lParam); return LVar1; } LVar1 = Main_WndProc_Windowed(hWnd,message,wParam,lParam); return LVar1; } void __cdecl lego::main::Main_ChangeRenderState (D3DRenderStateType dwRenderStateType,D3DRenderStateType dwRenderState) { D3DRenderStateType DVar1; DVar1 = dwRenderStateType; // IDirect3DDevice3->GetRenderState(this, D3DRenderStateType dwRenderStateType, DWORD* // lpdwRenderState) (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetRenderState) (globs::mainGlobs.imDevice,dwRenderStateType,&dwRenderStateType); if (dwRenderStateType != dwRenderState) { // IDirect3DDevice3->SetRenderState(this, D3DRenderStateType dwRenderStateType, DWORD // dwRenderState) (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetRenderState) (globs::mainGlobs.imDevice,DVar1,dwRenderState); if (globs::mainGlobs.renderStateData[DVar1].changed == 0) { globs::mainGlobs.renderStateData[DVar1].changed = 1; globs::mainGlobs.renderStateData[DVar1].origValue = dwRenderStateType; } else { if (globs::mainGlobs.renderStateData[DVar1].origValue == dwRenderStateType) { globs::mainGlobs.renderStateData[DVar1].changed = 0; return; } } } return; } void __cdecl lego::main::Main_RestoreStates(void) { MainFlags *pMVar1; D3DRenderStateType DVar2; DVar2 = 0; pMVar1 = (MainFlags *)&globs::mainGlobs.renderStateData[0].changed; do { if (*pMVar1 != MAIN_FLAG_NONE) { // IDirect3DDevice3->SetRenderState(this, D3DRenderStateType dwRenderStateType, DWORD // dwRenderState) (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetRenderState) (globs::mainGlobs.imDevice,DVar2,pMVar1[-1]); *pMVar1 = MAIN_FLAG_NONE; } pMVar1 = pMVar1 + 2; DVar2 += D3DRENDERSTATE_TEXTUREHANDLE; } while (pMVar1 < &globs::mainGlobs.flags); return; } BOOL __cdecl lego::main::Main_SetCDVolume(float leftVolume,float rightVolume) { BOOL BVar1; BVar1 = Main_CDVolume(&leftVolume,&rightVolume,1); return BVar1; } BOOL __cdecl lego::main::Main_GetCDVolume(float *out_leftVolume,float *out_rightVolume) { BOOL BVar1; BVar1 = Main_CDVolume(out_leftVolume,out_rightVolume,0); return BVar1; } BOOL __cdecl lego::main::Main_CDVolume(float *ref_leftVolume,float *ref_rightVolume,BOOL set) { UINT UVar1; MMRESULT MVar2; LPMIXERCONTROLA buffer; uint *buffer_00; uint uVar3; int iVar4; uint *puVar5; uint uVar6; uint uVar7; _union_1085 *p_Var8; UINT_PTR uMxId; tagMIXERCAPSA *ptVar9; tagMIXERLINEA *ptVar10; tagMIXERLINECONTROLSA *ptVar11; tMIXERCONTROLDETAILS *ptVar12; float10 extraout_ST0; longlong lVar13; HMIXEROBJ local_154; BOOL local_150; uint local_14c; uint local_148; uint local_144; uint local_140; UINT local_13c; uint local_138; LPMIXERCONTROLA local_134; uint local_130; undefined4 uStack300; int local_128; undefined4 local_124; tMIXERCONTROLDETAILS local_120; int local_108; undefined4 local_104; uint local_100; undefined4 uStack252; uint local_f8; undefined4 uStack244; tagMIXERLINECONTROLSA local_f0; tagMIXERLINEA local_d8; tagMIXERCAPSA local_30; UVar1 = mixerGetNumDevs(); local_150 = 0; if (set != 0) { if ((ushort)((ushort)(*ref_leftVolume < 1.0) << 8 | (ushort)(*ref_leftVolume == 1.0) << 0xe) == 0) { *ref_leftVolume = 1.0; } if (*ref_leftVolume < 0.0) { *ref_leftVolume = 0.0; } if ((ushort)((ushort)(*ref_rightVolume < 1.0) << 8 | (ushort)(*ref_rightVolume == 1.0) << 0xe) == 0) { *ref_rightVolume = 1.0; } if (*ref_rightVolume < 0.0) { *ref_rightVolume = 0.0; } } local_140 = 0; local_13c = UVar1; if (UVar1 != 0) { do { uMxId = local_140; MVar2 = mixerOpen((LPHMIXER)&local_154,local_140,0,0,0); if (MVar2 == 0) { ptVar9 = &local_30; for (iVar4 = 0xc; iVar4 != 0; iVar4 += -1) { *(undefined4 *)ptVar9 = 0; ptVar9 = (tagMIXERCAPSA *)&ptVar9->vDriverVersion; } mixerGetDevCapsA(uMxId,(LPMIXERCAPSA)&local_30,0x30); local_148 = 0; if (local_30.cDestinations != 0) { do { uVar3 = local_148; ptVar10 = &local_d8; for (iVar4 = 0x2a; iVar4 != 0; iVar4 += -1) { ptVar10->cbStruct = 0; ptVar10 = (tagMIXERLINEA *)&ptVar10->dwDestination; } local_d8.cbStruct = 0xa8; local_d8.dwDestination = local_148; MVar2 = mixerGetLineInfoA(local_154,(LPMIXERLINEA)&local_d8,0); if (MVar2 == 0) { local_138 = local_d8.cConnections; local_144 = 0; uMxId = local_140; if (local_d8.cConnections != 0) { do { uVar7 = local_144; local_d8.cbStruct = 0xa8; local_d8.dwDestination = uVar3; local_d8.dwSource = local_144; MVar2 = mixerGetLineInfoA(local_154,(LPMIXERLINEA)&local_d8,1); if ((MVar2 == 0) && (local_d8.dwComponentType == 0x1005)) { ptVar11 = &local_f0; for (iVar4 = 6; iVar4 != 0; iVar4 += -1) { ptVar11->cbStruct = 0; ptVar11 = (tagMIXERLINECONTROLSA *)&ptVar11->dwLineID; } local_f0.cbStruct = 0x18; local_f0.dwLineID = local_d8.dwLineID; local_f0.cControls = local_d8.cControls; local_f0.cbmxctrl = 0x94; buffer = (LPMIXERCONTROLA)io::Mem_Alloc(local_d8.cControls * 0x94); local_134 = buffer; local_f0.pamxctrl = buffer; MVar2 = mixerGetLineControlsA(local_154,(LPMIXERLINECONTROLSA)&local_f0,0); if ((MVar2 == 0) && (local_14c = 0, local_d8.cControls != 0)) { p_Var8 = &buffer->Bounds; do { if (((*(uint *)&p_Var8[-4].field_0x4 & 0x50000000) != 0) && ((*(uint *)&p_Var8[-4].field_0x4 & 0x50030001) != 0)) { local_120.dwControlID = *(DWORD *)(p_Var8 + -4); ptVar12 = &local_120; for (iVar4 = 6; iVar4 != 0; iVar4 += -1) { ptVar12->cbStruct = 0; ptVar12 = (tMIXERCONTROLDETAILS *)&ptVar12->dwControlID; } local_120.cbStruct = 0x18; local_120.cChannels = local_d8.cChannels; local_120.cbDetails = 4; local_120.u = 0; buffer_00 = (uint *)io::Mem_Alloc(local_d8.cChannels << 2); local_120.paDetails = buffer_00; if (set == 0) { MVar2 = mixerGetControlDetailsA (local_154,(LPMIXERCONTROLDETAILS)&local_120,0); if (MVar2 == 0) { local_100 = *buffer_00 - *(int *)p_Var8; uStack252 = 0; local_108 = *(int *)&p_Var8->field_0x4 - *(int *)p_Var8; local_104 = 0; *ref_leftVolume = (float)(ulonglong)local_100 / (float)local_108; if (local_d8.cChannels == 2) { local_130 = buffer_00[1] - *(int *)p_Var8; uStack300 = 0; local_128 = *(int *)&p_Var8->field_0x4 - *(int *)p_Var8; local_124 = 0; local_150 = 1; *ref_rightVolume = (float)(ulonglong)local_130 / (float)local_128; } else { local_150 = 1; *ref_rightVolume = (float)(ulonglong)local_100 / (float)local_108; } } } else { iVar4 = *(int *)p_Var8; local_f8 = *(int *)&p_Var8->field_0x4 - iVar4; uStack244 = 0; lVar13 = __ftol((float10)*ref_leftVolume * (float10)(ulonglong)local_f8) ; uVar7 = (int)lVar13 + iVar4; lVar13 = __ftol((float10)*ref_rightVolume * extraout_ST0); uVar3 = (int)lVar13 + iVar4; if (local_d8.cChannels == 2) { *buffer_00 = uVar7; buffer_00[1] = uVar3; } else { uVar6 = 0; if (local_d8.cChannels != 0) { puVar5 = buffer_00; do { *puVar5 = uVar3 + uVar7 >> 1; uVar6 += 1; puVar5 = puVar5 + 1; } while (uVar6 < local_d8.cChannels); } } MVar2 = mixerSetControlDetails (local_154,(LPMIXERCONTROLDETAILS)&local_120,0); if (MVar2 == 0) { local_150 = 1; } } io::Mem_Free(buffer_00); buffer = local_134; } local_14c += 1; p_Var8 = (_union_1085 *)&p_Var8[6].field_0x4; uVar3 = local_148; uVar7 = local_144; } while (local_14c < local_d8.cControls); } io::Mem_Free(buffer); } local_144 = uVar7 + 1; uMxId = local_140; } while (local_144 < local_138); } } local_148 = uVar3 + 1; } while (local_148 < local_30.cDestinations); } mixerClose((HMIXER)local_154); UVar1 = local_13c; } local_140 = uMxId + 1; } while (local_140 < UVar1); } return local_150; } void __cdecl lego::cfg::Config_Initialise(void) { int iVar1; Config **ppCVar2; ppCVar2 = globs::configGlobs.listSet; for (iVar1 = 0x20; iVar1 != 0; iVar1 += -1) { *ppCVar2 = NULL; ppCVar2 = ppCVar2 + 1; } globs::configGlobs.freeList = NULL; globs::configGlobs.listCount = 0; globs::configGlobs.flags = CONFIG_GLOB_FLAG_INITIALISED; return; } void __cdecl lego::cfg::Config_Shutdown(void) { Config **ppCVar1; ppCVar1 = globs::configGlobs.listSet; do { if (*ppCVar1 != NULL) { io::Mem_Free(*ppCVar1); } ppCVar1 = ppCVar1 + 1; } while (ppCVar1 < &globs::configGlobs.freeList); globs::configGlobs.freeList = NULL; globs::configGlobs.flags = CONFIG_GLOB_FLAG_NONE; return; } Config * __cdecl lego::cfg::Config_Load(char *filename) { char cVar1; Config *current; uint uVar2; char *pcVar3; Config *root; char *text; char *pcVar4; char *pcVar5; bool isComment; char c; root = NULL; isComment = false; text = (char *)io::File_LoadBinary(filename,(uint *)&filename); if ((byte *)text != NULL) { root = Config_Create(NULL); pcVar4 = NULL; root->fileData = text; if (filename != NULL) { do { c = *text; if (c == ';') { isComment = true; } else { if (c == '\n') { isComment = false; } } if ((((isComment) || (c == '\t')) || (c == '\n')) || ((c == '\r' || (c == ' ')))) { *text = 0; } text = (char *)((byte *)text + 1); pcVar4 = pcVar4 + 1; } while (pcVar4 < filename); } pcVar4 = root->fileData; pcVar5 = NULL; current = root; pcVar3 = filename; if (filename != NULL) { do { if (*pcVar4 == '\0') { pcVar4 = pcVar4 + 1; } else { if ((*pcVar4 == '}') && (pcVar4[1] == '\0')) { uVar2 = current->depth - 1; LAB_004791e1: current->depth = uVar2; } else { if (current->key == NULL) { current->key = pcVar4; } else { current->value = pcVar4; current = Config_Create(current); if ((*pcVar4 == '{') && (pcVar4[1] == '\0')) { uVar2 = current->depth + 1; goto LAB_004791e1; } } } while ((pcVar3 = filename, pcVar5 < filename && (cVar1 = *pcVar4, pcVar4 = pcVar4 + 1, cVar1 != '\0'))) { pcVar5 = pcVar5 + 1; } } pcVar5 = pcVar5 + 1; } while (pcVar5 < pcVar3); } } return root; } // Variadic function to join a path used for all CFGProperty lookup functions // NULL must be specified as the final argument, to signal the end of path arguments. // The returned buffer is TEMPORARY, and must be used immediately before the next // call to this function. char * __cdecl lego::cfg::Config_BuildStringID(char *keyPath1,...) { char cVar1; uint uVar2; uint uVar3; int iVar4; char **ppcVar5; undefined4 *puVar6; char *pcVar7; char *pcVar8; Config_Globs *pCVar9; Config_Globs *pCVar10; undefined4 *puVar11; char *in_stack_00000008; uVar2 = 0xffffffff; do { pcVar8 = keyPath1; if (uVar2 == 0) break; uVar2 -= 1; pcVar8 = keyPath1 + 1; cVar1 = *keyPath1; keyPath1 = pcVar8; } while (cVar1 != '\0'); uVar2 = ~uVar2; ppcVar5 = (char **)&stack0x0000000c; puVar6 = (undefined4 *)(pcVar8 + -uVar2); pCVar9 = &globs::configGlobs; for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *(undefined4 *)pCVar9->s_JoinPath_string = *puVar6; puVar6 = puVar6 + 1; pCVar9 = (Config_Globs *)(pCVar9->s_JoinPath_string + 4); } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { pCVar9->s_JoinPath_string[0] = *(char *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); pCVar9 = (Config_Globs *)(pCVar9->s_JoinPath_string + 1); } if (in_stack_00000008 != NULL) { do { uVar2 = 0xffffffff; pcVar8 = "::"; do { pcVar7 = pcVar8; if (uVar2 == 0) break; uVar2 -= 1; pcVar7 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar7; } while (cVar1 != '\0'); uVar2 = ~uVar2; iVar4 = -1; pCVar9 = &globs::configGlobs; do { pCVar10 = pCVar9; if (iVar4 == 0) break; iVar4 += -1; pCVar10 = (Config_Globs *)(pCVar9->s_JoinPath_string + 1); pcVar8 = pCVar9->s_JoinPath_string; pCVar9 = pCVar10; } while (*pcVar8 != '\0'); puVar6 = (undefined4 *)(pcVar7 + -uVar2); puVar11 = (undefined4 *)((int)&pCVar10[-1].flags + 3); for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar11 = *puVar6; puVar6 = puVar6 + 1; puVar11 = puVar11 + 1; } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } uVar2 = 0xffffffff; do { pcVar8 = in_stack_00000008; if (uVar2 == 0) break; uVar2 -= 1; pcVar8 = in_stack_00000008 + 1; cVar1 = *in_stack_00000008; in_stack_00000008 = pcVar8; } while (cVar1 != '\0'); uVar2 = ~uVar2; iVar4 = -1; pCVar9 = &globs::configGlobs; do { pCVar10 = pCVar9; if (iVar4 == 0) break; iVar4 += -1; pCVar10 = (Config_Globs *)(pCVar9->s_JoinPath_string + 1); pcVar7 = pCVar9->s_JoinPath_string; pCVar9 = pCVar10; } while (*pcVar7 != '\0'); puVar6 = (undefined4 *)(pcVar8 + -uVar2); puVar11 = (undefined4 *)((int)&pCVar10[-1].flags + 3); for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar11 = *puVar6; puVar6 = puVar6 + 1; puVar11 = puVar11 + 1; } in_stack_00000008 = *ppcVar5; for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } ppcVar5 = ppcVar5 + 1; } while (in_stack_00000008 != NULL); } return globs::configGlobs.s_JoinPath_string; } Config * __cdecl lego::cfg::Config_FindArray(Config *prop,char *keyPath) { Config *getProp; getProp = Config_FindItem(prop,keyPath); if ((getProp != NULL) && (getProp->depth < getProp->linkNext->depth)) { return getProp->linkNext; } return NULL; } // Returns the next CFGProperty in the same block, and at the same depth // Returns NULL if there are no more properties, or if prop is NULL Config * __cdecl lego::cfg::Config_GetNextItem(Config *prop) { uint nextDepth; uint currentDepth; currentDepth = prop->depth; nextDepth = currentDepth; if (prop != NULL) { do { if (nextDepth < currentDepth) { return NULL; } prop = prop->linkNext; if (prop->depth == currentDepth) { return prop; } nextDepth = prop->depth; } while (prop != NULL); } return NULL; } char * __cdecl lego::cfg::Config_GetStringValue(Config *prop,char *keyPath) { char cVar1; Config *pCVar2; undefined4 *puVar3; uint uVar4; uint uVar5; undefined4 *puVar6; char *pcVar7; char *pcVar8; undefined4 *puVar9; pCVar2 = Config_FindItem(prop,keyPath); if ((pCVar2 == NULL) || (pCVar2->value == NULL)) { return (char *)NULL; } uVar4 = 0xffffffff; pcVar7 = pCVar2->value; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar7; pcVar7 = pcVar7 + 1; } while (cVar1 != '\0'); puVar3 = (undefined4 *)io::Mem_Alloc(~uVar4); uVar4 = 0xffffffff; pcVar7 = pCVar2->value; do { pcVar8 = pcVar7; if (uVar4 == 0) break; uVar4 -= 1; pcVar8 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar8; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar6 = (undefined4 *)(pcVar8 + -uVar4); puVar9 = puVar3; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar9 = *puVar6; puVar6 = puVar6 + 1; puVar9 = puVar9 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } return (char *)puVar3; } char * __cdecl lego::cfg::Config_GetTempStringValue(Config *prop,char *keyPath) { Config *getProp; getProp = Config_FindItem(prop,keyPath); if (getProp != NULL) { return getProp->value; } return NULL; } BoolTri __cdecl lego::cfg::Config_GetBoolValue(Config *prop,char *keyPath) { char *str; BoolTri BVar1; BVar1 = BOOL3_ERROR; str = Config_GetStringValue(prop,keyPath); if (str != NULL) { BVar1 = util::Util_GetBoolFromString(str); io::Mem_Free(str); } return BVar1; } // Reads a CFG float property specified in degrees, and returns the value in radians float10 __cdecl lego::cfg::Config_GetAngle(Config *prop,char *keyPath) { char *pcVar1; float10 fVar2; pcVar1 = Config_GetTempStringValue(prop,keyPath); if (pcVar1 == NULL) { pcVar1 = ____EMPTYSTR__; } else { pcVar1 = Config_GetTempStringValue(prop,keyPath); } fVar2 = std::atof(pcVar1); if (fVar2 != (float10)0.0) { // value / 360.0 * (M_PI * 2.0) return fVar2 * (float10)0.002777778 * (float10)6.283185; } return (float10)0.0; } BOOL __cdecl lego::cfg::Config_GetRGBValue(Config *prop,char *keyPath,float *out_r,float *out_g,float *out_b) { char *input; int numParts; int channel; uint result; char *parts_0; char *parts_1; char *parts_2; result = 0; input = Config_GetStringValue(prop,keyPath); if (input != NULL) { numParts = util::Util_Tokenise(input,&parts_0,":"); if (numParts == 3) { channel = std::atoi(parts_0); // channel / 255.0 *out_r = (float)channel * 0.003921569; channel = std::atoi(parts_1); *out_g = (float)channel * 0.003921569; channel = std::atoi(parts_2); *out_b = (float)channel * 0.003921569; } result = (uint)(numParts == 3); io::Mem_Free(input); } return result; } void __cdecl lego::cfg::Config_Free(Config *root) { Config *prop; io::Mem_Free(root->fileData); if (root != NULL) { do { prop = root->linkNext; Config_Remove(root); root = prop; } while (prop != NULL); } return; } Config * __cdecl lego::cfg::Config_Create(Config *prev) { uint uVar1; Config *pCVar2; Config *pCVar3; Config *next; if (globs::configGlobs.freeList == NULL) { Config_AddList(); } pCVar2 = globs::configGlobs.freeList; next = globs::configGlobs.freeList; pCVar3 = (globs::configGlobs.freeList)->nextFree; (globs::configGlobs.freeList)->nextFree = globs::configGlobs.freeList; globs::configGlobs.freeList = pCVar3; pCVar2->key = NULL; pCVar2->value = NULL; pCVar2->linkNext = NULL; if (prev != NULL) { prev->linkNext = pCVar2; pCVar2->linkPrev = prev; uVar1 = prev->depth; pCVar2->fileData = NULL; pCVar2->depth = uVar1; return next; } pCVar2->depth = 0; pCVar2->linkPrev = NULL; return next; } void __cdecl lego::cfg::Config_Remove(Config *prop) { prop->nextFree = globs::configGlobs.freeList; globs::configGlobs.freeList = prop; return; } Config * __cdecl lego::cfg::Config_FindItem(Config *prop,char *keyPath) { char *pcVar1; int numParts; int tmpCmp; uint uVar2; char *pcVar3; uint uVar4; undefined4 *puVar5; size_t sVar6; char *pcVar7; undefined4 *puVar8; bool isWildcard; Config *result; char *input_parts [101]; char c; uint depth; Config *previous; depth = 0xffffffff; pcVar7 = keyPath; do { if (depth == 0) break; depth -= 1; c = *pcVar7; pcVar7 = pcVar7 + 1; } while (c != '\0'); result = NULL; input_parts[0] = (char *)io::Mem_Alloc(~depth); depth = 0xffffffff; do { pcVar7 = keyPath; if (depth == 0) break; depth -= 1; pcVar7 = keyPath + 1; c = *keyPath; keyPath = pcVar7; } while (c != '\0'); depth = ~depth; puVar5 = (undefined4 *)(pcVar7 + -depth); puVar8 = (undefined4 *)input_parts[0]; for (uVar2 = depth >> 2; uVar2 != 0; uVar2 -= 1) { *puVar8 = *puVar5; puVar5 = puVar5 + 1; puVar8 = puVar8 + 1; } for (depth &= 3; depth != 0; depth -= 1) { *(undefined *)puVar8 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } numParts = util::Util_Tokenise(input_parts[0],input_parts + 1,"::"); if (prop != NULL) { do { if (prop->depth == numParts - 1U) { // CFG_IsKeyMatch isWildcard = false; if (numParts == 1) { pcVar7 = prop->key; sVar6 = 0; c = *pcVar7; pcVar3 = pcVar7; while ((c != '\0' && (c != '*'))) { pcVar1 = pcVar3 + 1; sVar6 += 1; pcVar3 = pcVar3 + 1; c = *pcVar1; } if (*pcVar3 == '*') { tmpCmp = std::_strnicmp(input_parts[1],pcVar7,sVar6); isWildcard = tmpCmp == 0; } } if ((isWildcard) || (tmpCmp = std::_stricmp(input_parts[numParts],prop->key), tmpCmp == 0)) { isWildcard = false; depth = numParts - 1U; for (previous = prop; previous != NULL; previous = previous->linkPrev) { // CFG_IsKeyMatch uVar2 = depth - 1; uVar4 = depth; if (previous->depth == uVar2) { if (depth == 1) { pcVar7 = previous->key; sVar6 = 0; c = *pcVar7; pcVar3 = pcVar7; while ((c != '\0' && (c != '*'))) { pcVar1 = pcVar3 + 1; sVar6 += 1; pcVar3 = pcVar3 + 1; c = *pcVar1; } if (*pcVar3 == '*') { tmpCmp = std::_strnicmp(input_parts[1],pcVar7,sVar6); isWildcard = tmpCmp == 0; } } uVar4 = uVar2; if ((!isWildcard) && (tmpCmp = std::_stricmp(input_parts[depth],previous->key), tmpCmp != 0)) break; } depth = uVar4; } if ((depth == 0) && (result = prop, !isWildcard)) break; } } prop = prop->linkNext; } while (prop != NULL); } io::Mem_Free(input_parts[0]); return result; } void __cdecl lego::cfg::Config_AddList(void) { Config *pCVar1; Config *pCVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::configGlobs.listCount & 0x1f); pCVar2 = (Config *)io::Mem_Alloc(uVar4 * 0x20); globs::configGlobs.listSet[globs::configGlobs.listCount] = pCVar2; pCVar2 = globs::configGlobs.listSet[globs::configGlobs.listCount]; if (pCVar2 != NULL) { globs::configGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pCVar1 = pCVar2; do { pCVar1->nextFree = pCVar1 + 1; iVar3 += -1; pCVar1 = pCVar1 + 1; } while (iVar3 != 0); } pCVar2[uVar4 - 1].nextFree = globs::configGlobs.freeList; globs::configGlobs.freeList = pCVar2; } return; } // out_vector = norm({ rand(), rand(), rand() }) Vector3F * __cdecl lego::math::Maths_Vector3DRandom(Vector3F *out_vector) { Vector3F *pVVar1; pVVar1 = D3DRMVectorRandom(out_vector); return pVVar1; } // out_vector = ::D3DRMVectorRotate(out_vector, v, axis, theta) // // SIDE EFFECTS: This function normalizes the input axis vector. Vector3F * __cdecl lego::math::Maths_Vector3DRotate(Vector3F *out_vector,Vector3F *v,Vector3F *axis,float theta) { Vector3F *pVVar1; pVVar1 = D3DRMVectorRotate(out_vector,v,axis,theta); return pVVar1; } // out_vector = norm(cross_product((c - b), (b - a))) Vector3F * __cdecl lego::math::Maths_PlaneNormal(Vector3F *out_vector,Vector3F *p1,Vector3F *p2,Vector3F *p3) { float fVar1; float fVar2; float fVar3; float fVar4; float fVar5; float fVar6; float fVar7; fVar1 = p3->x - p2->x; fVar4 = p2->x - p1->x; fVar3 = p3->y - p2->y; fVar5 = p3->z - p2->z; fVar6 = p2->y - p1->y; fVar7 = p2->z - p1->z; fVar2 = fVar1 * fVar7 - fVar5 * fVar4; fVar4 = fVar3 * fVar4 - fVar1 * fVar6; fVar3 = fVar5 * fVar6 - fVar3 * fVar7; fVar1 = 1.0 / SQRT(fVar3 * fVar3 + fVar4 * fVar4 + fVar2 * fVar2); out_vector->x = fVar1 * fVar3; out_vector->y = fVar1 * fVar2; out_vector->z = fVar1 * fVar4; return out_vector; } float10 __cdecl lego::math::Maths_TriangleAreaZ(Vector3F *p1,Vector3F *p2,Vector3F *p3,BOOL bfc) { float fVar1; float fVar2; float fVar3; float fVar4; Vector3F *pVVar5; Vector3F *pVVar6; int iVar7; float *pfVar8; Vector3F *pVVar9; Vector3F **ppVVar10; uint uVar11; float10 fVar12; float local_8c; uint local_88; float local_7c; Vector3F local_78; Vector3F local_6c; Vector3F local_60; Vector3F *local_54 [5]; Vector3F *local_40; Vector3F local_3c; Vector3F local_30 [3]; local_54[0] = &local_78; local_54[1] = &local_6c; local_54[3] = &local_60; local_54[2] = &local_6c; local_54[4] = &local_60; local_78.x = p1->x; local_40 = &local_78; local_78.y = p1->y; local_6c.x = p2->x; local_6c.y = p2->y; local_60.x = p3->x; local_60.y = p3->y; local_7c = 0.0; local_8c = 0.0; local_78.z = 0.0; local_6c.z = 0.0; local_60.z = 0.0; if (bfc == 0) { local_3c.z = -1.0; } else { Maths_PlaneNormal(&local_3c,&local_78,&local_6c,&local_60); } if (local_3c.z < 0.0) { uVar11 = 0; pVVar9 = local_30; ppVVar10 = local_54 + 1; pfVar8 = &local_30[1].z; do { pVVar5 = *ppVVar10; pVVar6 = ppVVar10[-1]; fVar1 = pVVar5->y; fVar2 = pVVar5->z; fVar3 = pVVar6->y; fVar4 = pVVar6->z; pfVar8[-2] = pVVar5->x - pVVar6->x; pfVar8[-1] = fVar1 - fVar3; *pfVar8 = fVar2 - fVar4; fVar2 = SQRT(pfVar8[-2] * pfVar8[-2] + *pfVar8 * *pfVar8 + pfVar8[-1] * pfVar8[-1]); fVar3 = 1.0 / fVar2; fVar1 = pfVar8[-2]; pVVar9->x = fVar2; fVar2 = pVVar9->x; pfVar8[-2] = fVar3 * fVar1; pfVar8[-1] = fVar3 * pfVar8[-1]; *pfVar8 = fVar3 * *pfVar8; if ((ushort)((ushort)(fVar2 < local_8c) << 8 | (ushort)(fVar2 == local_8c) << 0xe) == 0) { local_8c = pVVar9->x; local_88 = uVar11; } uVar11 += 1; ppVVar10 = ppVVar10 + 2; pfVar8 = pfVar8 + 3; pVVar9 = (Vector3F *)&pVVar9->y; } while (uVar11 < 3); uVar11 = (local_88 + 1) % 3; local_30[local_88 + 1].x = local_30[local_88 + 1].x * -1.0; local_30[local_88 + 1].y = local_30[local_88 + 1].y * -1.0; local_30[local_88 + 1].z = local_30[local_88 + 1].z * -1.0; // Standard library math functions have some nasty ASM in them. // I believe the second function is testing against FPU control word results(?) fVar12 = std::acos((float10)local_30[uVar11 + 1].x * (float10)local_30[local_88 + 1].x + (float10)local_30[local_88 + 1].z * (float10)local_30[uVar11 + 1].z + (float10)local_30[local_88 + 1].y * (float10)local_30[uVar11 + 1].y); iVar7 = std::_finite((double)fVar12); if (iVar7 != 0) { fVar12 = (float10)fsin((float10)(float)fVar12); local_7c = (float)((float10)(&local_30[0].x)[local_88] * (float10)0.5 * fVar12 * (float10)(&local_30[0].x)[uVar11]); } } return (float10)local_7c; } short __cdecl lego::math::Maths_Rand(void) { std::globals::g_rand = std::globals::g_rand * 0x343fd + 0x269ec3; return (short)((ushort)(std::globals::g_rand >> 0x10) & 0x7fff); } float10 __cdecl lego::math::Maths_RandRange(float low,float high) { short sVar1; sVar1 = Maths_Rand(); return (float10)(int)sVar1 * (float10)3.051851e-05 * ((float10)high - (float10)low) + (float10)low ; } // out_vector = a + (norm(b) * (dot_product((c - a), norm(d)) / dot_product(norm(b), norm(d))) // CONDITION: dot_product(norm(b), norm(d)) != 0.0 BOOL __cdecl lego::math::Maths_RayPlaneIntersection (Vector3F *out_endPoint,Vector3F *rayOrigin,Vector3F *ray,Vector3F *planePoint, Vector3F *planeNormal) { float fVar1; float fVar2; float fVar3; float fVar4; float fVar5; float fVar6; float fVar7; BOOL BVar8; Vector3F norm_b; Vector3F norm_d; fVar1 = planeNormal->x; fVar2 = ray->x; fVar3 = planeNormal->y; fVar4 = ray->y; fVar5 = ray->z; fVar6 = planeNormal->z; fVar7 = 1.0 / SQRT(fVar5 * fVar5 + fVar4 * fVar4 + fVar2 * fVar2); ray = (Vector3F *)(1.0 / SQRT(fVar6 * fVar6 + fVar3 * fVar3 + fVar1 * fVar1)); norm_b.x = fVar7 * fVar2; norm_b.y = fVar7 * fVar4; norm_b.z = fVar7 * fVar5; norm_d.x = (float)ray * fVar1; norm_d.y = (float)ray * fVar3; norm_d.z = (float)ray * fVar6; BVar8 = Maths_RayPlaneDistance((float *)&ray,rayOrigin,&norm_b,planePoint,&norm_d); if (BVar8 != 0) { Maths_RayEndPoint(out_endPoint,rayOrigin,&norm_b,(float)ray); return TRUE; } return 0; } // out_value = dot_product((c - a), d) / dot_product(b, d) // CONDITION: dot_product(b, d) != 0.0 BOOL __cdecl lego::math::Maths_RayPlaneDistance (float *out_dist,Vector3F *rayOrigin,Vector3F *ray,Vector3F *planePoint, Vector3F *planeNormal) { float dot_product; // Vector3_DotProduct(b, d) dot_product = planeNormal->x * ray->x + ray->z * planeNormal->z + ray->y * planeNormal->y; if (dot_product != 0.0) { // Vector3_Multiply((Vector3_Subtract(c, a), d) *out_dist = ((planePoint->x - rayOrigin->x) * planeNormal->x + (planePoint->y - rayOrigin->y) * planeNormal->y + (planePoint->z - rayOrigin->z) * planeNormal->z) / dot_product; return TRUE; } return 0; } // out_vector = a + (b * scalar) Vector3F * __cdecl lego::math::Maths_RayEndPoint(Vector3F *out_endPoint,Vector3F *rayOrigin,Vector3F *ray,float dist) { float fVar1; float fVar2; fVar1 = ray->y; fVar2 = ray->z; out_endPoint->x = dist * ray->x + rayOrigin->x; out_endPoint->y = rayOrigin->y + fVar1 * dist; out_endPoint->z = rayOrigin->z + fVar2 * dist; return out_endPoint; } // out_point = a + (b * dot_product((a - c), (perpendicular(d) / dot_product(perpendicular(b), d)))) // CONDITION: dot_product(perpendicular(b), d) != 0.0 Point2F * __cdecl lego::math::Maths_Vector2DIntersection (Point2F *out_intersection,Point2F *start1,Point2F *vector1,Point2F *start2, Point2F *vector2) { float fVar1; fVar1 = -vector1->y * vector2->x - -vector1->x * vector2->y; if (fVar1 != 0.0) { fVar1 = (start1->x - start2->x) * -(vector2->y / fVar1) + (vector2->x / fVar1) * (start1->y - start2->y); out_intersection->x = fVar1 * vector1->x; out_intersection->y = fVar1 * vector1->y; out_intersection->x = start1->x + out_intersection->x; out_intersection->y = out_intersection->y + start1->y; return out_intersection; } return NULL; } BOOL __cdecl lego::math::Maths_PointInsidePoly(Point2F *point,Point2F *fromList,Point2F *toList,uint count) { float fVar1; float *pfVar2; uint uVar3; int iVar4; uVar3 = 0; if (count != 0) { pfVar2 = &fromList->y; iVar4 = (int)toList - (int)fromList; do { if (((((ushort)((ushort)(*pfVar2 < point->y) << 8 | (ushort)(*pfVar2 == point->y) << 0xe) != 0 ) && (point->y <= *(float *)(iVar4 + (int)pfVar2))) || ((point->y <= *pfVar2 && ((ushort)((ushort)(*(float *)(iVar4 + (int)pfVar2) < point->y) << 8 | (ushort)(*(float *)(iVar4 + (int)pfVar2) == point->y) << 0xe) != 0)))) && (fVar1 = (toList->x - pfVar2[-1]) * ((*(float *)(iVar4 + (int)pfVar2) - *pfVar2) / (point->y - *pfVar2)) + pfVar2[-1], (ushort)((ushort)(fVar1 < point->x) << 8 | (ushort)(fVar1 == point->x) << 0xe) == 0)) { uVar3 += 1; } toList = toList + 1; pfVar2 = pfVar2 + 2; count -= 1; } while (count != 0); } return uVar3 & 1; } BOOL __cdecl lego::math::Maths_RaySphereIntersection (Vector3F *center,float radius,Vector3F *camera,Vector3F *line) { float fVar1; float fVar2; float fVar3; float fVar4; fVar1 = camera->y - center->y; fVar4 = camera->z - center->z; fVar3 = camera->x - center->x; fVar2 = (line->z + line->z) * fVar4 + (line->y + line->y) * fVar1 + (line->x + line->x) * fVar3; fVar1 = fVar2 * fVar2 - ((fVar3 * fVar3 + fVar4 * fVar4 + fVar1 * fVar1) * 4.0 - radius * radius); if ((ushort)((ushort)(fVar1 < 0.0) << 8 | (ushort)(fVar1 == 0.0) << 0xe) == 0) { return TRUE; } return 0; } // out_matrix = { { // l[0,0]*r[0,0] + l[0,1]*r[1,0] + l[0,2]*r[2,0] + l[0,3]*r[3,0], // l[0,0]*r[0,1] + l[0,1]*r[1,1] + l[0,2]*r[2,1] + l[0,3]*r[3,1], // l[0,0]*r[0,2] + l[0,1]*r[1,2] + l[0,2]*r[2,2] + l[0,3]*r[3,2], // l[0,0]*r[0,3] + l[0,1]*r[1,3] + l[0,2]*r[2,3] + l[0,3]*r[3,3] // },{ // l[1,0]*r[0,0] + l[1,1]*r[1,0] + l[1,2]*r[2,0] + l[1,3]*r[3,0], // l[1,0]*r[0,1] + l[1,1]*r[1,1] + l[1,2]*r[2,1] + l[1,3]*r[3,1], // l[1,0]*r[0,2] + l[1,1]*r[1,2] + l[1,2]*r[2,2] + l[1,3]*r[3,2], // l[1,0]*r[0,3] + l[1,1]*r[1,3] + l[1,2]*r[2,3] + l[1,3]*r[3,3] // },{ // l[2,0]*r[0,0] + l[2,1]*r[1,0] + l[2,2]*r[2,0] + l[2,3]*r[3,0], // l[2,0]*r[0,1] + l[2,1]*r[1,1] + l[2,2]*r[2,1] + l[2,3]*r[3,1], // l[2,0]*r[0,2] + l[2,1]*r[1,2] + l[2,2]*r[2,2] + l[2,3]*r[3,2], // l[2,0]*r[0,3] + l[2,1]*r[1,3] + l[2,2]*r[2,3] + l[2,3]*r[3,3] // },{ // l[3,0]*r[0,0] + l[3,1]*r[1,0] + l[3,2]*r[2,0] + l[3,3]*r[3,0], // l[3,0]*r[0,1] + l[3,1]*r[1,1] + l[3,2]*r[2,1] + l[3,3]*r[3,1], // l[3,0]*r[0,2] + l[3,1]*r[1,2] + l[3,2]*r[2,2] + l[3,3]*r[3,2], // l[3,0]*r[0,3] + l[3,1]*r[1,3] + l[3,2]*r[2,3] + l[3,3]*r[3,3] // } } // NOTE: right and left operands are ordered in reverse in the parameter list. void __cdecl lego::math::Matrix_Mult(Matrix4F *out_matrix,Matrix4F *right,Matrix4F *left) { float (*pafVar1) [4]; float (*pafVar2) [4]; Matrix4F *pMVar3; Matrix4F *pMVar4; int iVar5; float *pfVar6; int iVar7; int iVar8; Matrix4F *pMVar9; Matrix_Zero(out_matrix); iVar5 = (int)out_matrix - (int)left; out_matrix = (Matrix4F *)&DAT_00000004; do { pfVar6 = (float *)(iVar5 + (int)left); iVar7 = 4; pMVar9 = right; do { iVar8 = 4; pMVar3 = pMVar9; pMVar4 = left; do { pafVar1 = pMVar4->values; pafVar2 = pMVar3->values; pMVar3 = (Matrix4F *)pMVar3->values[1]; pMVar4 = (Matrix4F *)(pMVar4->values + 1); iVar8 += -1; *pfVar6 = (*pafVar1)[0] * (*pafVar2)[0] + *pfVar6; } while (iVar8 != 0); pfVar6 = pfVar6 + 1; pMVar9 = (Matrix4F *)(pMVar9->values + 1); iVar7 += -1; } while (iVar7 != 0); left = (Matrix4F *)left->values[1]; out_matrix = (Matrix4F *)((int)out_matrix[-1].values[3] + 0xf); } while (out_matrix != NULL); return; } // out_matrix = { { 1, 0, 0, 0 }, // { 0, cos(t), -sin(t), 0 }, // { 0, sin(t), cos(t), 0 }, // { 0, 0, 0, 1 } } void __cdecl lego::math::Matrix_RotX(Matrix4F *out_matrix,float rot) { float10 cosine; float10 sine; cosine = (float10)fcos((float10)rot); sine = (float10)fsin((float10)rot); Matrix_Identity(out_matrix); out_matrix->values[1][2] = -(float)sine; out_matrix->values[1][1] = (float)cosine; out_matrix->values[2][2] = (float)cosine; out_matrix->values[2][1] = (float)sine; return; } // out_matrix = { { cos(t), 0, sin(t), 0 }, // { 0, 1, 0, 0 }, // { -sin(t), 0, cos(t), 0 }, // { 0, 0, 0, 1 } } void __cdecl lego::math::Matrix_RotY(Matrix4F *out_matrix,float rot) { float10 cosine; float10 sine; cosine = (float10)fcos((float10)rot); sine = (float10)fsin((float10)rot); Matrix_Identity(out_matrix); out_matrix->values[2][0] = -(float)sine; out_matrix->values[0] = (float)cosine; out_matrix->values[2][2] = (float)cosine; out_matrix->values[2] = (float)sine; return; } // out_matrix = { { cos(t), -sin(t), 0, 0 }, // { sin(t), cos(t), 0, 0 }, // { 0, 0, 1, 0 }, // { 0, 0, 0, 1 } } void __cdecl lego::math::Matrix_RotZ(Matrix4F *out_matrix,float rot) { float10 cosine; float10 sine; cosine = (float10)fcos((float10)rot); sine = (float10)fsin((float10)rot); Matrix_Identity(out_matrix); out_matrix->values[1] = -(float)sine; out_matrix->values[0] = (float)cosine; out_matrix->values[1][1] = (float)cosine; out_matrix->values[1][0] = (float)sine; return; } // out_matrix = { { 1, 0, 0, 0 }, // { 0, 1, 0, 0 }, // { 0, 0, 1, 0 }, // { x, y, z, 1 } } void __cdecl lego::math::Matrix_Translate(Matrix4F *out_matrix,Vector3F *trans) { Matrix_Identity(out_matrix); out_matrix->values[3][0] = trans->x; out_matrix->values[3][1] = trans->y; out_matrix->values[3][2] = trans->z; return; } // out_matrix = { { 1, 0, 0, 0 }, // { 0, 1, 0, 0 }, // { 0, 0, 1, 0 }, // { 0, 0, 0, 1 } } void __cdecl lego::math::Matrix_Identity(Matrix4F *out_matrix) { float fVar1; int iVar2; int iVar3; iVar3 = 0; do { iVar2 = 0; do { if (iVar3 == iVar2) { fVar1 = 1.0; } else { fVar1 = 0.0; } out_matrix->values[0] = fVar1; iVar2 += 1; out_matrix = (Matrix4F *)(out_matrix->values + 1); } while (iVar2 < 4); iVar3 += 1; } while (iVar3 < 4); return; } // out_matrix = { { 0, 0, 0, 0 }, // { 0, 0, 0, 0 }, // { 0, 0, 0, 0 }, // { 0, 0, 0, 0 } } void __cdecl lego::math::Matrix_Zero(Matrix4F *out_matrix) { int iVar1; for (iVar1 = 0x10; iVar1 != 0; iVar1 += -1) { out_matrix->values[0] = 0.0; out_matrix = (Matrix4F *)(out_matrix->values + 1); } return; } // out_matrix = a void __cdecl lego::math::Matrix_Copy(Matrix4F *out_matrix,Matrix4F *src) { Matrix4F *pMVar1; int iVar2; int iVar3; iVar3 = 4; pMVar1 = out_matrix; do { iVar2 = 4; do { pMVar1->values[0] = *(float *)(((int)src - (int)out_matrix) + (int)pMVar1); pMVar1 = (Matrix4F *)(pMVar1->values + 1); iVar2 += -1; } while (iVar2 != 0); iVar3 += -1; } while (iVar3 != 0); return; } Font * __cdecl lego::image::Font_Load(char *fname) { uint uVar1; uint uVar2; Image *image; Font *font; void *pvVar3; int iVar4; uint uVar5; uint uVar6; float *pfVar7; float *pfVar8; float10 fVar9; float10 fVar10; float10 extraout_ST0; float10 extraout_ST1; longlong lVar11; longlong lVar12; int local_58; uint local_50; int local_48; uint local_38; uint local_34; uint local_30; uint local_2c; uint local_28; float *local_24; undefined4 uStack32; Image *local_1c; uint local_18; undefined4 uStack20; char *local_10; undefined4 uStack12; uint local_8; undefined4 uStack4; image = Image_LoadBMPScaled(fname,0,0); if (image != NULL) { local_1c = image; font = Font_Create(image); if (font != NULL) { Image_SetPenZeroTrans(image); uVar5 = (int)image->width / 10; uVar2 = (int)image->height / 0x13; local_28 = uVar5; local_2c = Image_GetPen255BigEndian(image); local_30 = Image_GetPixelMaskBigEndian(image); pvVar3 = Image_LockSurface(image,&local_34,&local_38); if (pvVar3 != NULL) { fVar9 = (float10)(ulonglong)uVar5; uStack32 = 0; uVar1 = uVar5 - 1; pfVar7 = &font->posSet[0].width; local_50 = 0; local_48 = 0x13; local_24 = pfVar7; do { uStack20 = 0; fVar10 = (float10)(ulonglong)local_50; fname = NULL; local_58 = 10; pfVar8 = pfVar7; local_18 = local_50; do { uStack12 = 0; local_10 = fname; pfVar8[-2] = (float)ZEXT48(fname); pfVar8[-1] = (float)fVar10; *pfVar8 = (float)fVar9; pfVar8[1] = (float)(ulonglong)uVar2; if (uVar1 != 0) { lVar11 = __ftol(fVar10); uVar6 = uVar1; do { uStack4 = 0; local_8 = uVar6; lVar12 = __ftol((float10)(ulonglong)uVar6 + (float10)ZEXT48(fname)); iVar4 = (int)lVar12 * (local_38 >> 3) + local_34 * (int)lVar11; uVar5 = local_28; fVar10 = extraout_ST0; fVar9 = extraout_ST1; if ((CONCAT31(CONCAT21(CONCAT11(*(undefined *)(iVar4 + (int)pvVar3), *(undefined *)(iVar4 + 1 + (int)pvVar3)), *(undefined *)(iVar4 + 2 + (int)pvVar3)), *(undefined *)(iVar4 + 3 + (int)pvVar3)) & local_30) != local_2c) break; uVar6 -= 1; *pfVar8 = *pfVar8 - 1.0; } while (uVar6 != 0); } pfVar8 = pfVar8 + 0x4c; fname = fname + uVar5; local_58 += -1; } while (local_58 != 0); local_50 += uVar2; pfVar7 = pfVar7 + 4; local_48 += -1; if (local_48 == 0) { lVar11 = __ftol((float10)font->posSet[0].height); font->fontHeight = (uint)lVar11; lVar11 = __ftol((float10)*local_24); font->tabWidth = (int)lVar11 << 3; Image_UnlockSurface(local_1c); return font; } } while( true ); } Font_Remove(font); } Image_Remove(image); } return NULL; } void __cdecl lego::image::Font_VGetStringInfo (Font *font,uint *out_width,uint *out_lineCount,char *msg,va_list argptr) { uint uVar1; uVar1 = Font_VPrintF2(font,0,0,FALSE,out_lineCount,msg,argptr); if (out_width != NULL) { *out_width = uVar1; } return; } uint __cdecl lego::image::Font_PrintF(Font *font,int x,int y,char *msg,...) { uint uVar1; uVar1 = Font_VPrintF2(font,x,y,TRUE,NULL,msg,&stack0x00000014); return uVar1; } uint __cdecl lego::image::Font_VPrintF(Font *font,int x,int y,char *msg,va_list argptr) { uint uVar1; uVar1 = Font_VPrintF2(font,x,y,TRUE,NULL,msg,argptr); return uVar1; } uint __cdecl lego::image::Font_VPrintF2 (Font *font,int x,int y,BOOL render,uint *out_lineCount,char *msg,va_list argptr) { char *pcVar1; char cVar2; char *pcVar3; uint uVar4; uint uVar5; uint uVar6; Image *image; byte bVar7; uint local_828; uint local_824; uint local_820; uint local_81c; uint local_818; Point2F local_808; char local_800 [12]; char acStack2036 [1012]; char local_400 [1024]; cVar2 = *msg; local_824 = font->fontHeight; local_818 = 1; local_828 = 0; local_81c = 0; pcVar3 = local_400; while (cVar2 != '\0') { if ((*msg == '%') && (msg[1] == 'b')) { *pcVar3 = '@'; pcVar3[1] = '['; pcVar3[2] = '0'; pcVar3[3] = 'x'; pcVar3[4] = '%'; pcVar3[5] = '0'; pcVar3[6] = '.'; pcVar3[7] = '8'; pcVar3[8] = 'x'; pcVar3 = pcVar3 + 9; msg = msg + 1; *pcVar3 = ']'; } else { *pcVar3 = *msg; } pcVar1 = msg + 1; msg = msg + 1; pcVar3 = pcVar3 + 1; cVar2 = *pcVar1; } *pcVar3 = '\0'; uVar4 = std::vsprintf(local_800,local_400,argptr); local_820 = 0; uVar6 = 0; if (uVar4 != 0) { do { cVar2 = local_800[local_820]; if (cVar2 == '\n') { if (local_81c < local_828) { local_81c = local_828; } y += local_824; local_824 = font->fontHeight; local_828 = 0; local_818 += 1; } else { if (cVar2 == '\t') { uVar6 = font->tabWidth - local_828 % font->tabWidth; } else { if ((((local_820 < uVar4 - 0xc) && (cVar2 == '@')) && (local_800[local_820 + 1] == '[')) && (((local_800[local_820 + 2] == '0' && (local_800[local_820 + 3] == 'x')) && (acStack2036[local_820] == ']')))) { image = NULL; uVar6 = 0; pcVar3 = local_800 + local_820 + 4; bVar7 = 0x1c; do { // int std::isdigit(int c) if (std::globals::_pcharwidth < 2) { uVar5 = *(byte *)(std::globals::_pctype + (byte)pcVar3[uVar6]) & C1_DIGIT; } else { // C1_DIGIT (0x4) uVar5 = std::_isctype((uint)(byte)pcVar3[uVar6],C1_DIGIT); } image = (Image *)((uint)image | (uint)(byte)pcVar3[uVar6] - ((-(uint)(uVar5 != 0) & 0xffffffd9) + 0x57) << (bVar7 & 0x1f)); uVar6 += 1; bVar7 = bVar7 - 4; } while (uVar6 < 8); if (image != NULL) { local_808.x = (float)(ulonglong)(local_828 + x); local_808.y = (float)y; local_828 += image->width; if (local_824 < image->height) { local_824 = image->height; } Image_DisplayScaled(image,NULL,&local_808,NULL); } local_820 += 0xc; goto LAB_0047a6f3; } uVar6 = Font_OutputChar(font,local_828 + x,y,cVar2,render); } local_828 += uVar6; } LAB_0047a6f3: local_820 += 1; uVar6 = local_828; } while (local_820 < uVar4); } if (out_lineCount != NULL) { *out_lineCount = local_818; } if (local_81c < uVar6) { local_81c = uVar6; } return local_81c; } uint __cdecl lego::image::Font_OutputChar(Font *font,int x,int y,char c,BOOL render) { uint uVar1; uint uVar2; longlong lVar3; Point2F local_8; local_8.x = (float)x; local_8.y = (float)y; uVar1 = (byte)(c - 0x20) / 10; uVar2 = (uint)(byte)(c - 0x20) % 10; if (uVar1 < 0x13) { if (render != 0) { Image_DisplayScaled(font->image,font->posSet[uVar2] + uVar1,&local_8,NULL); } lVar3 = __ftol((float10)font->posSet[uVar2][uVar1].width); return (uint)lVar3; } return 0; } uint __cdecl lego::image::Font_GetCharWidth(Font *font,char c) { uint uVar1; uVar1 = Font_OutputChar(font,0,0,c,FALSE); return uVar1; } uint __cdecl lego::image::Font_GetHeight(Font *font) { return font->fontHeight; } void __cdecl lego::image::Font_Remove(Font *font) { Image_Remove(font->image); font->nextFree = globs::fontGlobs.freeList; globs::fontGlobs.freeList = font; return; } Font * __cdecl lego::image::Font_Create(Image *image) { int iVar1; Font *pFVar2; Font *pFVar3; pFVar2 = globs::fontGlobs.freeList; if (globs::fontGlobs.freeList == NULL) { Font_AddList(); pFVar2 = globs::fontGlobs.freeList; } globs::fontGlobs.freeList = pFVar2->nextFree; pFVar3 = pFVar2; for (iVar1 = 0x2fd; iVar1 != 0; iVar1 += -1) { pFVar3->image = NULL; pFVar3 = (Font *)pFVar3->posSet; } pFVar2->nextFree = pFVar2; pFVar2->image = image; return pFVar2; } void __cdecl lego::image::Font_AddList(void) { Font *pFVar1; Font *pFVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::fontGlobs.listCount & 0x1f); pFVar2 = (Font *)io::Mem_Alloc(uVar4 * 0xbf4); globs::fontGlobs.listSet[globs::fontGlobs.listCount] = pFVar2; pFVar2 = globs::fontGlobs.listSet[globs::fontGlobs.listCount]; if (pFVar2 != NULL) { globs::fontGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pFVar1 = pFVar2; do { pFVar1->nextFree = pFVar1 + 1; iVar3 += -1; pFVar1 = pFVar1 + 1; } while (iVar3 != 0); } pFVar2[uVar4 - 1].nextFree = globs::fontGlobs.freeList; globs::fontGlobs.freeList = pFVar2; } return; } BOOL __cdecl lego::snd::Sound3D_Initialise(HWND hWnd) { HRESULT HVar1; WAVEFORMATEX *pWVar2; int iVar3; WAVEFORMATEX wfx; DSBUFFERDESC dsbd; globs::sound3DGlobs.intialised = 0; globs::sound3DGlobs.listenerFrame = NULL; do { HVar1 = DirectSoundCreate(NULL,&globs::sound3DGlobs.lpDSnd,NULL); if (HVar1 == 0) { // DSSCL_PRIORITY (0x2) pWVar2 = (WAVEFORMATEX *) (*(code *)(globs::sound3DGlobs.lpDSnd)->lpVtbl->SetCooperativeLevel) (globs::sound3DGlobs.lpDSnd,hWnd,2); if (pWVar2 == NULL) { dsbd.dwSize = 0x14; // DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME dsbd.dwFlags = 0x91; dsbd.dwBufferBytes = (DWORD)pWVar2; dsbd.dwReserved = (DWORD)pWVar2; dsbd.lpwfxFormat = pWVar2; HVar1 = (*(code *)(globs::sound3DGlobs.lpDSnd)->lpVtbl->CreateSoundBuffer) (globs::sound3DGlobs.lpDSnd,&dsbd, (IDirectSoundBuffer *)&globs::sound3DGlobs.lpDSBuff,NULL); if (HVar1 == 0) { wfx.wFormatTag = 1; wfx.nChannels = 2; wfx.wBitsPerSample = 0x10; wfx.nSamplesPerSec = 22050; // wfx.wBitsPerSample / 8 * wfx.nChannels wfx.nBlockAlign = 4; // wfx.nSamplesPerSec * wfx.nBlockAlign wfx.nAvgBytesPerSec = 88200; wfx.cbSize = 0; (*(code *)(globs::sound3DGlobs.lpDSBuff)->lpVtbl->SetFormat) (globs::sound3DGlobs.lpDSBuff,&wfx); HVar1 = (*(globs::sound3DGlobs.lpDSBuff)->lpVtbl->QueryInterface) (globs::sound3DGlobs.lpDSBuff,&idl::IID_IDirectSound3DListener, &globs::sound3DGlobs.lp3DListenerInfo); if (HVar1 == 0) { // 100.0f (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->SetDopplerFactor) (globs::sound3DGlobs.lp3DListenerInfo,(float)&DAT_42c80000,0); goto LAB_0047aa15; } (*(globs::sound3DGlobs.lpDSBuff)->lpVtbl->Release)(globs::sound3DGlobs.lpDSBuff); goto LAB_0047aa04; } (*(globs::sound3DGlobs.lpDSnd)->lpVtbl->Release)(globs::sound3DGlobs.lpDSnd); } else { LAB_0047aa04: (*(globs::sound3DGlobs.lpDSnd)->lpVtbl->Release)(globs::sound3DGlobs.lpDSnd); } globs::sound3DGlobs.lpDSnd = NULL; } LAB_0047aa15: if (globs::sound3DGlobs.lpDSnd == NULL) { iVar3 = 5; } else { iVar3 = 1; globs::sound3DGlobs.intialised = 1; } if (iVar3 != 4) { if (globs::sound3DGlobs.intialised != 0) { // SET THE PRIMARY BUFFER TO CONTINUOUSLY PLAY - OPTIMISATION FOR FREQUENT STARTING AND // STOPPING OF PLAYBACK // // DSBPLAY_LOOPING (0x1) (*(code *)(globs::sound3DGlobs.lpDSBuff)->lpVtbl->Play)(globs::sound3DGlobs.lpDSBuff,0,0,1); // DEFAULT VALUES // // DS3D_DEFERRED (0x1) (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->SetRolloffFactor) (globs::sound3DGlobs.lp3DListenerInfo,1.0,1); // DISABLE DOPPLER - DONT NEED TO SET VELOCITY ON SOUNDS // // DS3D_DEFERRED (0x1) (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->SetDopplerFactor) (globs::sound3DGlobs.lp3DListenerInfo,0.0,1); (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->CommitDeferredSettings) (globs::sound3DGlobs.lp3DListenerInfo); globs::sound3DGlobs.minDistanceForAttentuation = 1.0; globs::sound3DGlobs.maxDistance = 800.0; (*(code *)(globs::sound3DGlobs.lpDSBuff)->lpVtbl->GetVolume) (globs::sound3DGlobs.lpDSBuff,&globs::sound3DGlobs.windowsVolume); Sound3D_SetVolumeToDefault(); } return 1; } } while( true ); } void __cdecl lego::snd::Sound3D_ShutDown(void) { if (globs::sound3DGlobs.intialised != 0) { Sound3D_SetGlobalVolume(globs::sound3DGlobs.windowsVolume); (*(code *)(globs::sound3DGlobs.lpDSBuff)->lpVtbl->Stop)(globs::sound3DGlobs.lpDSBuff); (*(globs::sound3DGlobs.lpDSBuff)->lpVtbl->Release)((IUnknown *)globs::sound3DGlobs.lpDSBuff); (*(globs::sound3DGlobs.lpDSnd)->lpVtbl->Release)((IUnknown *)globs::sound3DGlobs.lpDSnd); globs::sound3DGlobs.lpDSnd = NULL; globs::sound3DGlobs.intialised = 0; } return; } BOOL __cdecl lego::snd::Sound3D_CheckVolumeLimits(int vol) { // is volume in range [-10000 to 0], inclusive if ((vol < 1) && (-10001 < vol)) { return 1; } return 0; } int __cdecl lego::snd::Sound3D_Load(char *fName,BOOL stream,BOOL simultaneous,int volume) { char cVar1; BOOL BVar2; char *pcVar3; FILE *pFVar4; uint uVar5; uint uVar6; LPCSTR finalFilename; Sound3DFlags SVar7; undefined4 *puVar8; char *pcVar9; Sound3D_SoundData *pSVar10; uint sfxIndex; char wavFilename [260]; char cdromFilename [260]; bool success; success = false; if ((globs::sound3DGlobs.intialised != 0) && (BVar2 = Sound3D_GetFreeSoundIndex(&sfxIndex), BVar2 != 0)) { globs::sound3DGlobs.soundTable[sfxIndex].flags = SAMPLE_NONE; std::sprintf(wavFilename,"%s.wav",fName); if (stream == 0) { BVar2 = Sound3D_LoadSample(globs::sound3DGlobs.soundTable + sfxIndex,wavFilename,simultaneous) ; if (BVar2 != 0) { SVar7 = globs::sound3DGlobs.soundTable[sfxIndex].flags & ~SAMPLE_STREAMED; globs::sound3DGlobs.soundTable[sfxIndex].flags = SVar7; if (simultaneous != 0) { globs::sound3DGlobs.soundTable[sfxIndex].flags = SVar7 | SAMPLE_MULTIPLE; } success = true; } } else { pcVar3 = io::File_VerifyFilename(wavFilename); finalFilename = NULL; pFVar4 = std::fopen(pcVar3,"r"); if (pFVar4 == NULL) { BVar2 = io::File_GetCDFilePath(cdromFilename,wavFilename); if (BVar2 != 0) { finalFilename = cdromFilename; } } else { std::fclose(pFVar4); finalFilename = pcVar3; } if ((finalFilename != NULL) && (pFVar4 = std::fopen(finalFilename,"r"), pFVar4 != NULL)) { std::fseek(pFVar4,0,2); uVar5 = std::ftell(pFVar4); uVar6 = sfxIndex; globs::sound3DGlobs.soundTable[sfxIndex].size = uVar5; uVar5 = GetWaveAvgBytesPerSec(finalFilename); globs::sound3DGlobs.soundTable[uVar6].avgBytesPerSec = uVar5; globs::sound3DGlobs.soundTable[uVar6].flags = globs::sound3DGlobs.soundTable[uVar6].flags | SAMPLE_STREAMED; std::fclose(pFVar4); success = true; } } if (success) { uVar6 = 0xffffffff; pcVar3 = wavFilename; do { pcVar9 = pcVar3; if (uVar6 == 0) break; uVar6 -= 1; pcVar9 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar9; } while (cVar1 != '\0'); uVar6 = ~uVar6; puVar8 = (undefined4 *)(pcVar9 + -uVar6); pSVar10 = globs::sound3DGlobs.soundTable + sfxIndex; for (uVar5 = uVar6 >> 2; uVar5 != 0; uVar5 -= 1) { *(undefined4 *)pSVar10->filename = *puVar8; puVar8 = puVar8 + 1; pSVar10 = (Sound3D_SoundData *)(pSVar10->filename + 4); } for (uVar6 &= 3; uVar6 != 0; uVar6 -= 1) { pSVar10->filename[0] = *(char *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); pSVar10 = (Sound3D_SoundData *)(pSVar10->filename + 1); } BVar2 = Sound3D_CheckVolumeLimits(volume); if (BVar2 == 0) { globs::sound3DGlobs.soundTable[sfxIndex].volume = 0; globs::sound3DGlobs.soundTable[sfxIndex].flags = globs::sound3DGlobs.soundTable[sfxIndex].flags | (SAMPLE_ISUSED|SAMPLE_VOLUME); return sfxIndex; } globs::sound3DGlobs.soundTable[sfxIndex].volume = volume; globs::sound3DGlobs.soundTable[sfxIndex].flags = globs::sound3DGlobs.soundTable[sfxIndex].flags | (SAMPLE_ISUSED|SAMPLE_VOLUME); return sfxIndex; } } return -1; } BOOL __cdecl lego::snd::Sound3D_GetFreeSoundIndex(uint *out_soundTableIndex) { Sound3DFlags *pSVar1; uint uVar2; uVar2 = 0; pSVar1 = &globs::sound3DGlobs.soundTable[0].flags; do { if ((*(byte *)pSVar1 & 1) == 0) { *out_soundTableIndex = uVar2; return 1; } pSVar1 = pSVar1 + 0x4d; uVar2 += 1; } while (pSVar1 < globs::fileGlobs.wadBasePath + 8); return 0; } BOOL __cdecl lego::snd::Sound3D_Remove(int soundTableIndex) { WAVEFORMATEX *hMem; IDirectSoundBuffer *This; IDirectSoundBuffer **ppIVar1; int iVar2; if ((globs::sound3DGlobs.intialised != 0) && (soundTableIndex != -1)) { hMem = globs::sound3DGlobs.soundTable[soundTableIndex].waveFormat; globs::sound3DGlobs.soundTable[soundTableIndex].flags = globs::sound3DGlobs.soundTable[soundTableIndex].flags & ~SAMPLE_ISUSED; if (hMem != NULL) { GlobalFree(hMem); globs::sound3DGlobs.soundTable[soundTableIndex].waveFormat = NULL; } ppIVar1 = globs::sound3DGlobs.soundTable[soundTableIndex].dSoundBuffers; iVar2 = 3; do { This = *ppIVar1; if (This != NULL) { (*This->lpVtbl->Release)((IUnknown *)This); *ppIVar1 = NULL; } ppIVar1 = ppIVar1 + 1; iVar2 += -1; } while (iVar2 != 0); return 1; } return 0; } void __cdecl lego::snd::Sound3D_MakeListener(IDirect3DRMFrame3 *frame) { if (globs::sound3DGlobs.intialised != 0) { globs::sound3DGlobs.listenerFrame = frame; } return; } void __cdecl lego::snd::Sound3D_UpdateListener(void) { if ((globs::sound3DGlobs.intialised != 0) && (globs::sound3DGlobs.listenerFrame != NULL)) { Sound3D_ListenerCallback(globs::sound3DGlobs.listenerFrame,NULL,0.0); } return; } void __cdecl lego::snd::Sound3D_ListenerCallback(IDirect3DRMFrame3 *obj,void *arg,float delta) { IDirect3DRMFrame3 *This; BOOL BVar1; bool bVar2; Vector3F local_18; Vector3F local_c; This = obj; (*obj->lpVtbl->GetScene)(obj,&obj); (*This->lpVtbl->GetPosition)(This,obj,&local_18); BVar1 = Sound3D_D3DVectorEqual(&local_18,&globs::sound3DGlobs.s_ListenerCallback_oldPos); bVar2 = BVar1 == 0; if (bVar2) { // IDirectSound3DListener->SetPosition(float x, float y, float z, DWORD dwApply) (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->SetPosition) (globs::sound3DGlobs.lp3DListenerInfo,local_18.x,local_18.y,local_18.z,1); globs::sound3DGlobs.s_ListenerCallback_oldPos.x = local_18.x; globs::sound3DGlobs.s_ListenerCallback_oldPos.y = local_18.y; globs::sound3DGlobs.s_ListenerCallback_oldPos.z = local_18.z; } (*This->lpVtbl->GetOrientation)(This,obj,&local_18,&local_c); BVar1 = Sound3D_D3DVectorEqual(&local_18,&globs::sound3DGlobs.s_ListenerCallback_oldOrien); if (BVar1 != 0) { BVar1 = Sound3D_D3DVectorEqual(&local_c,&globs::sound3DGlobs.s_ListenerCallback_oldOrienUp); if (BVar1 != 0) goto LAB_0047afa5; } (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->SetOrientation) (globs::sound3DGlobs.lp3DListenerInfo,local_18.x,local_18.y,local_18.z,local_c.x, local_c.y,local_c.z,1); globs::sound3DGlobs.s_ListenerCallback_oldOrien.x = local_18.x; globs::sound3DGlobs.s_ListenerCallback_oldOrien.y = local_18.y; globs::sound3DGlobs.s_ListenerCallback_oldOrien.z = local_18.z; globs::sound3DGlobs.s_ListenerCallback_oldOrienUp.x = local_c.x; globs::sound3DGlobs.s_ListenerCallback_oldOrienUp.y = local_c.y; globs::sound3DGlobs.s_ListenerCallback_oldOrienUp.z = local_c.z; bVar2 = true; LAB_0047afa5: if (bVar2) { (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->CommitDeferredSettings) (globs::sound3DGlobs.lp3DListenerInfo); } (*obj->lpVtbl->Release)(obj); return; } void __cdecl lego::snd::Sound3D_SetWorldPos(IDirectSound3DBuffer *sound3DBuff,Vector3F *wPos,Vector3F *vel) { // IDirectSound3DBuffer->SetPosition(float x, float y, float z, DWORD dwApply) (*(code *)sound3DBuff->lpVtbl->SetPosition)(sound3DBuff,wPos->x,wPos->y,wPos->z,0); return; } BOOL __cdecl lego::snd::Sound3D_CheckAlreadyExists(IDirect3DRMFrame3 *frame,IDirectSound3DBuffer *sound3DBuff) { Sound3D_SoundRecord *pSVar1; pSVar1 = globs::sound3DGlobs.soundRecord; if (globs::sound3DGlobs.soundRecord == NULL) { return (BOOL)NULL; } do { if (sound3DBuff == pSVar1->sound3DBuff) { Sound3D_RemoveSound(pSVar1->frame,pSVar1->sound3DBuff); return (BOOL)(Sound3D_SoundRecord *)0x1; } pSVar1 = pSVar1->next; } while (pSVar1 != NULL); return (BOOL)pSVar1; } int __cdecl lego::snd::Sound3D_Play2 (Sound3DPlay mode,IDirect3DRMFrame3 *frame,int soundTableIndex,BOOL loop, Vector3F *opt_wPos) { Sound3DFlags SVar1; char *filename; FILE *stream; BOOL BVar2; IDirect3DRMFrame3 *This; uint uVar3; int *unaff_EBP; IDirectSound3DBuffer *unaff_ESI; char *fName; IDirectSound3DBuffer *soundBuff; float rvZ; undefined4 uVar4; IDirectSound3DBuffer *sound3DBuff; IDirectSound3DBuffer *local_118; IDirect3DRMFrame3 *local_114; Vector3F local_110; char local_104 [244]; IDirect3DRMFrame3 *pIStack16; int iStack8; fName = NULL; if ((globs::sound3DGlobs.intialised != 0) && (soundTableIndex != -1)) { SVar1 = globs::sound3DGlobs.soundTable[soundTableIndex].flags; if ((SVar1 & SAMPLE_VOLUME) != SAMPLE_NONE) { if ((SVar1 & SAMPLE_STREAMED) == SAMPLE_NONE) { if ((SVar1 & SAMPLE_MULTIPLE) == SAMPLE_NONE) { soundBuff = (IDirectSound3DBuffer *) globs::sound3DGlobs.soundTable[soundTableIndex].dSoundBuffers[0]; } else { uVar3 = globs::sound3DGlobs.soundTable[soundTableIndex].bufferIndex + 1; globs::sound3DGlobs.soundTable[soundTableIndex].bufferIndex = uVar3; if (2 < uVar3) { globs::sound3DGlobs.soundTable[soundTableIndex].bufferIndex = 0; } soundBuff = *(IDirectSound3DBuffer **) (soundTableIndex * 0x134 + 0x5077b8 + globs::sound3DGlobs.soundTable[soundTableIndex].bufferIndex * 4); } (*soundBuff->lpVtbl->QueryInterface) ((IUnknown *)soundBuff,(IID *)&idl::IID_IDirectSound3DBuffer,&local_118); This = (IDirect3DRMFrame3 *)globs::sound3DGlobs.soundTable[soundTableIndex].volume; if (mode == Sound3DPlay_Normal) { This = This + -200; } sound3DBuff = soundBuff; (*(code *)soundBuff->lpVtbl->SetConeOutsideVolume)(); uVar4 = 1; // IDirectSound3DBuffer->SetMinDistance(float flMinDistance, DWORD dwApply) rvZ = globs::sound3DGlobs.minDistanceForAttentuation; (**(code **)(*unaff_EBP + 0x44))(unaff_EBP,globs::sound3DGlobs.minDistanceForAttentuation,1) ; // IDirectSound3DBuffer->SetMaxDistance(float flMaxDistance, DWORD dwApply) (*This->lpVtbl->AddScale) (This,(D3DRMCombineType)globs::sound3DGlobs.maxDistance,1.401298e-45, (float)unaff_EBP,rvZ); if (mode == Sound3DPlay_OnFrame) { // IDirectSound3DBuffer->SetMode(DWORD dwMode, DWORD dwApply) // (dwMode = DS3DMODE_NORMAL (0x0), dwApply = TRUE (0x1)) (*(code *)unaff_ESI->lpVtbl->SetMode)(unaff_ESI,0,1); // IDirect3DRMFrame3->GetScene(this, IDirect3DRMFrame3** lplpRoot) // (this = param_2 (rmFrame3), lplpRoot => local_114) (*pIStack16->lpVtbl->GetScene)(pIStack16,(IDirect3DRMFrame3 **)&stack0xfffffed4); Sound3D_CheckAlreadyExists(pIStack16,sound3DBuff); gfx::Sound3D_AttachSound(pIStack16,sound3DBuff); Sound3D_AddSoundRecord(pIStack16,(IDirectSoundBuffer *)soundBuff,sound3DBuff); // IDirect3DRMFrame3->GetPosition(this, IDirect3DRMFrame3* lpRef, Vector3F* lprvPos) // (this = param_2 (rmFrame3), lpRef = GetScene) (*pIStack16->lpVtbl->GetPosition)(pIStack16,This,(Vector3F *)&stack0xfffffed8); // IDirectSound3DBuffer->SetPosition(float x, float y, float z, DWORD dwApply) (**(code **)(*(int *)mode + 0x4c))(mode,uVar4,sound3DBuff,This,1); // IDirect3DRMFrame3->Release(this) // (this = GetScene) (*pIStack16->lpVtbl->Release)((IUnknown *)pIStack16); } else { if (mode == Sound3DPlay_OnPos) { // IDirectSound3DBuffer->SetMode(DWORD dwMode, DWORD dwApply) // (dwMode = DS3DMODE_NORMAL (0x0), dwApply = TRUE (0x1)) (*(code *)unaff_ESI->lpVtbl->SetMode)(unaff_ESI,0,1); Sound3D_SetWorldPos(unaff_ESI,(Vector3F *)frame,NULL); Sound3D_CheckAlreadyExists(NULL,unaff_ESI); } else { if (mode != Sound3DPlay_Normal) goto LAB_0047b26d; // IDirectSound3DBuffer->SetMode(DWORD dwMode, DWORD dwApply) // (dwMode = DS3DMODE_DISABLE (0x2), dwApply = TRUE (0x1)) (*(code *)unaff_ESI->lpVtbl->SetMode)(unaff_ESI,2,1); Sound3D_CheckAlreadyExists(NULL,unaff_ESI); } Sound3D_AddSoundRecord(NULL,(IDirectSoundBuffer *)soundBuff,unaff_ESI); } LAB_0047b26d: (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->CommitDeferredSettings) (globs::sound3DGlobs.lp3DListenerInfo); (*(code *)soundBuff->lpVtbl->SetConeAngles)(soundBuff,0); if (iStack8 != 0) { (*(code *)soundBuff->lpVtbl->SetAllParameters)(soundBuff,0,0,1); return soundTableIndex * 3 + globs::sound3DGlobs.soundTable[soundTableIndex].bufferIndex; } (*(code *)soundBuff->lpVtbl->SetAllParameters)(soundBuff,0,0,0); return soundTableIndex * 3 + globs::sound3DGlobs.soundTable[soundTableIndex].bufferIndex; } filename = io::File_VerifyFilename(globs::sound3DGlobs.soundTable[soundTableIndex].filename); stream = std::fopen(filename,"r"); if (stream == NULL) { BVar2 = io::File_GetCDFilePath (local_104,globs::sound3DGlobs.soundTable[soundTableIndex].filename); if (BVar2 != 0) { fName = local_104; } } else { std::fclose(stream); fName = filename; } if (fName != NULL) { Sound3D_Stream_Play(fName,loop,globs::sound3DGlobs.soundTable[soundTableIndex].volume); return soundTableIndex * 3; } } } return -1; } void __cdecl lego::snd::Sound3D_AddSoundRecord (IDirect3DRMFrame3 *frame,IDirectSoundBuffer *soundBuff,IDirectSound3DBuffer *sound3DBuff) { Sound3D_SoundRecord *pSVar1; pSVar1 = (Sound3D_SoundRecord *)io::Mem_Alloc(0x10); pSVar1->next = globs::sound3DGlobs.soundRecord; pSVar1->frame = frame; pSVar1->sound3DBuff = sound3DBuff; pSVar1->soundBuff = soundBuff; globs::sound3DGlobs.soundRecord = pSVar1; return; } void __cdecl lego::snd::Sound3D_SetBufferVolume(int handle,int newvolume) { byte bVar1; IDirectSoundBuffer *pIVar2; BOOL BVar3; uint uVar4; int iVar5; IDirectSoundBuffer **ppIVar6; BVar3 = Sound3D_CheckVolumeLimits(newvolume); bVar1 = *(byte *)&globs::sound3DGlobs.soundTable[handle].flags; uVar4 = -(uint)(BVar3 != 0) & newvolume; globs::sound3DGlobs.soundTable[handle].volume = uVar4; if ((bVar1 & 4) != 0) { ppIVar6 = globs::sound3DGlobs.soundTable[handle].dSoundBuffers; iVar5 = 3; do { pIVar2 = *ppIVar6; if (pIVar2 != NULL) { (*(code *)pIVar2->lpVtbl->SetVolume)(pIVar2,globs::sound3DGlobs.soundTable[handle].volume); } ppIVar6 = ppIVar6 + 1; iVar5 += -1; } while (iVar5 != 0); return; } pIVar2 = globs::sound3DGlobs.soundTable[handle].dSoundBuffers[0]; if (pIVar2 != NULL) { (*(code *)pIVar2->lpVtbl->SetVolume)(pIVar2,uVar4); } return; } int __cdecl lego::snd::Sound3D_GetBufferVolume(int handle) { return globs::sound3DGlobs.soundTable[handle].volume; } IDirectSoundBuffer * __cdecl lego::snd::Sound3D_GetSoundBuffer(int handle) { if (handle == -1) { return NULL; } // globals::g_SampleDatas_TABLE[sfxType / 3].dSoundBuffers[sfxType % 3] return *(IDirectSoundBuffer **) ((handle % 3) * 4 + 0x5077b8 + ((uint)(handle - handle % 3) / 3) * 0x134); } void __cdecl lego::snd::Sound3D_StopSound(int handle) { IDirectSoundBuffer *dSoundBuffer; dSoundBuffer = Sound3D_GetSoundBuffer(handle); if (((globs::sound3DGlobs.intialised != 0) && (handle != -1)) && (dSoundBuffer != NULL)) { (*(code *)dSoundBuffer->lpVtbl->Stop)(dSoundBuffer); } return; } void __cdecl lego::snd::Sound3D_StopAllSounds(void) { Sound3D_SoundRecord *pSVar1; pSVar1 = globs::sound3DGlobs.soundRecord; if (globs::sound3DGlobs.soundRecord != NULL) { do { (*(code *)pSVar1->soundBuff->lpVtbl->Stop)(pSVar1->soundBuff); pSVar1 = pSVar1->next; } while (pSVar1 != NULL); } Sound3D_Stream_Stop(FALSE); Sound3D_Stream_Stop(TRUE); return; } void __cdecl lego::gfx::Sound3D_AttachSound(IDirect3DRMFrame3 *frame,IDirectSound3DBuffer *sound3DBuff) { Container_AppData *appData; Sound3D_SoundFrameRecord *soundRecord; IDirect3DRMFrame3 **ppIVar1; int iVar2; appData = (*frame->lpVtbl->GetAppData)(frame); soundRecord = (Sound3D_SoundFrameRecord *)io::Mem_Alloc(0x14); if (appData == NULL) { soundRecord->next = NULL; } else { soundRecord->next = appData->soundList; } soundRecord->sound3DBuff = sound3DBuff; (soundRecord->pos).x = 0.0; (soundRecord->pos).y = 0.0; (soundRecord->pos).z = 0.0; Container_Frame_SetAppData(frame,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,soundRecord,NULL); iVar2 = 0; ppIVar1 = globs::sound3DGlobs.updateFrameList; do { if (*ppIVar1 == NULL) { globs::sound3DGlobs.updateFrameList[iVar2] = frame; return; } ppIVar1 = ppIVar1 + 1; iVar2 += 1; } while (ppIVar1 < &globs::sound3DGlobs.reserved1); return; } void __cdecl lego::snd::Sound3D_RemoveSound(IDirect3DRMFrame3 *frame,IDirectSound3DBuffer *sound3DBuff) { Sound3D_SoundFrameRecord *buffer; Container_AppData *appData; BOOL BVar1; IDirect3DRMFrame3 **ppIVar2; (*sound3DBuff->lpVtbl->Release)(sound3DBuff); if (frame == NULL) { Sound3D_RemoveSoundRecord(NULL,sound3DBuff); return; } appData = (*frame->lpVtbl->GetAppData)(frame); BVar1 = Sound3D_RecurseRemoveSound(frame,sound3DBuff,appData->soundList); if (BVar1 != 0) { Sound3D_RemoveSoundRecord(frame,sound3DBuff); buffer = appData->soundList; appData->soundList = buffer->next; io::Mem_Free(buffer); } ppIVar2 = globs::sound3DGlobs.updateFrameList; do { if (frame == *ppIVar2) { *ppIVar2 = NULL; } ppIVar2 = ppIVar2 + 1; } while (ppIVar2 < &globs::sound3DGlobs.reserved1); return; } void __cdecl lego::snd::Sound3D_RemoveSoundRecord(IDirect3DRMFrame3 *frame,IDirectSound3DBuffer *sound3DBuff) { Sound3D_SoundRecord *buffer; BOOL BVar1; BVar1 = Sound3D_RecurseRemoveSoundRecord(frame,sound3DBuff,globs::sound3DGlobs.soundRecord); buffer = globs::sound3DGlobs.soundRecord; if (BVar1 != 0) { globs::sound3DGlobs.soundRecord = (globs::sound3DGlobs.soundRecord)->next; io::Mem_Free(buffer); } return; } BOOL __cdecl lego::snd::Sound3D_RecurseRemoveSoundRecord (IDirect3DRMFrame3 *owner,IDirectSound3DBuffer *sound3DBuff,Sound3D_SoundRecord *record) { Sound3D_SoundRecord *buffer; BOOL BVar1; if (record == NULL) { return 0; } BVar1 = Sound3D_RecurseRemoveSoundRecord(owner,sound3DBuff,record->next); if (BVar1 != 0) { buffer = record->next; record->next = buffer->next; io::Mem_Free(buffer); } return (uint)(sound3DBuff == record->sound3DBuff); } BOOL __cdecl lego::snd::Sound3D_RecurseRemoveSound (IDirect3DRMFrame3 *owner,IDirectSound3DBuffer *sound3DBuff, Sound3D_SoundFrameRecord *record) { Sound3D_SoundFrameRecord *buffer; BOOL BVar1; if (record == NULL) { return 0; } BVar1 = Sound3D_RecurseRemoveSound(owner,sound3DBuff,record->next); if (BVar1 != 0) { Sound3D_RemoveSoundRecord(owner,sound3DBuff); buffer = record->next; record->next = buffer->next; io::Mem_Free(buffer); } return (uint)(sound3DBuff == record->sound3DBuff); } void __cdecl lego::snd::Sound3D_Update(void) { Sound3D_SoundRecord *pSVar1; uint in_ECX; Sound3D_SoundRecord *pSVar2; IDirect3DRMFrame3 **lpSndBufFrame; uint local_4; pSVar2 = globs::sound3DGlobs.soundRecord; lpSndBufFrame = globs::sound3DGlobs.updateFrameList; local_4 = in_ECX; do { // (inlined) Sound3D_UpdateFrames(); if (*lpSndBufFrame != NULL) { Sound3D_SoundCallback(*lpSndBufFrame,NULL,0.0); } lpSndBufFrame = lpSndBufFrame + 1; } while (lpSndBufFrame < &globs::sound3DGlobs.reserved1); if (pSVar2 != NULL) { do { pSVar1 = pSVar2->next; (*(code *)pSVar2->soundBuff->lpVtbl->GetStatus)(pSVar2->soundBuff,&local_4); if ((local_4 & 1) == 0) { Sound3D_RemoveSound(pSVar2->frame,pSVar2->sound3DBuff); } pSVar2 = pSVar1; } while (pSVar1 != NULL); } Sound3D_Stream_CheckPosition(FALSE); Sound3D_Stream_CheckPosition(TRUE); return; } void __cdecl lego::snd::Sound3D_SoundCallback(IDirect3DRMFrame3 *tFrame,void *arg,float delay) { Container_AppData *appData; BOOL BVar1; Vector3F position; IDirect3DRMFrame3 *rmFrame3_00; Sound3D_SoundFrameRecord *sndRes; rmFrame3_00 = tFrame; appData = (*tFrame->lpVtbl->GetAppData)(tFrame); sndRes = appData->soundList; (*rmFrame3_00->lpVtbl->GetScene)(rmFrame3_00,&tFrame); for (; sndRes != NULL; sndRes = sndRes->next) { (*rmFrame3_00->lpVtbl->GetPosition)(rmFrame3_00,tFrame,&position); BVar1 = Sound3D_D3DVectorEqual(&position,&sndRes->pos); if (BVar1 == 0) { // IDirectSound3DBuffer->SetPosition(this, float x, float y, float z, DWORD dwApply) (*(code *)sndRes->sound3DBuff->lpVtbl->SetPosition) (sndRes->sound3DBuff,position.x,position.y,position.z,0); (sndRes->pos).x = position.x; (sndRes->pos).y = position.y; (sndRes->pos).z = position.z; } } (*tFrame->lpVtbl->Release)(tFrame); return; } void __cdecl lego::snd::Sound3D_SetMinDistForAtten(float dist) { Sound3D_SoundRecord **ppSVar1; Sound3D_SoundRecord *pSVar2; globs::sound3DGlobs.minDistanceForAttentuation = dist; pSVar2 = globs::sound3DGlobs.soundRecord; if (globs::sound3DGlobs.soundRecord != NULL) { do { (*(code *)pSVar2->sound3DBuff->lpVtbl->SetMinDistance)(pSVar2->sound3DBuff,dist,0); ppSVar1 = &pSVar2->next; pSVar2 = *ppSVar1; } while (*ppSVar1 != NULL); } return; } void __cdecl lego::snd::Sound3D_SetMaxDist(float dist) { Sound3D_SoundRecord **ppSVar1; Sound3D_SoundRecord *pSVar2; globs::sound3DGlobs.maxDistance = dist; pSVar2 = globs::sound3DGlobs.soundRecord; if (globs::sound3DGlobs.soundRecord != NULL) { do { (*(code *)pSVar2->sound3DBuff->lpVtbl->SetMaxDistance)(pSVar2->sound3DBuff,dist,0); ppSVar1 = &pSVar2->next; pSVar2 = *ppSVar1; } while (*ppSVar1 != NULL); } return; } void __cdecl lego::snd::Sound3D_SetGlobalVolume(int vol) { BOOL BVar1; if (globs::sound3DGlobs.intialised != 0) { BVar1 = Sound3D_CheckVolumeLimits(vol); if (BVar1 != 0) { globs::sound3DGlobs.volume = vol; (*(code *)(globs::sound3DGlobs.lpDSBuff)->lpVtbl->SetVolume)(globs::sound3DGlobs.lpDSBuff,vol) ; } } return; } void __cdecl lego::snd::Sound3D_SetGlobalVolumePrescaled(int vol_0_10) { if ((-1 < vol_0_10) && (vol_0_10 < 0xb)) { Sound3D_SetGlobalVolume(globs::constant::c_SetGlobalVolumePrescaled_realVol[vol_0_10]); } return; } void __cdecl lego::snd::Sound3D_SetVolumeToDefault(void) { if (globs::sound3DGlobs.intialised != 0) { globs::sound3DGlobs.volume = -300; (*(code *)(globs::sound3DGlobs.lpDSBuff)->lpVtbl->SetVolume)(globs::sound3DGlobs.lpDSBuff,-NAN); } return; } BOOL __cdecl lego::snd::Sound3D_LoadSample(Sound3D_SoundData *out_sound,char *fName,BOOL simultaneous) { Sound3D_SoundData *sound; byte *fileData; byte *pbDest; BOOL BVar1; int iVar2; Sound3D_SoundData *pSVar3; uint local_2c; MMCKINFO local_28; MMCKINFO local_14; sound = out_sound; pSVar3 = out_sound; for (iVar2 = 0x4d; iVar2 != 0; iVar2 += -1) { *(undefined4 *)pSVar3->filename = 0; pSVar3 = (Sound3D_SoundData *)(pSVar3->filename + 4); } fileData = io::File_LoadBinary(fName,(uint *)&fName); if (fileData != NULL) { iVar2 = WaveOpenFile(fileData,(uint)fName,(HMMIO *)&out_sound,&sound->waveFormat,&local_14); if (iVar2 == 0) { iVar2 = WaveStartDataRead((HMMIO *)&out_sound,&local_28,&local_14); if (iVar2 == 0) { pbDest = (byte *)GlobalAlloc(0,local_28.cksize); sound->data = pbDest; if (pbDest != NULL) { iVar2 = WaveReadFile((HMMIO)out_sound,local_28.cksize,pbDest,&local_28,&local_2c); if (iVar2 == 0) { sound->size = local_2c; if (out_sound != NULL) { mmioClose((HMMIO)out_sound,0); out_sound = NULL; } BVar1 = Sound3D_CreateSoundBuffer(sound); if (BVar1 != 0) { BVar1 = Sound3D_SendSoundToBuffer(sound); if (BVar1 != 0) { if (sound->data != NULL) { GlobalFree(sound->data); sound->data = NULL; } io::Mem_Free(fileData); return 1; } } } } } } } if (sound->data != NULL) { GlobalFree(sound->data); sound->data = NULL; } return 0; } BOOL __cdecl lego::snd::Sound3D_CreateSoundBuffer(Sound3D_SoundData *sound) { int iVar1; IDirectSoundBuffer **ppIVar2; uint uVar3; undefined4 local_14; undefined4 local_10; uint local_c; int local_8; WAVEFORMATEX *local_4; local_4 = sound->waveFormat; local_c = sound->size; local_8 = 0; local_14 = 0x14; local_10 = 0x200f2; iVar1 = (*(code *)(globs::sound3DGlobs.lpDSnd)->lpVtbl->CreateSoundBuffer) (globs::sound3DGlobs.lpDSnd,&local_14,sound->dSoundBuffers,0); if (iVar1 != 0) { return 0; } sound->bufferIndex = 0; if (local_8 != 0) { uVar3 = 1; ppIVar2 = sound->dSoundBuffers; do { ppIVar2 = ppIVar2 + 1; iVar1 = (*(code *)(globs::sound3DGlobs.lpDSnd)->lpVtbl->DuplicateSoundBuffer) (globs::sound3DGlobs.lpDSnd,sound->dSoundBuffers[0],ppIVar2); if (iVar1 != 0) { return 0; } uVar3 += 1; } while (uVar3 < 3); return TRUE; } return TRUE; } BOOL __cdecl lego::snd::Sound3D_SendSoundToBuffer(Sound3D_SoundData *sound) { Sound3D_SoundData *pSVar1; int iVar2; uint uVar3; Sound3D_SoundData *pSVar4; undefined4 *puVar5; Sound3D_SoundData **ppSVar6; undefined4 *puVar7; uint uStack48; undefined *puStack44; undefined4 *puStack40; Sound3D_SoundData **ppSStack36; undefined4 *puStack32; undefined4 *puStack28; undefined4 local_c; undefined4 local_8; undefined local_4 [4]; pSVar1 = sound; puStack32 = &local_8; puStack28 = NULL; ppSStack36 = &sound; puStack40 = &local_c; local_c = 0; puStack44 = local_4; uStack48 = sound->size; local_8 = 0; iVar2 = (*(code *)sound->dSoundBuffers[0]->lpVtbl->Lock)(sound->dSoundBuffers[0],sound->offset); if (iVar2 == -0x7787ff6a) { (*(code *)pSVar1->dSoundBuffers[0]->lpVtbl->Restore)(pSVar1->dSoundBuffers[0]); (*(code *)pSVar1->dSoundBuffers[0]->lpVtbl->Lock) (pSVar1->dSoundBuffers[0],pSVar1->offset,pSVar1->size,&puStack40,&uStack48,&puStack32, &puStack44,0); } else { if (iVar2 != 0) { return 0; } } pSVar4 = (Sound3D_SoundData *)pSVar1->data; ppSVar6 = ppSStack36; for (uVar3 = (uint)puStack44 >> 2; uVar3 != 0; uVar3 -= 1) { *ppSVar6 = *(Sound3D_SoundData **)pSVar4; pSVar4 = (Sound3D_SoundData *)((int)pSVar4 + 4); ppSVar6 = ppSVar6 + 1; } for (uVar3 = (uint)puStack44 & 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)ppSVar6 = pSVar4->filename[0]; pSVar4 = (Sound3D_SoundData *)((int)pSVar4 + 1); ppSVar6 = (Sound3D_SoundData **)((int)ppSVar6 + 1); } if (puStack28 != NULL) { puVar5 = (undefined4 *)(puStack44 + (int)pSVar1->data); puVar7 = puStack28; for (uVar3 = (uint)puStack40 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar7 = *puVar5; puVar5 = puVar5 + 1; puVar7 = puVar7 + 1; } for (uVar3 = (uint)puStack40 & 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } } iVar2 = (*(code *)pSVar1->dSoundBuffers[0]->lpVtbl->Unlock) (pSVar1->dSoundBuffers[0],ppSStack36,puStack44,puStack28,puStack40); if (iVar2 == 0) { iVar2 = (*(code *)pSVar1->dSoundBuffers[0]->lpVtbl->GetFrequency) (pSVar1->dSoundBuffers[0],&pSVar1->frequency); if (iVar2 == 0) { iVar2 = (*(code *)pSVar1->dSoundBuffers[0]->lpVtbl->GetVolume) (pSVar1->dSoundBuffers[0],&pSVar1->volume); return (uint)(iVar2 == 0); } return 0; } return 0; } float10 __cdecl lego::snd::Sound3D_GetSamplePlayTime(int handle) { uint uVar1; if (handle == -1) { return (float10)0.0; } uVar1 = globs::sound3DGlobs.soundTable[handle].size; if ((*(byte *)&globs::sound3DGlobs.soundTable[handle].flags & 8) != 0) { return (float10)(ulonglong)uVar1 / (float10)globs::sound3DGlobs.soundTable[handle].avgBytesPerSec; } return (float10)(ulonglong)uVar1 / (float10)(globs::sound3DGlobs.soundTable[handle].waveFormat)->nAvgBytesPerSec; } BOOL __cdecl lego::snd::Sound3D_Stream_Play(char *fName,BOOL loop,int volume) { BOOL BVar1; IDirectSoundBuffer *pIVar2; Sound3D_StreamData *pSVar3; pSVar3 = &globs::sound3DGlobs.loopStreamData; if (loop == 0) { pSVar3 = &globs::sound3DGlobs.streamData; } if ((pSVar3->playing != 0) || (pSVar3->fileOpen != 0)) { Sound3D_Stream_Stop(loop); } BVar1 = Sound3D_Stream_BufferSetup(fName,loop,volume); if (BVar1 != 0) { pIVar2 = globs::sound3DGlobs.lpDSStreamBuff; if (loop != 0) { pIVar2 = globs::sound3DGlobs.lpDSLoopStreamBuff; } (*(code *)pIVar2->lpVtbl->SetCurrentPosition)(pIVar2,0); pIVar2 = globs::sound3DGlobs.lpDSStreamBuff; if (loop != 0) { pIVar2 = globs::sound3DGlobs.lpDSLoopStreamBuff; } // DSBPLAY_LOOPING (0x1) (*(code *)pIVar2->lpVtbl->Play)(pIVar2,0,0,1); pSVar3->playing = 1; return TRUE; } pSVar3->playing = 0; return 0; } BOOL __cdecl lego::snd::Sound3D_Stream_Stop(BOOL looping) { IDirectSoundBuffer *pIVar1; Sound3D_StreamData *pSVar2; pSVar2 = &globs::sound3DGlobs.loopStreamData; if (looping == 0) { pSVar2 = &globs::sound3DGlobs.streamData; } pSVar2->playing = 0; if (pSVar2->fileOpen != 0) { pIVar1 = globs::sound3DGlobs.lpDSStreamBuff; if (looping != 0) { pIVar1 = globs::sound3DGlobs.lpDSLoopStreamBuff; } (*(code *)pIVar1->lpVtbl->Stop)(pIVar1); WaveCloseReadFile(&(pSVar2->wiWave).hmmio,&(pSVar2->wiWave).waveFormat); pIVar1 = globs::sound3DGlobs.lpDSStreamBuff; if (looping != 0) { pIVar1 = globs::sound3DGlobs.lpDSLoopStreamBuff; } (*pIVar1->lpVtbl->Release)((IUnknown *)pIVar1); pSVar2->fileOpen = 0; } return TRUE; } BOOL __cdecl lego::snd::Sound3D_Stream_BufferSetup(char *waveFName,BOOL loop,int volume) { MMCKINFO *out_pckInRIFF; Sound3D_WaveData *out_ppwfxInfo; HMMIO *out_phmmioIn; WAVEFORMATEX *pWVar1; DWORD looping; int iVar2; uint uVar3; Sound3D_StreamData *pSVar4; DSBUFFERDESC sndBuffer; pSVar4 = &globs::sound3DGlobs.loopStreamData; if (loop == 0) { pSVar4 = &globs::sound3DGlobs.streamData; } out_pckInRIFF = &(pSVar4->wiWave).mmckInRIFF; out_ppwfxInfo = &pSVar4->wiWave; out_phmmioIn = &(pSVar4->wiWave).hmmio; iVar2 = WaveOpenFile2(waveFName,out_phmmioIn,&out_ppwfxInfo->waveFormat,out_pckInRIFF); if (iVar2 != 0) { return 0; } if (out_ppwfxInfo->waveFormat->wFormatTag != WAVE_FORMAT_PCM) { WaveCloseReadFile(out_phmmioIn,&out_ppwfxInfo->waveFormat); return 0; } iVar2 = WaveStartDataRead(out_phmmioIn,&(pSVar4->wiWave).mmck,out_pckInRIFF); if (iVar2 == 0) { pWVar1 = out_ppwfxInfo->waveFormat; uVar3 = pWVar1->nSamplesPerSec * (uint)pWVar1->nBlockAlign * 3 >> 2; (pSVar4->wiWave).dwNotifySize = uVar3; uVar3 %= (uint)pWVar1->nBlockAlign; if (uVar3 != 0) { (pSVar4->wiWave).dwNotifySize = (pSVar4->wiWave).dwNotifySize + (pWVar1->nBlockAlign - uVar3); } sndBuffer.dwSize = 0x14; sndBuffer.dwFlags = 0x100e0; sndBuffer.dwBufferBytes = (pSVar4->wiWave).dwNotifySize << 2; sndBuffer.dwReserved = 0; (pSVar4->wiWave).dwBufferSize = sndBuffer.dwBufferBytes; sndBuffer.lpwfxFormat = out_ppwfxInfo->waveFormat; iVar2 = (*(code *)(globs::sound3DGlobs.lpDSnd)->lpVtbl->CreateSoundBuffer) (globs::sound3DGlobs.lpDSnd,&sndBuffer,&waveFName,0); looping = sndBuffer.dwReserved; if (iVar2 == 0) { if (sndBuffer.dwReserved == 0) { globs::sound3DGlobs.lpDSStreamBuff = (IDirectSoundBuffer *)sndBuffer.dwBufferBytes; } else { globs::sound3DGlobs.lpDSLoopStreamBuff = (IDirectSoundBuffer *)sndBuffer.dwBufferBytes; } (**(code **)(*(int *)sndBuffer.dwBufferBytes + 0x3c)) (sndBuffer.dwBufferBytes,sndBuffer.lpwfxFormat); (pSVar4->wiWave).bFoundEnd = 0; (pSVar4->wiWave).dwNextWriteOffset = 0; (pSVar4->wiWave).dwNextProgressCheck = (pSVar4->wiWave).dwNotifySize << 1; (pSVar4->wiWave).bLoopFile = looping; Sound3D_Stream_FillDataBuffer(looping); (pSVar4->wiWave).bDonePlaying = 0; pSVar4->fileOpen = 1; return 1; } return 0; } WaveCloseReadFile(out_phmmioIn,&out_ppwfxInfo->waveFormat); return 0; } BOOL __cdecl lego::snd::Sound3D_Stream_FillDataBuffer(BOOL looping) { MMCKINFO *pckIn; HMMIO *phmmioIn; undefined2 uVar1; int iVar2; uint uVar3; IDirectSoundBuffer *pIVar4; uint uVar5; uint uVar6; char cVar7; int unaff_EBP; int iVar8; undefined *puVar9; uint *puVar10; undefined *puStack44; undefined4 uStack40; undefined local_14 [4]; undefined local_10 [8]; undefined local_8 [4]; uint local_4; iVar8 = 0x507628; if (looping == 0) { iVar8 = 0x5075cc; } pIVar4 = globs::sound3DGlobs.lpDSStreamBuff; if (looping != 0) { pIVar4 = globs::sound3DGlobs.lpDSLoopStreamBuff; } puStack44 = local_8; uStack40 = 0; iVar2 = (*(code *)pIVar4->lpVtbl->Lock)(pIVar4,0,*(undefined4 *)(iVar8 + 0x34),local_10); if (iVar2 != 0) { return 0; } pckIn = (MMCKINFO *)(iVar8 + 0xc); phmmioIn = (HMMIO *)(iVar8 + 8); WaveReadFile(*phmmioIn,(uint)local_14,(byte *)&local_4,pckIn,(uint *)&puStack44); if (puStack44 < local_14) { puVar9 = puStack44; iVar2 = unaff_EBP; if (*(int *)(iVar8 + 0x50) == 0) { if (puStack44 < *(undefined **)(iVar8 + 0x38)) { *(undefined4 *)(iVar8 + 0x54) = 1; } uVar5 = (int)local_14 - (int)puStack44; cVar7 = (*(short *)(*(int *)(iVar8 + 4) + 0xe) != 8) + -1; uVar1 = CONCAT11(cVar7,cVar7); uVar3 = CONCAT22(uVar1,uVar1) & 0x80808080; puVar10 = (uint *)((int)&local_4 + (int)puStack44); for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = uVar3; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(byte *)puVar10 = (byte)uVar3; puVar10 = (uint *)((int)puVar10 + 1); } } else { do { looping = iVar2; WaveStartDataRead(phmmioIn,pckIn,(MMCKINFO *)(iVar8 + 0x20)); WaveReadFile(*phmmioIn,(int)local_14 - (int)puVar9,puVar9 + (int)&local_4,pckIn, (uint *)&puStack44); puVar9 = puVar9 + (int)puStack44; iVar2 = looping; } while (puVar9 < local_14); } } pIVar4 = globs::sound3DGlobs.lpDSStreamBuff; if (looping != 0) { pIVar4 = globs::sound3DGlobs.lpDSLoopStreamBuff; } iVar2 = 0; (*(code *)pIVar4->lpVtbl->Unlock)(pIVar4,&local_4,local_14,0); uVar3 = *(uint *)(iVar8 + 0x34); uVar6 = *(int *)(iVar8 + 0x3c) + iVar2; *(uint *)(iVar8 + 0x3c) = uVar6; if (uVar3 <= uVar6) { *(uint *)(iVar8 + 0x3c) = uVar6 - uVar3; uVar6 = uVar3; } *(undefined4 *)(iVar8 + 0x40) = 0; *(undefined4 *)(iVar8 + 0x48) = 0; return uVar6; } void __cdecl lego::snd::Sound3D_Stream_CheckPosition(BOOL looping) { MMCKINFO *pckIn; HMMIO *phmmioIn; byte bVar1; void *pvVar2; HRESULT HVar3; IDirectSoundBuffer *pIVar4; uint uVar5; uint unaff_EBX; uint *unaff_EBP; uint unaff_ESI; Sound3D_StreamData *pSVar6; uint uVar7; uint *puVar8; DWORD local_18; void *local_14; undefined4 local_10; uint local_c; int local_8; DWORD local_4; pSVar6 = &globs::sound3DGlobs.loopStreamData; if (looping == 0) { pSVar6 = &globs::sound3DGlobs.streamData; } if ((pSVar6->playing != 0) && (pSVar6->fileOpen != 0)) { pIVar4 = globs::sound3DGlobs.lpDSStreamBuff; if (looping != 0) { pIVar4 = globs::sound3DGlobs.lpDSLoopStreamBuff; } // IDirectSoundBuffer->GetCurrentPosition(this, DWORD* pdwCurrentPlayCursor, DWORD* // pdwCurrentWriteCursor) (*(code *)pIVar4->lpVtbl->GetCurrentPosition)(pIVar4,&local_c,&local_4); uVar7 = (pSVar6->wiWave).dwLastPos; uVar5 = local_c; if (local_c < uVar7) { uVar5 = (pSVar6->wiWave).dwBufferSize + local_c; } uVar7 = (pSVar6->wiWave).dwProgress + (uVar5 - uVar7); (pSVar6->wiWave).dwLastPos = local_c; (pSVar6->wiWave).dwProgress = uVar7; pvVar2 = NULL; if ((pSVar6->wiWave).dwNextProgressCheck < uVar7) { while ((local_10 = 0, (pSVar6->wiWave).bDonePlaying == 0 || (pvVar2 != NULL))) { local_8 = 1; if ((pSVar6->wiWave).bFoundEnd == 0) { pIVar4 = globs::sound3DGlobs.lpDSStreamBuff; if (looping != 0) { pIVar4 = globs::sound3DGlobs.lpDSLoopStreamBuff; } // IDirectSoundBuffer->Lock(this, DWORD dwOffset, DWORD dwBytes, void** ppvAudioPtr1, // DWORD* pdwAudioBytes1) HVar3 = (*(code *)pIVar4->lpVtbl->Lock) (pIVar4,(pSVar6->wiWave).dwNextWriteOffset,(pSVar6->wiWave).dwNotifySize ,&local_14,&local_18); if (HVar3 != 0) { return; } pckIn = &(pSVar6->wiWave).mmck; phmmioIn = &(pSVar6->wiWave).hmmio; WaveReadFile(*phmmioIn,unaff_ESI,(byte *)unaff_EBP,pckIn,(uint *)&stack0xffffffe4); uVar7 = unaff_EBX; if (unaff_EBX < unaff_ESI) { if ((pSVar6->wiWave).bLoopFile == 0) { (pSVar6->wiWave).bFoundEnd = 1; bVar1 = (((pSVar6->wiWave).waveFormat)->wBitsPerSample != 8) - 1; puVar8 = (uint *)(unaff_EBX + (int)unaff_EBP); for (uVar5 = unaff_ESI - unaff_EBX >> 2; uVar5 != 0; uVar5 -= 1) { *puVar8 = CONCAT22(CONCAT11(bVar1,bVar1),CONCAT11(bVar1,bVar1)) & 0x80808080; puVar8 = puVar8 + 1; } for (uVar5 = unaff_ESI - unaff_EBX & 3; uVar5 != 0; uVar5 -= 1) { *(byte *)puVar8 = bVar1 & 0x80; puVar8 = (uint *)((int)puVar8 + 1); } } else { do { WaveStartDataRead(phmmioIn,pckIn,&(pSVar6->wiWave).mmckInRIFF); WaveReadFile(*phmmioIn,unaff_ESI - unaff_EBX,(byte *)(unaff_EBX + (int)unaff_EBP), pckIn,(uint *)&stack0xffffffe4); unaff_EBX += uVar7; } while (unaff_EBX < unaff_ESI); } } unaff_EBX = uVar7; pIVar4 = globs::sound3DGlobs.lpDSStreamBuff; if (local_8 != 0) { pIVar4 = globs::sound3DGlobs.lpDSLoopStreamBuff; } // IDirectSoundBuffer->Unlock(this, void* pvAudioPtr1, DWORD dwAudioBytes1, void* // pvAudioPtr2, DWORD dwAudioBytes2) (*(code *)pIVar4->lpVtbl->Unlock)(pIVar4,unaff_EBP,unaff_ESI,NULL,0); uVar5 = (pSVar6->wiWave).dwNextWriteOffset + unaff_ESI; uVar7 = (pSVar6->wiWave).dwBufferSize; (pSVar6->wiWave).dwNextWriteOffset = uVar5; (pSVar6->wiWave).dwNextProgressCheck = (pSVar6->wiWave).dwNextProgressCheck + unaff_ESI; looping = local_8; if (uVar7 <= uVar5) { (pSVar6->wiWave).dwNextWriteOffset = uVar5 - uVar7; } } else { pIVar4 = globs::sound3DGlobs.lpDSStreamBuff; if (looping != 0) { pIVar4 = globs::sound3DGlobs.lpDSLoopStreamBuff; } (*(code *)pIVar4->lpVtbl->Lock) (pIVar4,(pSVar6->wiWave).dwNextWriteOffset,(pSVar6->wiWave).dwNotifySize, &local_14,&local_18); bVar1 = (((pSVar6->wiWave).waveFormat)->wBitsPerSample != 8) - 1; puVar8 = unaff_EBP; for (uVar7 = unaff_ESI >> 2; uVar7 != 0; uVar7 -= 1) { *puVar8 = CONCAT22(CONCAT11(bVar1,bVar1),CONCAT11(bVar1,bVar1)) & 0x80808080; puVar8 = puVar8 + 1; } for (uVar7 = unaff_ESI & 3; uVar7 != 0; uVar7 -= 1) { *(byte *)puVar8 = bVar1 & 0x80; puVar8 = (uint *)((int)puVar8 + 1); } pIVar4 = globs::sound3DGlobs.lpDSStreamBuff; if (looping != 0) { pIVar4 = globs::sound3DGlobs.lpDSLoopStreamBuff; } (*(code *)pIVar4->lpVtbl->Unlock)(pIVar4,unaff_EBP,unaff_ESI,NULL,0); uVar7 = (pSVar6->wiWave).mmckInRIFF.cksize; uVar5 = (pSVar6->wiWave).dwNotifySize; if (((uVar5 < uVar7) && (uVar7 - uVar5 <= (pSVar6->wiWave).dwProgress)) || (uVar7 <= (pSVar6->wiWave).dwProgress)) { (pSVar6->wiWave).bDonePlaying = 1; } (pSVar6->wiWave).dwNextProgressCheck = (pSVar6->wiWave).dwNextProgressCheck + unaff_ESI; } pvVar2 = local_14; if ((pSVar6->wiWave).dwProgress <= (pSVar6->wiWave).dwNextProgressCheck) { return; } } Sound3D_Stream_Stop(looping); } } return; } // return (a.x == b.x) && (a.y == b.y) && (a.z == b.z) BOOL __cdecl lego::snd::Sound3D_D3DVectorEqual(Vector3F *a,Vector3F *b) { if (((a->x == b->x) && (a->y == b->y)) && (a->z == b->z)) { return 1; } return 0; } float10 __cdecl lego::snd::Sound3D_SetRollOffFactor(float rollOff) { if (globs::sound3DGlobs.intialised != 0) { if (rollOff < 0.0) { rollOff = 0.0; } if ((ushort)((ushort)(rollOff < 10.0) << 8 | (ushort)(rollOff == 10.0) << 0xe) == 0) { rollOff = 10.0; } (*(code *)(globs::sound3DGlobs.lp3DListenerInfo)->lpVtbl->SetRolloffFactor) (globs::sound3DGlobs.lp3DListenerInfo,rollOff,0); } return (float10)rollOff; } int __cdecl lego::snd::Sound3D_MinVolume(void) { return -10000; } void __cdecl lego::ddraw::DirectDraw_Initialise(HWND hWnd) { globs::directDrawGlobs.hWnd = hWnd; globs::directDrawGlobs.lpDirectDraw = NULL; globs::directDrawGlobs.fSurf = NULL; globs::directDrawGlobs.bSurf = NULL; globs::directDrawGlobs.zSurf = NULL; globs::directDrawGlobs.lpFrontClipper = NULL; globs::directDrawGlobs.driverList = NULL; globs::directDrawGlobs.deviceList = NULL; globs::directDrawGlobs.modeList = NULL; globs::directDrawGlobs.driverCount = 0; globs::directDrawGlobs.deviceCount = 0; globs::directDrawGlobs.modeCount = 0; return; } BOOL __cdecl lego::ddraw::DirectDraw_EnumDrivers(Graphics_Driver *ref_list,uint *out_count) { globs::directDrawGlobs.driverList = ref_list; DirectDrawEnumerateA(DirectDraw_EnumDriverCallback,NULL); *out_count = globs::directDrawGlobs.driverCount; return 1; } BOOL lego::ddraw::DirectDraw_EnumDriverCallback (LPGUID lpGUID,LPSTR lpDriverDescription,LPSTR lpDriverName,LPVOID lpContext) { Graphics_Driver *pGVar1; globs::directDrawGlobs.driverList[globs::directDrawGlobs.driverCount].flags = GRAPHICS_DRIVER_FLAG_VALID; if (lpGUID == NULL) { globs::directDrawGlobs.driverList[globs::directDrawGlobs.driverCount].flags = globs::directDrawGlobs.driverList[globs::directDrawGlobs.driverCount].flags | GRAPHICS_DRIVER_FLAG_PRIMARY; globs::directDrawGlobs.driverList[globs::directDrawGlobs.driverCount].flags = globs::directDrawGlobs.driverList[globs::directDrawGlobs.driverCount].flags | GRAPHICS_DRIVER_FLAG_WINDOWOK; } else { pGVar1 = globs::directDrawGlobs.driverList + globs::directDrawGlobs.driverCount; (pGVar1->guid).Data1 = lpGUID->Data1; *(undefined4 *)&(pGVar1->guid).Data2 = *(undefined4 *)&lpGUID->Data2; *(undefined4 *)(pGVar1->guid).Data4 = *(undefined4 *)lpGUID->Data4; *(undefined4 *)((pGVar1->guid).Data4 + 4) = *(undefined4 *)(lpGUID->Data4 + 4); } std::sprintf(globs::directDrawGlobs.driverList[globs::directDrawGlobs.driverCount].desc,"%s (%s)", lpDriverDescription,lpDriverName); globs::directDrawGlobs.driverCount = globs::directDrawGlobs.driverCount + 1; return 1; } BOOL __cdecl lego::ddraw::DirectDraw_EnumDevices (Graphics_Driver *driver,Graphics_Device *ref_list,uint *out_count) { HRESULT HVar1; uint uVar2; GUID *pGVar3; IUnknown *local_8; Graphics_Device *local_4; uVar2 = 0; globs::directDrawGlobs.deviceCount = 0; HVar1 = DirectDrawCreate(&driver->guid,(IDirectDraw **)&local_4,NULL); if (HVar1 == 0) { HVar1 = (**(code **)(local_4->guid).Data1) ((IUnknown *)local_4,(IID *)&idl::IID_IDirectDraw4,&local_8); if (HVar1 == 0) { pGVar3 = &idl::IID_IDirect3D3; HVar1 = (*local_8->lpVtbl->QueryInterface)(local_8,(IID *)&idl::IID_IDirect3D3,&driver); if (HVar1 == 0) { globs::directDrawGlobs.deviceList = local_4; (*local_8->lpVtbl[1].QueryInterface)(local_8,(IID *)DirectDraw_EnumDeviceCallback,NULL); (**(code **)(*(int *)pGVar3 + 8))(pGVar3); } uVar2 = (uint)(HVar1 == 0); (**(code **)(*(int *)pGVar3 + 8))(pGVar3); } (**(code **)((local_4->guid).Data1 + 8))(local_4); } *out_count = globs::directDrawGlobs.deviceCount; return uVar2; } HRESULT lego::ddraw::DirectDraw_EnumDeviceCallback (LPGUID lpGuid,LPSTR lpDeviceDescription,LPSTR lpDeviceName, D3DDEVICEDESC_V1 *lpHWDesc,D3DDEVICEDESC_V1 *lpHELDesc,LPVOID lpContext) { Graphics_Device *pGVar1; Graphics_DeviceFlags GVar2; pGVar1 = globs::directDrawGlobs.deviceList + globs::directDrawGlobs.deviceCount; pGVar1->flags = GRAPHICS_DEVICE_FLAG_VALID; if (lpHWDesc->dcmColorModel != 0) { pGVar1->flags = GRAPHICS_DEVICE_FLAG_VALID|GRAPHICS_DEVICE_FLAG_HARDWARE; lpHELDesc = lpHWDesc; } // D3DDD_COLORMODEL (0x1) and D3DCOLOR_RGB (0x2) if (((*(byte *)&lpHELDesc->dwFlags & 1) != 0) && (lpHELDesc->dcmColorModel == 2)) { pGVar1->flags = pGVar1->flags | GRAPHICS_DEVICE_FLAG_COLOUR; } // D3DDD_DEVICERENDERBITDEPTH (0x80) if ((*(byte *)&lpHELDesc->dwFlags & 0x80) != 0) { // // DDBD_8 (0x800) 8 bpp if ((lpHELDesc->dwDeviceRenderBitDepth & 0x800) != 0) { pGVar1->flags = pGVar1->flags | GRAPHICS_DEVICE_FLAG_DEPTH8; } // DDBD_16 (0x400) 16 bpp if ((lpHELDesc->dwDeviceRenderBitDepth & 0x400) != 0) { pGVar1->flags = pGVar1->flags | GRAPHICS_DEVICE_FLAG_DEPTH16; } // DDBD_24 (0x200) 24 bpp if ((lpHELDesc->dwDeviceRenderBitDepth & 0x200) != 0) { pGVar1->flags = pGVar1->flags | GRAPHICS_DEVICE_FLAG_DEPTH24; } // DDBD_32 (0x100) 32 bpp if ((lpHELDesc->dwDeviceRenderBitDepth & 0x100) != 0) { pGVar1->flags = pGVar1->flags | GRAPHICS_DEVICE_FLAG_DEPTH32; } } // D3DDD_DEVCAPS (0x2) if ((*(byte *)&lpHELDesc->dwFlags & 2) != 0) { // D3DDEVCAPS_TEXTUREVIDEOMEMORY (0x200) if ((lpHELDesc->dwDevCaps & 0x200) == 0) { // D3DDEVCAPS_TEXTURESYSTEMMEMORY (0x100) if ((lpHELDesc->dwDevCaps & 0x100) == 0) goto LAB_0047c71d; GVar2 = pGVar1->flags | GRAPHICS_DEVICE_FLAG_SYSTEMTEXTURE; } else { GVar2 = pGVar1->flags | GRAPHICS_DEVICE_FLAG_VIDEOTEXTURE; } pGVar1->flags = GVar2; } LAB_0047c71d: (pGVar1->guid).Data1 = lpGuid->Data1; *(undefined4 *)&(pGVar1->guid).Data2 = *(undefined4 *)&lpGuid->Data2; *(undefined4 *)(pGVar1->guid).Data4 = *(undefined4 *)lpGuid->Data4; *(undefined4 *)((pGVar1->guid).Data4 + 4) = *(undefined4 *)(lpGuid->Data4 + 4); std::sprintf(pGVar1->desc,"%s (%s)",lpDeviceName,lpDeviceDescription); // DIENUM_CONTINUE (0x1) globs::directDrawGlobs.deviceCount = globs::directDrawGlobs.deviceCount + 1; return 1; } BOOL __cdecl lego::ddraw::DirectDraw_EnumModes (Graphics_Driver *driver,BOOL fullScreen,Graphics_Mode *ref_list,uint *out_count) { HRESULT HVar1; uint uVar2; IDirectDraw *ddraw1; uVar2 = 0; globs::directDrawGlobs.modeCount = 0; if ((driver != NULL) && ((driver->flags & GRAPHICS_DRIVER_FLAG_VALID) != GRAPHICS_DRIVER_FLAG_NONE)) { HVar1 = DirectDrawCreate((LPGUID)(~-(uint)((driver->flags & GRAPHICS_DRIVER_FLAG_PRIMARY) != GRAPHICS_DRIVER_FLAG_NONE) & (uint)driver),&ddraw1, NULL); if (HVar1 == 0) { HVar1 = (*ddraw1->lpVtbl->QueryInterface) (ddraw1,&idl::IID_IDirectDraw4,(IDirectDraw4 **)&driver); if (HVar1 == 0) { globs::directDrawGlobs.modeList = ref_list; // IDirectDraw4->EnumDisplayModes(this, DWORD dwFlags, DDSURFACEDESC2* lpDDSurfaceDesc, // void* lpContext, DDENUMMODESCALLBACK2* lpEnumModesCallback) (**(code **)((driver->guid).Data1 + 0x20)) ((IDirectDraw4 *)driver,0,NULL,&fullScreen,DirectDraw_EnumModeCallback); (**(code **)((driver->guid).Data1 + 8))((IDirectDraw4 *)driver); } uVar2 = (uint)(HVar1 == 0); (*ddraw1->lpVtbl->Release)(ddraw1); } } *out_count = globs::directDrawGlobs.modeCount; return uVar2; } HRESULT lego::ddraw::DirectDraw_EnumModeCallback(DDSURFACEDESC2 *lpDDSurfaceDesc,LPVOID lpContext) { uint uVar1; Graphics_Mode *pGVar2; pGVar2 = globs::directDrawGlobs.modeList + globs::directDrawGlobs.modeCount; pGVar2->flags = GRAPHICS_MODE_FLAG_VALID; pGVar2->width = lpDDSurfaceDesc->dwWidth; pGVar2->height = lpDDSurfaceDesc->dwHeight; pGVar2->bitDepth = (lpDDSurfaceDesc->ddpfPixelFormat).dwRGBBitCount; // WARNING: Load size is inaccurate // lpContext (BOOL* isFullScreen) if (*lpContext == 0) { std::sprintf(pGVar2->desc,"%ix%i",lpDDSurfaceDesc->dwWidth,lpDDSurfaceDesc->dwHeight); } else { std::sprintf(pGVar2->desc,"%ix%i (%i bit)",lpDDSurfaceDesc->dwWidth,lpDDSurfaceDesc->dwHeight, (lpDDSurfaceDesc->ddpfPixelFormat).dwRGBBitCount); } // WARNING: Load size is inaccurate // lpContext (BOOL* isFullScreen) if ((*lpContext == 0) && (globs::directDrawGlobs.modeCount != 0)) { uVar1 = main::Main_GetWindowsBitDepth(); if (pGVar2->bitDepth != uVar1) { // Bit depth doesn't match system, we can't use this in windowed pGVar2->flags = pGVar2->flags & 0xfffffffe; // DDENUMRET_OK (0x1) // skip incrementing COUNT and return return 1; } } // DDENUMRET_OK (0x1) globs::directDrawGlobs.modeCount = globs::directDrawGlobs.modeCount + 1; return 1; } BOOL __cdecl lego::ddraw::DirectDraw_Setup (BOOL fullscreen,Graphics_Driver *driver,Graphics_Device *device,Graphics_Mode *screen, uint xPos,uint yPos,uint width,uint height) { HRESULT HVar1; int iVar2; BOOL BVar3; LPGUID lpGUID; DDSURFACEDESC2 *pDVar4; IDirectDraw *ddraw1; uint dwBPP; DDSCAPS2 caps; DDSURFACEDESC2 surf; lpGUID = NULL; dwBPP = 0x10; if ((driver != NULL) && ((*(byte *)&driver->flags & GRAPHICS_DRIVER_FLAG_VALID) == 0)) { driver = NULL; } if ((device != NULL) && ((*(byte *)&device->flags & GRAPHICS_DEVICE_FLAG_VALID) == 0)) { device = NULL; } if (screen != NULL) { if ((*(byte *)&screen->flags & GRAPHICS_MODE_FLAG_VALID) == 0) { screen = NULL; } if (screen != NULL) { width = screen->width; height = screen->height; dwBPP = screen->bitDepth; } } globs::directDrawGlobs.fullScreen = fullscreen; if (driver != NULL) { lpGUID = (LPGUID)(~-(uint)((driver->flags & GRAPHICS_DRIVER_FLAG_PRIMARY) != GRAPHICS_DRIVER_FLAG_NONE) & (uint)driver); } globs::directDrawGlobs.width = width; globs::directDrawGlobs.height = height; main::Main_SetupDisplay(fullscreen,xPos,yPos,width,height); HVar1 = DirectDrawCreate(lpGUID,&ddraw1,NULL); if (HVar1 == 0) { HVar1 = (*ddraw1->lpVtbl->QueryInterface) (ddraw1,&idl::IID_IDirectDraw4,&globs::directDrawGlobs.lpDirectDraw); if (HVar1 == 0) { // IDirectDraw4->SetCooperativeLevel(this, HWND hWnd, DWORD dwFlags) // // FullScreen = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN (0x11) // Windowed = DDSCL_NORMAL (0x8) HVar1 = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->SetCooperativeLevel) (globs::directDrawGlobs.lpDirectDraw,globs::directDrawGlobs.hWnd, (-(uint)(fullscreen != 0) & 9) + 8); if (HVar1 == 0) { if (fullscreen == 0) { iVar2 = 0; } else { // IDirectDraw4->SetDisplayMode(this, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD // dwRefreshRate, DWORD dwFlags) iVar2 = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->SetDisplayMode) (globs::directDrawGlobs.lpDirectDraw,width,height,dwBPP,0,0); } if (iVar2 == 0) { pDVar4 = &surf; for (iVar2 = 0x1f; iVar2 != 0; iVar2 += -1) { pDVar4->dwSize = 0; pDVar4 = (DDSURFACEDESC2 *)&pDVar4->dwFlags; } surf.dwSize = 0x7c; surf.dwFlags = 1; surf.ddsCaps.dwCaps = 0x2200; if (fullscreen != 0) { surf.dwFlags = 0x21; surf.dwBackBufferCount_Depth = 1; surf.ddsCaps.dwCaps = 0x2218; } // IDirectDraw4->CreateSurface(this, DDSURFACEDESC2* lpDDSurfaceDesc, // IDirectDrawSurface4** lplpDDSurface, IUnknown* pUnkOuter) HVar1 = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreateSurface) (globs::directDrawGlobs.lpDirectDraw,&surf,&globs::directDrawGlobs.fSurf ,NULL); if (HVar1 == 0) { if (fullscreen == 0) { surf.ddsCaps.dwCaps = surf.ddsCaps.dwCaps & 0xfffffdff | 0x40; surf.dwFlags |= 6; // IDirectDraw4->CreateSurface(this, DDSURFACEDESC2* lpDDSurfaceDesc, // IDirectDrawSurface4** lplpDDSurface, IUnknown* pUnkOuter) surf.dwHeight = height; surf.dwWidth = width; iVar2 = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreateSurface) (globs::directDrawGlobs.lpDirectDraw,&surf, &globs::directDrawGlobs.bSurf,NULL); } else { caps.dwCaps = 4; caps.dwCaps2 = 0; caps.dwCaps3 = 0; caps.dwCaps4_VolumeDepth = 0; // IDirectDrawSurface4->GetAttachedSurface(this, DDSCAPS2* lpDDSCaps, // IDirectDrawSurface4** lplpDDAttachedSurface) iVar2 = (*(globs::directDrawGlobs.fSurf)->lpVtbl->GetAttachedSurface) (globs::directDrawGlobs.fSurf,&caps,&globs::directDrawGlobs.bSurf); } if (iVar2 == 0) { BVar3 = DirectDraw_CreateClipper(fullscreen,width,height); if ((BVar3 != 0) && (BVar3 = main::Main_SetupDirect3D (device,ddraw1,globs::directDrawGlobs.bSurf,fullscreen), BVar3 != 0)) { (*ddraw1->lpVtbl->Release)(ddraw1); if (fullscreen != 0) { ShowCursor(FALSE); } return TRUE; } (*(globs::directDrawGlobs.bSurf)->lpVtbl->Release)(globs::directDrawGlobs.bSurf); globs::directDrawGlobs.bSurf = NULL; } (*(globs::directDrawGlobs.fSurf)->lpVtbl->Release)(globs::directDrawGlobs.fSurf); globs::directDrawGlobs.fSurf = NULL; } } } (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->Release)(globs::directDrawGlobs.lpDirectDraw) ; globs::directDrawGlobs.lpDirectDraw = NULL; } (*ddraw1->lpVtbl->Release)(ddraw1); } return FALSE; } void __cdecl lego::ddraw::DirectDraw_Flip(void) { if (globs::directDrawGlobs.fullScreen != 0) { // DDFLIP_WAIT (0x1) (*(globs::directDrawGlobs.fSurf)->lpVtbl->Flip)(globs::directDrawGlobs.fSurf,NULL,1); return; } DirectDraw_BlitBuffers(); return; } BOOL __cdecl lego::ddraw::DirectDraw_SaveBMP(IDirectDrawSurface4 *surface,char *fname) { uint uVar1; char cVar2; char cVar3; File *f; HRESULT HVar4; undefined4 *puVar5; int iVar6; uint uVar7; int iVar8; byte bVar9; BOOL BVar10; DDSURFACEDESC2 *pDVar11; uint size; undefined4 *puVar12; int local_e8; uint local_d8; undefined uStack180; undefined auStack179 [9]; undefined4 local_aa; undefined4 local_a6; uint local_a2; uint local_9e; undefined2 local_9a; undefined2 uStack152; undefined4 local_96; undefined4 local_92; undefined4 local_8e; undefined4 local_8a; undefined4 local_86; undefined4 uStack130; DDSURFACEDESC2 local_7c; bVar9 = 0; uStack180 = 0; BVar10 = 0; puVar5 = (undefined4 *)auStack179; for (iVar6 = 0xd; iVar6 != 0; iVar6 += -1) { *puVar5 = 0; puVar5 = puVar5 + 1; } *(undefined *)puVar5 = 0; cVar3 = '\0'; cVar2 = '\0'; f = io::File_Open(fname,"wb"); if (f != NULL) { pDVar11 = &local_7c; for (iVar6 = 0x1f; iVar6 != 0; iVar6 += -1) { pDVar11->dwSize = 0; pDVar11 = (DDSURFACEDESC2 *)&pDVar11->dwFlags; } local_7c.dwSize = 0x7c; HVar4 = (*surface->lpVtbl->Lock)(surface,NULL,&local_7c,1,NULL); if (HVar4 == 0) { iVar6 = (-(uint)((local_7c.dwWidth * 3 & 3) != 0) & 4) + (local_7c.dwWidth * 3 & 0xfffffffc); size = iVar6 * local_7c.dwHeight; puVar5 = (undefined4 *)io::Mem_Alloc(size); if (puVar5 != NULL) { puVar12 = puVar5; for (uVar7 = size >> 2; uVar7 != 0; uVar7 -= 1) { *puVar12 = 0; puVar12 = puVar12 + 1; } for (iVar8 = 0; iVar8 != 0; iVar8 += -1) { *(undefined *)puVar12 = 0; puVar12 = (undefined4 *)((int)puVar12 + 1); } uVar7 = 0; do { if ((local_7c.ddpfPixelFormat.dwRBitMask >> ((byte)uVar7 & 0x1f) & 1) != 0) { cVar3 += '\x01'; } uVar7 += 1; } while (uVar7 < 0x20); uVar7 = 0; do { if ((local_7c.ddpfPixelFormat.dwGBitMask >> ((byte)uVar7 & 0x1f) & 1) != 0) { cVar2 += '\x01'; } uVar7 += 1; } while (uVar7 < 0x20); uVar7 = 0; do { if ((local_7c.ddpfPixelFormat.dwBBitMask >> ((byte)uVar7 & 0x1f) & 1) != 0) { bVar9 += 1; } uVar7 += 1; } while (uVar7 < 0x20); uVar7 = 0; if (local_7c.dwHeight != 0) { do { iVar8 = 0; local_d8 = 0; if (local_7c.dwWidth != 0) { local_e8 = 0; do { iVar8 += 3; uVar1 = *(uint *)((int)local_7c.lpSurface + local_e8 + uVar7 * local_7c.lPitch); *(char *)((int)puVar5 + iVar8 + ((local_7c.dwHeight - uVar7) + -1) * iVar6 + -1) = (char)(uVar1 >> (bVar9 + cVar2 & 0x1f)) << (8U - cVar3 & 0x1f); *(char *)((int)puVar5 + iVar8 + ((local_7c.dwHeight - uVar7) + -1) * iVar6 + -2) = (char)(uVar1 >> (bVar9 & 0x1f)) << (8U - cVar2 & 0x1f); *(char *)((int)puVar5 + iVar8 + ((local_7c.dwHeight - uVar7) + -1) * iVar6 + -3) = (char)uVar1 << (8 - bVar9 & 0x1f); local_e8 += local_7c.ddpfPixelFormat.dwRGBBitCount >> 3; local_d8 += 1; } while (local_d8 < local_7c.dwWidth); } uVar7 += 1; } while (uVar7 < local_7c.dwHeight); } BVar10 = 1; } (*surface->lpVtbl->Unlock)(surface,NULL); auStack179._1_4_ = size + 0x36; uStack180 = 0x42; auStack179[0] = 0x4d; local_aa = 0x36; local_a6 = 0x28; local_a2 = local_7c.dwWidth; local_9e = local_7c.dwHeight; local_9a = 1; uStack152 = 0x18; local_96 = 0; local_92 = 0; local_8e = 1; local_8a = 1; local_86 = 0; uStack130 = 0; if (BVar10 != 0) { io::File_Write(&uStack180,0x36,1,f); io::File_Write(puVar5,size,1,f); } io::Mem_Free(puVar5); } io::File_Close(f); } return BVar10; } void __cdecl lego::ddraw::DirectDraw_ReturnFrontBuffer(void) { if (globs::directDrawGlobs.fullScreen != 0) { // DDBLT_WAIT (0x1000000) (*(globs::directDrawGlobs.bSurf)->lpVtbl->Blt) (globs::directDrawGlobs.bSurf,NULL,globs::directDrawGlobs.fSurf,NULL,0x1000000,NULL); } return; } void __cdecl lego::ddraw::DirectDraw_BlitBuffers(void) { POINT ptClient; RECT dstRect; RECT srcRect; dstRect.right = globs::directDrawGlobs.width; ptClient.y = 0; ptClient.x = 0; dstRect.left = 0; dstRect.top = 0; dstRect.bottom = globs::directDrawGlobs.height; ClientToScreen(globs::directDrawGlobs.hWnd,(LPPOINT)&ptClient); OffsetRect((LPRECT)&dstRect,ptClient.x,ptClient.y); srcRect.bottom = globs::directDrawGlobs.height; srcRect.left = 0; srcRect.top = 0; srcRect.right = globs::directDrawGlobs.width; // DDBLT_WAIT (0x1000000) (*(globs::directDrawGlobs.fSurf)->lpVtbl->Blt) (globs::directDrawGlobs.fSurf,(LPRECT)&dstRect,globs::directDrawGlobs.bSurf, (LPRECT)&srcRect,0x1000000,NULL); return; } void __cdecl lego::ddraw::DirectDraw_Shutdown(void) { if (globs::directDrawGlobs.fSurf != NULL) { (*(globs::directDrawGlobs.fSurf)->lpVtbl->Release)((IUnknown *)globs::directDrawGlobs.fSurf); } if (globs::directDrawGlobs.lpFrontClipper != NULL) { (*(globs::directDrawGlobs.lpFrontClipper)->lpVtbl->Release) ((IUnknown *)globs::directDrawGlobs.lpFrontClipper); } if (globs::directDrawGlobs.lpBackClipper != NULL) { (*(globs::directDrawGlobs.lpBackClipper)->lpVtbl->Release) ((IUnknown *)globs::directDrawGlobs.lpBackClipper); } if (globs::directDrawGlobs.lpDirectDraw != NULL) { if (globs::directDrawGlobs.fullScreen != 0) { (*(code *)(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->RestoreDisplayMode) (globs::directDrawGlobs.lpDirectDraw); } if (globs::directDrawGlobs.lpDirectDraw != NULL) { (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->Release) ((IUnknown *)globs::directDrawGlobs.lpDirectDraw); } } return; } void __cdecl lego::ddraw::DirectDraw_AdjustTextureUsage(uint *ref_textureUsage) { HRESULT HVar1; int iVar2; uint unaff_EDI; DDPIXELFORMAT *pDVar3; DDPIXELFORMAT pixFmt; pDVar3 = &pixFmt; for (iVar2 = 8; iVar2 != 0; iVar2 += -1) { pDVar3->dwSize = 0; pDVar3 = (DDPIXELFORMAT *)((int)pDVar3 + 4); } pixFmt.dwSize = 0x20; // DDBD_8 (0x800), D3DRMFPTF_PALETTIZED (0x4) HVar1 = (*(globs::mainGlobs.device)->lpVtbl->FindPreferredTextureFormat) (globs::mainGlobs.device,0x800,4,&pixFmt); if (HVar1 != 0) { pDVar3 = &pixFmt; for (iVar2 = 8; iVar2 != 0; iVar2 += -1) { pDVar3->dwSize = 0; pDVar3 = (DDPIXELFORMAT *)&pDVar3->dwFlags; } pixFmt.dwSize = 0x20; // DDBD_16 (0x400), (0x0) HVar1 = (*(globs::mainGlobs.device)->lpVtbl->FindPreferredTextureFormat) (globs::mainGlobs.device,0x400,0,&pixFmt); if (HVar1 == 0) { *(uint *)pixFmt.dwGBitMask = (unaff_EDI >> 3) * *(int *)pixFmt.dwGBitMask; } } return; } BOOL __cdecl lego::ddraw::DirectDraw_GetAvailTextureMem(uint *out_total,uint *out_avil) { int iVar1; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; local_c = 0; local_8 = 0; // DDSCAPS_TEXTURE (0x1000) local_10 = 0x1000; local_4 = 0; *out_total = 0; *out_avil = 0; iVar1 = (*(code *)(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->GetAvailableVidMem) (globs::directDrawGlobs.lpDirectDraw,&local_10,out_total,out_avil); return (uint)(iVar1 == 0); } HRESULT __cdecl lego::ddraw::DirectDraw_Clear(Area2F *window,uint colour) { HRESULT HVar1; int iVar2; undefined4 *puVar3; longlong lVar4; tagRECT local_74; undefined4 local_64 [20]; uint local_14; puVar3 = local_64; for (iVar2 = 0x19; iVar2 != 0; iVar2 += -1) { *puVar3 = 0; puVar3 = puVar3 + 1; } local_64[0] = 100; local_14 = DirectDraw_GetColour(globs::directDrawGlobs.bSurf,colour); if (window != NULL) { lVar4 = __ftol((float10)window->x); local_74.left = (LONG)lVar4; lVar4 = __ftol((float10)window->y); local_74.top = (LONG)lVar4; lVar4 = __ftol((float10)window->width + (float10)window->x); local_74.right = (LONG)lVar4; lVar4 = __ftol((float10)window->height + (float10)window->y); local_74.bottom = (LONG)lVar4; // DDBLT_WAIT | DDBLT_COLORFILL (0x1000000 | 0x400) HVar1 = (*(globs::directDrawGlobs.bSurf)->lpVtbl->Blt) (globs::directDrawGlobs.bSurf,(LPRECT)&local_74,NULL,NULL,0x1000400,local_64); return HVar1; } // DDBLT_WAIT | DDBLT_COLORFILL (0x1000000 | 0x400) HVar1 = (*(globs::directDrawGlobs.bSurf)->lpVtbl->Blt) (globs::directDrawGlobs.bSurf,NULL,NULL,NULL,0x1000400,local_64); return HVar1; } BOOL __cdecl lego::ddraw::DirectDraw_CreateClipper(BOOL fullscreen,uint width,uint height) { int iVar1; HRGN hrgn; DWORD size; LPRGNDATA lpRgnData; int unaff_EBX; int unaff_EBP; IDirectDraw4 *pIVar2; pIVar2 = globs::directDrawGlobs.lpDirectDraw; iVar1 = (*(code *)(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreateClipper) (globs::directDrawGlobs.lpDirectDraw,0,0x76bc98,0); if (iVar1 == 0) { hrgn = CreateRectRgn(0,0,unaff_EBP,unaff_EBX); size = GetRegionData(hrgn,0,NULL); lpRgnData = (LPRGNDATA)io::Mem_Alloc(size); GetRegionData(hrgn,size,lpRgnData); iVar1 = (*(code *)(globs::directDrawGlobs.lpBackClipper)->lpVtbl->SetClipList) (globs::directDrawGlobs.lpBackClipper,lpRgnData,0); if (iVar1 == 0) { io::Mem_Free(lpRgnData); iVar1 = (*(code *)(globs::directDrawGlobs.bSurf)->lpVtbl->SetClipper) (globs::directDrawGlobs.bSurf,globs::directDrawGlobs.lpBackClipper); if (iVar1 == 0) { if (pIVar2 != NULL) { return 1; } iVar1 = (*(code *)(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreateClipper) (globs::directDrawGlobs.lpDirectDraw,0,0x76bc94,0); if (iVar1 == 0) { iVar1 = (*(code *)(globs::directDrawGlobs.lpFrontClipper)->lpVtbl->SetHWnd) (globs::directDrawGlobs.lpFrontClipper,0,globs::directDrawGlobs.hWnd); if (iVar1 == 0) { iVar1 = (*(code *)(globs::directDrawGlobs.fSurf)->lpVtbl->SetClipper) (globs::directDrawGlobs.fSurf,globs::directDrawGlobs.lpFrontClipper); if (iVar1 == 0) { return 1; } } } } (*(globs::directDrawGlobs.lpBackClipper)->lpVtbl->Release) ((IUnknown *)globs::directDrawGlobs.lpBackClipper); globs::directDrawGlobs.lpBackClipper = NULL; } io::Mem_Free(lpRgnData); } return 0; } // WARNING: Could not reconcile some variable overlaps // Previously named DirectDraw_Blt8To16 void __cdecl lego::ddraw::DirectDraw_Blt8ToSurface (IDirectDrawSurface4 *target,IDirectDrawSurface4 *source,D3DRMPaletteEntry *palette) { uint uVar1; uint uVar2; uint uVar3; uint uVar4; bool bVar5; HRESULT HVar6; int iVar7; char cVar8; uint uVar9; uint uVar10; char cVar11; byte bVar12; DDSURFACEDESC2 *pDVar13; uint uStack296; int iStack288; uint uStack272; byte bStack256; byte bStack252; DDSURFACEDESC2 local_f8; DDSURFACEDESC2 local_7c; pDVar13 = &local_7c; for (iVar7 = 0x1f; iVar7 != 0; iVar7 += -1) { pDVar13->dwSize = 0; pDVar13 = (DDSURFACEDESC2 *)&pDVar13->dwFlags; } pDVar13 = &local_f8; for (iVar7 = 0x1f; iVar7 != 0; iVar7 += -1) { pDVar13->dwSize = 0; pDVar13 = (DDSURFACEDESC2 *)&pDVar13->dwFlags; } local_7c.dwSize = 0x7c; local_f8.dwSize = 0x7c; HVar6 = (*source->lpVtbl->Lock)(source,NULL,&local_f8,1,NULL); if (HVar6 == 0) { if ((local_f8.ddpfPixelFormat.dwRGBBitCount == 8) && (HVar6 = (*target->lpVtbl->Lock)(target,NULL,&local_7c,1,NULL), HVar6 == 0)) { if ((local_7c.ddpfPixelFormat.dwRGBBitCount == 0x10) && ((local_7c.dwWidth == local_f8.dwWidth && (local_7c.dwHeight == local_f8.dwHeight)))) { iVar7 = 0; cVar8 = '\0'; do { if ((local_7c.ddpfPixelFormat.dwRBitMask >> ((byte)iVar7 & 0x1f) & 1) != 0) { cVar8 += '\x01'; } iVar7 += 1; } while (iVar7 < 0x20); iVar7 = 0; cVar11 = '\0'; do { if ((local_7c.ddpfPixelFormat.dwGBitMask >> ((byte)iVar7 & 0x1f) & 1) != 0) { cVar11 += '\x01'; } iVar7 += 1; } while (iVar7 < 0x20); iVar7 = 0; bVar12 = 0; do { if ((local_7c.ddpfPixelFormat.dwBBitMask >> ((byte)iVar7 & 0x1f) & 1) != 0) { bVar12 += 1; } iVar7 += 1; } while (iVar7 < 0x20); uStack296 = 0; if (local_f8.dwHeight != 0) { do { uVar10 = 0; if (local_f8.dwWidth != 0) { bStack256 = 8 - cVar8; bStack252 = 8 - cVar11; uStack272._0_1_ = 8 - bVar12; do { iStack288 = 0x18; uVar1 = *(uint *)(uStack296 * local_f8.lPitch + uVar10 + (int)local_f8.lpSurface); uVar9 = 3; bVar5 = true; do { uVar2 = uVar1 >> ((byte)iStack288 & 0x1f) & 0xff; uVar3 = (uint)(palette[uVar2].red >> (bStack256 & 0x1f)); uVar4 = (uint)(palette[uVar2].green >> (bStack252 & 0x1f)); uVar2 = (uint)(palette[uVar2].blue >> ((byte)uStack272 & 0x1f)); if (bVar5) { uStack272 = (uVar3 << (bVar12 + cVar11 & 0x1f) | uVar4 << (bVar12 & 0x1f) | uVar2) << 0x10; } else { uStack272 |= uVar3 << (cVar11 + bVar12 & 0x1f) | uVar4 << (bVar12 & 0x1f) | uVar2; *(uint *)((int)local_7c.lpSurface + (uVar10 + (uVar9 >> 1 & 1) * 2) * 2 + uStack296 * local_7c.lPitch) = uStack272; } uVar9 -= 1; bVar5 = (bool)(bVar5 ^ 1); iStack288 += -8; } while (-1 < iStack288); uVar10 += 4; } while (uVar10 < local_f8.dwWidth); } uStack296 += 1; } while (uStack296 < local_f8.dwHeight); } } (*target->lpVtbl->Unlock)(target,NULL); } (*source->lpVtbl->Unlock)(source,NULL); } return; } uint __cdecl lego::ddraw::DirectDraw_GetColour(IDirectDrawSurface4 *surf,uint colour) { IDirectDrawSurface4Vtbl *pIVar1; byte bVar2; uint uVar3; uint uVar4; uint uVar5; uint uVar6; int iVar7; byte *pbVar8; uint unaff_EBP; int *unaff_ESI; DDPIXELFORMAT *pDVar9; IDirectDrawPalette *ddPal; DDPIXELFORMAT pixFmt; D3DRMPaletteEntry palEntries [256]; uVar6 = colour >> 8 & 0xff; pIVar1 = surf->lpVtbl; pDVar9 = &pixFmt; for (iVar7 = 8; iVar7 != 0; iVar7 += -1) { pDVar9->dwSize = 0; pDVar9 = (DDPIXELFORMAT *)&pDVar9->dwFlags; } pixFmt.dwSize = 0x20; (*pIVar1->GetPixelFormat)(surf,&pixFmt); if (((byte)ddPal & 0x40) == 0) { (*surf->lpVtbl->GetPalette)(surf,(IDirectDrawPalette **)&stack0xfffffbd4); (**(code **)(*unaff_ESI + 0x10))(unaff_ESI,0,0,0x100); uVar3 = 0; pbVar8 = (byte *)((int)&ddPal + 1); while ((((DWORD *)(uint)pbVar8[-1] != &pixFmt.dwRBitMask || (*pbVar8 != uVar6)) || ((uint)pbVar8[1] != (colour & 0xff)))) { uVar3 += 1; pbVar8 = pbVar8 + 4; if (0xff < uVar3) { return 0; } } return uVar3; } uVar3 = DirectDraw_CountMaskBits(pixFmt.dwFourCC); uVar4 = DirectDraw_CountMaskBits(pixFmt.dwRGBBitCount); uVar5 = DirectDraw_CountMaskBits(pixFmt.dwRBitMask); bVar2 = (byte)uVar5; return (unaff_EBP >> (8U - (char)uVar3 & 0x1f)) << (bVar2 + (char)uVar4 & 0x1f) | (uVar6 >> (8U - (char)uVar4 & 0x1f)) << (bVar2 & 0x1f) | (colour & 0xff) >> (8 - bVar2 & 0x1f); } uint __cdecl lego::ddraw::DirectDraw_CountMaskBits(uint mask) { uint count; count = 0; if (mask != 0) { do { mask &= mask - 1; count += 1; } while (mask != 0); } return count; } void __cdecl lego::image::Image_Initialise(void) { int iVar1; Image_Globs *pIVar2; pIVar2 = &globs::imageGlobs; for (iVar1 = 0x20; iVar1 != 0; iVar1 += -1) { pIVar2->listSet[0] = NULL; pIVar2 = (Image_Globs *)(pIVar2->listSet + 1); } globs::imageGlobs.flags = 1; return; } void __cdecl lego::image::Image_Shutdown(void) { Image_Globs *pIVar1; Image_RemoveAll(); pIVar1 = &globs::imageGlobs; do { if (pIVar1->listSet[0] != NULL) { io::Mem_Free(pIVar1->listSet[0]); } pIVar1 = (Image_Globs *)(pIVar1->listSet + 1); } while (pIVar1 < (Image_Globs *)&globs::imageGlobs.freeList); globs::imageGlobs.freeList = NULL; globs::imageGlobs.flags = 0; return; } void __cdecl lego::image::Image_Remove(Image *image) { (*image->surface->lpVtbl->Release)((IUnknown *)image->surface); image->nextFree = globs::imageGlobs.freeList; globs::imageGlobs.freeList = image; return; } BOOL __cdecl lego::image::Image_CopyToDataToSurface(IDirectDrawSurface4 *surface,D3DRMImage *image) { HRESULT HVar1; int iVar2; DWORD *pDVar3; DDSURFACEDESC2 local_7c; pDVar3 = &local_7c.dwFlags; for (iVar2 = 0x1e; iVar2 != 0; iVar2 += -1) { *pDVar3 = 0; pDVar3 = pDVar3 + 1; } // IDirectDrawSurface4::Lock(IDirectDrawSurface4* This, RECT* a, DDSURFACEDESC2* b, // DWORD c, HANDLE d) // DDLOCK_WRITEONLY | DDLOCK_WAIT (0x20 | 0x1) local_7c.dwSize = 0x7c; HVar1 = (*surface->lpVtbl->Lock)(surface,NULL,&local_7c,0x21,NULL); if (HVar1 == 0) { iVar2 = image->depth; if (7 < iVar2) { if (iVar2 == 8) { Image_8BitSourceCopy(&local_7c,image); } else { if ((iVar2 != 0x10) && (iVar2 == 0x18)) { Image_24BitSourceCopy(&local_7c,image); } } } // IDirectDrawSurface4::Unock(IDirectDrawSurface4* This, RECT* a) (*surface->lpVtbl->Unlock)(surface,NULL); return 1; } return 0; } BOOL __cdecl lego::image::Image_8BitSourceCopy(DDSURFACEDESC2 *desc,D3DRMImage *image) { DWORD DVar1; int iVar2; D3DRMPaletteEntry *pDVar3; uint uVar4; uint uVar5; uint uVar6; uint uVar7; uint uVar8; uint uVar9; uint uVar10; uint uVar11; uint uVar12; uint uVar13; int iVar14; undefined2 *puVar15; undefined2 *puVar16; byte *pbVar17; int local_30; byte local_2c; byte local_18; byte local_10; DVar1 = (desc->ddpfPixelFormat).dwRGBBitCount; if (DVar1 == 8) { return 0; } if (DVar1 == 0x10) { uVar9 = (desc->ddpfPixelFormat).dwGBitMask; puVar16 = (undefined2 *)desc->lpSurface; iVar2 = image->bytes_per_line; pDVar3 = image->palette; uVar4 = desc->lPitch; pbVar17 = image->buffer1; uVar10 = (desc->ddpfPixelFormat).dwBBitMask; uVar8 = (desc->ddpfPixelFormat).dwRBitMask; uVar5 = Image_CountMaskBits(uVar8); uVar6 = Image_CountMaskBits(uVar9); uVar7 = Image_CountMaskBits(uVar10); uVar8 = Image_CountMaskBitShift(uVar8); uVar9 = Image_CountMaskBitShift(uVar9); uVar10 = Image_CountMaskBitShift(uVar10); local_30 = 0; if (0 < image->height) { do { iVar14 = 0; if (0 < image->width) { local_2c = 8 - (char)uVar7; local_10 = 8 - (char)uVar6; uVar11 = 8 - uVar5; uVar13 = uVar7; puVar15 = puVar16; do { uVar12 = (uint)*pbVar17; pbVar17 = pbVar17 + 1; puVar16 = puVar15 + 1; local_18 = (byte)(8 - uVar5); uVar13 = (uVar13 & 0xffff0000 | (uint)(pDVar3[uVar12].blue >> (local_2c & 0x1f))) << ((byte)uVar10 & 0x1f) | ((uint)pDVar3 & 0xffff0000 | (uint)(pDVar3[uVar12].red >> (local_18 & 0x1f))) << ((byte)uVar8 & 0x1f) | (uVar11 & 0xffff0000 | (uint)(pDVar3[uVar12].green >> (local_10 & 0x1f))) << ((byte)uVar9 & 0x1f); iVar14 += 1; *puVar15 = (short)uVar13; uVar11 = image->width; puVar15 = puVar16; } while (iVar14 < (int)uVar11); } pbVar17 = pbVar17 + (iVar2 - image->width); puVar16 = puVar16 + ((uVar4 >> 1) - image->width); local_30 += 1; } while (local_30 < image->height); } Image_FlipSurface(desc); return 1; } if (DVar1 == 0x18) { return 0; } if (DVar1 != 0x20) { return 1; } return 0; } uint __cdecl lego::image::Image_CountMaskBits(uint mask) { uint uVar1; uint uVar2; uVar1 = 0; uVar2 = 0; do { if ((mask & 1 << ((byte)uVar2 & 0x1f)) != 0) { uVar1 += 1; } uVar2 += 1; } while (uVar2 < 0x20); return uVar1; } uint __cdecl lego::image::Image_CountMaskBitShift(uint mask) { uint uVar1; uVar1 = 0; do { if ((mask & 1 << ((byte)uVar1 & 0x1f)) != 0) { return uVar1; } uVar1 += 1; } while (uVar1 < 0x20); return 0xffffffff; } void __cdecl lego::image::Image_FlipSurface(DDSURFACEDESC2 *desc) { uint size; int iVar1; undefined4 *buffer; uint uVar2; undefined4 *puVar3; undefined4 *puVar4; undefined4 *puVar5; undefined4 *local_8; uint local_4; puVar3 = (undefined4 *)desc->lpSurface; iVar1 = (int)desc->lPitch / 2; size = iVar1 * 2; local_8 = (undefined4 *)((int)puVar3 + (desc->dwHeight - 1) * iVar1 * 2); buffer = (undefined4 *)io::Mem_Alloc(size); local_4 = 0; if ((desc->dwHeight & 0xfffffffe) != 0) { do { puVar4 = puVar3; puVar5 = buffer; for (uVar2 = size >> 2; uVar2 != 0; uVar2 -= 1) { *puVar5 = *puVar4; puVar4 = puVar4 + 1; puVar5 = puVar5 + 1; } for (uVar2 = size & 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar5 = *(undefined *)puVar4; puVar4 = (undefined4 *)((int)puVar4 + 1); puVar5 = (undefined4 *)((int)puVar5 + 1); } puVar4 = local_8; puVar5 = puVar3; for (uVar2 = size >> 2; uVar2 != 0; uVar2 -= 1) { *puVar5 = *puVar4; puVar4 = puVar4 + 1; puVar5 = puVar5 + 1; } for (uVar2 = size & 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar5 = *(undefined *)puVar4; puVar4 = (undefined4 *)((int)puVar4 + 1); puVar5 = (undefined4 *)((int)puVar5 + 1); } puVar4 = buffer; puVar5 = local_8; for (uVar2 = size >> 2; uVar2 != 0; uVar2 -= 1) { *puVar5 = *puVar4; puVar4 = puVar4 + 1; puVar5 = puVar5 + 1; } for (uVar2 = size & 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar5 = *(undefined *)puVar4; puVar4 = (undefined4 *)((int)puVar4 + 1); puVar5 = (undefined4 *)((int)puVar5 + 1); } local_4 += 1; puVar3 = (undefined4 *)((int)puVar3 + size); local_8 = (undefined4 *)((int)local_8 + iVar1 * -2); } while (local_4 < desc->dwHeight >> 1); } io::Mem_Free(buffer); return; } BOOL __cdecl lego::image::Image_24BitSourceCopy(DDSURFACEDESC2 *desc,D3DRMImage *image) { byte *pbVar1; byte *pbVar2; byte bVar3; DWORD DVar4; int iVar5; uint uVar6; uint uVar7; uint uVar8; uint uVar9; uint uVar10; uint uVar11; uint uVar12; uint uVar13; uint uVar14; D3DRMImage *pDVar15; int iVar16; byte *pbVar17; undefined2 *puVar18; undefined2 *puVar19; int local_2c; byte local_18; byte local_10; DVar4 = (desc->ddpfPixelFormat).dwRGBBitCount; if (DVar4 == 8) { return 0; } if (DVar4 == 0x10) { uVar11 = (desc->ddpfPixelFormat).dwGBitMask; uVar12 = (desc->ddpfPixelFormat).dwBBitMask; puVar19 = (undefined2 *)desc->lpSurface; iVar5 = image->bytes_per_line; pbVar17 = image->buffer1; uVar6 = desc->lPitch; uVar10 = (desc->ddpfPixelFormat).dwRBitMask; uVar7 = Image_CountMaskBits(uVar10); uVar8 = Image_CountMaskBits(uVar11); uVar9 = Image_CountMaskBits(uVar12); uVar10 = Image_CountMaskBitShift(uVar10); uVar11 = Image_CountMaskBitShift(uVar11); uVar12 = Image_CountMaskBitShift(uVar12); local_2c = 0; if (0 < image->height) { do { iVar16 = 0; if (0 < image->width) { local_10 = 8 - (char)uVar7; local_18 = 8 - (char)uVar9; uVar13 = uVar8; uVar14 = uVar7; pDVar15 = image; puVar18 = puVar19; do { bVar3 = *pbVar17; pbVar1 = pbVar17 + 1; puVar19 = puVar18 + 1; pbVar2 = pbVar17 + 2; pbVar17 = pbVar17 + 3; uVar14 = (uVar14 & 0xffff0000 | (uint)(bVar3 >> (local_18 & 0x1f))) << ((byte)uVar12 & 0x1f); pDVar15 = (D3DRMImage *) (((uint)pDVar15 & 0xffff0000 | (uint)(*pbVar1 >> (8U - (char)uVar8 & 0x1f))) << ((byte)uVar11 & 0x1f) | uVar14 | (uVar13 & 0xffff0000 | (uint)(*pbVar2 >> (local_10 & 0x1f))) << ((byte)uVar10 & 0x1f)); iVar16 += 1; *puVar18 = (short)pDVar15; uVar13 = image->width; puVar18 = puVar19; } while (iVar16 < (int)uVar13); } pbVar17 = pbVar17 + iVar5 + image->width * -3; local_2c += 1; puVar19 = puVar19 + ((uVar6 >> 1) - image->width); } while (local_2c < image->height); } Image_FlipSurface(desc); return 1; } if (DVar4 == 0x18) { return 0; } if (DVar4 != 0x20) { return 1; } return 0; } Image * __cdecl lego::image::Image_LoadBMPScaled(char *fileName,uint width,uint height) { COLORREF pen255; BITMAP_FILE_INFO_STRUCT *data; HRESULT HVar1; BOOL BVar2; Image *pIVar3; int iVar4; uint unaff_EBX; COLORREF unaff_ESI; IDirectDrawSurface4 *unaff_EDI; int *piVar5; DWORD *pDVar6; DDSURFACEDESC2 *pDVar7; IDirectDrawSurface4 *local_4c4; COLORREF local_4c0; uint length; D3DRMImage local_4b8; DDSURFACEDESC2 surfaceDesc; char local_400 [1024]; local_4b8.width = 0; piVar5 = &local_4b8.height; for (iVar4 = 0xe; iVar4 != 0; iVar4 += -1) { *piVar5 = 0; piVar5 = piVar5 + 1; } surfaceDesc.dwSize = 0; pDVar6 = &surfaceDesc.dwFlags; for (iVar4 = 0x1e; iVar4 != 0; iVar4 += -1) { *pDVar6 = 0; pDVar6 = pDVar6 + 1; } length = 0; local_4c4 = NULL; pen255 = Image_RGB2CR(0,0,0); local_4c0 = pen255; data = (BITMAP_FILE_INFO_STRUCT *)io::File_LoadBinary(fileName,&length); if (data != NULL) { BMP_Parse(data,length,&local_4b8); if (local_4b8.rgb == 0) { local_4c0 = Image_RGB2CR((local_4b8.palette)->red,(local_4b8.palette)->green, (local_4b8.palette)->blue); if (local_4b8.rgb == 0) { pen255 = Image_RGB2CR(local_4b8.palette[0xff].red,local_4b8.palette[0xff].green, local_4b8.palette[0xff].blue); } } std::sprintf(local_400,"Data\\%s",fileName); pDVar7 = &surfaceDesc; for (iVar4 = 0x1f; iVar4 != 0; iVar4 += -1) { pDVar7->dwSize = 0; pDVar7 = (DDSURFACEDESC2 *)&pDVar7->dwFlags; } surfaceDesc.dwWidth = local_4b8.width; surfaceDesc.dwHeight = local_4b8.height; surfaceDesc.dwSize = 0x7c; surfaceDesc.dwFlags = 7; surfaceDesc.ddsCaps.dwCaps = 0x840; // IDirectDraw4::CreateSurface(IDirectDraw4* This, DDSURFACEDESC2* lpDDSurfaceDesc, // IDirectDrawSurface4** lplpDDSurface, IUnknown* pUnkOuter) HVar1 = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreateSurface) (globs::directDrawGlobs.lpDirectDraw,&surfaceDesc,&local_4c4,NULL); if (HVar1 == 0) { BVar2 = Image_CopyToDataToSurface(unaff_EDI,(D3DRMImage *)&stack0xfffffb38); if (BVar2 != 0) { pIVar3 = Image_Create(unaff_EDI,unaff_EBX,(uint)local_4c4,unaff_ESI,pen255); if (pIVar3 != NULL) { BMP_Cleanup((D3DRMImage *)&stack0xfffffb38); io::Mem_Free(data); return pIVar3; } } } if (unaff_EDI != NULL) { (*unaff_EDI->lpVtbl->Release)((IUnknown *)unaff_EDI); } BMP_Cleanup((D3DRMImage *)&stack0xfffffb38); io::Mem_Free(data); } return NULL; } COLORREF __cdecl lego::image::Image_RGB2CR(byte red,byte green,byte blue) { _red = (uint)CONCAT12(blue,CONCAT11(green,red)); return _red; } void __cdecl lego::image::Image_SetPenZeroTrans(Image *image) { DDCOLORKEY colorKey; colorKey.dwColorSpaceLowValue = image->penZero; colorKey.dwColorSpaceHighValue = colorKey.dwColorSpaceLowValue; (*image->surface->lpVtbl->SetColorKey)(image->surface,8,&colorKey); image->flags = image->flags | IMAGE_FLAG_TRANS; return; } void __cdecl lego::image::Image_SetupTrans (Image *image,float red_low,float green_low,float blue_low,float red_high,float green_high ,float blue_high) { byte bVar1; COLORREF rgb; COLORREF rgb_00; longlong lVar2; byte bVar3; DDCOLORKEY colorKey; lVar2 = __ftol((float10)blue_low * (float10)255.0); bVar3 = (byte)lVar2; lVar2 = __ftol((float10)green_low * (float10)255.0); bVar1 = (byte)lVar2; lVar2 = __ftol((float10)red_low * (float10)255.0); rgb = Image_RGB2CR((byte)lVar2,bVar1,bVar3); lVar2 = __ftol((float10)blue_high * (float10)255.0); bVar3 = (byte)lVar2; lVar2 = __ftol((float10)green_high * (float10)255.0); bVar1 = (byte)lVar2; lVar2 = __ftol((float10)red_high * (float10)255.0); rgb_00 = Image_RGB2CR((byte)lVar2,bVar1,bVar3); colorKey.dwColorSpaceLowValue = Image_DDColorMatch(image->surface,rgb); colorKey.dwColorSpaceHighValue = Image_DDColorMatch(image->surface,rgb_00); // IDirectDrawSurface4::SetColorKey(DWORD a, LPDDCOLORKEY b) (*image->surface->lpVtbl->SetColorKey)(image->surface,8,&colorKey); image->flags = image->flags | IMAGE_FLAG_TRANS; return; } // Image_Blt void __cdecl lego::image::Image_DisplayScaled(Image *image,Area2F *src,Point2F *destPos,Size2F *destSize) { float fVar1; float10 fVar2; longlong lVar3; DWORD DVar4; undefined4 local_20; undefined4 local_1c; undefined4 local_18; undefined4 local_14; undefined4 local_10; undefined4 local_c; undefined4 local_8; undefined4 local_4; if (src != NULL) { fVar2 = std::floor((double)src->x); lVar3 = __ftol(fVar2); local_10 = (undefined4)lVar3; fVar2 = std::floor((double)src->y); lVar3 = __ftol(fVar2); local_c = (undefined4)lVar3; fVar2 = std::floor((double)(src->width + src->x)); lVar3 = __ftol(fVar2); local_8 = (undefined4)lVar3; fVar2 = std::floor((double)(src->height + src->y)); lVar3 = __ftol(fVar2); local_4 = (undefined4)lVar3; } if (destPos != NULL) { fVar2 = std::floor((double)destPos->x); lVar3 = __ftol(fVar2); local_20 = (undefined4)lVar3; fVar2 = std::floor((double)destPos->y); lVar3 = __ftol(fVar2); local_1c = (undefined4)lVar3; if (destSize == NULL) { if (src == NULL) { fVar2 = std::floor((double)((float)(ulonglong)image->width + destPos->x)); lVar3 = __ftol(fVar2); local_18 = (undefined4)lVar3; fVar1 = (float)(ulonglong)image->height; } else { fVar2 = std::floor((double)(src->width + destPos->x)); lVar3 = __ftol(fVar2); local_18 = (undefined4)lVar3; fVar1 = src->height; } } else { fVar2 = std::floor((double)(destSize->width + destPos->x)); lVar3 = __ftol(fVar2); local_18 = (undefined4)lVar3; fVar1 = destSize->height; } fVar2 = std::floor((double)(fVar1 + destPos->y)); lVar3 = __ftol(fVar2); local_14 = (undefined4)lVar3; } if ((*(byte *)&image->flags & 2) == 0) { DVar4 = 0x1000000; } else { DVar4 = 0x1008000; } (*(globs::directDrawGlobs.bSurf)->lpVtbl->Blt) (globs::directDrawGlobs.bSurf,(LPRECT)(-(uint)(destPos != NULL) & (uint)&local_20), image->surface,(LPRECT)(-(uint)(src != NULL) & (uint)&local_10),DVar4,NULL); return; } void * __cdecl lego::image::Image_LockSurface(Image *image,uint *out_pitch,uint *out_bpp) { DDSURFACEDESC2 *pDVar1; HRESULT HVar2; int iVar3; DDSURFACEDESC2 s; pDVar1 = &s; for (iVar3 = 0x1f; iVar3 != 0; iVar3 += -1) { pDVar1->dwSize = 0; pDVar1 = (DDSURFACEDESC2 *)((int)pDVar1 + 4); } s.dwSize = 0x7c; HVar2 = (*image->surface->lpVtbl->Lock)(image->surface,NULL,&s,1,NULL); if (HVar2 == 0) { *out_pitch = s.lPitch; *out_bpp = s.ddpfPixelFormat.dwRGBBitCount; return s.lpSurface; } return NULL; } void __cdecl lego::image::Image_UnlockSurface(Image *image) { (*image->surface->lpVtbl->Unlock)(image->surface,NULL); return; } // WARNING: Could not reconcile some variable overlaps uint __cdecl lego::image::Image_GetPen255BigEndian(Image *image) { int iVar1; DDPIXELFORMAT *pDVar2; uint local_24; DDPIXELFORMAT pixelFmt; pDVar2 = &pixelFmt; for (iVar1 = 8; iVar1 != 0; iVar1 += -1) { pDVar2->dwSize = 0; pDVar2 = (DDPIXELFORMAT *)&pDVar2->dwFlags; } pixelFmt.dwSize = 0x20; local_24 = (*image->surface->lpVtbl->GetPixelFormat)(image->surface,&pixelFmt); if (local_24 == 0) { local_24 = CONCAT13(*(undefined *)&image->pen255, CONCAT12(*(undefined *)((int)&image->pen255 + 1), CONCAT11(*(undefined *)((int)&image->pen255 + 2), *(undefined *)((int)&image->pen255 + 3)))); } return local_24; } uint __cdecl lego::image::Image_GetPixelMaskBigEndian(Image *image) { DDPIXELFORMAT *pDVar1; HRESULT HVar2; int iVar3; DDPIXELFORMAT pixelFmt; pDVar1 = &pixelFmt; for (iVar3 = 8; iVar3 != 0; iVar3 += -1) { pDVar1->dwSize = 0; pDVar1 = (DDPIXELFORMAT *)((int)pDVar1 + 4); } pixelFmt.dwSize = 0x20; HVar2 = (*image->surface->lpVtbl->GetPixelFormat)(image->surface,&pixelFmt); if (HVar2 == 0) { return -1 << (0x20U - (char)pixelFmt.dwRGBBitCount & 0x1f); } return 0; } BOOL __cdecl lego::image::Image_GetPixel(Image *image,uint x,uint y,uint *out_colour) { HRESULT HVar1; int iVar2; DDSURFACEDESC2 *pDVar3; DDSURFACEDESC2 local_7c; pDVar3 = &local_7c; for (iVar2 = 0x1f; iVar2 != 0; iVar2 += -1) { pDVar3->dwSize = 0; pDVar3 = (DDSURFACEDESC2 *)&pDVar3->dwFlags; } local_7c.dwSize = 0x7c; if ((x < image->width) && (y < image->height)) { HVar1 = (*image->surface->lpVtbl->Lock)(image->surface,NULL,&local_7c,0x11,NULL); if (HVar1 == 0) { *out_colour = *(uint *)((int)local_7c.lpSurface + (local_7c.ddpfPixelFormat.dwRGBBitCount >> 3) * x + local_7c.lPitch * y ) >> (0x20U - (char)local_7c.ddpfPixelFormat.dwRGBBitCount & 0x1f); (*image->surface->lpVtbl->Unlock)(image->surface,NULL); return TRUE; } } return 0; } Image * __cdecl lego::image::Image_Create (IDirectDrawSurface4 *surface,uint width,uint height,COLORREF penZero,COLORREF pen255) { Image *pIVar1; Image *pIVar2; DWORD DVar3; if (globs::imageGlobs.freeList == NULL) { Image_AddList(); } pIVar1 = globs::imageGlobs.freeList; pIVar2 = (globs::imageGlobs.freeList)->nextFree; (globs::imageGlobs.freeList)->nextFree = globs::imageGlobs.freeList; globs::imageGlobs.freeList = pIVar2; pIVar1->flags = IMAGE_FLAG_NONE; pIVar1->width = width; pIVar1->height = height; pIVar1->surface = surface; pIVar1->penZeroRGB = penZero; DVar3 = Image_DDColorMatch(surface,penZero); pIVar1->penZero = DVar3; DVar3 = Image_DDColorMatch(surface,pen255); pIVar1->pen255 = DVar3; return pIVar1; } void __cdecl lego::image::Image_AddList(void) { Image *pIVar1; Image *pIVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::imageGlobs.listCount & 0x1f); pIVar2 = (Image *)io::Mem_Alloc(uVar4 * 0x20); globs::imageGlobs.listSet[globs::imageGlobs.listCount] = pIVar2; pIVar2 = globs::imageGlobs.listSet[globs::imageGlobs.listCount]; if (pIVar2 != NULL) { globs::imageGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pIVar1 = pIVar2; do { pIVar1->nextFree = pIVar1 + 1; iVar3 += -1; pIVar1 = pIVar1 + 1; } while (iVar3 != 0); } pIVar2[uVar4 - 1].nextFree = globs::imageGlobs.freeList; globs::imageGlobs.freeList = pIVar2; } return; } void __cdecl lego::image::Image_RemoveAll(void) { int iVar1; Image *image; Image_Globs *pIVar2; uint uVar3; int iVar4; uVar3 = 0; if (globs::imageGlobs.listCount != 0) { pIVar2 = &globs::imageGlobs; do { if ((pIVar2->listSet[0] != NULL) && (iVar1 = 1 << ((byte)uVar3 & 0x1f), iVar1 != 0)) { iVar4 = 0; do { image = (Image *)((int)&pIVar2->listSet[0]->surface + iVar4); if ((image != NULL) && (image->nextFree == image)) { Image_Remove(image); } iVar4 += 0x20; iVar1 += -1; } while (iVar1 != 0); } uVar3 += 1; pIVar2 = (Image_Globs *)(pIVar2->listSet + 1); } while (uVar3 < globs::imageGlobs.listCount); } return; } DWORD __cdecl lego::image::Image_DDColorMatch(IDirectDrawSurface4 *pdds,DWORD rgb) { byte bVar1; HRESULT HVar2; uint uVar3; uint uVar4; int iVar6; uint unaff_ESI; DWORD DVar7; DWORD *pDVar8; DDSURFACEDESC2 *lpDDSurfaceDesc; char cVar9; char cVar10; byte out_red; byte out_blue; byte out_green; DDSURFACEDESC2 s; uint uVar5; pDVar8 = &s.dwFlags; for (iVar6 = 0x1e; iVar6 != 0; iVar6 += -1) { *pDVar8 = 0; pDVar8 = pDVar8 + 1; } DVar7 = 0; s.dwSize = 0x7c; Image_CR2RGB(rgb,&out_red,&out_green,&out_blue); lpDDSurfaceDesc = &s; HVar2 = (*pdds->lpVtbl->Lock)(pdds,NULL,lpDDSurfaceDesc,1,NULL); if (HVar2 == 0) { uVar3 = Image_CountMaskBits(s.ddckCKSrcBlt.dwColorSpaceHighValue); uVar4 = Image_CountMaskBits(s.ddpfPixelFormat.dwSize); cVar9 = (char)uVar4; uVar4 = Image_CountMaskBits(s.ddpfPixelFormat.dwFlags); cVar10 = (char)uVar4; uVar4 = Image_CountMaskBitShift(s.ddckCKSrcBlt.dwColorSpaceHighValue); uVar5 = Image_CountMaskBitShift(s.ddpfPixelFormat.dwSize); bVar1 = (byte)uVar5; uVar5 = Image_CountMaskBitShift(s.ddpfPixelFormat.dwFlags); DVar7 = ((_out_red & 0xff) >> (8U - cVar9 & 0x1f)) << (bVar1 & 0x1f) | (((uint)lpDDSurfaceDesc & 0xff) >> (8U - (char)uVar3 & 0x1f)) << ((byte)uVar4 & 0x1f) | ((unaff_ESI & 0xff) >> (8U - cVar10 & 0x1f)) << ((byte)uVar5 & 0x1f); if (s.ddckCKSrcBlt.dwColorSpaceLowValue < 0x20) { DVar7 &= (1 << ((byte)s.ddckCKSrcBlt.dwColorSpaceLowValue & 0x1f)) - 1U; } (**(code **)(*(int *)s.ddsCaps.dwCaps2 + 0x80))(s.ddsCaps.dwCaps2,0); } return DVar7; } void __cdecl lego::image::Image_CR2RGB(COLORREF cr,byte *out_r,byte *out_g,byte *out_b) { if (out_r != NULL) { *out_r = (byte)cr; } if (out_g != NULL) { *out_g = (byte)(cr >> 8); } if (out_b != NULL) { *out_b = cr._2_1_; } return; } void __cdecl lego::image::Image_GetScreenshot(Image *ref_image,uint xsize,uint ysize) { HRESULT err; int iVar1; DDSURFACEDESC2 *pDVar2; IDirectDrawSurface4 *ddSurface4; RECT dstRect; DDSURFACEDESC2 surfDesc; pDVar2 = &surfDesc; for (iVar1 = 0x1f; iVar1 != 0; iVar1 += -1) { pDVar2->dwSize = 0; pDVar2 = (DDSURFACEDESC2 *)&pDVar2->dwFlags; } surfDesc.dwSize = 0x7c; surfDesc.dwWidth = xsize; surfDesc.dwHeight = ysize; surfDesc.ddsCaps.dwCaps = 0x840; surfDesc.dwFlags = 7; err = (*(globs::directDrawGlobs.lpDirectDraw)->lpVtbl->CreateSurface) (globs::directDrawGlobs.lpDirectDraw,&surfDesc,&ddSurface4,NULL); if (err != 0) { debug::Error_SetDXError(err,3,"C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Images.c",1140); return; } dstRect.left = 0; dstRect.top = 0; dstRect.right = xsize; dstRect.bottom = ysize; (*ddSurface4->lpVtbl->Blt)(ddSurface4,&dstRect,globs::directDrawGlobs.bSurf,NULL,0,NULL); Image_InitFromSurface(ref_image,ddSurface4,xsize,ysize,0,0); return; } void __cdecl lego::image::Image_InitFromSurface (Image *ref_newImage,IDirectDrawSurface4 *surface,uint width,uint height,COLORREF penZero, COLORREF pen255) { DWORD DVar1; if (globs::imageGlobs.freeList == NULL) { Image_AddList(); } ref_newImage->width = width; ref_newImage->nextFree = ref_newImage; ref_newImage->flags = IMAGE_FLAG_NONE; ref_newImage->height = height; ref_newImage->surface = surface; ref_newImage->penZeroRGB = penZero; DVar1 = Image_DDColorMatch(surface,penZero); ref_newImage->penZero = DVar1; DVar1 = Image_DDColorMatch(surface,pen255); ref_newImage->pen255 = DVar1; return; } BOOL __cdecl lego::image::Image_SaveBMP(Image *image,char *fname) { BOOL BVar1; BVar1 = ddraw::DirectDraw_SaveBMP(image->surface,fname); return BVar1; } G98CSurface * __thiscall lego::video::G98CSurface___deletor(void *this,G98CSurface *This,byte flag) { G98CSurface___dtor((G98CSurface *)this); if (((uint)This & 1) != 0) { // Function shared between multiple uses that just calls std::free(void* ptr) game::RadarMap_Free_UnwindMultiUse((RadarMap *)this); } return (G98CSurface *)this; } void __thiscall lego::video::G98CSurface___dtor(G98CSurface *this) { IDirectDrawSurface4 *ddSurface4; IDirectDrawPalette *This; this->vftable = &G98CSurface___vftable; ddSurface4 = this->m_surf; if (ddSurface4 != NULL) { (*ddSurface4->lpVtbl->Release)(ddSurface4); this->m_surf = NULL; } This = this->m_palette; if (This != NULL) { (*This->lpVtbl->Release)((IUnknown *)This); this->m_palette = NULL; } return; } G98CSurface * __thiscall lego::video::G98CSurface___ctor (G98CSurface *this,int width,int height,int bpp,bool vram,bool fullScreen) { bool bVar1; this->m_clipper = NULL; this->m_squashToEdge = false; this->m_15bit = false; this->m_surf = NULL; this->m_surfaceInited = false; this->vftable = &G98CSurface___vftable; G98CSurface__PreInit(this,fullScreen); bVar1 = G98CSurface__Init(this,width,height,bpp,vram); if (bVar1 != false) { this->m_surfaceInited = true; } return this; } bool __thiscall lego::video::G98CSurface__Init(G98CSurface *this,int width,int height,int bpp,bool vram) { IDirectDrawSurface4 *This; HRESULT HVar1; byte *pbVar2; int iVar3; int iVar4; DWORD DVar5; int iVar6; uint uVar7; D3DRMPaletteEntry palette [256]; // (dwFlags should initially be 0) // dwFlags = DDSD_CAPS (0x1) // if (width != 0) dwFlags |= DDSD_WIDTH (0x4) // if (height != 0) dwFlags |= DDSD_HEIGHT (0x2) uVar7 = (this->m_desc).dwFlags | -(uint)(height != 0) & 2 | -(uint)(width != 0) & 4 | 1; (this->m_desc).dwFlags = uVar7; this->m_bpp = bpp; if (width != 0) { (this->m_desc).dwWidth = width; } if (height != 0) { (this->m_desc).dwHeight = height; } if ((width == 0) && (height == 0)) { // DDSCAPS_PRIMARYSURFACE (0x200) (this->m_desc).ddsCaps.dwCaps = 0x200; } else { // DDSCAPS_OFFSCREENPLAIN (0x40) (this->m_desc).ddsCaps.dwCaps = 0x40; // if (useVideoMemory) // DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN (0x4000 | 0x40) // else // DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN (0x800 | 0x40) (this->m_desc).ddsCaps.dwCaps = (-(uint)(vram != false) & 0x3800) + 0x840; } if (bpp != 0) { // DDSD_PIXELFORMAT (0x1000) (this->m_desc).dwFlags = uVar7 | 0x1000; (this->m_desc).ddpfPixelFormat.dwSize = 0x20; // specify as 16-bpp when proper depth is 15-bpp DVar5 = 0x10; if (bpp != 0xf) { DVar5 = bpp; } (this->m_desc).ddpfPixelFormat.dwRGBBitCount = DVar5; if (bpp == 24) { // 24-bpp (this->m_desc).ddpfPixelFormat.dwRBitMask = 0xff0000; (this->m_desc).ddpfPixelFormat.dwGBitMask = 0xff00; (this->m_desc).ddpfPixelFormat.dwBBitMask = 0xff; // DDPF_RGB (0x40) (this->m_desc).ddpfPixelFormat.dwFlags = 0x40; } else { if (bpp == 0x10) { // 16-bpp (proper) (this->m_desc).ddpfPixelFormat.dwRBitMask = 0xf800; (this->m_desc).ddpfPixelFormat.dwGBitMask = 0x7e0; (this->m_desc).ddpfPixelFormat.dwBBitMask = 0x1f; // DDPF_RGB (0x40) (this->m_desc).ddpfPixelFormat.dwFlags = 0x40; } else { if (bpp == 0xf) { // 15-bpp (treated as 16-bpp) (this->m_desc).ddpfPixelFormat.dwRBitMask = 0x7c00; (this->m_desc).ddpfPixelFormat.dwGBitMask = 0x3e0; (this->m_desc).ddpfPixelFormat.dwBBitMask = 0x1f; // DDPF_RGB (0x40) (this->m_desc).ddpfPixelFormat.dwFlags = 0x40; } else { if (bpp == 8) { // 8-bpp (indexed) (this->m_desc).ddpfPixelFormat.dwRBitMask = 0xff0000; (this->m_desc).ddpfPixelFormat.dwGBitMask = 0xff00; (this->m_desc).ddpfPixelFormat.dwBBitMask = 0xff; // DDPF_RGB | DDPF_PALETTEINDEXED8 (0x40 | 0x20) (this->m_desc).ddpfPixelFormat.dwFlags = 0x60; } } } } } HVar1 = (*(globs::animationGlobs.ddraw)->lpVtbl->CreateSurface) (globs::animationGlobs.ddraw,&this->m_desc,&this->m_surf,NULL); if (HVar1 == 0) { G98CSurface__Lock(this); G98CSurface__Unlock(this); if ((this->m_desc).ddpfPixelFormat.dwRGBBitCount != 8) { LAB_0047e975: if ((this->m_desc).ddpfPixelFormat.dwRGBBitCount == 0x10) { // Count number of bits to check if we're actually using 15-bpp handling (when surface // considers it as 16-bpp) iVar6 = G98CSurface__CountMaskBits(this,(this->m_desc).ddpfPixelFormat.dwGBitMask); iVar3 = G98CSurface__CountMaskBits(this,(this->m_desc).ddpfPixelFormat.dwBBitMask); iVar4 = G98CSurface__CountMaskBits(this,(this->m_desc).ddpfPixelFormat.dwRBitMask); if (iVar6 + iVar3 + iVar4 == 0xf) { this->m_15bit = true; } } return true; } pbVar2 = &palette[0].green; iVar6 = 0x100; do { pbVar2[-1] = 0; *pbVar2 = 0; pbVar2[1] = 0; pbVar2[2] = 0; pbVar2 = pbVar2 + 4; iVar6 += -1; } while (iVar6 != 0); // DDPCAPS_8BIT (0x4) HVar1 = (*(globs::animationGlobs.ddraw)->lpVtbl->CreatePalette) (globs::animationGlobs.ddraw,4,palette,&this->m_palette,NULL); if (HVar1 == 0) { This = this->m_surf; HVar1 = (*This->lpVtbl->SetPalette)(This,this->m_palette); if (HVar1 == 0) goto LAB_0047e975; } } return false; } void __thiscall lego::video::G98CSurface__PreInit(G98CSurface *this,bool fullscreen) { int iVar1; DDSURFACEDESC2 *pDVar2; pDVar2 = &this->m_desc; for (iVar1 = 0x1f; iVar1 != 0; iVar1 += -1) { pDVar2->dwSize = 0; pDVar2 = (DDSURFACEDESC2 *)&pDVar2->dwFlags; } (this->m_desc).dwSize = 0x7c; this->m_surf = NULL; this->m_palette = NULL; this->m_surfaceLocked = false; this->m_colourKeyed = false; return; } int __thiscall lego::video::G98CSurface__Width(void *this,G98CSurface *This) { return *(int *)((int)this + 0x28); } int __thiscall lego::video::G98CSurface__Height(void *this,G98CSurface *This) { return *(int *)((int)this + 0x24); } bool __thiscall lego::video::G98CSurface__Lock(G98CSurface *this) { DDSURFACEDESC2 *pDVar1; IDirectDrawSurface4 *pIVar2; IDirectDrawSurface4Vtbl *pIVar3; HRESULT HVar4; int iVar5; DDSURFACEDESC2 *pDVar6; if (this->m_surfaceLocked == false) { pDVar1 = &this->m_desc; pDVar6 = pDVar1; for (iVar5 = 0x1f; iVar5 != 0; iVar5 += -1) { pDVar6->dwSize = 0; pDVar6 = (DDSURFACEDESC2 *)&pDVar6->dwFlags; } pIVar2 = this->m_surf; pIVar3 = pIVar2->lpVtbl; pDVar1->dwSize = 0x7c; HVar4 = (*pIVar3->Lock)(pIVar2,NULL,pDVar1,0x801,NULL); if (HVar4 == 0) { this->m_surfaceLocked = true; return true; } } return false; } bool __thiscall lego::video::G98CSurface__Unlock(G98CSurface *this) { HRESULT HVar1; if (this->m_surfaceLocked != false) { HVar1 = (*this->m_surf->lpVtbl->Unlock)(this->m_surf,NULL); if (HVar1 == 0) { this->m_surfaceLocked = false; return true; } } return false; } int __thiscall lego::video::G98CSurface__CountMaskBits(G98CSurface *this,uint mask) { int count; uint i; count = 0; i = 0; do { if ((mask & 1 << ((byte)i & 0x1f)) != 0) { count += 1; } i += 1; } while (i < 32); return count; } G98CAnimation * __thiscall lego::video::G98CAnimation___ctor(G98CAnimation *this,char *filename) { IAVIStream **lplpIAVIStream; LONG LVar1; LONG LVar2; LONG LVar3; char *szFile; HRESULT HVar4; IGetFrame *pIVar5; DWORD DVar6; G98CSurface *pGVar7; int iVar8; AVISTREAMINFOA *pAVar9; undefined4 *in_FS_OFFSET; undefined4 local_c; undefined *puStack8; undefined4 local_4; local_c = *in_FS_OFFSET; local_4 = 0xffffffff; puStack8 = &LAB_0049e08b; *in_FS_OFFSET = &local_c; this->m_colourKeySet = false; this->m_init = false; this->m_movieSurf = NULL; this->vftable = &G98CAnimation___vftable; szFile = io::File_VerifyFilename(filename); lplpIAVIStream = &this->m_aviStream; this->m_decompressFn = NULL; *lplpIAVIStream = NULL; pAVar9 = &this->m_aviStreamInfo; for (iVar8 = 0x23; iVar8 != 0; iVar8 += -1) { pAVar9->fccType = 0; pAVar9 = (AVISTREAMINFOA *)&pAVar9->fccHandler; } (this->m_movieRect).top = 0; (this->m_movieRect).bottom = 0; (this->m_movieRect).left = 0; (this->m_movieRect).right = 0; if (globs::animationGlobs.g98NoAvis == false) { // fccType "sdiv" (as DWORD) HVar4 = AVIStreamOpenFromFileA(lplpIAVIStream,szFile,L'\x73646976',0,0,NULL); if (HVar4 == 0) { // AVIGETFRAMEF_BESTDISPLAYFMT (0x1) pIVar5 = AVIStreamGetFrameOpen(*lplpIAVIStream,(BITMAPINFOHEADER *)0x1); this->m_decompressFn = pIVar5; if (pIVar5 != NULL) { HVar4 = AVIStreamInfoA(*lplpIAVIStream,&this->m_aviStreamInfo,0x8c); if (HVar4 == 0) { DVar6 = timeGetTime(); LVar1 = (this->m_aviStreamInfo).rcFrame.bottom; LVar2 = (this->m_aviStreamInfo).rcFrame.left; (this->m_movieRect).top = (this->m_aviStreamInfo).rcFrame.top; LVar3 = (this->m_aviStreamInfo).rcFrame.right; this->m_init = true; this->m_currFrame = 0; (this->m_movieRect).bottom = LVar1; (this->m_movieRect).left = LVar2; (this->m_movieRect).right = LVar3; this->m_startTime = (float)(ulonglong)DVar6 * 0.001; pGVar7 = (G98CSurface *)std::operator_new(0x98); local_4 = 0; if (pGVar7 == NULL) { pGVar7 = NULL; } else { pGVar7 = G98CSurface___ctor(pGVar7,(this->m_movieRect).right - (this->m_movieRect).left, (this->m_movieRect).bottom - (this->m_movieRect).top,0,false ,false); } this->m_movieSurf = pGVar7; } } } } *in_FS_OFFSET = local_c; return this; } G98CAnimation * __thiscall lego::video::G98CAnimation___deletor(void *this,G98CAnimation *This,byte flag) { G98CAnimation___dtor((G98CAnimation *)this); if (((uint)This & 1) != 0) { game::RadarMap_Free_UnwindMultiUse((RadarMap *)this); } return (G98CAnimation *)this; } void __thiscall lego::video::G98CAnimation___dtor(G98CAnimation *this) { G98CSurface *This; this->vftable = &G98CAnimation___vftable; if (globs::animationGlobs.g98NoAvis == false) { if (this->m_aviStream != NULL) { AVIStreamRelease(this->m_aviStream); } This = this->m_movieSurf; if (This != NULL) { (*This->vftable->deletor)(This,1); } } return; } void __thiscall lego::video::G98CAnimation__BMICopy(G98CAnimation *this,BITMAPINFO *bmi) { G98CSurface *this_00; G98CSurface *pGVar1; uint uVar2; bool bVar3; bool bVar4; int stride; int height; uint uVar5; DWORD depth; undefined4 *puVar6; int width; undefined4 *puVar7; undefined4 *puVar8; BYTE *pBVar9; undefined4 *puVar10; bool local_8; bVar3 = false; this_00 = this->m_movieSurf; if ((this_00->m_surfaceLocked == false) && (bVar4 = G98CSurface__Lock(this_00), bVar4 != false)) { bVar3 = true; } puVar7 = (undefined4 *)(this_00->m_desc).lpSurface; width = (this->m_movieRect).right - (this->m_movieRect).left; pGVar1 = this->m_movieSurf; height = (this->m_movieRect).bottom - (this->m_movieRect).top; pBVar9 = &bmi->bmiColors[-10].rgbBlue + (bmi->bmiHeader).biSize; stride = (int)(pGVar1->m_desc).lPitch / 2; depth = 0xf; if (pGVar1->m_15bit == false) { depth = (pGVar1->m_desc).ddpfPixelFormat.dwRGBBitCount; } if (depth == 0xf) { puVar6 = (undefined4 *)(pBVar9 + (height + -1) * stride * 2); if (0 < height) { uVar2 = width * 2; do { puVar8 = puVar6; puVar10 = puVar7; for (uVar5 = uVar2 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar10 = *puVar8; puVar8 = puVar8 + 1; puVar10 = puVar10 + 1; } for (uVar5 = uVar2 & 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } puVar6 = (undefined4 *)((int)puVar6 + stride * -2); puVar7 = (undefined4 *)((int)puVar7 + stride * 2); height += -1; } while (height != 0); } } else { // "Corporate needs you to find the differences between these two code blocks." // // (swap out the first `depth == 0xf` confition for `depth == 15 || depth == 16`) if (pGVar1->m_15bit == false) { depth = (pGVar1->m_desc).ddpfPixelFormat.dwRGBBitCount; } else { depth = 0xf; } if ((depth == 0x10) && (puVar6 = (undefined4 *)(pBVar9 + (height + -1) * stride * 2), 0 < height)) { uVar2 = width * 2; do { puVar8 = puVar6; puVar10 = puVar7; for (uVar5 = uVar2 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar10 = *puVar8; puVar8 = puVar8 + 1; puVar10 = puVar10 + 1; } for (uVar5 = uVar2 & 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } puVar6 = (undefined4 *)((int)puVar6 + stride * -2); puVar7 = (undefined4 *)((int)puVar7 + stride * 2); height += -1; } while (height != 0); } } if (bVar3) { G98CSurface__Unlock(this_00); } return; } bool __thiscall lego::video::G98CAnimation__Update(G98CAnimation *this) { BITMAPINFO *bmi; DWORD DVar1; float10 fVar2; longlong lVar3; if (this->m_init == false) { return false; } if (globs::animationGlobs.g98NoAvis != false) { return false; } bmi = (BITMAPINFO *)AVIStreamGetFrame(this->m_decompressFn,this->m_currFrame); if (bmi != NULL) { G98CAnimation__BMICopy(this,bmi); DVar1 = timeGetTime(); fVar2 = (float10)(ulonglong)(this->m_aviStreamInfo).dwRate / (float10)(ulonglong)(this->m_aviStreamInfo).dwScale; this->m_aviTimeScale = (float)fVar2; this->m_currTime = (float)((float10)(ulonglong)DVar1 * (float10)0.001); lVar3 = __ftol(((float10)(ulonglong)DVar1 * (float10)0.001 - (float10)this->m_startTime) * fVar2 ); this->m_currFrame = (uint)lVar3; } return true; } uint __thiscall lego::video::G98CAnimation__Length(G98CAnimation *this) { if (globs::animationGlobs.g98NoAvis != false) { return 0; } return (this->m_aviStreamInfo).dwLength; } void __thiscall lego::video::G98CAnimation__SetTime(G98CAnimation *this,uint time) { DWORD DVar1; if (globs::animationGlobs.g98NoAvis == false) { this->m_currFrame = time; DVar1 = timeGetTime(); this->m_currTime = (float)(ulonglong)DVar1 * 0.001; this->m_startTime = (float)(ulonglong)DVar1 * 0.001 - (float)(ulonglong)this->m_currFrame / this->m_aviTimeScale; } return; } uint __thiscall lego::video::G98CAnimation__GetTime(G98CAnimation *this) { return ~-(uint)(globs::animationGlobs.g98NoAvis != false) & this->m_currFrame; } void __cdecl lego::video::Animation_Initialise(IDirectDraw4 *directDraw) { globs::animationGlobs.ddraw = directDraw; AVIFileInit(); return; } Animation_t * __cdecl lego::video::Animation_Load(char *fName) { G98CAnimation *pGVar1; undefined4 *in_FS_OFFSET; undefined4 local_c; undefined *puStack8; undefined4 local_4; local_4 = 0xffffffff; puStack8 = &LAB_0049e0ab; local_c = *in_FS_OFFSET; *in_FS_OFFSET = &local_c; pGVar1 = (G98CAnimation *)std::operator_new(0xc4); local_4 = 0; if (pGVar1 != NULL) { pGVar1 = G98CAnimation___ctor(pGVar1,fName); *in_FS_OFFSET = local_c; return (Animation_t *)pGVar1; } *in_FS_OFFSET = local_c; return (Animation_t *)NULL; } BOOL __cdecl lego::video::Animation_Update(Animation_t *anim) { bool bVar1; bVar1 = G98CAnimation__Update((G98CAnimation *)anim); return (uint)bVar1; } void __cdecl lego::video::Animation_BlitToBackBuffer(Animation_t *anim,RECT *destRect) { IDirectDrawSurface4 *lpDDSrcSurface; IDirectDrawSurface4 *This; if (anim->m_init != false) { lpDDSrcSurface = anim->m_movieSurf->m_surf; This = ddraw::DirectDraw_bSurf(); // DDBLT_WAIT (0x1000000) (*This->lpVtbl->Blt)(This,(LPRECT)destRect,lpDDSrcSurface,NULL,0x1000000,NULL); } return; } void __cdecl lego::video::Animation_SetTime(Animation_t *anim,uint time) { G98CAnimation__SetTime((G98CAnimation *)anim,time); return; } uint __cdecl lego::video::Animation_GetTime(Animation_t *anim) { uint uVar1; uVar1 = G98CAnimation__GetTime((G98CAnimation *)anim); return uVar1; } uint __cdecl lego::video::Animation_GetLength(Animation_t *anim) { uint uVar1; uVar1 = G98CAnimation__Length((G98CAnimation *)anim); return uVar1; } void __cdecl lego::video::Animation_Free(Animation_t *anim) { if (anim != NULL) { (*anim->vftable->deletor)((G98CAnimation *)anim,1); } return; } BOOL __cdecl lego::video::Animation_IsOk(Animation_t *anim) { return (uint)anim->m_init; } BOOL __cdecl lego::input::Input_InitKeysAndDI(void) { HRESULT HVar1; int iVar2; char *pcVar3; int iVar4; GUID guidSysKeyboard; // GUID_SysKeyboard {6F1D2B61-D5A0-11CF-BFC7-444553540000} HVar1 = DirectInputCreateA(globs::mainGlobs.hInst,0x500,(IUnknown **)&globs::INPUT.lpdi,NULL); if (HVar1 != 0) { iVar4 = 118; pcVar3 = "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Input.c"; iVar2 = 2; HVar1 = DirectInputCreateA(globs::mainGlobs.hInst,0x500,(IUnknown **)&globs::INPUT.lpdi,NULL); debug::Error_SetDXError(HVar1,iVar2,pcVar3,iVar4); return 0; } HVar1 = (*(globs::INPUT.lpdi)->lpVtbl->CreateDevice) (globs::INPUT.lpdi,(LPGUID)&guidSysKeyboard,&globs::INPUT.lpdiKeyboard,NULL); if (HVar1 != 0) { iVar4 = 121; pcVar3 = "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Input.c"; iVar2 = 2; HVar1 = (*(globs::INPUT.lpdi)->lpVtbl->CreateDevice) (globs::INPUT.lpdi,(LPGUID)&guidSysKeyboard,&globs::INPUT.lpdiKeyboard,NULL); debug::Error_SetDXError(HVar1,iVar2,pcVar3,iVar4); return 0; } HVar1 = (*(globs::INPUT.lpdiKeyboard)->lpVtbl->SetDataFormat) (globs::INPUT.lpdiKeyboard,&idl::c_dfDIKeyboard); if (HVar1 != 0) { iVar4 = 124; pcVar3 = "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Input.c"; iVar2 = 2; HVar1 = (*(globs::INPUT.lpdiKeyboard)->lpVtbl->SetDataFormat) (globs::INPUT.lpdiKeyboard,&idl::c_dfDIKeyboard); debug::Error_SetDXError(HVar1,iVar2,pcVar3,iVar4); return 0; } // DISCL_FOREGROUND | DISCL_NONEXCLUSIVE (0x4 | 0x2) HVar1 = (*(globs::INPUT.lpdiKeyboard)->lpVtbl->SetCooperativeLevel) (globs::INPUT.lpdiKeyboard,globs::mainGlobs.hWnd,6); if (HVar1 != 0) { iVar4 = 127; pcVar3 = "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Input.c"; iVar2 = 2; // DISCL_FOREGROUND | DISCL_NONEXCLUSIVE (0x4 | 0x2) HVar1 = (*(globs::INPUT.lpdiKeyboard)->lpVtbl->SetCooperativeLevel) (globs::INPUT.lpdiKeyboard,globs::mainGlobs.hWnd,6); debug::Error_SetDXError(HVar1,iVar2,pcVar3,iVar4); return 0; } HVar1 = (*(globs::INPUT.lpdiKeyboard)->lpVtbl->Acquire)(globs::INPUT.lpdiKeyboard); globs::INPUT.fKeybdAcquired = (uint)(HVar1 == 0); return 1; } void __cdecl lego::input::Input_ReadKeys(void) { IDirectInputDeviceA *This; HRESULT HVar1; int iVar2; undefined4 *puVar3; Input_Globs *pIVar4; This = globs::INPUT.lpdiKeyboard; iVar2 = 1; if (((byte)globs::mainGlobs.flags & MAIN_FLAG_FULLSCREEN) == 0) { iVar2 = globs::mainGlobs.active; } if (iVar2 == 0) { puVar3 = (undefined4 *)globs::INPUT.Key_Map; for (iVar2 = 0x40; iVar2 != 0; iVar2 += -1) { *puVar3 = 0; puVar3 = puVar3 + 1; } pIVar4 = &globs::INPUT; for (iVar2 = 0x40; iVar2 != 0; iVar2 += -1) { *(undefined4 *)pIVar4->prevKey_Map = 0; pIVar4 = (Input_Globs *)(pIVar4->prevKey_Map + 4); } (*(globs::INPUT.lpdiKeyboard)->lpVtbl->Unacquire)(globs::INPUT.lpdiKeyboard); return; } if (globs::INPUT.lpdiKeyboard != NULL) { if (globs::INPUT.fKeybdAcquired == 0) { iVar2 = -0x7ff8ffe2; } else { puVar3 = (undefined4 *)globs::INPUT.Key_Map; pIVar4 = &globs::INPUT; for (iVar2 = 0x40; iVar2 != 0; iVar2 += -1) { *(undefined4 *)pIVar4->prevKey_Map = *puVar3; puVar3 = puVar3 + 1; pIVar4 = (Input_Globs *)(pIVar4->prevKey_Map + 4); } puVar3 = (undefined4 *)globs::INPUT.Key_Map; for (iVar2 = 0x40; iVar2 != 0; iVar2 += -1) { *puVar3 = 0; puVar3 = puVar3 + 1; } iVar2 = (*This->lpVtbl->GetDeviceState)(This,0x100,(LPVOID)0x76bb80); } if (iVar2 != 0) { globs::INPUT.fKeybdAcquired = 0; HVar1 = (*(globs::INPUT.lpdiKeyboard)->lpVtbl->Acquire)(globs::INPUT.lpdiKeyboard); if (HVar1 == 0) { globs::INPUT.fKeybdAcquired = 1; } } } return; } uint __cdecl lego::input::Input_AnyKeyPressed(void) { uint uVar1; bool *pbVar2; int iVar3; uVar1 = 0; pbVar2 = globs::INPUT.Key_Map; iVar3 = 0x100; do { if (*pbVar2 != false) { uVar1 += 1; } pbVar2 = pbVar2 + 1; iVar3 += -1; } while (iVar3 != 0); return uVar1; } void __cdecl lego::input::Input_ReleaseKeysAndDI(void) { if (globs::INPUT.fKeybdAcquired != 0) { (*(globs::INPUT.lpdiKeyboard)->lpVtbl->Unacquire)(globs::INPUT.lpdiKeyboard); globs::INPUT.fKeybdAcquired = 0; } if (globs::INPUT.lpdiKeyboard != NULL) { (*(globs::INPUT.lpdiKeyboard)->lpVtbl->Release)((IUnknown *)globs::INPUT.lpdiKeyboard); } if (globs::INPUT.lpdi != NULL) { (*(globs::INPUT.lpdi)->lpVtbl->Release)((IUnknown *)globs::INPUT.lpdi); } return; } void __cdecl lego::input::Input_ReadMouse2(void) { BOOL BVar1; tagPOINT clientPos; tagPOINT mousePos; tagRECT clientRect; BVar1 = GetClientRect(globs::mainGlobs.hWnd,(LPRECT)&clientRect); if (BVar1 != 0) { clientPos.y = 0; clientPos.x = 0; ClientToScreen(globs::mainGlobs.hWnd,(LPPOINT)&clientPos); GetCursorPos((LPPOINT)&mousePos); mousePos.x -= clientPos.x; mousePos.y -= clientPos.y; if ((int)globs::mainGlobs.appWidth <= mousePos.x) { mousePos.x = globs::mainGlobs.appWidth - 1; } if ((int)globs::mainGlobs.appHeight <= mousePos.y) { mousePos.y = globs::mainGlobs.appHeight - 1; } if (mousePos.x < 0) { mousePos.x = 0; } if (mousePos.y < 0) { mousePos.y = 0; } globs::INPUT.diffx = mousePos.x - globs::INPUT.msx; globs::INPUT.diffy = mousePos.y - globs::INPUT.msy; globs::INPUT.msx = mousePos.x; globs::INPUT.msy = mousePos.y; } return; } BOOL __cdecl lego::input::Input_SetCursorPos(int x,int y) { BOOL BVar1; tagPOINT client; client.y = 0; client.x = 0; ClientToScreen(globs::mainGlobs.hWnd,(LPPOINT)&client); globs::INPUT.msy = y; globs::INPUT.msx = x; globs::INPUT.diffx = 0; globs::INPUT.diffy = 0; BVar1 = SetCursorPos(client.x + x,client.y + y); return BVar1; } // WARNING: Could not reconcile some variable overlaps void __cdecl lego::io::File_Initialise(char *programName,BOOL insistOnCD,char *registryLocation) { char cVar1; bool bVar2; int iVar3; BOOL BVar4; HANDLE handle; FILE *pFVar5; uint uVar6; uint uVar7; undefined4 *puVar8; char *pcVar9; char *pcVar10; char *pcVar11; undefined4 *puVar12; BOOL failed; char cwd [260]; _finddata32_t fileinfo; char dataDir [260]; char msgError [1024]; char fname [1024]; char msgNoCD [1024]; bVar2 = false; failed = 0; std::_getcwd(cwd,MAX_PATH); uVar6 = 0xffffffff; pcVar10 = cwd; do { if (uVar6 == 0) break; uVar6 -= 1; cVar1 = *pcVar10; pcVar10 = pcVar10 + 1; } while (cVar1 != '\0'); if (cwd[~uVar6 - 2] == '\\') { uVar6 = 0xffffffff; pcVar10 = cwd; do { if (uVar6 == 0) break; uVar6 -= 1; cVar1 = *pcVar10; pcVar10 = pcVar10 + 1; } while (cVar1 != '\0'); cwd[~uVar6 - 2] = '\0'; } std::sprintf(globs::fileGlobs.dataDir,"%s\\%s",cwd,"Data"); uVar6 = 0; do { std::sprintf((char *)&fileinfo,"%s%i.wad",programName,uVar6); iVar3 = File_LoadWad((char *)&fileinfo); if (iVar3 != -1) { bVar2 = true; } uVar6 += 1; } while (uVar6 < 10); std::_getcwd(dataDir,MAX_PATH); uVar6 = 0xffffffff; pcVar10 = "\\Data"; do { pcVar9 = pcVar10; if (uVar6 == 0) break; uVar6 -= 1; pcVar9 = pcVar10 + 1; cVar1 = *pcVar10; pcVar10 = pcVar9; } while (cVar1 != '\0'); uVar6 = ~uVar6; iVar3 = -1; pcVar10 = dataDir; do { pcVar11 = pcVar10; if (iVar3 == 0) break; iVar3 += -1; pcVar11 = pcVar10 + 1; cVar1 = *pcVar10; pcVar10 = pcVar11; } while (cVar1 != '\0'); puVar8 = (undefined4 *)(pcVar9 + -uVar6); puVar12 = (undefined4 *)(pcVar11 + -1); for (uVar7 = uVar6 >> 2; uVar7 != 0; uVar7 -= 1) { *puVar12 = *puVar8; puVar8 = puVar8 + 1; puVar12 = puVar12 + 1; } for (uVar6 &= 3; uVar6 != 0; uVar6 -= 1) { *(undefined *)puVar12 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar12 = (undefined4 *)((int)puVar12 + 1); } File_SetBaseSearchPath(dataDir); iVar3 = File_FindDataCD(); while ((iVar3 == 0 && (insistOnCD != 0))) { msgError._0_4_ = 0x6f727245; msgError._4_2_ = 0x72; puVar8 = (undefined4 *)(msgError + 6); for (iVar3 = 0xfe; iVar3 != 0; iVar3 += -1) { *puVar8 = 0; puVar8 = puVar8 + 1; } *(undefined2 *)puVar8 = 0; BVar4 = registry::Registry_GetValue (registryLocation,"CDMissing",REGISTRY_STRING_VALUE,msgNoCD,0x400); if (BVar4 == 0) { LAB_0047f59b: std::exit(0); } else { registry::Registry_GetValue (registryLocation,"SetupError",REGISTRY_STRING_VALUE,msgError,0x400); iVar3 = MessageBoxA(NULL,msgNoCD,msgError,1); if (iVar3 == 2) goto LAB_0047f59b; } iVar3 = File_FindDataCD(); } if ((iVar3 == 0) && (!bVar2)) { failed = 1; handle = std::_findfirst32("*.*",&fileinfo); if (handle != (HANDLE)0xffffffff) { do { if ((((byte)fileinfo.attrib & 0x10) != 0) && (iVar3 = std::_stricmp(fileinfo.name,"Data"), iVar3 == 0)) { failed = 0; break; } iVar3 = std::_findnext32(handle,&fileinfo); } while (iVar3 == 0); std::_findclose(handle); } } if (insistOnCD != 0) { std::sprintf(fname,"%s\\%s","Data","cd.key"); pFVar5 = std::fopen(fname,"r"); if (pFVar5 != NULL) { std::fclose(pFVar5); failed = 1; } } if (failed == 0) { std::_mkdir("Data"); std::sprintf(fname,"%s\\%s","Data","delme.dat"); pFVar5 = std::fopen(fname,"r"); if (pFVar5 != NULL) { std::fclose(pFVar5); std::_chmod(fname,FILE_ATTRIBUTE_NORMAL); std::remove(fname); return; } } else { msgError._0_4_ = 0x6f727245; msgError._4_2_ = 0x72; puVar8 = (undefined4 *)(msgError + 6); for (iVar3 = 0xfe; iVar3 != 0; iVar3 += -1) { *puVar8 = 0; puVar8 = puVar8 + 1; } *(undefined2 *)puVar8 = 0; BVar4 = registry::Registry_GetValue (registryLocation,"DataMissing",REGISTRY_STRING_VALUE,msgNoCD,0x400); if (BVar4 != 0) { registry::Registry_GetValue (registryLocation,"SetupError",REGISTRY_STRING_VALUE,msgError,0x400); MessageBoxA(NULL,msgNoCD,msgError,0); } std::exit(0); } return; } BOOL __cdecl lego::io::File_FindDataCD(void) { UINT driveType; FILE *stream; char letter; uint rootName; char buffer [260]; letter = 0x43; rootName = 0x5c3a41; do { rootName = rootName & 0xffffff00 | (uint)(byte)letter; driveType = GetDriveTypeA((LPCSTR)&rootName); if (driveType == DRIVE_CDROM) { std::sprintf(buffer,"%c:\\%s\\%s",letter,"Data","cd.key"); stream = std::fopen(buffer,"r"); if (stream != NULL) { std::fclose(stream); globs::fileGlobs.cdLetter = letter; return TRUE; } } letter += 1; } while ((byte)letter < 0x5b); return 0; } // This allows the translation from File paths into Wad names. BOOL __cdecl lego::io::File_SetBaseSearchPath(char *basePath) { char cVar1; uint uVar2; uint uVar3; int iVar4; undefined4 *puVar5; char *pcVar6; File_Globs *pFVar7; if (basePath != NULL) { uVar2 = 0xffffffff; pcVar6 = basePath; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); // if (std::strlen(dirname) != 0 && std::strlen(dirname) < 0x400) if (((int)(~uVar2 - 1) < 0x401) && (~uVar2 != 1)) { // std::strcpy(globals::g_FILEPATH_DATADIR_STRIP, dirname); uVar2 = 0xffffffff; do { pcVar6 = basePath; if (uVar2 == 0) break; uVar2 -= 1; pcVar6 = basePath + 1; cVar1 = *basePath; basePath = pcVar6; } while (cVar1 != '\0'); uVar2 = ~uVar2; puVar5 = (undefined4 *)(pcVar6 + -uVar2); pFVar7 = &globs::fileGlobs; for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *(undefined4 *)pFVar7->wadBasePath = *puVar5; puVar5 = puVar5 + 1; pFVar7 = (File_Globs *)(pFVar7->wadBasePath + 4); } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { pFVar7->wadBasePath[0] = *(char *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); pFVar7 = (File_Globs *)(pFVar7->wadBasePath + 1); } globs::fileGlobs.basePathSet = TRUE; return TRUE; } } globs::fileGlobs.basePathSet = 0; pFVar7 = &globs::fileGlobs; for (iVar4 = 0x100; iVar4 != 0; iVar4 += -1) { *(undefined4 *)pFVar7->wadBasePath = 0; pFVar7 = (File_Globs *)(pFVar7->wadBasePath + 4); } return 0; } void __cdecl lego::io::File_Error(char *msg,...) { char buffer [1024]; std::vsprintf(buffer,msg,&stack0x00000008); OutputDebugStringA(buffer); return; } int __cdecl lego::io::File_LoadWad(char *fName) { int iVar1; // File_ErrorFile(0); // Open the wad error log util::logf_removed(NULL); iVar1 = wad::Wad_Load(fName); return iVar1; } BOOL __cdecl lego::io::File_GetCDFilePath(char *out_path,char *fname) { if ((char)globs::fileGlobs._2580_4_ != '\0') { std::sprintf(out_path,"%c:\\%s\\%s",globs::fileGlobs._2580_4_ & 0xff,"Data",fname); return TRUE; } return 0; } int __cdecl lego::io::File_MakeDir(char *path) { int iVar1; char buffer [260]; std::sprintf(buffer,"%s\\%s","Data",path); iVar1 = std::_mkdir(buffer); return iVar1; } File * __cdecl lego::io::File_Open(char *fName,char *mode) { char *pcVar1; FileSys FVar2; File *file; FILE *pFVar3; char *pcVar4; BOOL BVar5; char buffer [160]; pcVar1 = File_VerifyFilename(fName); FVar2 = _File_CheckSystem(pcVar1,mode); if (FVar2 == FileSys_Wad) { file = _File_Alloc(FileSys_Wad); if (file == NULL) { return NULL; } pcVar4 = _File_GetWadName(pcVar1); BVar5 = _File_OpenWad((WADFILE *)file->stream,pcVar4); if (BVar5 != 0) { pcVar1 = _File_GetWadName(pcVar1); util::logf_removed("WAD Load %s\n",pcVar1); return file; } pcVar1 = _File_GetWadName(pcVar1); pcVar4 = "WAD Fail %s\n"; } else { if (FVar2 != FileSys_Standard) { File_Error("%s(%i) : Error in call to %s\n", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",330,"File_Open"); return NULL; } file = _File_Alloc(FileSys_Standard); if (file == NULL) { return NULL; } pFVar3 = std::fopen(pcVar1,mode); file->stream = pFVar3; if (pFVar3 != NULL) { util::logf_removed("STD Load %s\n",pcVar1); return file; } pcVar4 = util::Util_StrIStr(mode,"w"); if ((pcVar4 == NULL) && (BVar5 = File_GetCDFilePath(buffer,fName), BVar5 != 0)) { pFVar3 = std::fopen(buffer,mode); file->stream = pFVar3; if (pFVar3 != NULL) { return file; } } pcVar4 = "STD Fail %s\n"; } util::logf_removed(pcVar4,pcVar1); _File_Dealloc(file); return NULL; } int __cdecl lego::io::File_Seek(File *f,int pos,int origin) { int *piVar1; FileSys FVar2; int iVar3; FVar2 = _File_GetSystem(f); if (FVar2 != FileSys_Wad) { if (FVar2 != FileSys_Standard) { File_Error("%s(%i) : Unknown file system in call to %s", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",368,"File_Seek"); return 0; } iVar3 = std::fseek((FILE *)f->stream,pos,origin); return iVar3; } if (origin == 0) { *(int *)(f->stream + 4) = pos; piVar1 = (int *)f->stream; iVar3 = wad::Wad_hLength(*piVar1); if (iVar3 < piVar1[1]) { iVar3 = wad::Wad_hLength(*piVar1); *(int *)(f->stream + 4) = iVar3; } if (*(int *)(f->stream + 4) < 0) { *(undefined4 *)(f->stream + 4) = 0; } } else { if (origin != 1) { if (origin != 2) { File_Error("Uknown seek mode (%i)",origin); return 0; } iVar3 = wad::Wad_hLength(*(int *)f->stream); *(int *)(f->stream + 4) = iVar3 + pos; return 0; } *(int *)(f->stream + 4) = *(int *)(f->stream + 4) + pos; piVar1 = (int *)f->stream; iVar3 = wad::Wad_hLength(*piVar1); if (iVar3 < piVar1[1]) { iVar3 = wad::Wad_hLength(*piVar1); *(int *)(f->stream + 4) = iVar3; } if (*(int *)(f->stream + 4) < 0) { *(undefined4 *)(f->stream + 4) = 0; return 0; } } return 0; } int __cdecl lego::io::File_Read(void *out_buffer,int size,int count,File *f) { int iVar1; FileSys FVar2; size_t sVar3; int iVar4; void *pvVar5; uint uVar6; uint uVar7; undefined4 *puVar8; FVar2 = _File_GetSystem(f); if (FVar2 == FileSys_Wad) { iVar4 = wad::Wad_hLength(*(int *)f->stream); uVar6 = count * size; iVar1 = ((int *)f->stream)[1]; if (iVar4 < (int)(iVar1 + uVar6)) { uVar6 = iVar4 - iVar1; } pvVar5 = wad::Wad_hData(*(int *)f->stream); puVar8 = (undefined4 *)((int)pvVar5 + *(int *)(f->stream + 4)); for (uVar7 = uVar6 >> 2; uVar7 != 0; uVar7 -= 1) { *(undefined4 *)out_buffer = *puVar8; puVar8 = puVar8 + 1; out_buffer = (undefined4 *)((int)out_buffer + 4); } for (uVar7 = uVar6 & 3; uVar7 != 0; uVar7 -= 1) { *(undefined *)out_buffer = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); out_buffer = (undefined4 *)((int)out_buffer + 1); } *(uint *)(f->stream + 4) = *(int *)(f->stream + 4) + uVar6; return (int)uVar6 / size; } if (FVar2 == FileSys_Standard) { sVar3 = std::fread(out_buffer,size,count,(FILE *)f->stream); return sVar3; } File_Error("%s(%i) : Unknown file system in call to %s", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",395,____EMPTYSTR__); return 0; } int __cdecl lego::io::File_Write(void *buffer,int size,int count,File *f) { FileSys FVar1; size_t sVar2; FVar1 = _File_GetSystem(f); if (FVar1 == FileSys_Wad) { File_Error("Cannot write to a file stored in a Wad!"); return 0; } if (FVar1 != FileSys_Standard) { File_Error("%s(%i) : Unknown file system in call to %s", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",414,"File_Write"); return 0; } sVar2 = std::fwrite(buffer,size,count,(FILE *)f->stream); return sVar2; } int __cdecl lego::io::File_Close(File *f) { FileSys FVar1; FVar1 = _File_GetSystem(f); if ((-1 < (int)FVar1) && ((int)FVar1 < 2)) { _File_Dealloc(f); return 0; } File_Error("%s(%i) : Unknown file system in call to %s", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",431,"File_Close"); return 0; } int __cdecl lego::io::File_Tell(File *f) { FileSys FVar1; int iVar2; FVar1 = _File_GetSystem(f); if (FVar1 == FileSys_Wad) { return *(int *)(f->stream + 4); } if (FVar1 != FileSys_Standard) { File_Error("%s(%i) : Unknown file system in call to %s", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",469,"File_Tell"); return 0; } iVar2 = std::ftell((FILE *)f->stream); return iVar2; } BOOL __cdecl lego::io::File_Exists(char *fName) { char *fName_00; FileSys FVar1; FILE *pFVar2; BOOL BVar3; char cdName [260]; fName_00 = File_VerifyFilename(fName); FVar1 = _File_CheckSystem(fName_00,"r"); if (FVar1 == FileSys_Standard) { pFVar2 = std::fopen(fName_00,"r"); if (pFVar2 != NULL) { std::fclose(pFVar2); return TRUE; } BVar3 = File_GetCDFilePath(cdName,fName); if (BVar3 != 0) { pFVar2 = std::fopen(cdName,"r"); if (pFVar2 != NULL) { std::fclose(pFVar2); return TRUE; } } } else { if (FVar1 == FileSys_Wad) { BVar3 = wad::Wad_IsFileInWad(fName_00,globs::currWadHandle); return BVar3; } } return 0; } int __cdecl lego::io::File_GetC(File *f) { int iVar1; int iVar2; FileSys FVar3; int iVar4; void *pvVar5; FVar3 = _File_GetSystem(f); if (FVar3 == FileSys_Wad) { iVar4 = wad::Wad_hLength(*(int *)f->stream); if (iVar4 + -1 <= ((int *)f->stream)[1]) { return -1; } iVar4 = f->stream; iVar1 = *(int *)(iVar4 + 4); pvVar5 = wad::Wad_hData(*(int *)f->stream); iVar2 = *(int *)((int)pvVar5 + iVar1); *(int *)(iVar4 + 4) = iVar1 + 1; return iVar2; } if (FVar3 != FileSys_Standard) { File_Error("%s(%i) : Unknown file system in call to %s", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",545,"File_GetC"); return 0; } iVar4 = std::fgetc((FILE *)f->stream); return iVar4; } int __cdecl lego::io::File_Length(File *f) { int pos; int iVar1; pos = File_Tell(f); File_Seek(f,0,SEEK_END); iVar1 = File_Tell(f); File_Seek(f,pos,SEEK_SET); return iVar1; } char * __cdecl lego::io::File_InternalFGetS(char *out_str,int num,File *f) { char cVar1; int iVar2; int iVar3; iVar3 = 0; iVar2 = File_GetC(f); cVar1 = (char)iVar2; *out_str = cVar1; while ((((cVar1 != '\0' && (out_str[iVar3] != '\n')) && (out_str[iVar3] != -1)) && (iVar3 != num)) ) { iVar3 += 1; iVar2 = File_GetC(f); cVar1 = (char)iVar2; out_str[iVar3] = cVar1; } out_str[iVar3 + 1] = '\0'; return (char *)(-(uint)(iVar3 != 0) & (uint)out_str); } char * __cdecl lego::io::File_GetS(char *out_str,int num,File *f) { FileSys FVar1; char *pcVar2; FVar1 = _File_GetSystem(f); if (FVar1 == FileSys_Wad) { pcVar2 = File_InternalFGetS(out_str,num,f); return pcVar2; } if (FVar1 != FileSys_Standard) { File_Error("%s(%i) : Unknown file system in call to %s", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",587,"File_GetS"); return NULL; } pcVar2 = std::fgets(out_str,num,(FILE *)f->stream); return pcVar2; } int __cdecl lego::io::File_PrintF(File *f,char *msg,...) { FileSys FVar1; FVar1 = _File_GetSystem(f); if (FVar1 == FileSys_Wad) { File_Error("\"fprintf\" is unsupprted for wad files"); return 0; } if (FVar1 != FileSys_Standard) { File_Error("%s(%i) : Unknown file system in call to %s", "C:\\Dev\\SourceSafe\\gods98_dx6\\gods98\\src\\Files.c",612,"File_PrintF"); return 0; } std::vfprintf((FILE *)f->stream,msg,&stack0x0000000c); return 0; } FileSys __cdecl lego::io::_File_GetSystem(File *f) { return f->type; } FileSys __cdecl lego::io::_File_CheckSystem(char *fName,char *mode) { char cVar1; char *pcVar2; int iVar3; if ((fName != NULL) && (mode != NULL)) { iVar3 = -1; pcVar2 = fName; do { if (iVar3 == 0) break; iVar3 += -1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); if (iVar3 != -2) { iVar3 = -1; pcVar2 = mode; do { if (iVar3 == 0) break; iVar3 += -1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); if (iVar3 != -2) { if ((*mode != 'w') && (*mode != 'W')) { iVar3 = globs::currWadHandle; pcVar2 = _File_GetWadName(fName); iVar3 = wad::Wad_IsFileInWad(pcVar2,iVar3); return (uint)(iVar3 == -1); } return FileSys_Standard; } } } return FileSys_Error; } BOOL __cdecl lego::io::_File_OpenWad(WADFILE *wad,char *fName) { int iVar1; wad->eof = 0; wad->streamPos = 0; iVar1 = lego::wad::Wad_FileOpen(fName,globs::currWadHandle); wad->hFile = iVar1; return (uint)(iVar1 != -1); } File * __cdecl lego::io::_File_Alloc(FileSys fType) { File *pFVar1; File *file; WADFILE *wadStream; if (fType == FileSys_Standard) { pFVar1 = (File *)_File_Malloc(8); pFVar1->type = FileSys_Standard; return pFVar1; } if (fType == FileSys_Wad) { file = (File *)_File_Malloc(8); if (file != NULL) { file->type = FileSys_Wad; wadStream = (WADFILE *)_File_Malloc(0xc); file->stream = wadStream; if (wadStream != NULL) { return file; } _File_Free(file); } } return NULL; } // (Change to whatever is required) void * __cdecl lego::io::_File_Malloc(int size) { void *pvVar1; pvVar1 = Mem_Alloc(size); return pvVar1; } // (Change to whatever is required) void __cdecl lego::io::_File_Free(void *ptr) { Mem_Free(ptr); return; } void __cdecl lego::io::_File_Dealloc(File *file) { FileSys FVar1; if (file != NULL) { FVar1 = _File_GetSystem(file); if (FVar1 == FileSys_Standard) { if ((FILE *)file->stream != NULL) { std::fclose((FILE *)file->stream); _File_Free(file); return; } } else { FVar1 = _File_GetSystem(file); if (FVar1 != FileSys_Wad) { return; } if ((int *)file->stream != NULL) { wad::Wad_FileClose(*(int *)file->stream); _File_Free((void *)file->stream); } } _File_Free(file); } return; } char * __cdecl lego::io::_File_GetWadName(char *fName) { char cVar1; int iVar2; uint uVar3; uint uVar4; int iVar5; char *pcVar6; File_Globs *pFVar7; if (globs::fileGlobs.basePathSet == 0) { return fName; } uVar3 = 0xffffffff; pcVar6 = fName; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); uVar4 = 0xffffffff; pFVar7 = &globs::fileGlobs; do { if (uVar4 == 0) break; uVar4 -= 1; pcVar6 = pFVar7->wadBasePath; pFVar7 = (File_Globs *)(pFVar7->wadBasePath + 1); } while (*pcVar6 != '\0'); iVar5 = ~uVar4 - 1; if ((int)(~uVar3 - 1) <= iVar5) { return fName; } cVar1 = fName[iVar5]; fName[iVar5] = '\0'; iVar2 = std::_stricmp(fName,globs::fileGlobs.wadBasePath); if (iVar2 == 0) { std::sprintf(globs::fileGlobs.s_GetWadName_wadedName,"%s",fName + ~uVar4); fName[iVar5] = cVar1; return globs::fileGlobs.s_GetWadName_wadedName; } fName[iVar5] = cVar1; return fName; } char * __cdecl lego::io::File_GetLine(char *out_str,uint size,File *file) { char cVar1; char *pcVar2; uint uVar3; int iVar4; char *pcVar5; pcVar2 = File_GetS(out_str,size,file); uVar3 = 0xffffffff; pcVar5 = out_str; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); uVar3 = ~uVar3; iVar4 = uVar3 - 2; if (out_str[iVar4] == '\n') { out_str[iVar4] = '\0'; } if ((iVar4 != 0) && (out_str[uVar3 - 3] == '\r')) { out_str[uVar3 - 3] = '\0'; } return pcVar2; } byte * __cdecl lego::io::File_LoadBinary(char *filename,uint *out_size) { byte *buffer; buffer = (byte *)File_Load(filename,out_size,TRUE); return buffer; } void * __cdecl lego::io::File_Load(char *filename,uint *out_size,BOOL binary) { char *mode; File *file; uint length; void *out_buffer; mode = "rb"; if (binary == 0) { mode = "r"; } file = File_Open(filename,mode); if (file != NULL) { File_Seek(file,0,SEEK_END); length = File_Tell(file); if (globs::fileGlobs.loadCallback != NULL) { (*globs::fileGlobs.loadCallback)(filename,length,globs::fileGlobs.loadCallbackData); } out_buffer = Mem_Alloc(length); if (out_buffer != NULL) { File_Seek(file,0,SEEK_SET); File_Read(out_buffer,1,length,file); if (out_size != NULL) { *out_size = length; } File_Close(file); return out_buffer; } File_Close(file); } return NULL; } uint __cdecl lego::io::File_LoadBinaryHandle(char *filename,uint *out_size) { File *f; uint fileSize; int bufferIndex; void *out_buffer; f = File_Open(filename,"rb"); if (f != NULL) { File_Seek(f,0,SEEK_END); fileSize = File_Tell(f); if (globs::fileGlobs.loadCallback != NULL) { (*globs::fileGlobs.loadCallback)(filename,fileSize,globs::fileGlobs.loadCallbackData); } bufferIndex = Mem_AllocHandle(fileSize); if (bufferIndex != -1) { out_buffer = Mem_AddressHandle(bufferIndex); File_Seek(f,0,SEEK_SET); File_Read(out_buffer,1,fileSize,f); if (out_size != NULL) { *out_size = fileSize; } File_Close(f); return bufferIndex; } File_Close(f); } return 0xffffffff; } char * __cdecl lego::io::File_VerifyFilename(char *filename) { char cVar1; char *pcVar2; int iVar3; uint uVar4; char part [260]; if (filename != NULL) { if (*filename == '\\') { filename = filename + 1; } std::sprintf(part,"%s\\%s",0x5352a8,filename); pcVar2 = std::_fullpath(globs::fileGlobs.s_VerifyFilename_full,part,MAX_PATH); if (pcVar2 != NULL) { uVar4 = 0xffffffff; pcVar2 = globs::fileGlobs.dataDir; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar2; pcVar2 = pcVar2 + 1; } while (cVar1 != '\0'); iVar3 = std::strncmp(globs::fileGlobs.s_VerifyFilename_full,globs::fileGlobs.dataDir, ~uVar4 - 1); if (iVar3 == 0) { return globs::fileGlobs.s_VerifyFilename_full; } } } return NULL; } void __cdecl lego::io::File_SetLoadCallback(FileLoadCallback callback,void *data) { globs::fileGlobs.loadCallback = callback; globs::fileGlobs.loadCallbackData = data; return; } void __cdecl lego::io::File_CheckRedundantFiles(char *logName) { char cVar1; FILE *stream; int iVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; char *pcVar7; char (*pacVar8) [1024]; char buffer [1024]; stream = (FILE *)File_Open(logName,"r"); if (stream != NULL) { globs::checkGlobs.numInList = 0; iVar2 = std::fscanf(stream,"%s",buffer); while (iVar2 != -1) { uVar3 = 0xffffffff; pacVar8 = globs::checkGlobs.loadedList[globs::checkGlobs.numInList]; globs::checkGlobs.numInList += 1; pcVar6 = buffer; do { pcVar7 = pcVar6; if (uVar3 == 0) break; uVar3 -= 1; pcVar7 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar7; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar7 + -uVar3); for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *(undefined4 *)*pacVar8 = *puVar5; puVar5 = puVar5 + 1; pacVar8 = (char (*) [1024])(*pacVar8 + 4); } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { (*pacVar8)[0] = *(char *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); pacVar8 = (char (*) [1024])(*pacVar8 + 1); } iVar2 = std::fscanf(stream,"%s",buffer); } File_CheckDirectory(globs::fileGlobs.dataDir); std::fclose(stream); } return; } void __cdecl lego::io::File_CheckDirectory(char *dirName) { char cVar1; byte bVar2; HANDLE handle; byte *pbVar3; uint uVar4; uint uVar5; int iVar6; char *pcVar7; undefined4 *puVar8; char *pcVar9; char *pcVar10; undefined4 *puVar11; bool bVar12; byte local_518; char local_504 [260]; char name [1024]; uVar4 = 0xffffffff; pcVar7 = dirName; do { pcVar9 = pcVar7; if (uVar4 == 0) break; uVar4 -= 1; pcVar9 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar9; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar8 = (undefined4 *)(pcVar9 + -uVar4); puVar11 = (undefined4 *)name; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar11 = *puVar8; puVar8 = puVar8 + 1; puVar11 = puVar11 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } uVar4 = 0xffffffff; pcVar7 = "\\*.*"; do { pcVar9 = pcVar7; if (uVar4 == 0) break; uVar4 -= 1; pcVar9 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar9; } while (cVar1 != '\0'); uVar4 = ~uVar4; iVar6 = -1; pcVar7 = name; do { pcVar10 = pcVar7; if (iVar6 == 0) break; iVar6 += -1; pcVar10 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar10; } while (cVar1 != '\0'); puVar8 = (undefined4 *)(pcVar9 + -uVar4); puVar11 = (undefined4 *)(pcVar10 + -1); for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar11 = *puVar8; puVar8 = puVar8 + 1; puVar11 = puVar11 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } handle = std::_findfirst32(name,(_finddata32_t *)&local_518); if (handle != (HANDLE)0xffffffff) { do { pcVar7 = "."; pbVar3 = (byte *)local_504; do { bVar2 = *pbVar3; bVar12 = bVar2 < (byte)*pcVar7; if (bVar2 != *pcVar7) { LAB_00480709: iVar6 = (1 - (uint)bVar12) - (uint)(bVar12 != 0); goto LAB_0048070e; } if (bVar2 == 0) break; bVar2 = pbVar3[1]; bVar12 = bVar2 < ((byte *)pcVar7)[1]; if (bVar2 != ((byte *)pcVar7)[1]) goto LAB_00480709; pbVar3 = pbVar3 + 2; pcVar7 = (char *)((byte *)pcVar7 + 2); } while (bVar2 != 0); iVar6 = 0; LAB_0048070e: if (iVar6 != 0) { pcVar7 = ".."; pbVar3 = (byte *)local_504; do { bVar2 = *pbVar3; bVar12 = bVar2 < (byte)*pcVar7; if (bVar2 != *pcVar7) { LAB_00480743: iVar6 = (1 - (uint)bVar12) - (uint)(bVar12 != 0); goto LAB_00480748; } if (bVar2 == 0) break; bVar2 = pbVar3[1]; bVar12 = bVar2 < ((byte *)pcVar7)[1]; if (bVar2 != ((byte *)pcVar7)[1]) goto LAB_00480743; pbVar3 = pbVar3 + 2; pcVar7 = (char *)((byte *)pcVar7 + 2); } while (bVar2 != 0); iVar6 = 0; LAB_00480748: if (iVar6 != 0) { uVar4 = 0xffffffff; pcVar7 = dirName; do { pcVar9 = pcVar7; if (uVar4 == 0) break; uVar4 -= 1; pcVar9 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar9; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar8 = (undefined4 *)(pcVar9 + -uVar4); puVar11 = (undefined4 *)name; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar11 = *puVar8; puVar8 = puVar8 + 1; puVar11 = puVar11 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } uVar4 = 0xffffffff; pcVar7 = "\\"; do { pcVar9 = pcVar7; if (uVar4 == 0) break; uVar4 -= 1; pcVar9 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar9; } while (cVar1 != '\0'); uVar4 = ~uVar4; iVar6 = -1; pcVar7 = name; do { pcVar10 = pcVar7; if (iVar6 == 0) break; iVar6 += -1; pcVar10 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar10; } while (cVar1 != '\0'); puVar8 = (undefined4 *)(pcVar9 + -uVar4); puVar11 = (undefined4 *)(pcVar10 + -1); for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar11 = *puVar8; puVar8 = puVar8 + 1; puVar11 = puVar11 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } uVar4 = 0xffffffff; pcVar7 = local_504; do { pcVar9 = pcVar7; if (uVar4 == 0) break; uVar4 -= 1; pcVar9 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar9; } while (cVar1 != '\0'); uVar4 = ~uVar4; iVar6 = -1; pcVar7 = name; do { pcVar10 = pcVar7; if (iVar6 == 0) break; iVar6 += -1; pcVar10 = pcVar7 + 1; cVar1 = *pcVar7; pcVar7 = pcVar10; } while (cVar1 != '\0'); puVar8 = (undefined4 *)(pcVar9 + -uVar4); puVar11 = (undefined4 *)(pcVar10 + -1); for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar11 = *puVar8; puVar8 = puVar8 + 1; puVar11 = puVar11 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } if ((local_518 & 0x10) == 0) { File_CheckFile(name); } else { File_CheckDirectory(name); } } } iVar6 = std::_findnext32(handle,(_finddata32_t *)&local_518); } while (iVar6 == 0); std::_findclose(handle); } return; } void __cdecl lego::io::File_CheckFile(char *fileName) { int iVar1; uint uVar2; FileCheck_Globs *_Str2; uVar2 = 0; if (globs::checkGlobs.numInList != 0) { _Str2 = &globs::checkGlobs; do { iVar1 = std::_stricmp(fileName,(char *)_Str2); if (iVar1 == 0) { return; } uVar2 += 1; _Str2 = (FileCheck_Globs *)_Str2->loadedList[1]; } while (uVar2 < globs::checkGlobs.numInList); } return; } BOOL __cdecl lego::gfx::Mesh_Initialise(char *sharedTextureDir) { char cVar1; uint uVar2; uint uVar3; int iVar4; uint uVar5; undefined4 *puVar6; char *pcVar7; undefined4 *puVar8; Mesh **ppMVar9; globs::meshGlobs.postRenderMeshList = NULL; Mesh_ClearPostRenderList(); if (sharedTextureDir != NULL) { uVar2 = 0xffffffff; pcVar7 = sharedTextureDir; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar7; pcVar7 = pcVar7 + 1; } while (cVar1 != '\0'); uVar2 = ~uVar2; uVar5 = uVar2 - 1; if (sharedTextureDir[uVar2 - 2] != '\\') { uVar5 = uVar2; } globs::meshGlobs.sharedTextureDir = (char *)io::Mem_Alloc(uVar5 + 1); uVar2 = 0xffffffff; do { pcVar7 = sharedTextureDir; if (uVar2 == 0) break; uVar2 -= 1; pcVar7 = sharedTextureDir + 1; cVar1 = *sharedTextureDir; sharedTextureDir = pcVar7; } while (cVar1 != '\0'); uVar2 = ~uVar2; puVar6 = (undefined4 *)(pcVar7 + -uVar2); puVar8 = (undefined4 *)globs::meshGlobs.sharedTextureDir; for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar8 = *puVar6; puVar6 = puVar6 + 1; puVar8 = puVar8 + 1; } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } globs::meshGlobs.sharedTextureDir[uVar5 - 1] = '\\'; globs::meshGlobs.sharedTextureDir[uVar5] = '\0'; } ppMVar9 = globs::meshGlobs.listSet; for (iVar4 = 0x14; iVar4 != 0; iVar4 += -1) { *ppMVar9 = NULL; ppMVar9 = ppMVar9 + 1; } globs::meshGlobs.freeList = NULL; globs::meshGlobs.listCount = 0; Mesh_CreateGlobalMaterial(); return TRUE; } BOOL __cdecl lego::gfx::Mesh_CreateGlobalMaterial(void) { HRESULT HVar1; IDirect3D3 *d3d3; D3DMaterial material; material.dwSize = 0x50; material.diffuse.red = 1.0; material.diffuse.green = 1.0; material.diffuse.blue = 1.0; material.diffuse.alpha = 1.0; material.ambient.red = 0.0; material.ambient.green = 0.0; material.ambient.blue = 0.0; material.ambient.alpha = 0.0; material.specular.red = 0.0; material.specular.green = 0.0; material.specular.blue = 0.0; material.specular.alpha = 0.0; material.emissive.red = 0.0; material.emissive.green = 0.0; material.emissive.blue = 0.0; material.emissive.alpha = 0.0; material.power = 0.0; material.hTexture = 0; material.dwRampSize = 0; // IDirect3DDevice3->GetDirect3D(this, IDirect3D3** lplpD3D) (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetDirect3D)(globs::mainGlobs.imDevice,&d3d3); // IDirect3D3->CreateMaterial(this, IDirect3DMaterial3** lplpDirect3DMaterial3, // IUnknown* pUnkOuter) HVar1 = (**(code **)((int)*d3d3 + 0x14))(d3d3,&globs::meshGlobs.imMat,NULL); if (HVar1 == 0) { // IDirect3DMaterial3->GetHandle(this, IDirect3DDevice3* lpDirect3DDevice, DWORD* // lpHandle) HVar1 = (*(code *)(globs::meshGlobs.imMat)->lpVtbl->GetHandle) (globs::meshGlobs.imMat,globs::mainGlobs.imDevice,&globs::meshGlobs.matHandle) ; if (HVar1 == 0) { Mesh_SetMaterial(&material); if (d3d3 != NULL) { (**(code **)((int)*d3d3 + 8))(d3d3); } return TRUE; } if (d3d3 != NULL) { (**(code **)((int)*d3d3 + 8))(d3d3); } } else { if (d3d3 != NULL) { (**(code **)((int)*d3d3 + 8))(d3d3); return FALSE; } } return FALSE; } BOOL __cdecl lego::gfx::Mesh_SetMaterial(D3DMaterial *newMaterial) { HRESULT HVar1; HVar1 = (*(code *)(globs::meshGlobs.imMat)->lpVtbl->SetMaterial) (globs::meshGlobs.imMat,newMaterial); return (uint)(HVar1 == 0); } Mesh * __cdecl lego::gfx::Mesh_ObtainFromList(void) { int iVar1; Mesh *pMVar2; Mesh *newMesh; if (globs::meshGlobs.freeList == NULL) { Mesh_AddList(); } newMesh = globs::meshGlobs.freeList; pMVar2 = globs::meshGlobs.freeList; globs::meshGlobs.freeList = (globs::meshGlobs.freeList)->nextFree; for (iVar1 = 0xd; iVar1 != 0; iVar1 += -1) { pMVar2->groupCount = 0; pMVar2 = (Mesh *)&pMVar2->listSize; } newMesh->nextFree = newMesh; return newMesh; } void __cdecl lego::gfx::Mesh_ReturnToList(Mesh *mesh) { mesh->nextFree = globs::meshGlobs.freeList; globs::meshGlobs.freeList = mesh; return; } void __cdecl lego::gfx::Mesh_AddList(void) { Mesh *pMVar1; Mesh *pMVar2; int iVar3; uint uVar4; uVar4 = 1 << ((byte)globs::meshGlobs.listCount & 0x1f); pMVar2 = (Mesh *)io::Mem_Alloc(uVar4 * 0x34); globs::meshGlobs.listSet[globs::meshGlobs.listCount] = pMVar2; pMVar2 = globs::meshGlobs.listSet[globs::meshGlobs.listCount]; if (pMVar2 != NULL) { globs::meshGlobs.listCount += 1; if (1 < uVar4) { iVar3 = uVar4 - 1; pMVar1 = pMVar2; do { pMVar1->nextFree = pMVar1 + 1; iVar3 += -1; pMVar1 = pMVar1 + 1; } while (iVar3 != 0); } pMVar2[uVar4 - 1].nextFree = globs::meshGlobs.freeList; globs::meshGlobs.freeList = pMVar2; } return; } Mesh * __cdecl lego::gfx::Mesh_CreateOnFrame (IDirect3DRMFrame3 *frame,MeshRenderCallback renderFunc,uint renderFlags,void *data, Mesh_Type type) { IDirect3DRMUserVisual **ppIVar1; Mesh *meshData; meshData = Mesh_ObtainFromList(); Container_GetRoot(); ppIVar1 = &meshData->uv; // IDirect3DRM3->CreateUserVisual(this, TD3DRMUserVisualCallback fn, void* lpArg, // IDirect3DRMUserVisual** lplpD3DRMUV) (*(code *)(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateUserVisual) (globs::mainGlobs.lpD3DRM,Mesh_RenderCallback,meshData,ppIVar1); // IDirect3DRMFrame3->AddVisual(this, IDirect3DRMVisual* lpD3DRMVisual) (*frame->lpVtbl->AddVisual)(frame,(IDirect3DRMVisual *)*ppIVar1); // IDirect3DRMUserVisual->SetAppData(this, Struct_34* ulData) (*(*ppIVar1)->lpVtbl->SetAppData)((IDirect3DRMVisual *)*ppIVar1,meshData); (meshData->renderDesc).renderCallbackData = data; meshData->frameCreatedOn = frame; (meshData->renderDesc).renderCallback = renderFunc; (meshData->renderDesc).renderFlags = renderFlags; if (type == Mesh_Type_PostEffect) { meshData->numOfRefs = 1; meshData->flags = meshData->flags | 2; return meshData; } if (type == Mesh_Type_LightWaveObject) { meshData->flags = meshData->flags | 4; } meshData->numOfRefs = 1; return meshData; } Mesh * __cdecl lego::gfx::Mesh_Clone(Mesh *mesh,IDirect3DRMFrame3 *frame) { IDirect3DRMUserVisual **ppIVar1; Mesh *mesh_00; Mesh_Group *pMVar2; int iVar3; uint uVar4; IDirect3DRMFrame3 *unaff_EBP; Mesh *pMVar5; Mesh_Group *pMVar6; D3DRMGroupIndex groupID; Mesh *pMVar7; mesh_00 = Mesh_ObtainFromList(); if (mesh->clonedFrom != NULL) { mesh = mesh->clonedFrom; } pMVar5 = mesh; pMVar7 = mesh_00; for (iVar3 = 0xd; iVar3 != 0; iVar3 += -1) { pMVar7->groupCount = pMVar5->groupCount; pMVar5 = (Mesh *)&pMVar5->listSize; pMVar7 = (Mesh *)&pMVar7->listSize; } mesh_00->clonedFrom = mesh; mesh_00->listSize = mesh_00->groupCount; pMVar2 = (Mesh_Group *)io::Mem_Alloc(mesh_00->groupCount * 0x70); mesh_00->groupList = pMVar2; pMVar6 = mesh->groupList; for (uVar4 = mesh_00->groupCount * 0x70 >> 2; uVar4 != 0; uVar4 -= 1) { pMVar2->faceDataSize = pMVar6->faceDataSize; pMVar6 = (Mesh_Group *)&pMVar6->vertexCount; pMVar2 = (Mesh_Group *)&pMVar2->vertexCount; } for (iVar3 = 0; iVar3 != 0; iVar3 += -1) { *(undefined *)&pMVar2->faceDataSize = *(undefined *)&pMVar6->faceDataSize; pMVar6 = (Mesh_Group *)((int)&pMVar6->faceDataSize + 1); pMVar2 = (Mesh_Group *)((int)&pMVar2->faceDataSize + 1); } groupID = D3DRMGROUP_0; if (mesh_00->groupCount != 0) { iVar3 = 0; do { Mesh_CreateGroupMaterial(mesh_00,groupID); Mesh_SetGroupMaterial (mesh_00,groupID,(D3DMaterial *)((int)&(mesh->groupList->material).dwSize + iVar3)); groupID += 1; iVar3 += 0x70; } while (groupID < mesh_00->groupCount); } ppIVar1 = &mesh_00->uv; // IDirect3DRM3->CreateUserVisual(this, TD3DRMUserVisualCallback fn, void* lpArg, // IDirect3DRMUserVisual** lplpD3DRMUV) (*(code *)(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateUserVisual) (globs::mainGlobs.lpD3DRM,Mesh_RenderCallback,mesh_00,ppIVar1); // IDirect3DRMFrame3->AddVisual(this, IDirect3DRMVisual* lpD3DRMVisual) (*unaff_EBP->lpVtbl->AddVisual)(unaff_EBP,(IDirect3DRMVisual *)*ppIVar1); // IDirect3DRMUserVisual->SetAppData(this, Struct_3c* ulData) (*(*ppIVar1)->lpVtbl->SetAppData)((IUnknown *)*ppIVar1,(DWORD)mesh_00); mesh_00->frameCreatedOn = unaff_EBP; mesh->numOfRefs = mesh->numOfRefs + 1; mesh->flags = mesh->flags | 0x200000; mesh_00->numOfRefs = 0; return mesh_00; } Mesh * __cdecl lego::gfx::Mesh_Load(char *filename,IDirect3DRMFrame3 *frame,BOOL noTextures) { char *pcVar1; char cVar2; BOOL BVar3; Mesh *mesh; uint uVar4; uint uVar5; char *pcVar6; char *pcVar7; undefined4 *puVar8; undefined4 *puVar9; APPOBJ *lightWaveObject; char filenameBuffer [260]; uVar4 = 0xffffffff; pcVar7 = filename; do { pcVar6 = pcVar7; if (uVar4 == 0) break; uVar4 -= 1; pcVar6 = pcVar7 + 1; cVar2 = *pcVar7; pcVar7 = pcVar6; } while (cVar2 != '\0'); uVar4 = ~uVar4; pcVar7 = filenameBuffer; puVar8 = (undefined4 *)(pcVar6 + -uVar4); puVar9 = (undefined4 *)filenameBuffer; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar9 = *puVar8; puVar8 = puVar8 + 1; puVar9 = puVar9 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } pcVar6 = filenameBuffer; while (filenameBuffer[0] != '\0') { if (filenameBuffer[0] == '\\') { pcVar7 = pcVar6; } pcVar1 = pcVar6 + 1; pcVar6 = pcVar6 + 1; filenameBuffer[0] = *pcVar1; } pcVar7[pcVar7 != filenameBuffer] = '\0'; BVar3 = lw::LoadAppObj(filename,&lightWaveObject,0); if (BVar3 == 0) { return NULL; } mesh = Mesh_CreateOnFrame(frame,NULL,0x3000,NULL,Mesh_Type_LightWaveObject); Mesh_ParseLWO(filenameBuffer,mesh,lightWaveObject,noTextures); lw::FreeLWOB(lightWaveObject); return mesh; } // WARNING: Type propagation algorithm not settling BOOL __cdecl lego::gfx::Mesh_ParseLWO(char *basePath,Mesh *mesh,APPOBJ *lightWaveObject,BOOL noTextures) { float r; uint uVar1; LWPOLY *pLVar2; Vector3F *buffer; Vector3F **buffer_00; uint *buffer_01; undefined4 *buffer_02; uint *buffer_03; uint *buffer_04; void *buffer_05; undefined4 *buffer_06; Mesh_LightWave_Surface *pMVar3; D3DRMGroupIndex groupID; char *pcVar4; Container_Texture *pCVar5; uint uVar6; int iVar7; float *pfVar8; int iVar9; float *pfVar10; uint *puVar11; int iVar12; int iVar13; int iVar14; int iVar15; uint uVar16; undefined4 *puVar17; int iVar18; float g; float fVar19; Point2F *textCoords; Point2F *local_ac; uint local_a8; uint local_a4; uint *local_a0; int *local_9c; Vector3F *local_98; uint *local_8c; Vector3F **local_88; Point2F *local_78; Point2F *local_74; int local_3c [4]; undefined4 local_2c; undefined4 local_28; Vector3F local_24; Vector3F local_18; Vector3F local_c; uVar6 = (lightWaveObject->aoSize).lwVertCount; local_3c[2] = 2; local_2c = 2; uVar1 = (lightWaveObject->aoSize).lwPolyCount; iVar12 = uVar6 * 2; iVar15 = uVar1 * 6; local_3c[0] = 0; local_3c[1] = 1; local_3c[3] = 0; local_28 = 3; local_74 = NULL; if (lightWaveObject->aoFileUV == NULL) { local_78 = (Point2F *)io::Mem_Alloc(uVar6 * 0x10); } else { local_74 = (Point2F *)io::Mem_Alloc(uVar6 * 0x140); Mesh_UViewMesh(lightWaveObject,local_74); iVar12 = (lightWaveObject->aoSize).lwVertCount * 2; local_78 = (Point2F *)io::Mem_Alloc((lightWaveObject->aoSize).lwSurfaceCount * iVar12 * 8); } uVar16 = iVar12 * (lightWaveObject->aoSize).lwSurfaceCount; buffer = (Vector3F *)io::Mem_Alloc(uVar16 * 0xc); buffer_00 = (Vector3F **)io::Mem_Alloc(uVar16 * 4); buffer_01 = (uint *)io::Mem_Alloc((lightWaveObject->aoSize).lwSurfaceCount << 2); buffer_02 = (undefined4 *)io::Mem_Alloc(uVar16 * 4); buffer_03 = (uint *)io::Mem_Alloc(iVar15 * (lightWaveObject->aoSize).lwSurfaceCount * 4); buffer_04 = (uint *)io::Mem_Alloc((lightWaveObject->aoSize).lwSurfaceCount << 2); buffer_05 = io::Mem_Alloc((lightWaveObject->aoSize).lwPolyCount * 0xc); buffer_06 = (undefined4 *)io::Mem_Alloc(iVar12 * 0xc); puVar11 = buffer_01; for (uVar6 = (lightWaveObject->aoSize).lwSurfaceCount & 0x3fffffff; uVar6 != 0; uVar6 -= 1) { *puVar11 = 0; puVar11 = puVar11 + 1; } for (iVar7 = 0; iVar7 != 0; iVar7 += -1) { *(undefined *)puVar11 = 0; puVar11 = (uint *)((int)puVar11 + 1); } puVar17 = buffer_02; for (uVar16 &= 0x3fffffff; uVar16 != 0; uVar16 -= 1) { *puVar17 = 0xffffffff; puVar17 = puVar17 + 1; } for (iVar7 = 0; iVar7 != 0; iVar7 += -1) { *(undefined *)puVar17 = 0xff; puVar17 = (undefined4 *)((int)puVar17 + 1); } puVar11 = buffer_04; for (uVar6 = (lightWaveObject->aoSize).lwSurfaceCount & 0x3fffffff; uVar6 != 0; uVar6 -= 1) { *puVar11 = 0; puVar11 = puVar11 + 1; } for (iVar7 = 0; iVar7 != 0; iVar7 += -1) { *(undefined *)puVar11 = 0; puVar11 = (uint *)((int)puVar11 + 1); } puVar17 = buffer_06; for (uVar6 = iVar12 * 3 & 0x3fffffff; uVar6 != 0; uVar6 -= 1) { *puVar17 = 0; puVar17 = puVar17 + 1; } for (iVar7 = 0; iVar7 != 0; iVar7 += -1) { *(undefined *)puVar17 = 0; puVar17 = (undefined4 *)((int)puVar17 + 1); } pMVar3 = (Mesh_LightWave_Surface *)io::Mem_Alloc((lightWaveObject->aoSize).lwSurfaceCount * 0x3c); mesh->lightWaveSurf = pMVar3; for (uVar6 = (lightWaveObject->aoSize).lwSurfaceCount * 0xf & 0x3fffffff; uVar6 != 0; uVar6 -= 1) { pMVar3->textureSeq = NULL; pMVar3 = (Mesh_LightWave_Surface *)&pMVar3->texture; } for (iVar7 = 0; iVar7 != 0; iVar7 += -1) { *(undefined *)&pMVar3->textureSeq = 0; pMVar3 = (Mesh_LightWave_Surface *)((int)&pMVar3->textureSeq + 1); } local_8c = NULL; if ((lightWaveObject->aoSize).lwPolyCount != 0) { local_9c = NULL; do { pLVar2 = lightWaveObject->aoPoly; pfVar10 = lightWaveObject->aoVerts; pfVar8 = &local_24.y; uVar6 = 0; do { uVar16 = uVar6 + 2; uVar6 = (uint)*(ushort *)(uVar6 + *(int *)((int)&pLVar2->plyData + (int)local_9c)); pfVar8[-1] = pfVar10[uVar6 * 3]; *pfVar8 = pfVar10[uVar6 * 3 + 1]; pfVar8[1] = pfVar10[uVar6 * 3 + 2]; pfVar8 = pfVar8 + 3; uVar6 = uVar16; } while (uVar16 < 6); math::Maths_PlaneNormal ((Vector3F *)((int)buffer_05 + (int)local_9c),&local_24,&local_18,&local_c); local_8c = (uint *)((int)local_8c + 1); local_9c = (int *)((int)local_9c + 0xc); } while (local_8c < (lightWaveObject->aoSize).lwPolyCount); } Mesh_GetSurfInfo(basePath,lightWaveObject,mesh->lightWaveSurf,noTextures); iVar7 = 0; local_8c = NULL; if ((lightWaveObject->aoSize).lwPolyCount != 0) { pfVar10 = (float *)((int)buffer_05 + 8); do { iVar9 = *(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7); iVar13 = iVar15 * iVar9; iVar9 = iVar12 * iVar9; if (*(int *)((int)&lightWaveObject->aoPoly->plyCount + iVar7) == 3) { local_a4 = 0; do { iVar14 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; uVar6 = (uint)*(ushort *)(*(int *)(iVar14 + 8) + local_a4); if (buffer_02[uVar6 + iVar9] == -1) { buffer[buffer_01[*(int *)(iVar14 + 4)] + iVar9].x = lightWaveObject->aoVerts[uVar6 * 3]; buffer[buffer_01[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] + iVar9].y = lightWaveObject->aoVerts[uVar6 * 3 + 1]; buffer[buffer_01[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] + iVar9].z = lightWaveObject->aoVerts[uVar6 * 3 + 2]; if (lightWaveObject->aoFileUV != NULL) { iVar14 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; uVar16 = (uint)*(ushort *)(*(int *)(iVar14 + 8) + local_a4); uVar6 = buffer_01[*(int *)(iVar14 + 4)]; local_78[uVar6 + iVar9].x = local_74[uVar16].x; local_78[uVar6 + iVar9].y = local_74[uVar16].y; } uVar6 = (uint)*(ushort *) (*(int *)((int)&lightWaveObject->aoPoly->plyData + iVar7) + local_a4); pfVar8 = (float *)(buffer_06 + uVar6 * 3); *pfVar8 = pfVar10[-2] + (float)buffer_06[uVar6 * 3]; pfVar8[1] = pfVar8[1] + pfVar10[-1]; pfVar8[2] = pfVar8[2] + *pfVar10; uVar6 = (uint)*(ushort *) (*(int *)((int)&lightWaveObject->aoPoly->plyData + iVar7) + local_a4); pfVar8 = (float *)(buffer_06 + uVar6 * 3); fVar19 = 1.0 / SQRT(*pfVar8 * *pfVar8 + pfVar8[2] * pfVar8[2] + (float)buffer_06[uVar6 * 3 + 1] * (float)buffer_06[uVar6 * 3 + 1]); *pfVar8 = fVar19 * *pfVar8; pfVar8[1] = fVar19 * pfVar8[1]; pfVar8[2] = fVar19 * pfVar8[2]; iVar14 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; buffer_00[buffer_01[*(int *)(iVar14 + 4)] + iVar9] = (Vector3F *)(buffer_06 + (uint)*(ushort *)(*(int *)(iVar14 + 8) + local_a4) * 3); iVar14 = *(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7); buffer_03[buffer_04[iVar14] + iVar13] = buffer_01[iVar14]; buffer_04[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] = buffer_04[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] + 1; iVar14 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; buffer_02[(uint)*(ushort *)(*(int *)(iVar14 + 8) + local_a4) + iVar9] = buffer_01[*(int *)(iVar14 + 4)]; iVar14 = *(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7); puVar11 = buffer_01; } else { pfVar8 = (float *)(buffer_06 + uVar6 * 3); *pfVar8 = pfVar10[-2] + (float)buffer_06[uVar6 * 3]; pfVar8[1] = pfVar8[1] + pfVar10[-1]; pfVar8[2] = pfVar8[2] + *pfVar10; pfVar8 = (float *)(buffer_06 + (uint)*(ushort *) (*(int *)((int)&lightWaveObject->aoPoly->plyData + iVar7) + local_a4) * 3); fVar19 = 1.0 / SQRT(*pfVar8 * *pfVar8 + pfVar8[2] * pfVar8[2] + pfVar8[1] * pfVar8[1]); *pfVar8 = fVar19 * *pfVar8; pfVar8[1] = fVar19 * pfVar8[1]; pfVar8[2] = fVar19 * pfVar8[2]; iVar14 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; buffer_03[buffer_04[*(int *)(iVar14 + 4)] + iVar13] = buffer_02[(uint)*(ushort *)(*(int *)(iVar14 + 8) + local_a4) + iVar9]; iVar14 = *(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7); puVar11 = buffer_04; } local_a4 += 2; puVar11[iVar14] = puVar11[iVar14] + 1; } while (local_a4 < 6); } else { local_9c = local_3c; local_a8 = 6; do { iVar18 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; iVar14 = *local_9c * 2; uVar6 = (uint)*(ushort *)(*(int *)(iVar18 + 8) + iVar14); if (buffer_02[iVar9 + uVar6] == -1) { buffer[buffer_01[*(int *)(iVar18 + 4)] + iVar9].x = lightWaveObject->aoVerts[uVar6 * 3]; buffer[buffer_01[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] + iVar9].y = lightWaveObject->aoVerts[uVar6 * 3 + 1]; buffer[buffer_01[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] + iVar9].z = lightWaveObject->aoVerts[uVar6 * 3 + 2]; if (lightWaveObject->aoFileUV != NULL) { iVar18 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; uVar16 = (uint)*(ushort *)(*(int *)(iVar18 + 8) + iVar14); uVar6 = buffer_01[*(int *)(iVar18 + 4)]; local_78[uVar6 + iVar9].x = local_74[uVar16].x; local_78[uVar6 + iVar9].y = local_74[uVar16].y; } uVar6 = (uint)*(ushort *) (*(int *)((int)&lightWaveObject->aoPoly->plyData + iVar7) + iVar14); pfVar8 = (float *)(buffer_06 + uVar6 * 3); *pfVar8 = pfVar10[-2] + (float)buffer_06[uVar6 * 3]; pfVar8[1] = pfVar8[1] + pfVar10[-1]; pfVar8[2] = pfVar8[2] + *pfVar10; uVar6 = (uint)*(ushort *) (*(int *)((int)&lightWaveObject->aoPoly->plyData + iVar7) + iVar14); pfVar8 = (float *)(buffer_06 + uVar6 * 3); fVar19 = 1.0 / SQRT(*pfVar8 * *pfVar8 + (float)buffer_06[uVar6 * 3 + 2] * (float)buffer_06[uVar6 * 3 + 2] + (float)buffer_06[uVar6 * 3 + 1] * (float)buffer_06[uVar6 * 3 + 1]); *pfVar8 = fVar19 * *pfVar8; pfVar8[1] = fVar19 * pfVar8[1]; pfVar8[2] = fVar19 * pfVar8[2]; iVar18 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; buffer_00[buffer_01[*(int *)(iVar18 + 4)] + iVar9] = (Vector3F *)(buffer_06 + (uint)*(ushort *)(*(int *)(iVar18 + 8) + iVar14) * 3); iVar18 = *(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7); buffer_03[buffer_04[iVar18] + iVar13] = buffer_01[iVar18]; buffer_04[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] = buffer_04[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] + 1; iVar18 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; buffer_02[(uint)*(ushort *)(*(int *)(iVar18 + 8) + iVar14) + iVar9] = buffer_01[*(int *)(iVar18 + 4)]; puVar11 = buffer_01; } else { pfVar8 = (float *)(buffer_06 + uVar6 * 3); *pfVar8 = pfVar10[-2] + (float)buffer_06[uVar6 * 3]; pfVar8[1] = pfVar8[1] + pfVar10[-1]; pfVar8[2] = pfVar8[2] + *pfVar10; pfVar8 = (float *)(buffer_06 + (uint)*(ushort *) (*(int *)((int)&lightWaveObject->aoPoly->plyData + iVar7) + iVar14) * 3); fVar19 = 1.0 / SQRT(*pfVar8 * *pfVar8 + pfVar8[2] * pfVar8[2] + pfVar8[1] * pfVar8[1]); *pfVar8 = *pfVar8 * fVar19; pfVar8[1] = fVar19 * pfVar8[1]; pfVar8[2] = fVar19 * pfVar8[2]; iVar18 = (int)&lightWaveObject->aoPoly->plyCount + iVar7; buffer_03[buffer_04[*(int *)(iVar18 + 4)] + iVar13] = buffer_02[(uint)*(ushort *)(*(int *)(iVar18 + 8) + iVar14) + iVar9]; puVar11 = buffer_04; } puVar11[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] = puVar11[*(int *)((int)&lightWaveObject->aoPoly->plySurface + iVar7)] + 1; local_9c = local_9c + 1; local_a8 += -1; } while (local_a8 != 0); } local_8c = (uint *)((int)local_8c + 1); iVar7 += 0xc; pfVar10 = pfVar10 + 3; } while (local_8c < (lightWaveObject->aoSize).lwPolyCount); } iVar15 = 0; local_a8 = 0; if ((lightWaveObject->aoSize).lwSurfaceCount != 0) { local_a4 = 0; local_ac = local_78; local_a0 = buffer_01; local_98 = buffer; local_8c = buffer_03; local_88 = buffer_00; do { uVar6 = *(uint *)(((int)buffer_04 - (int)buffer_01) + (int)local_a0); groupID = Mesh_AddGroup(mesh,uVar6,uVar6 / 3,3,local_8c); if (lightWaveObject->aoFileUV == NULL) { pcVar4 = lightWaveObject->aoSurface->srfTCLR + local_a4 + -0x10; Mesh_GetTextureUVsWrap (*local_a0,local_98,local_78,*(float *)(pcVar4 + 0x24),*(float *)(pcVar4 + 0x28), *(float *)(pcVar4 + 0x2c),*(float *)(pcVar4 + 0x30),*(float *)(pcVar4 + 0x34), *(float *)(pcVar4 + 0x38),*(LWTEXFLAGS *)(pcVar4 + 0x14)); uVar6 = *local_a0; textCoords = local_78; } else { uVar6 = *local_a0; textCoords = local_ac; } Mesh_SetVertices_VNT(mesh,groupID,0,uVar6,local_98,local_88,(Point2I *)textCoords); if ((*(uint *)((int)&mesh->lightWaveSurf->flags + iVar15) & 0x200) == 0) { uVar6 = 0x3000; } else { Mesh_AlterGroupRenderFlags(mesh,groupID,0x2800); uVar6 = 0x2800; } if ((*(uint *)((int)&mesh->lightWaveSurf->flags + iVar15) & 0x100) != 0) { uVar6 |= 0x4000000; Mesh_AlterGroupRenderFlags(mesh,groupID,uVar6); } if ((*(byte *)((int)&mesh->lightWaveSurf->texFlags + iVar15) & 0x20) == 0) { Mesh_AlterGroupRenderFlags(mesh,groupID,uVar6 | 0x800000); } if ((lightWaveObject->aoSurface->srfTCLR[local_a4 + 4] & 0x80U) == 0) { pCVar5 = *(Container_Texture **)((int)&mesh->lightWaveSurf->texture + iVar15); if (pCVar5 != NULL) goto LAB_004818c5; } else { pCVar5 = *(Container_Texture **)((int)&mesh->lightWaveSurf->textureSeq + iVar15); if (pCVar5 != NULL) { pCVar5 = (Container_Texture *)pCVar5->surface; LAB_004818c5: Mesh_SetGroupTexture(mesh,groupID,pCVar5); } } pMVar3 = mesh->lightWaveSurf; iVar7 = (int)&pMVar3->textureSeq + iVar15; Mesh_SetGroupColour(mesh,groupID,*(float *)(iVar7 + 0xc) * *(float *)(iVar7 + 0x1c), *(float *)(iVar7 + 0x10) * *(float *)(iVar7 + 0x1c), *(float *)((int)&(pMVar3->colour).blue + iVar15) * *(float *)((int)&pMVar3->diffuse + iVar15),Mesh_Colour_Diffuse); iVar7 = (int)&mesh->lightWaveSurf->textureSeq + iVar15; Mesh_SetGroupColour(mesh,groupID,*(float *)(iVar7 + 0xc) * *(float *)(iVar7 + 0x20), *(float *)(iVar7 + 0x10) * *(float *)(iVar7 + 0x20), *(float *)(iVar7 + 0x14) * *(float *)(iVar7 + 0x20),Mesh_Colour_Emissive); iVar7 = (int)&mesh->lightWaveSurf->textureSeq + iVar15; if ((*(byte *)((int)&mesh->lightWaveSurf->flags + iVar15) & 8) == 0) { fVar19 = *(float *)(iVar7 + 0x24); g = *(float *)(iVar7 + 0x24); r = *(float *)(iVar7 + 0x24); } else { fVar19 = *(float *)(iVar7 + 0x14) * *(float *)(iVar7 + 0x24); g = *(float *)(iVar7 + 0x10) * *(float *)(iVar7 + 0x24); r = *(float *)(iVar7 + 0xc) * *(float *)(iVar7 + 0x24); } Mesh_SetGroupColour(mesh,groupID,r,g,fVar19,Mesh_Colour_Specular); Mesh_SetGroupMaterialValues (mesh,groupID,*(float *)((int)&mesh->lightWaveSurf->power + iVar15) * 10.0, Mesh_Colour_Power); Mesh_SetGroupMaterialValues (mesh,groupID,1.0 - *(float *)((int)&mesh->lightWaveSurf->transparency + iVar15), Mesh_Colour_Alpha); pMVar3 = (Mesh_LightWave_Surface *)((int)&mesh->lightWaveSurf->textureSeq + iVar15); iVar15 += 0x3c; mesh->groupList[groupID].lightWaveSurfaceInfo = pMVar3; local_ac = local_ac + iVar12; local_88 = local_88 + iVar12; local_98 = local_98 + iVar12; local_8c = local_8c + uVar1 * 6; local_a0 = local_a0 + 1; local_a8 += 1; local_a4 += 0x54; } while (local_a8 < (lightWaveObject->aoSize).lwSurfaceCount); } io::Mem_Free(buffer); io::Mem_Free(buffer_00); io::Mem_Free(local_78); io::Mem_Free(buffer_01); io::Mem_Free(buffer_02); io::Mem_Free(buffer_03); io::Mem_Free(buffer_04); io::Mem_Free(buffer_05); io::Mem_Free(buffer_06); if (local_74 != NULL) { io::Mem_Free(local_74); } return TRUE; } void __cdecl lego::gfx::Mesh_GetSurfInfo (char *basePath,APPOBJ *lightWaveObject,Mesh_LightWave_Surface *lightWaveSurf, BOOL noTextures) { byte bVar1; char *path; BOOL BVar2; void *pvVar3; Container_Texture *pCVar4; float fVar5; ColourRGBAF *pCVar6; int iVar7; uint local_618; uint local_614; uint local_610; uint local_60c; char drive [4]; char pathBuff [260]; char ext [256]; char fname [256]; char textName [256]; char baseName [256]; char dir [256]; local_614 = 0; if ((lightWaveObject->aoSize).lwSurfaceCount != 0) { pCVar6 = &lightWaveSurf->colour; iVar7 = 0; do { path = *(char **)(lightWaveObject->aoSurface->srfTCLR + iVar7 + -8); if ((path == NULL) || (noTextures != 0)) { pCVar6->red = (float)(uint)(byte)lightWaveObject->aoSurface->srfTCLR[iVar7 + -4] * 0.00390625; pCVar6->green = (float)(uint)(byte)lightWaveObject->aoSurface->srfTCLR[iVar7 + -3] * 0.00390625; bVar1 = lightWaveObject->aoSurface->srfTCLR[iVar7 + -2]; LAB_00481d09: local_618 = (uint)bVar1; pCVar6->blue = (float)local_618 * 0.00390625; } else { std::_splitpath(path,drive,dir,fname,ext); if ((lightWaveObject->aoSurface->srfTCLR[iVar7 + 4] & 0x80U) == 0) { std::sprintf(pathBuff,"%s%s",fname,ext); pCVar4 = Mesh_LoadTexture(basePath,pathBuff,NULL,NULL); pCVar6[-1].blue = (float)pCVar4; } else { BVar2 = Mesh_GetTextureSeqInfo(fname,baseName,(int *)&local_60c,(int *)&local_610); if (BVar2 != 0) { pvVar3 = io::Mem_Alloc(400); pCVar6[-1].green = (float)pvVar3; fVar5 = 0.0; do { Mesh_GetNextInSequence(baseName,textName,&local_60c,local_610); std::sprintf(pathBuff,"%s%s",textName,ext); pCVar4 = Mesh_LoadTexture(basePath,pathBuff,NULL,NULL); *(Container_Texture **)((int)pCVar6[-1].green + (int)fVar5 * 4) = pCVar4; if (*(int *)((int)pCVar6[-1].green + (int)fVar5 * 4) == 0) break; fVar5 = (float)((int)fVar5 + 1); } while ((uint)fVar5 < 100); pCVar6[-1].alpha = fVar5; pvVar3 = io::Mem_ReAlloc((void *)pCVar6[-1].green,(int)fVar5 * 4); pCVar6[-1].green = (float)pvVar3; } } if ((lightWaveObject->aoSurface->srfTCLR[iVar7 + 8] & 0x80U) != 0) { pCVar6->red = (float)(uint)(byte)lightWaveObject->aoSurface->srfTCLR[iVar7 + -4] * 0.00390625; pCVar6->green = (float)(uint)(byte)lightWaveObject->aoSurface->srfTCLR[iVar7 + -3] * 0.00390625; bVar1 = lightWaveObject->aoSurface->srfTCLR[iVar7 + -2]; goto LAB_00481d09; } pCVar6->red = 1.0; pCVar6->green = 1.0; pCVar6->blue = 1.0; } pCVar6[1].green = *(float *)(lightWaveObject->aoSurface->srfTCLR + iVar7 + 0x2c); pCVar6[2].red = *(float *)(lightWaveObject->aoSurface->srfTCLR + iVar7 + 0x30); pCVar6[1].red = *(float *)(lightWaveObject->aoSurface->srfTCLR + iVar7 + 0x34); pCVar6[1].blue = *(float *)(lightWaveObject->aoSurface->srfTCLR + iVar7 + 0x3c); pCVar6[1].alpha = *(float *)(lightWaveObject->aoSurface->srfTCLR + iVar7 + 0x40); pCVar6[2].green = *(float *)(lightWaveObject->aoSurface->srfTCLR + iVar7 + 8); pCVar6[2].blue = *(float *)(lightWaveObject->aoSurface->srfTCLR + iVar7 + 4); local_614 += 1; pCVar6 = (ColourRGBAF *)&pCVar6[3].alpha; iVar7 = iVar7 + 0x54; } while (local_614 < (lightWaveObject->aoSize).lwSurfaceCount); } return; } BOOL __cdecl lego::gfx::Mesh_GetTextureSeqInfo(char *tname,char *out_tfname,int *out_tstart,int *out_tnumlen) { char cVar1; byte bVar2; uint uVar3; uint uVar4; uint uVar5; int iVar6; int iVar7; undefined4 *puVar8; char *pcVar9; char *pcVar10; undefined4 *puVar11; bool bVar12; int local_4; pcVar9 = tname; uVar3 = 0xffffffff; pcVar10 = tname; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar10; pcVar10 = pcVar10 + 1; } while (cVar1 != '\0'); uVar3 = ~uVar3; iVar6 = 1; local_4 = 0; if ((0x2f < (byte)tname[uVar3 - 2]) && ((byte)tname[uVar3 - 2] < 0x3a)) { iVar7 = uVar3 - 2; bVar12 = iVar7 == 0; if (!bVar12) { do { bVar2 = pcVar9[iVar7]; tname = (char *)(uint)bVar2; if ((bVar2 < 0x30) || (0x39 < bVar2)) break; local_4 += (int)(tname + -0x30) * iVar6; iVar6 *= 10; iVar7 += -1; } while (iVar7 != 0); bVar12 = iVar7 == 0; } if (!bVar12) { uVar4 = 0xffffffff; do { pcVar10 = pcVar9; if (uVar4 == 0) break; uVar4 -= 1; pcVar10 = pcVar9 + 1; cVar1 = *pcVar9; pcVar9 = pcVar10; } while (cVar1 != '\0'); uVar4 = ~uVar4; puVar8 = (undefined4 *)(pcVar10 + -uVar4); puVar11 = (undefined4 *)out_tfname; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar11 = *puVar8; puVar8 = puVar8 + 1; puVar11 = puVar11 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } out_tfname[iVar7 + 1] = '\0'; *out_tnumlen = (uVar3 - iVar7) + -2; *out_tstart = local_4; return (BOOL)out_tnumlen; } } return (BOOL)NULL; } void __cdecl lego::gfx::Mesh_GetNextInSequence (char *baseName,char *out_nextTextName,uint *ref_texNum,uint tnumlen) { char cVar1; int iVar2; uint uVar3; uint uVar4; int iVar5; undefined4 *puVar6; char *pcVar7; char *pcVar8; char *pcVar9; undefined4 *puVar10; char local_10 [16]; uVar3 = 0xffffffff; do { pcVar8 = baseName; if (uVar3 == 0) break; uVar3 -= 1; pcVar8 = baseName + 1; cVar1 = *baseName; baseName = pcVar8; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar6 = (undefined4 *)(pcVar8 + -uVar3); puVar10 = (undefined4 *)out_nextTextName; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar10 = *puVar6; puVar6 = puVar6 + 1; puVar10 = puVar10 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } std::sprintf(local_10,"%d",*ref_texNum); uVar3 = 0xffffffff; pcVar8 = local_10; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar8; pcVar8 = pcVar8 + 1; } while (cVar1 != '\0'); iVar2 = tnumlen - (~uVar3 - 1); while (iVar2 != 0) { uVar3 = 0xffffffff; pcVar8 = "0"; do { pcVar7 = pcVar8; if (uVar3 == 0) break; uVar3 -= 1; pcVar7 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar7; } while (cVar1 != '\0'); uVar3 = ~uVar3; iVar5 = -1; pcVar8 = out_nextTextName; do { pcVar9 = pcVar8; if (iVar5 == 0) break; iVar5 += -1; pcVar9 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar9; } while (cVar1 != '\0'); puVar6 = (undefined4 *)(pcVar7 + -uVar3); puVar10 = (undefined4 *)(pcVar9 + -1); for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar10 = *puVar6; puVar6 = puVar6 + 1; puVar10 = puVar10 + 1; } iVar2 += -1; for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } } uVar3 = 0xffffffff; *ref_texNum = *ref_texNum + 1; pcVar8 = local_10; do { pcVar7 = pcVar8; if (uVar3 == 0) break; uVar3 -= 1; pcVar7 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar7; } while (cVar1 != '\0'); uVar3 = ~uVar3; iVar2 = -1; do { pcVar8 = out_nextTextName; if (iVar2 == 0) break; iVar2 += -1; pcVar8 = out_nextTextName + 1; cVar1 = *out_nextTextName; out_nextTextName = pcVar8; } while (cVar1 != '\0'); puVar6 = (undefined4 *)(pcVar7 + -uVar3); puVar10 = (undefined4 *)(pcVar8 + -1); for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar10 = *puVar6; puVar6 = puVar6 + 1; puVar10 = puVar10 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar6; puVar6 = (undefined4 *)((int)puVar6 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } return; } void __cdecl lego::gfx::Mesh_UViewMesh(APPOBJ *lightWaveObject,Point2F *textCoords) { ushort *puVar1; float fVar2; float fVar3; char cVar4; File *file; bool bVar5; undefined4 *buffer; char *pcVar6; float *pfVar7; uint uVar8; int iVar9; uint uVar10; undefined4 *puVar11; char *pcVar12; undefined4 *puVar13; float10 fVar14; int local_840; int local_83c; int local_838; uint local_834; int local_830; int local_820; char *local_814; char *local_810; char line [1024]; char lineSplit [1024]; file = lightWaveObject->aoFileUV; local_838 = -1; local_83c = -1; local_830 = 0; local_840 = -2; local_834 = 0; buffer = (undefined4 *)io::Mem_Alloc((lightWaveObject->aoSize).lwVertCount << 3); puVar11 = buffer; for (uVar8 = ((lightWaveObject->aoSize).lwVertCount << 3) >> 2; uVar8 != 0; uVar8 -= 1) { *puVar11 = 0; puVar11 = puVar11 + 1; } for (iVar9 = 0; iVar9 != 0; iVar9 += -1) { *(undefined *)puVar11 = 0; puVar11 = (undefined4 *)((int)puVar11 + 1); } pcVar6 = io::File_GetLine(line,0x400,file); do { if (pcVar6 == NULL) { io::Mem_Free(buffer); return; } uVar8 = 0xffffffff; pcVar6 = line; do { pcVar12 = pcVar6; if (uVar8 == 0) break; uVar8 -= 1; pcVar12 = pcVar6 + 1; cVar4 = *pcVar6; pcVar6 = pcVar12; } while (cVar4 != '\0'); uVar8 = ~uVar8; puVar11 = (undefined4 *)(pcVar12 + -uVar8); puVar13 = (undefined4 *)lineSplit; for (uVar10 = uVar8 >> 2; uVar10 != 0; uVar10 -= 1) { *puVar13 = *puVar11; puVar11 = puVar11 + 1; puVar13 = puVar13 + 1; } for (uVar8 &= 3; uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar13 = *(undefined *)puVar11; puVar11 = (undefined4 *)((int)puVar11 + 1); puVar13 = (undefined4 *)((int)puVar13 + 1); } iVar9 = util::Util_WSTokenise(lineSplit,&local_814); if (iVar9 != 0) { if (local_830 == 2) { local_838 = 0; } if (local_838 != -1) { uVar8 = (lightWaveObject->aoSize).lwSurfaceCount; if (local_838 < (int)(uVar8 * 2)) { if ((int)uVar8 <= local_838) { pcVar6 = util::Util_StrCpy(local_814); lightWaveObject->aoSurface[local_838 - (lightWaveObject->aoSize).lwSurfaceCount].srfPath = pcVar6; } local_838 += 1; } else { local_838 = -1; local_840 = -1; } } if (local_840 != -2) { if (local_840 == -1) { local_840 = 0; } else { uVar8 = (lightWaveObject->aoSize).lwPolyCount; if ((int)uVar8 <= local_840) { return; } if ((local_83c == -1) || ((int)lightWaveObject->aoPoly[local_820].plyCount <= local_83c)) { if (local_840 < (int)(uVar8 - 1)) { local_820 = std::atoi(local_814); if (local_83c != -1) { local_840 += 1; } local_83c = 0; } } else { fVar14 = std::atof(local_814); fVar2 = (float)fVar14; fVar14 = std::atof(local_810); fVar3 = (float)-fVar14; uVar8 = (uint)lightWaveObject->aoPoly[local_820].plyData[local_83c]; if ((textCoords[uVar8].x == fVar2) && (textCoords[uVar8].y == fVar3)) { bVar5 = false; } else { bVar5 = true; } if (buffer[uVar8] == 0) { textCoords[uVar8].x = fVar2; textCoords[lightWaveObject->aoPoly[local_820].plyData[local_83c]].y = fVar3; puVar1 = lightWaveObject->aoPoly[local_820].plyData + local_83c; local_83c += 1; buffer[*puVar1] = 1; } else { if (bVar5) { if (local_834 == 0) { pfVar7 = (float *)io::Mem_ReAlloc(lightWaveObject->aoVerts, ((lightWaveObject->aoSize).lwVertCount + 0xb) * 0xc); lightWaveObject->aoVerts = pfVar7; } uVar10 = (uint)lightWaveObject->aoPoly[local_820].plyData[local_83c]; uVar8 = (lightWaveObject->aoSize).lwVertCount; lightWaveObject->aoVerts[uVar8 * 3] = lightWaveObject->aoVerts[uVar10 * 3]; lightWaveObject->aoVerts[uVar8 * 3 + 1] = lightWaveObject->aoVerts[uVar10 * 3 + 1]; lightWaveObject->aoVerts[uVar8 * 3 + 2] = lightWaveObject->aoVerts[uVar10 * 3 + 2]; lightWaveObject->aoPoly[local_820].plyData[local_83c] = *(ushort *)&(lightWaveObject->aoSize).lwVertCount; textCoords[lightWaveObject->aoPoly[local_820].plyData[local_83c]].x = fVar2; textCoords[lightWaveObject->aoPoly[local_820].plyData[local_83c]].y = fVar3; local_834 += 1; (lightWaveObject->aoSize).lwVertCount = (lightWaveObject->aoSize).lwVertCount + 1; if (9 < local_834) { local_834 = 0; } } local_83c += 1; } } } } local_830 += 1; } pcVar6 = io::File_GetLine(line,0x400,file); } while( true ); } void __cdecl lego::gfx::Mesh_GetTextureUVsWrap (uint vertexCount,Vector3F *vertices,Point2F *coords,float sx,float sy,float sz,float px, float py,float pz,LWTEXFLAGS flags) { float fVar1; float fVar2; float fVar3; float *pfVar4; if (vertexCount != 0) { pfVar4 = &vertices->z; do { fVar1 = pfVar4[-1]; fVar2 = *pfVar4; if ((flags & TFM_AXIS_X) == 0) { fVar3 = (pfVar4[-2] - px) / sx; } else { fVar3 = (fVar2 - pz) / sz; } coords->x = fVar3 - -0.5; if ((flags & TFM_AXIS_Y) == 0) { fVar1 = (fVar1 - py) / sy; } else { fVar1 = (fVar2 - pz) / sz; } pfVar4 = pfVar4 + 3; vertexCount -= 1; coords->y = fVar1 - -0.5; coords = coords + 1; } while (vertexCount != 0); } return; } BOOL __cdecl lego::gfx::Mesh_SetTextureTime2(Mesh *mesh,float frame) { int *piVar1; int iVar2; int iVar3; D3DRMGroupIndex groupID; float10 fVar4; longlong lVar5; fVar4 = std::fmod((float10)frame,(float10)1.0); lVar5 = __ftol((float10)frame - fVar4); if ((*(byte *)&mesh->flags & 4) == 0) { return FALSE; } groupID = D3DRMGROUP_0; if (mesh->groupCount != 0) { iVar3 = 0; do { piVar1 = *(int **)((int)&mesh->groupList->lightWaveSurfaceInfo + iVar3); if (((*(byte *)(piVar1 + 0xd) & 0x80) != 0) && (piVar1[2] != 0)) { iVar2 = (piVar1[0xe] + (int)lVar5) % piVar1[2]; if (iVar2 < 0) { iVar2 = 0; } Mesh_SetGroupTexture(mesh,groupID,*(Container_Texture **)(*piVar1 + iVar2 * 4)); } groupID += 1; iVar3 += 0x70; } while (groupID < mesh->groupCount); } return TRUE; } void __cdecl lego::gfx::Mesh_Remove(Mesh *mesh,IDirect3DRMFrame3 *frame) { Mesh *pMVar1; IDirect3DRMUserVisual *pIVar2; uint uVar3; D3DRMGroupIndex groupID; int iVar4; int iVar5; (*frame->lpVtbl->DeleteVisual)(frame,(IDirect3DRMVisual *)mesh->uv); pMVar1 = mesh->clonedFrom; groupID = D3DRMGROUP_0; if (pMVar1 != NULL) { pIVar2 = mesh->uv; if (pIVar2 != NULL) { (*pIVar2->lpVtbl->Release)((IUnknown *)pIVar2); mesh->uv = NULL; } io::Mem_Free(mesh->groupList); Mesh_ReturnToList(mesh); mesh = pMVar1; } uVar3 = mesh->numOfRefs - 1; mesh->numOfRefs = uVar3; if (uVar3 == 0) { pIVar2 = mesh->uv; if (pIVar2 != NULL) { (*pIVar2->lpVtbl->Release)((IUnknown *)pIVar2); mesh->uv = NULL; } if (mesh->groupCount != 0) { iVar4 = 0; do { iVar5 = (int)&mesh->groupList->faceDataSize + iVar4; Mesh_RemoveGroupTexture(mesh,groupID); io::Mem_Free(*(void **)(iVar5 + 8)); io::Mem_Free(*(void **)(iVar5 + 0xc)); groupID += 1; iVar4 += 0x70; } while (groupID < mesh->groupCount); } if (mesh->lightWaveSurf != NULL) { io::Mem_Free(mesh->lightWaveSurf); } io::Mem_Free(mesh->groupList); Mesh_ReturnToList(mesh); } return; } Mesh_Group * __cdecl lego::gfx::Mesh_GetGroup (Mesh *mesh,D3DRMGroupIndex groupID,uint *out_vertexCount,uint *unused_out_faceCount, uint *out_vPerFace,uint *out_faceDataSize,uint *out_faceData) { ushort *puVar1; Mesh_Group *pMVar2; uint uVar3; pMVar2 = mesh->groupList + groupID; if (out_vertexCount != NULL) { *out_vertexCount = pMVar2->vertexCount; } if (out_vPerFace != NULL) { *out_vPerFace = 3; } if (out_faceDataSize != NULL) { *out_faceDataSize = pMVar2->faceDataSize; } if ((out_faceData != NULL) && (uVar3 = 0, pMVar2->faceDataSize != 0)) { do { puVar1 = pMVar2->faceData + uVar3; uVar3 += 1; *out_faceData = (uint)*puVar1; out_faceData = out_faceData + 1; } while (uVar3 < pMVar2->faceDataSize); } return pMVar2; } uint __cdecl lego::gfx::Mesh_GetGroupCount(Mesh *mesh) { return mesh->groupCount; } int __cdecl lego::gfx::Mesh_AddGroup(Mesh *mesh,uint vertexCount,uint faceCount,uint vPerFace,uint *faceData) { ushort uVar1; Mesh_Group *pMVar2; ushort *puVar3; uint uVar4; Mesh_Vertex *pMVar5; int iVar6; Mesh_Group *pMVar7; uint uVar8; if (mesh->groupList == NULL) { mesh->listSize = 10; mesh->groupCount = 1; pMVar2 = (Mesh_Group *)io::Mem_Alloc(0x460); mesh->groupList = pMVar2; } else { uVar4 = mesh->groupCount; mesh->groupCount = uVar4 + 1; if (uVar4 == mesh->listSize) { uVar4 = (mesh->listSize * 0x96) / 100; pMVar2 = (Mesh_Group *)io::Mem_ReAlloc(mesh->groupList,uVar4 * 0x70); if (pMVar2 == NULL) { return -1; } mesh->groupList = pMVar2; mesh->listSize = uVar4; } } pMVar2 = mesh->groupList + (mesh->groupCount - 1); pMVar7 = pMVar2; for (iVar6 = 0x1c; iVar6 != 0; iVar6 += -1) { pMVar7->faceDataSize = 0; pMVar7 = (Mesh_Group *)&pMVar7->vertexCount; } uVar8 = vPerFace * faceCount; puVar3 = (ushort *)io::Mem_Alloc(uVar8 * 2); pMVar2->faceData = puVar3; uVar4 = 0; pMVar2->faceDataSize = uVar8; if (uVar8 != 0) { do { uVar1 = *(ushort *)faceData; faceData = faceData + 1; pMVar2->faceData[uVar4] = uVar1; uVar4 += 1; } while (uVar4 < pMVar2->faceDataSize); } pMVar5 = (Mesh_Vertex *)io::Mem_Alloc(vertexCount << 5); pMVar2->vertices = pMVar5; for (uVar4 = (vertexCount << 5) >> 2; uVar4 != 0; uVar4 -= 1) { (pMVar5->position).x = 0.0; pMVar5 = (Mesh_Vertex *)&(pMVar5->position).y; } for (iVar6 = 0; iVar6 != 0; iVar6 += -1) { *(undefined *)&(pMVar5->position).x = 0; pMVar5 = (Mesh_Vertex *)((int)&(pMVar5->position).x + 1); } pMVar2->vertexCount = vertexCount; pMVar2->flags = 0; Mesh_CreateGroupMaterial(mesh,mesh->groupCount + D3DRMGROUP_ALLGROUPS); return mesh->groupCount - 1; } void __cdecl lego::gfx::Mesh_AlterGroupRenderFlags(Mesh *mesh,D3DRMGroupIndex groupID,uint newFlags) { mesh->groupList[groupID].renderFlags = newFlags; return; } void __cdecl lego::gfx::Mesh_Scale(Mesh *mesh,float x,float y,float z) { float *pfVar1; float *pfVar2; Mesh_Group *iVar3; int iVar4; uint uVar5; uint uVar6; int iVar7; uVar5 = 0; if (mesh->groupCount != 0) { iVar7 = 0; do { uVar6 = 0; iVar3 = (Mesh_Group *)((int)&mesh->groupList->faceDataSize + iVar7); if (iVar3->vertexCount != 0) { iVar4 = 0; do { uVar6 += 1; *(float *)((int)&(iVar3->vertices->position).x + iVar4) = x * *(float *)((int)&(iVar3->vertices->position).x + iVar4); *(float *)((int)&(iVar3->vertices->position).y + iVar4) = y * *(float *)((int)&(iVar3->vertices->position).y + iVar4); pfVar1 = (float *)((int)&(iVar3->vertices->position).z + iVar4); pfVar2 = (float *)((int)&(iVar3->vertices->position).z + iVar4); iVar4 += 0x20; *pfVar2 = z * *pfVar1; } while (uVar6 < iVar3->vertexCount); } uVar5 += 1; iVar7 += 0x70; } while (uVar5 < mesh->groupCount); } return; } void __cdecl lego::gfx::Mesh_SetVertices (Mesh *mesh,D3DRMGroupIndex groupID,uint index,uint count,Vertex *vertices) { int iVar1; float *pfVar2; Mesh_Group *pMVar3; float *pfVar4; pMVar3 = mesh->groupList + groupID; if (count != 0) { iVar1 = index << 5; pfVar2 = &vertices->tu; do { pfVar4 = (float *)((int)&(pMVar3->vertices->position).x + iVar1); *pfVar4 = pfVar2[-6]; pfVar4[1] = pfVar2[-5]; pfVar4[2] = pfVar2[-4]; pfVar4 = (float *)((int)&(pMVar3->vertices->normal).x + iVar1); count -= 1; *pfVar4 = pfVar2[-3]; pfVar4[1] = pfVar2[-2]; pfVar4[2] = pfVar2[-1]; *(float *)((int)&pMVar3->vertices->tu + iVar1) = *pfVar2; *(float *)((int)&pMVar3->vertices->tv + iVar1) = pfVar2[1]; iVar1 = iVar1 + 0x20; pfVar2 = pfVar2 + 9; } while (count != 0); } return; } void __cdecl lego::gfx::Mesh_GetVertices (Mesh *mesh,D3DRMGroupIndex groupID,uint index,uint count,Vertex *out_vertices) { int iVar1; float *pfVar2; Mesh_Group *pMVar3; float *pfVar4; pMVar3 = mesh->groupList + groupID; if (count != 0) { iVar1 = index << 5; pfVar2 = &out_vertices->tu; do { pfVar4 = (float *)((int)&(pMVar3->vertices->position).x + iVar1); pfVar2[-6] = *pfVar4; pfVar2[-5] = pfVar4[1]; pfVar2[-4] = pfVar4[2]; pfVar4 = (float *)((int)&(pMVar3->vertices->normal).x + iVar1); count -= 1; pfVar2[-3] = *pfVar4; pfVar2[-2] = pfVar4[1]; pfVar2[-1] = pfVar4[2]; *pfVar2 = *(float *)((int)&pMVar3->vertices->tu + iVar1); pfVar2[1] = *(float *)((int)&pMVar3->vertices->tv + iVar1); iVar1 = iVar1 + 0x20; pfVar2 = pfVar2 + 9; } while (count != 0); } return; } void __cdecl lego::gfx::Mesh_SetVertices_PointNormalAt (Mesh *mesh,D3DRMGroupIndex groupID,uint index,uint count,Vector3F *vertices, Vector3F *position,Point2F *textCoords) { float *pfVar1; float fVar2; Vector3F *pVVar3; int iVar4; int iVar5; Mesh_Group *pMVar6; float *pfVar7; pVVar3 = position; pMVar6 = mesh->groupList + groupID; if (count != 0) { position = (Vector3F *)count; iVar5 = index << 5; pfVar7 = &vertices->z; do { *(float *)((int)&(pMVar6->vertices->position).x + iVar5) = pfVar7[-2]; *(float *)((int)&(pMVar6->vertices->position).y + iVar5) = pfVar7[-1]; *(float *)((int)&(pMVar6->vertices->position).z + iVar5) = *pfVar7; iVar4 = (int)&(pMVar6->vertices->position).x + iVar5; *(float *)(iVar4 + 0xc) = pVVar3->x - *(float *)((int)&(pMVar6->vertices->position).x + iVar5) ; *(float *)(iVar4 + 0x10) = pVVar3->y - *(float *)(iVar4 + 4); *(float *)(iVar4 + 0x14) = pVVar3->z - *(float *)(iVar4 + 8); fVar2 = *(float *)((int)&(pMVar6->vertices->normal).y + iVar5); pfVar1 = (float *)((int)&(pMVar6->vertices->normal).x + iVar5); fVar2 = 1.0 / SQRT(*pfVar1 * *pfVar1 + pfVar1[2] * pfVar1[2] + fVar2 * fVar2); *pfVar1 = *pfVar1 * fVar2; pfVar1[1] = fVar2 * pfVar1[1]; pfVar1[2] = fVar2 * pfVar1[2]; *(float *)((int)&pMVar6->vertices->tu + iVar5) = textCoords->x; *(float *)((int)&pMVar6->vertices->tv + iVar5) = textCoords->y; position = (Vector3F *)((int)&position[-1].z + 3); iVar5 = iVar5 + 0x20; textCoords = textCoords + 1; pfVar7 = pfVar7 + 3; } while (position != NULL); } return; } void __cdecl lego::gfx::Mesh_SetVertices_SameNormal (Mesh *mesh,D3DRMGroupIndex groupID,uint index,uint count,Vector3F *vertices, Vector3F *normal,Point2F *textCoords) { float *pfVar1; int iVar2; Mesh_Group *pMVar3; float *pfVar4; pMVar3 = mesh->groupList + groupID; if (count != 0) { groupID = count; iVar2 = index << 5; pfVar4 = &vertices->z; do { *(float *)((int)&(pMVar3->vertices->position).x + iVar2) = pfVar4[-2]; *(float *)((int)&(pMVar3->vertices->position).y + iVar2) = pfVar4[-1]; *(float *)((int)&(pMVar3->vertices->position).z + iVar2) = *pfVar4; pfVar1 = (float *)((int)&(pMVar3->vertices->normal).x + iVar2); *pfVar1 = normal->x; pfVar1[1] = normal->y; pfVar1[2] = normal->z; *(float *)((int)&pMVar3->vertices->tu + iVar2) = textCoords->x; *(float *)((int)&pMVar3->vertices->tv + iVar2) = textCoords->y; groupID += D3DRMGROUP_ALLGROUPS; iVar2 = iVar2 + 0x20; pfVar4 = pfVar4 + 3; textCoords = textCoords + 1; } while (groupID != D3DRMGROUP_0); } return; } void __cdecl lego::gfx::Mesh_SetVertices_VNT (Mesh *mesh,D3DRMGroupIndex groupID,uint index,uint count,Vector3F *vertices, Vector3F **normal,Point2I *textCoords) { int iVar1; Mesh_Group *pMVar2; float *pfVar3; pMVar2 = mesh->groupList + groupID; if (count != 0) { groupID = count; iVar1 = index << 5; pfVar3 = &vertices->z; do { *(float *)((int)&(pMVar2->vertices->position).x + iVar1) = pfVar3[-2]; *(float *)((int)&(pMVar2->vertices->position).y + iVar1) = pfVar3[-1]; *(float *)((int)&(pMVar2->vertices->position).z + iVar1) = *pfVar3; *(float *)((int)&(pMVar2->vertices->normal).x + iVar1) = (*normal)->x; *(float *)((int)&(pMVar2->vertices->normal).y + iVar1) = (*normal)->y; *(float *)((int)&(pMVar2->vertices->normal).z + iVar1) = (*normal)->z; *(int *)((int)&pMVar2->vertices->tu + iVar1) = textCoords->x; *(int *)((int)&pMVar2->vertices->tv + iVar1) = textCoords->y; groupID += D3DRMGROUP_ALLGROUPS; iVar1 = iVar1 + 0x20; pfVar3 = pfVar3 + 3; normal = normal + 1; textCoords = textCoords + 1; } while (groupID != D3DRMGROUP_0); } return; } BOOL __cdecl lego::gfx::Mesh_IsGroupHidden(Mesh *mesh,D3DRMGroupIndex groupID) { return mesh->groupList[groupID].flags & 1; } void __cdecl lego::gfx::Mesh_HideGroup(Mesh *mesh,D3DRMGroupIndex groupID,BOOL hide) { Mesh_Group *pMVar1; pMVar1 = mesh->groupList + groupID; if (hide != 0) { pMVar1->flags = pMVar1->flags | 1; return; } pMVar1->flags = pMVar1->flags & 0xfffffffe; return; } void __cdecl lego::gfx::Mesh_Hide(Mesh *mesh,BOOL hide) { if (hide != 0) { mesh->flags = mesh->flags | 1; return; } mesh->flags = mesh->flags & 0xfffffffe; return; } BOOL __cdecl lego::gfx::Mesh_RenderCallback (IDirect3DRMUserVisual *lpD3DRMUV,Mesh *lpArg,D3DRMUserVisualReason lpD3DRMUVreason, IUnknown *lpD3DRMDev,IDirect3DRMViewport *lpD3DRMview) { Mesh *mesh; IDirect3DRMViewport *This; Container *pCVar1; Viewport *pVVar2; Mesh *view; BOOL BVar3; bool bVar4; uint uVar5; int iVar6; IDirect3DRMViewport2 *unaff_ESI; Mesh_Group *pMVar7; int unaff_retaddr; IDirect3DRMViewport2 *rmView2; Matrix4F transform4d; mesh = lpArg; uVar5 = 0; if (lpD3DRMUVreason == D3DRMUSERVISUAL_CANSEE) { if (((globs::mainGlobs.imDevice != NULL) && ((*(byte *)&lpArg->flags & 1) == 0)) && ((pCVar1 = Container_SearchOwner(lpArg->frameCreatedOn), pCVar1 == NULL || ((*(byte *)&pCVar1->flags & 0x80) == 0)))) { if ((mesh->flags & 0x1000000) == 0) { return 1; } if ((mesh->flags & 0x2000000) != 0) { return 1; } // DWORD IDirect3DRMViewport->GetAppData(this) // struct with field_28 -> IDirect3DRMFrame3* pVVar2 = (*((IDirect3DRMFrame3Vtbl *)lpD3DRMview->lpVtbl)->GetAppData)(lpD3DRMview); if (pVVar2->rendering == 0) { return 1; } // IDirect3DRMFrame3->GetScene(this, IDirect3DRMFrame3** lplpRoot) (*mesh->frameCreatedOn->lpVtbl->GetScene)(mesh->frameCreatedOn,(IDirect3DRMFrame3 **)&lpArg); // IDirect3DRMViewport2->GetCamera(this, IDirect3DRMFrame3** lplpCamera) (*pVVar2->lpVP->lpVtbl->GetCamera)(pVVar2->lpVP,(IDirect3DRMFrame3 **)&lpD3DRMview); // IDirect3DRMFrame3->LookAt(this, IDirect3DRMFrame3* lpTarget, IDirect3DRMFrame3* // lpRef, TD3DRMFrameConstraint rfcConstraint) // // D3DRMCONSTRAIN_Z (0x0) (*mesh->frameCreatedOn->lpVtbl->LookAt) (mesh->frameCreatedOn,(IDirect3DRMFrame3 *)lpD3DRMview,(IDirect3DRMFrame3 *)lpArg, D3DRMCONSTRAIN_Z); mesh->flags = mesh->flags | 0x2000000; return TRUE; } } else { if (lpD3DRMUVreason == D3DRMUSERVISUAL_RENDER) { if (globs::mainGlobs.imDevice != NULL) { lpD3DRMUVreason = D3DRMUSERVISUAL_CANSEE; bVar4 = false; lpArg->flags = lpArg->flags & 0xfdffffff; // IDirect3DDevice3->GetTransform(this, D3DTransformStateType dtstTransformStateType, // Matrix4F* lpD3DMatrix) (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetTransform) (globs::mainGlobs.imDevice,D3DTRANSFORMSTATE_WORLD,&transform4d); This = lpD3DRMview; Mesh_SetCurrentViewport(lpD3DRMview); // IDirect3DRMViewport->QueryInterface(this, IID_IDirect3DRMViewport2, // IDirect3DRMViewport2** lplpOut) (*((IDirect3DRMFrame3Vtbl *)This->lpVtbl)->QueryInterface) ((IUnknown *)This,(IID *)&idl::IID_IDirect3DRMViewport2,&rmView2); // DWORD IDirect3DRMViewport2->GetAppData(this) view = (Mesh *)(*unaff_ESI->lpVtbl->GetAppData)(unaff_ESI); lpArg = view; if ((*(byte *)&mesh->flags & 2) == 0) { if (((mesh->renderDesc).renderFlags & 0x1c00) == 0) { Mesh_StoreTextureAndMat(); Mesh_SetMeshRenderDesc(mesh,(Viewport *)view,(Matrix4F *)&stack0xffffffb4,0); bVar4 = true; Mesh_RenderMesh(mesh,(Matrix4F *)&stack0xffffffb4,0); } else { if (mesh->groupCount != 0) { transform4d.values[3][3] = 0.0; do { pMVar7 = (Mesh_Group *) ((int)&mesh->groupList->faceDataSize + (int)transform4d.values[3][3]); BVar3 = Mesh_CanRenderGroup(pMVar7); if (BVar3 != 0) { if ((pMVar7->flags & 0x80000) == 0) { if (pMVar7->renderFlags == 0) { if (!bVar4) { Mesh_StoreTextureAndMat(); Mesh_SetMeshRenderDesc (mesh,(Viewport *)lpArg,(Matrix4F *)&stack0xffffffb4,0); bVar4 = true; } Mesh_RenderGroup(mesh,pMVar7,(Matrix4F *)&stack0xffffffb4,0); } } else { unaff_retaddr = 1; } } uVar5 += 1; transform4d.values[3][3] = (float)((int)transform4d.values[3][3] + 0x70); } while (uVar5 < mesh->groupCount); } iVar6 = 0; transform4d.values[3][3] = 0.0; if (mesh->groupCount != 0) { do { pMVar7 = (Mesh_Group *)((int)&mesh->groupList->faceDataSize + iVar6); BVar3 = Mesh_CanRenderGroup(pMVar7); if (BVar3 != 0) { if ((pMVar7->flags & 0x80000) == 0) { if (pMVar7->renderFlags != 0) { if (!bVar4) { Mesh_StoreTextureAndMat(); Mesh_SetMeshRenderDesc (mesh,(Viewport *)lpArg,(Matrix4F *)&stack0xffffffb4,0); bVar4 = true; } Mesh_RenderGroup(mesh,pMVar7,(Matrix4F *)&stack0xffffffb4,0); } } else { unaff_retaddr = 1; } } transform4d.values[3][3] = (float)((int)transform4d.values[3][3] + 1); iVar6 += 0x70; } while ((uint)transform4d.values[3][3] < mesh->groupCount); } if (unaff_retaddr != 0) { Mesh_AddToPostRenderList(mesh,(Matrix4F *)&stack0xffffffb4); } } } else { Mesh_AddToPostRenderList(mesh,(Matrix4F *)&stack0xffffffb4); } if (bVar4) { main::Main_RestoreStates(); Mesh_RestoreTextureAndMat(); } if (unaff_ESI != NULL) { // IDirect3DRMViewport2->Release(this) (*unaff_ESI->lpVtbl->Release)((IUnknown *)unaff_ESI); } } return 1; } } return 0; } void __cdecl lego::gfx::Mesh_SetMeshRenderDesc(Mesh *mesh,Viewport *view,Matrix4F *matWorld,BOOL alphaBlend) { MeshRenderCallback p_Var1; p_Var1 = (mesh->renderDesc).renderCallback; if (p_Var1 != NULL) { (*p_Var1)(mesh,(mesh->renderDesc).renderCallbackData,view); } // D3DRENDERSTATE_SPECULARENABLE (0x1d), FALSE (0x0) main::Main_ChangeRenderState(D3DRENDERSTATE_SPECULARENABLE,FALSE); // D3DRENDERSTATE_SHADEMODE (0x9), D3DSHADE_GOURAUD (0x2) main::Main_ChangeRenderState(D3DRENDERSTATE_SHADEMODE,D3DSHADE_GOURAUD); // D3DRENDERSTATE_DITHERENABLE (0x1a), TRUE (0x1) main::Main_ChangeRenderState(D3DRENDERSTATE_DITHERENABLE,TRUE); if (((byte)globs::mainGlobs.flags & MAIN_FLAG_DONTMANAGETEXTURES) == 0) { // D3DTSS_COLORARG1 (0x2), D3DTA_TEXTURE (0x2) Mesh_ChangeTextureStageState(D3DTSS_COLORARG1,D3DTA_TEXTURE); // D3DTSS_COLORARG2 (0x3), D3DTA_DIFFUSE (0x0) Mesh_ChangeTextureStageState(D3DTSS_COLORARG2,D3DTA_DIFFUSE); // D3DTSS_ALPHAARG1 (0x5), D3DTA_TEXTURE (0x2) Mesh_ChangeTextureStageState(D3DTSS_ALPHAARG1,D3DTA_TEXTURE); // D3DTSS_ALPHAARG2 (0x6), D3DTA_DIFFUSE (0x0) Mesh_ChangeTextureStageState(D3DTSS_ALPHAARG2,D3DTA_DIFFUSE); } Mesh_SetRenderDesc((mesh->renderDesc).renderFlags,matWorld,alphaBlend); return; } void __cdecl lego::gfx::Mesh_SetRenderDesc(uint flags,Matrix4F *matWorld,BOOL alphaBlend) { uint uVar1; undefined4 uVar2; DWORD dwRenderState; Matrix4F identity; uVar1 = flags & 0x1c00; if ((uVar1 != 0) && (alphaBlend != 0)) { // D3DRENDERSTATE_FOGENABLE (0x1c), FALSE (0x0) main::Main_ChangeRenderState(D3DRENDERSTATE_FOGENABLE,FALSE); } if ((uVar1 == 0) || (alphaBlend != 0)) { if ((flags & 0x400) == 0) { if ((flags & 0x800) == 0) { if ((flags & 0x1000) == 0) goto LAB_00482e79; // D3DBLEND_SRCALPHA (0x5), D3DBLEND_INVSRCALPHA (0x6) Mesh_SetAlphaRender(D3DBLEND_SRCALPHA,D3DBLEND_INVSRCALPHA); } else { // D3DBLEND_SRCALPHA (0x5), D3DBLEND_ONE (0x2) Mesh_SetAlphaRender(D3DBLEND_SRCALPHA,D3DBLEND_ONE); } } else { // D3DBLEND_ONE (0x2), D3DBLEND_ONE (0x2) Mesh_SetAlphaRender(D3DBLEND_ONE,D3DBLEND_ONE); } } else { LAB_00482e79: // D3DRENDERSTATE_ALPHABLENDENABLE (0x1b), FALSE (0x0) main::Main_ChangeRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,FALSE); } if ((flags & 0x4000000) == 0) { // D3DCULL_CCW (0x3) uVar2 = D3DCULL_CCW; } else { // D3DCULL_NONE (0x1) uVar2 = D3DCULL_NONE; } // D3DRENDERSTATE_CULLMODE (0x16), ... main::Main_ChangeRenderState(D3DRENDERSTATE_CULLMODE,uVar2); if (((byte)globs::mainGlobs.flags & MAIN_FLAG_DONTMANAGETEXTURES) == 0) { if ((flags & 0x20000) == 0) { if ((flags & 0x40000) == 0) { // D3DTOP_MODULATE (0x4) dwRenderState = D3DTOP_MODULATE; } else { // D3DTOP_SELECTARG2 (0x3) dwRenderState = D3DTOP_SELECTARG2; } } else { // D3DTOP_SELECTARG1 (0x2) dwRenderState = D3DTOP_SELECTARG1; } // D3DTSS_ALPHAOP (0x4), ... Mesh_ChangeTextureStageState(D3DTSS_ALPHAOP,dwRenderState); } // D3DRENDERSTATE_ZENABLE (0x7), TRUE (0x1) main::Main_ChangeRenderState(D3DRENDERSTATE_ZENABLE,TRUE); if ((uVar1 == 0) || (alphaBlend == 0)) { uVar2 = TRUE; } else { uVar2 = FALSE; } // D3DRENDERSTATE_ZWRITEENABLE (0xe), [TRUE (0x1) | FALSE (0x0)] main::Main_ChangeRenderState(D3DRENDERSTATE_ZWRITEENABLE,uVar2); if ((flags & 0x2000) == 0) { if ((flags & 0x4000) == 0) goto LAB_00482f21; Mesh_SetIdentityMatrix(&identity); matWorld = &identity; } // D3DTRANSFORMSTATE_WORLD (0x1) Mesh_SetTransform(D3DTRANSFORMSTATE_WORLD,matWorld); LAB_00482f21: if ((flags & 0x800000) == 0) { // D3DRENDERSTATE_TEXTUREMAG (0x11), D3DFILTER_LINEAR (0x2) main::Main_ChangeRenderState(D3DRENDERSTATE_TEXTUREMAG,D3DFILTER_LINEAR); // D3DRENDERSTATE_TEXTUREMIN (0x12), D3DFILTER_MIPLINEAR (0x4) main::Main_ChangeRenderState(D3DRENDERSTATE_TEXTUREMIN,D3DFILTER_MIPLINEAR); return; } // D3DRENDERSTATE_TEXTUREMAG (0x11), D3DFILTER_NEAREST (0x1) main::Main_ChangeRenderState(D3DRENDERSTATE_TEXTUREMAG,D3DFILTER_NEAREST); // D3DRENDERSTATE_TEXTUREMIN (0x12), D3DFILTER_NEAREST (0x1) main::Main_ChangeRenderState(D3DRENDERSTATE_TEXTUREMIN,D3DFILTER_NEAREST); return; } void __cdecl lego::gfx::Mesh_SetAlphaRender(D3DBlend src,D3DBlend dest) { // D3DRENDERSTATE_ALPHABLENDENABLE (0x1b), TRUE (0x1) main::Main_ChangeRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,TRUE); // D3DRENDERSTATE_SRCBLEND (0x13) main::Main_ChangeRenderState(D3DRENDERSTATE_SRCBLEND,src); // D3DRENDERSTATE_DSTBLEND (0x20) main::Main_ChangeRenderState(D3DRENDERSTATE_DESTBLEND,dest); return; } void __cdecl lego::gfx::Mesh_AddToPostRenderList(Mesh *mesh,Matrix4F *matWorld) { Mesh_PostRenderInfo *pMVar1; int iVar2; Mesh_PostRenderInfo *pMVar3; pMVar1 = (Mesh_PostRenderInfo *)io::Mem_Alloc(0x48); pMVar3 = pMVar1; for (iVar2 = 0x12; iVar2 != 0; iVar2 += -1) { pMVar3->mesh = NULL; pMVar3 = (Mesh_PostRenderInfo *)&pMVar3->matWorld; } pMVar1->mesh = mesh; if (matWorld != NULL) { pMVar3 = pMVar1; for (iVar2 = 0x10; pMVar3 = (Mesh_PostRenderInfo *)&pMVar3->matWorld, iVar2 != 0; iVar2 += -1) { (*(float (*) [4])&pMVar3->mesh)[0] = matWorld->values[0]; matWorld = (Matrix4F *)(matWorld->values + 1); } } pMVar1->next = globs::meshGlobs.postRenderMeshList; globs::meshGlobs.postRenderMeshList = pMVar1; return; } void __cdecl lego::gfx::Mesh_ClearPostRenderList(void) { Mesh_PostRenderInfo *pMVar1; Mesh_PostRenderInfo *buffer; buffer = globs::meshGlobs.postRenderMeshList; if (globs::meshGlobs.postRenderMeshList != NULL) { do { pMVar1 = buffer->next; io::Mem_Free(buffer); buffer = pMVar1; } while (pMVar1 != NULL); } globs::meshGlobs.postRenderMeshList = NULL; return; } void __cdecl lego::gfx::Mesh_PostRenderAll(Viewport *view) { BOOL BVar1; Mesh *pMVar2; int iVar3; uint uVar4; Mesh_PostRenderInfo *pMVar5; Mesh_Group *pMVar6; pMVar5 = globs::meshGlobs.postRenderMeshList; if (globs::meshGlobs.postRenderMeshList != NULL) { Mesh_SetCurrentGODSViewport(view); Mesh_StoreTextureAndMat(); do { if ((*(byte *)&pMVar5->mesh->flags & 1) == 0) { Mesh_SetMeshRenderDesc(pMVar5->mesh,view,&pMVar5->matWorld,1); pMVar2 = pMVar5->mesh; if ((*(byte *)&pMVar2->flags & 2) == 0) { uVar4 = 0; if (pMVar2->groupCount != 0) { iVar3 = 0; do { pMVar6 = (Mesh_Group *)((int)&pMVar2->groupList->faceDataSize + iVar3); BVar1 = Mesh_CanRenderGroup(pMVar6); if (((BVar1 != 0) && ((pMVar6->flags & 0x80000) != 0)) && (pMVar6->renderFlags == 0)) { Mesh_RenderGroup(pMVar5->mesh,pMVar6,&pMVar5->matWorld,1); } pMVar2 = pMVar5->mesh; uVar4 += 1; iVar3 += 0x70; } while (uVar4 < pMVar2->groupCount); } pMVar2 = pMVar5->mesh; uVar4 = 0; if (pMVar2->groupCount != 0) { iVar3 = 0; do { pMVar6 = (Mesh_Group *)((int)&pMVar2->groupList->faceDataSize + iVar3); BVar1 = Mesh_CanRenderGroup(pMVar6); if (((BVar1 != 0) && ((pMVar6->flags & 0x80000) != 0)) && (pMVar6->renderFlags != 0)) { Mesh_RenderGroup(pMVar5->mesh,pMVar6,&pMVar5->matWorld,1); } pMVar2 = pMVar5->mesh; uVar4 += 1; iVar3 += 0x70; } while (uVar4 < pMVar2->groupCount); } } else { Mesh_RenderMesh(pMVar2,&pMVar5->matWorld,1); } } pMVar5 = pMVar5->next; } while (pMVar5 != NULL); Mesh_ClearPostRenderList(); main::Main_RestoreStates(); Mesh_RestoreTextureAndMat(); } return; } Container_Texture * __cdecl lego::gfx::Mesh_LoadTexture(char *baseDir,char *name,uint *out_width,uint *out_height) { char cVar1; Mesh_TextureReference *pMVar2; IDirectDrawSurface4 *surface; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; char *pcVar7; undefined4 *puVar8; uint *ref_count; IDirectDrawSurface4 *local_10c; Container_Texture *local_108; char filepath [260]; local_108 = (Container_Texture *)io::Mem_Alloc(0xc); if (baseDir == NULL) { // std::strcpy(filepath, filename) uVar3 = 0xffffffff; pcVar6 = name; do { pcVar7 = pcVar6; if (uVar3 == 0) break; uVar3 -= 1; pcVar7 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar7; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar7 + -uVar3); puVar8 = (undefined4 *)filepath; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar8 = *puVar5; puVar5 = puVar5 + 1; puVar8 = puVar8 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } else { std::sprintf(filepath,"%s%s",baseDir,name); } pMVar2 = Mesh_SearchTexturePathList (globs::meshGlobs.textureList,globs::meshGlobs.textureCount,filepath); if (pMVar2 != NULL) { surface = pMVar2->surface; if (surface != NULL) { (*surface->lpVtbl->AddRef)((IUnknown *)surface); } local_10c = (IDirectDrawSurface4 *)pMVar2->trans; goto LAB_004832a8; } surface = Container_LoadTextureSurface(filepath,1,out_width,out_height,(BOOL *)&local_10c); if (surface == NULL) { if (globs::meshGlobs.sharedTextureDir == NULL) goto LAB_004832a8; std::sprintf(filepath,"%s%s",globs::meshGlobs.sharedTextureDir,name); pMVar2 = Mesh_SearchTexturePathList (globs::meshGlobs.textureListShared,globs::meshGlobs.textureCountShared, filepath); if (pMVar2 != NULL) { surface = pMVar2->surface; if (surface != NULL) { (*surface->lpVtbl->AddRef)((IUnknown *)surface); } local_10c = (IDirectDrawSurface4 *)pMVar2->trans; goto LAB_004832a8; } surface = Container_LoadTextureSurface(filepath,1,out_width,out_height,(BOOL *)&local_10c); if (surface == NULL) goto LAB_004832a8; ref_count = &globs::meshGlobs.textureCountShared; pMVar2 = globs::meshGlobs.textureListShared; } else { ref_count = &globs::meshGlobs.textureCount; pMVar2 = globs::meshGlobs.textureList; } Mesh_AddTexturePathEntry(pMVar2,ref_count,filepath,surface,local_10c); LAB_004832a8: if (surface != NULL) { local_108->texture = NULL; local_108->surface = surface; local_108->colourKey = (BOOL)local_10c; return local_108; } io::Mem_Free(local_108); return NULL; } Mesh_TextureReference * __cdecl lego::gfx::Mesh_SearchTexturePathList(Mesh_TextureReference *list,uint count,char *path) { int iVar1; uint uVar2; char **ppcVar3; uVar2 = 0; if (count == 0) { return NULL; } ppcVar3 = &list->path; do { iVar1 = std::_stricmp(path,*ppcVar3); if (iVar1 == 0) { return list + uVar2; } uVar2 += 1; ppcVar3 = ppcVar3 + 3; } while (uVar2 < count); return NULL; } void __cdecl lego::gfx::Mesh_AddTexturePathEntry (Mesh_TextureReference *list,uint *ref_count,char *path,IDirectDrawSurface4 *surface, BOOL trans) { char *pcVar1; pcVar1 = util::Util_StrCpy(path); list[*ref_count].path = pcVar1; list[*ref_count].surface = surface; list[*ref_count].trans = trans; *ref_count = *ref_count + 1; return; } void __cdecl lego::gfx::Mesh_SetGroupTexture(Mesh *mesh,D3DRMGroupIndex groupID,Container_Texture *mt) { uint *puVar1; IDirectDrawSurface4 *This; if (mt != NULL) { This = mt->surface; if (This != NULL) { (*This->lpVtbl->QueryInterface) ((IUnknown *)This,(IID *)&idl::IID_IDirect3DTexture2, &mesh->groupList[groupID].imText); } if (mt->colourKey != 0) { puVar1 = &mesh->groupList[groupID].flags; *puVar1 = *puVar1 | 0x400000; return; } mesh->groupList[groupID].flags = mesh->groupList[groupID].flags & 0xffbfffff; } return; } void __cdecl lego::gfx::Mesh_RemoveGroupTexture(Mesh *mesh,D3DRMGroupIndex groupID) { Mesh_Group *pMVar1; IDirect3DTexture2 *This; pMVar1 = mesh->groupList; This = pMVar1[groupID].imText; if (This != NULL) { (*This->lpVtbl->Release)((IUnknown *)This); pMVar1[groupID].imText = NULL; } return; } BOOL __cdecl lego::gfx::Mesh_CreateGroupMaterial(Mesh *mesh,D3DRMGroupIndex groupID) { int iVar1; D3DMaterial *pDVar2; D3DMaterial *pDVar3; D3DMaterial material; material.hTexture = 0; material.dwRampSize = 0; material.dwSize = 0x50; material.diffuse.red = 1.0; material.diffuse.green = 1.0; material.diffuse.blue = 1.0; material.diffuse.alpha = 1.0; material.ambient.red = 0.0; material.ambient.green = 0.0; material.ambient.blue = 0.0; material.ambient.alpha = 0.0; material.specular.red = 0.0; material.specular.green = 0.0; material.specular.blue = 0.0; material.specular.alpha = 0.0; material.emissive.red = 0.0; material.emissive.green = 0.0; material.emissive.blue = 0.0; material.emissive.alpha = 0.0; material.power = 0.0; pDVar2 = &material; pDVar3 = &mesh->groupList[groupID].material; for (iVar1 = 0x14; iVar1 != 0; iVar1 += -1) { pDVar3->dwSize = pDVar2->dwSize; pDVar2 = (D3DMaterial *)&pDVar2->diffuse; pDVar3 = (D3DMaterial *)&pDVar3->diffuse; } return TRUE; } BOOL __cdecl lego::gfx::Mesh_SetGroupMaterial(Mesh *mesh,D3DRMGroupIndex groupID,D3DMaterial *mat) { int iVar1; D3DMaterial *pDVar2; pDVar2 = &mesh->groupList[groupID].material; for (iVar1 = 0x14; iVar1 != 0; iVar1 += -1) { pDVar2->dwSize = mat->dwSize; mat = (D3DMaterial *)&mat->diffuse; pDVar2 = (D3DMaterial *)&pDVar2->diffuse; } return TRUE; } BOOL __cdecl lego::gfx::Mesh_SetGroupColour (Mesh *mesh,D3DRMGroupIndex groupID,float r,float g,float b,Mesh_Colour type) { D3DMaterial *material; Mesh_Group *group; group = mesh->groupList + groupID; material = Mesh_GetGroupMaterial(mesh,groupID); if (r < 0.0) { r = 0.0; } if (g < 0.0) { g = 0.0; } if (b < 0.0) { b = 0.0; } if ((ushort)((ushort)(r < 1.0) << 8 | (ushort)(r == 1.0) << 0xe) == 0) { r = 1.0; } if ((ushort)((ushort)(g < 1.0) << 8 | (ushort)(g == 1.0) << 0xe) == 0) { g = 1.0; } if ((ushort)((ushort)(b < 1.0) << 8 | (ushort)(b == 1.0) << 0xe) == 0) { b = 1.0; } if (type == Mesh_Colour_Diffuse) { (material->diffuse).red = r; (material->diffuse).green = g; (material->diffuse).blue = b; if (((r == 1.0) && (g == 1.0)) && (b == 1.0)) { group->flags = group->flags | 0x100000; return TRUE; } group->flags = group->flags & 0xffefffff; return TRUE; } if (type == Mesh_Colour_Ambient) { (material->ambient).green = g; (material->ambient).red = r; (material->ambient).blue = b; return TRUE; } if (type != Mesh_Colour_Emissive) { if (type != Mesh_Colour_Specular) { return TRUE; } (material->specular).green = g; (material->specular).red = r; (material->specular).blue = b; return TRUE; } (material->emissive).green = g; (material->emissive).red = r; (material->emissive).blue = b; return TRUE; } D3DMaterial * __cdecl lego::gfx::Mesh_GetGroupMaterial(Mesh *mesh,D3DRMGroupIndex groupID) { return &mesh->groupList[groupID].material; } BOOL __cdecl lego::gfx::Mesh_SetGroupMaterialValues (Mesh *mesh,D3DRMGroupIndex groupID,float value,Mesh_Colour matType) { D3DMaterial *pDVar1; uint uVar2; Mesh_Group *pMVar3; pMVar3 = mesh->groupList + groupID; pDVar1 = Mesh_GetGroupMaterial(mesh,groupID); if (value < 0.0) { value = 0.0; } if ((ushort)((ushort)(value < 1.0) << 8 | (ushort)(value == 1.0) << 0xe) == 0) { value = 1.0; } if (matType != Mesh_Colour_Alpha) { if (matType == Mesh_Colour_Power) { pDVar1->power = value; return TRUE; } return TRUE; } uVar2 = pMVar3->flags & 0xeff7ffff; pMVar3->flags = uVar2; if (value == 0.0) { if (pMVar3->renderFlags == 0) { if (((mesh->renderDesc).renderFlags & 0x1c00) == 0) goto LAB_004837a4; uVar2 |= 0x10000000; } else { uVar2 |= 0x10000000; } } else { if ((value == 1.0) || ((pMVar3->renderFlags == 0 && (((mesh->renderDesc).renderFlags & 0x1c00) == 0)))) goto LAB_004837a4; uVar2 |= 0x80000; } pMVar3->flags = uVar2; LAB_004837a4: if (pMVar3->renderFlags == 0) { if (((mesh->renderDesc).renderFlags & 0xc00) != 0) { pMVar3->flags = pMVar3->flags | 0x80000; } } else { if ((pMVar3->renderFlags & 0xc00) != 0) { pMVar3->flags = pMVar3->flags | 0x80000; (pDVar1->diffuse).alpha = value; return TRUE; } } (pDVar1->diffuse).alpha = value; return TRUE; } void __cdecl lego::gfx::Mesh_SetIdentityMatrix(Matrix4F *out_matrix) { out_matrix->values[1][3] = 0.0; out_matrix->values[1][2] = 0.0; out_matrix->values[1][0] = 0.0; out_matrix->values[3] = 0.0; out_matrix->values[2] = 0.0; out_matrix->values[1] = 0.0; out_matrix->values[3][2] = 0.0; out_matrix->values[3][1] = 0.0; out_matrix->values[3][0] = 0.0; out_matrix->values[2][3] = 0.0; out_matrix->values[2][1] = 0.0; out_matrix->values[2][0] = 0.0; out_matrix->values[3][3] = 1.0; out_matrix->values[2][2] = 1.0; out_matrix->values[1][1] = 1.0; out_matrix->values[0] = 1.0; return; } BOOL __cdecl lego::gfx::Mesh_SetCurrentViewport(IDirect3DRMViewport *rmViewport) { HRESULT HVar1; int iVar2; IDirect3DRMViewport *This; IDirect3DViewport *d3dViewport; // IDirect3DRMViewport->GetDirect3DViewport(this, IDirect3DViewport** lplpD3DViewport) HVar1 = (*(code *)rmViewport->lpVtbl->GetDirect3DViewport) (rmViewport,(IDirect3DViewport **)&rmViewport); if (HVar1 != 0) { return 0; } HVar1 = (*rmViewport->lpVtbl->QueryInterface) ((IUnknown *)rmViewport,(IID *)&idl::IID_IDirect3DViewport3,&d3dViewport); This = rmViewport; if (HVar1 == 0) { if (rmViewport != NULL) { (*rmViewport->lpVtbl->Release)((IUnknown *)rmViewport); rmViewport = NULL; } iVar2 = (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetCurrentViewport) (globs::mainGlobs.imDevice,d3dViewport); This = (IDirect3DRMViewport *)d3dViewport; if (iVar2 == 0) { if (d3dViewport != NULL) { (*d3dViewport->lpVtbl->Release)((IUnknown *)d3dViewport); } return 1; } } if (This != NULL) { (*This->lpVtbl->Release)((IUnknown *)This); } return 0; } BOOL __cdecl lego::gfx::Mesh_SetCurrentGODSViewport(Viewport *view) { HRESULT HVar1; Viewport *pVVar2; Viewport *local_4; // IDirect3DRMViewport2->GetDirect3DViewport(this, IDirect3DViewport** lplpD3DViewport) HVar1 = (*view->lpVP->lpVtbl->GetDirect3DViewport)(view->lpVP,(IDirect3DViewport **)&view); if (HVar1 != 0) { return 0; } // IDirect3DViewport->QueryInterface(this, IID_IDirect3DViewport3, IDirect3DViewport3** // lplpOut) HVar1 = (**(code **)view->xoffset) ((IDirect3DViewport *)view,&idl::IID_IDirect3DViewport3, (IDirect3DViewport3 **)&local_4); pVVar2 = view; if (HVar1 == 0) { if (view != NULL) { // IDirect3DViewport->Release(this) (**(code **)((int)view->xoffset + 8))((IDirect3DViewport *)view); view = NULL; } // IDirect3DDevice3->SetCurrentViewport(this, IDirect3DViewport3* lpd3dViewport) HVar1 = (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetCurrentViewport) (globs::mainGlobs.imDevice,(IDirect3DViewport3 *)local_4); pVVar2 = local_4; if (HVar1 == 0) { if (local_4 != NULL) { // IDirect3DViewport3->Release(this) (**(code **)((int)local_4->xoffset + 8))((IDirect3DViewport3 *)local_4); } return 1; } } if (pVVar2 != NULL) { // IDirect3DViewport->Release(this) // -or- // IDirect3DViewport3->Release(this) (*((IDirect3DViewportVtbl *)pVVar2->xoffset)->Release)((IDirect3DViewport *)pVVar2); } return 0; } // Sets g_IDirect3DDevice3->SetTransform // RESULT: false if the current transform was not the same, and SetTransform failed BOOL __cdecl lego::gfx::Mesh_SetTransform(D3DTransformStateType state,Matrix4F *matrix) { int iVar1; float unaff_EBX; float unaff_ESI; Matrix4F *pMVar2; float unaff_EDI; Matrix4F *pMVar3; Matrix4F oldMatrix; Matrix4F newMatrix; pMVar2 = matrix; pMVar3 = &newMatrix; // std::memcpy(newMatrix, oldMatrix, 0x40) for (iVar1 = 0x10; iVar1 != 0; iVar1 += -1) { pMVar3->values[0] = pMVar2->values[0]; pMVar2 = (Matrix4F *)(pMVar2->values + 1); pMVar3 = (Matrix4F *)(pMVar3->values + 1); } // IDirect3DDevice3->GetTransform(this, D3DTransformStateType dtstTransformStateType, // Matrix4F* lpD3DMatrix) (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetTransform) (globs::mainGlobs.imDevice,state,&oldMatrix); if (((((unaff_EDI != oldMatrix.values[3][1]) || (unaff_ESI != oldMatrix.values[3][2])) || (unaff_EBX != oldMatrix.values[3][3])) || (((oldMatrix.values[0][0] != newMatrix.values[0][0] || (oldMatrix.values[0][1] != newMatrix.values[0][1])) || ((oldMatrix.values[0][2] != newMatrix.values[0][2] || ((oldMatrix.values[0][3] != newMatrix.values[0][3] || (oldMatrix.values[1][0] != newMatrix.values[1][0])))))))) || ((oldMatrix.values[1][1] != newMatrix.values[1][1] || (((((oldMatrix.values[1][2] != newMatrix.values[1][2] || (oldMatrix.values[1][3] != newMatrix.values[1][3])) || (oldMatrix.values[2][0] != newMatrix.values[2][0])) || ((oldMatrix.values[2][1] != newMatrix.values[2][1] || (oldMatrix.values[2][2] != newMatrix.values[2][2])))) || ((oldMatrix.values[2][3] != newMatrix.values[2][3] || (oldMatrix.values[3][0] != newMatrix.values[3][0])))))))) { // IDirect3DDevice3->SetTransform(this, D3DTransformStateType dtstTransformStateType, // Matrix4F* lpD3DMatrix) iVar1 = (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetTransform) (globs::mainGlobs.imDevice,state,matrix); if (iVar1 != 0) { return 0; } } return 1; } BOOL __cdecl lego::gfx::Mesh_ChangeTextureStageState (D3DTextureStageStateType dwRenderStateType,DWORD dwRenderState) { D3DTextureStageStateType dwState; HRESULT HVar1; dwState = dwRenderStateType; HVar1 = (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetTextureStageState) (globs::mainGlobs.imDevice,0,dwRenderStateType,&dwRenderStateType); if (HVar1 != 0) { dwRenderStateType = ~D3DTSS_TCI_PASSTHRU; } if (dwRenderStateType != dwRenderState) { HVar1 = (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetTextureStageState) (globs::mainGlobs.imDevice,0,dwState,(DWORD *)dwRenderState); if (HVar1 != 0) { return 0; } if (globs::meshGlobs.stateData[dwState].changed == 0) { globs::meshGlobs.stateData[dwState].changed = 1; globs::meshGlobs.stateData[dwState].origValue = dwRenderStateType; } else { if (globs::meshGlobs.stateData[dwState].origValue == dwRenderStateType) { globs::meshGlobs.stateData[dwState].changed = 0; return 1; } } } return 1; } void __cdecl lego::gfx::Mesh_StoreTextureAndMat(void) { (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetLightState) (globs::mainGlobs.imDevice,1,0x541568); globs::meshGlobs.currMatIM = globs::meshGlobs.oldMatIM; if (((byte)globs::mainGlobs.flags & MAIN_FLAG_DONTMANAGETEXTURES) == 0) { (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetTexture)(globs::mainGlobs.imDevice,0,0x54156c) ; globs::meshGlobs.currTextureIM = globs::meshGlobs.oldTextureIM; (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetRenderState) (globs::mainGlobs.imDevice,1,0x541564); if (globs::meshGlobs.oldTextureRM != 0) { (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetRenderState)(globs::mainGlobs.imDevice,1,0); return; } } else { (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->GetRenderState) (globs::mainGlobs.imDevice,1,0x541564); globs::meshGlobs.currTextureRM = globs::meshGlobs.oldTextureRM; } return; } void __cdecl lego::gfx::Mesh_RestoreTextureAndMat(void) { if (globs::meshGlobs.currMatIM != globs::meshGlobs.oldMatIM) { (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetLightState) (globs::mainGlobs.imDevice,1,globs::meshGlobs.oldMatIM); } if (((byte)globs::mainGlobs.flags & MAIN_FLAG_DONTMANAGETEXTURES) == 0) { if (globs::meshGlobs.currTextureIM != globs::meshGlobs.oldTextureIM) { (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetTexture) (globs::mainGlobs.imDevice,0,globs::meshGlobs.oldTextureIM); } if (globs::meshGlobs.oldTextureRM != 0) { (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetRenderState) (globs::mainGlobs.imDevice,1,globs::meshGlobs.oldTextureRM); return; } } else { (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetRenderState) (globs::mainGlobs.imDevice,1,globs::meshGlobs.oldTextureRM); } return; } BOOL __cdecl lego::gfx::Mesh_RenderMesh(Mesh *mesh,Matrix4F *matWorld,BOOL alphaBlend) { BOOL BVar1; uint uVar2; int iVar3; Mesh_Group *pMVar4; BOOL local_4; uVar2 = 0; local_4 = 1; if (mesh->groupCount != 0) { iVar3 = 0; do { pMVar4 = (Mesh_Group *)((int)&mesh->groupList->faceDataSize + iVar3); BVar1 = Mesh_CanRenderGroup(pMVar4); if ((BVar1 != 0) && (pMVar4->renderFlags == 0)) { BVar1 = Mesh_RenderGroup(mesh,pMVar4,matWorld,alphaBlend); if (BVar1 == 0) { local_4 = BVar1; } } uVar2 += 1; iVar3 += 0x70; } while (uVar2 < mesh->groupCount); } uVar2 = 0; if (mesh->groupCount != 0) { iVar3 = 0; do { pMVar4 = (Mesh_Group *)((int)&mesh->groupList->faceDataSize + iVar3); BVar1 = Mesh_CanRenderGroup(pMVar4); if ((BVar1 != 0) && (pMVar4->renderFlags != 0)) { BVar1 = Mesh_RenderGroup(mesh,pMVar4,matWorld,alphaBlend); if (BVar1 == 0) { local_4 = BVar1; } } uVar2 += 1; iVar3 += 0x70; } while (uVar2 < mesh->groupCount); } return local_4; } BOOL __cdecl lego::gfx::Mesh_CanRenderGroup(Mesh_Group *group) { if (((group->flags & 1) == 0) && ((group->flags & 0x10000000) == 0)) { return 1; } return 0; } BOOL __cdecl lego::gfx::Mesh_RenderGroup(Mesh *mesh,Mesh_Group *group,Matrix4F *matWorld,BOOL alphaBlend) { BOOL BVar1; uint uVar2; Mesh_SetGroupRenderDesc(mesh,group,matWorld,alphaBlend); BVar1 = Mesh_SetMaterial(&group->material); uVar2 = (uint)(BVar1 != 0); BVar1 = Mesh_RenderTriangleList (globs::meshGlobs.matHandle,group->imText,0x112,group->vertices, group->vertexCount,group->faceData,group->faceDataSize); if (BVar1 == 0) { uVar2 = 0; } return uVar2; } BOOL __cdecl lego::gfx::Mesh_SetGroupRenderDesc(Mesh *mesh,Mesh_Group *group,Matrix4F *matWorld,BOOL alphaBlend) { DWORD dwRenderState; if (((byte)globs::mainGlobs.flags & MAIN_FLAG_DONTMANAGETEXTURES) == 0) { if (((group->flags & 0x100000) == 0) || (group->imText == NULL)) { // D3DTOP_MODULATE (0x4) dwRenderState = D3DTOP_MODULATE; } else { // D3DTOP_SELECTARG1 (0x2) dwRenderState = D3DTOP_SELECTARG1; } // D3DTSS_COLOROP (0x1), ... Mesh_ChangeTextureStageState(D3DTSS_COLOROP,dwRenderState); } // D3DRENDERSTATE_COLORKEYENABLE (0x29), [BOOL] main::Main_ChangeRenderState(D3DRENDERSTATE_COLORKEYENABLE,(uint)((group->flags & 0x400000) != 0)) ; if (group->renderFlags != 0) { Mesh_SetRenderDesc(group->renderFlags,matWorld,alphaBlend); return 1; } return 0; } BOOL __cdecl lego::gfx::Mesh_RenderTriangleList (DWORD matHandle,IDirect3DTexture2 *texture,DWORD renderFlags,Mesh_Vertex *vertices, DWORD vertexCount,WORD *faceData,DWORD indexCount) { int iVar1; HRESULT HVar2; DWORD in_ECX; BOOL BVar3; DWORD local_4; BVar3 = 1; if (((byte)globs::mainGlobs.flags & MAIN_FLAG_DONTMANAGETEXTURES) == 0) { local_4 = in_ECX; if (texture != globs::meshGlobs.currTextureIM) { iVar1 = (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetTexture) (globs::mainGlobs.imDevice,0,texture); if (iVar1 == 0) { globs::meshGlobs.currTextureIM = texture; } else { BVar3 = 0; } } } else { local_4 = 0; if (texture != NULL) { (*(globs::mainGlobs.imDevice)->lpVtbl->QueryInterface) ((IUnknown *)globs::mainGlobs.imDevice,(IID *)&idl::IID_IDirect3DDevice2,&texture); // IDirect3DDevice2->GetCaps(this, D3DDEVICEDESC_V1* lpD3DHWDevDesc, D3DDEVICEDESC_V1* // lpD3DHELDevDesc) (*(code *)texture->lpVtbl->GetHandle)(texture,texture,&local_4); if (texture != NULL) { // IDirect3DDevice2->Release(this) (*texture->lpVtbl->Release)((IUnknown *)texture); } } if (local_4 != globs::meshGlobs.currTextureRM) { // D3DRENDERSTATE_TEXTUREHANDLE (0x1) main::Main_ChangeRenderState(D3DRENDERSTATE_TEXTUREHANDLE,local_4); globs::meshGlobs.currTextureRM = local_4; } } if (matHandle != globs::meshGlobs.currMatIM) { // D3DLIGHTSTATE_MATERIAL (0x1) iVar1 = (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->SetLightState) (globs::mainGlobs.imDevice,D3DLIGHTSTATE_MATERIAL,matHandle); if (iVar1 == 0) { globs::meshGlobs.currMatIM = matHandle; } else { BVar3 = 0; } } // IDirect3DDevice3->DrawIndexedPrimitive(this, D3DPrimitiveType dptPrimitiveType, DWORD // dwVertexTypeDesc, void* lpvVertices, DWORD dwVertexCount, WORD* lpwIndices, DWORD // dwIndexCount, DWORD dwFlags) // // D3DPT_TRIANGLELIST (0x4) HVar2 = (*(code *)(globs::mainGlobs.imDevice)->lpVtbl->DrawIndexedPrimitive) (globs::mainGlobs.imDevice,D3DPT_TRIANGLELIST,renderFlags,vertices,vertexCount, faceData,indexCount,0); if (HVar2 != 0) { BVar3 = 0; } return BVar3; } BOOL __cdecl lego::image::Flic_Setup(char *filename,Flic **out_fsp,FlicUserFlags flags) { char cVar1; IDirectDraw4 *pIVar2; Flic *flic; BOOL BVar3; byte *pbVar4; File *pFVar5; void *pvVar6; int iVar7; uint uVar8; uint uVar9; undefined4 *puVar10; DDSURFACEDESC2 *pDVar11; char *pcVar12; char *pcVar13; undefined4 *puVar14; DDCOLORKEY colorKey; char drive [4]; DDSURFACEDESC2 surfDesc; char errorMessage [128]; char fname [256]; char ext [256]; char dir [256]; pIVar2 = globs::directDrawGlobs.lpDirectDraw; flic = (Flic *)io::Mem_Alloc(0x6e8); *out_fsp = flic; for (iVar7 = 0x1ba; iVar7 != 0; iVar7 += -1) { flic->userflags = FLICDISK; flic = (Flic *)&flic->fsXc; } (*out_fsp)->fsDisplayMode = FLICMODE_HICOLOR; std::_splitpath(filename,drive,dir,fname,ext); BVar3 = Flic_LoadHeader(filename,out_fsp); if (BVar3 == 0) { return 0; } flic = *out_fsp; pDVar11 = &surfDesc; for (iVar7 = 0x1f; iVar7 != 0; iVar7 += -1) { pDVar11->dwSize = 0; pDVar11 = (DDSURFACEDESC2 *)&pDVar11->dwFlags; } surfDesc.dwSize = 0x7c; surfDesc.dwFlags = 7; surfDesc.ddsCaps.dwCaps = 0x840; surfDesc.dwWidth = (DWORD)(flic->fsHeader).width; surfDesc.dwHeight = (DWORD)(flic->fsHeader).height; flic->fsXsize = surfDesc.dwWidth; (*out_fsp)->fsYsize = surfDesc.dwHeight; (*pIVar2->lpVtbl->CreateSurface)(pIVar2,&surfDesc,&(*out_fsp)->fsSurface,NULL); colorKey.dwColorSpaceLowValue = 0; colorKey.dwColorSpaceHighValue = 0; // A GRAPHICAL CRASH(FREEZE?) WAS OBSERVED HERE WHEN RUNNING IN OLLYDBG // POINT OF FAILURE (pointer evaluated to -1) (*(*out_fsp)->fsSurface->lpVtbl->SetColorKey)((*out_fsp)->fsSurface,8,&colorKey); (*out_fsp)->userflags = flags; uVar8 = 0xffffffff; pcVar12 = filename; do { pcVar13 = pcVar12; if (uVar8 == 0) break; uVar8 -= 1; pcVar13 = pcVar12 + 1; cVar1 = *pcVar12; pcVar12 = pcVar13; } while (cVar1 != '\0'); uVar8 = ~uVar8; puVar10 = (undefined4 *)(pcVar13 + -uVar8); puVar14 = (undefined4 *)(*out_fsp)->filename; for (uVar9 = uVar8 >> 2; uVar9 != 0; uVar9 -= 1) { *puVar14 = *puVar10; puVar10 = puVar10 + 1; puVar14 = puVar14 + 1; } for (uVar8 &= 3; uVar8 != 0; uVar8 -= 1) { *(undefined *)puVar14 = *(undefined *)puVar10; puVar10 = (undefined4 *)((int)puVar10 + 1); puVar14 = (undefined4 *)((int)puVar14 + 1); } (*out_fsp)->fsXc = 0; (*out_fsp)->fsYc = 0; (*out_fsp)->currentframe = 0; (*out_fsp)->overallframe = 0; (*out_fsp)->framerate = 0x190000; flic = *out_fsp; if (((byte)flic->userflags & 1) == 1) { flic->pointerposition = 0; pbVar4 = (byte *)io::Mem_Alloc(((*out_fsp)->fsHeader).size); (*out_fsp)->rambufferhandle = pbVar4; pFVar5 = io::File_Open(filename,"rb"); (*out_fsp)->filehandle = pFVar5; io::File_Seek((*out_fsp)->filehandle,0x80,0); flic = *out_fsp; io::File_Read(flic->rambufferhandle,(flic->fsHeader).size,1,flic->filehandle); io::File_Close((*out_fsp)->filehandle); } else { flic->pointerposition = 0x80; pFVar5 = io::File_Open(filename,"rb"); (*out_fsp)->filehandle = pFVar5; if ((*out_fsp)->filehandle == NULL) { std::sprintf(errorMessage,"Not Enough Memory > %s",filename); return 0; } io::File_Seek((*out_fsp)->filehandle,0x80,0); } pvVar6 = io::Mem_Alloc(20000); (*out_fsp)->fsLoadBuffer = pvVar6; return TRUE; } BOOL __cdecl lego::image::Flic_Close(Flic *fsp) { if (fsp == NULL) { return 0; } if (((byte)fsp->userflags & FLICMEMORY) == FLICMEMORY) { io::Mem_Free(fsp->rambufferhandle); } else { io::File_Close(fsp->filehandle); } if (fsp->fsLoadBuffer != NULL) { io::Mem_Free(fsp->fsLoadBuffer); fsp->fsLoadBuffer = NULL; } return TRUE; } // see: BOOL __cdecl lego::image::Flic_LoadHeader(char *filename,Flic **fsp) { ushort uVar1; Flic *pFVar2; File *f; int iVar3; char *format; char errorMessage [128]; f = io::File_Open(filename,"rb"); if (f == NULL) { format = "Flic File Not Found %s"; } else { io::File_Seek(f,0,SEEK_SET); io::File_Read(&(*fsp)->fsHeader,0x88,1,f); pFVar2 = *fsp; iVar3 = io::File_Length(f); if ((pFVar2->fsHeader).size != iVar3) { io::File_Close(f); std::sprintf(errorMessage,"Flic File Invalid",filename); return 0; } uVar1 = (pFVar2->fsHeader).magic; if (uVar1 < 0x911a) { if ((uVar1 == 0x9119) || (uVar1 == 0x1234)) { LAB_004842d2: io::File_Close(f); return TRUE; } } else { if (((uVar1 == 0xaf11) || (uVar1 == 0xaf12)) || (uVar1 == 0xaf43)) goto LAB_004842d2; } io::File_Close(f); format = "Flic File Invalid %s"; } std::sprintf(errorMessage,format,filename); return 0; } BOOL __cdecl lego::image::Flic_Animate(Flic *fsp,Area2F *destArea,BOOL advance,BOOL trans) { IDirectDrawSurface4 *pIVar1; int iVar2; FlicError FVar3; DDSURFACEDESC2 *pDVar4; uint *puVar5; longlong lVar6; longlong lVar7; longlong lVar8; RECT dstRect; DDSURFACEDESC2 surfDesc; uint ddBltFX [25]; pIVar1 = globs::directDrawGlobs.bSurf; lVar6 = __ftol((float10)destArea->x); dstRect.left = (int)lVar6; lVar7 = __ftol((float10)destArea->y); dstRect.top = (int)lVar7; lVar8 = __ftol((float10)destArea->width); dstRect.right = (int)lVar8 + (int)lVar6; lVar6 = __ftol((float10)destArea->height); dstRect.bottom = (int)lVar6 + (int)lVar7; FVar3 = FLICNOERROR; pDVar4 = &surfDesc; for (iVar2 = 0x1f; iVar2 != 0; iVar2 += -1) { pDVar4->dwSize = 0; pDVar4 = (DDSURFACEDESC2 *)&pDVar4->dwFlags; } surfDesc.dwSize = 0x7c; (*fsp->fsSurface->lpVtbl->Lock)(fsp->fsSurface,NULL,&surfDesc,1,NULL); fsp->fsPitch = surfDesc.lPitch; fsp->fsSPtr = surfDesc.lpSurface; fsp->is15bit = (uint)(surfDesc.ddpfPixelFormat.dwGBitMask == 0x3e0); iVar2 = 1; if (fsp->currentframe != 0) { iVar2 = advance; } if (iVar2 != 0) { if (((byte)fsp->userflags & FLICMEMORY) == FLICMEMORY) { FVar3 = Flic_Memory(fsp); } else { FVar3 = Flic_Load(fsp); } } (*fsp->fsSurface->lpVtbl->Unlock)(fsp->fsSurface,NULL); puVar5 = ddBltFX; for (iVar2 = 0x19; iVar2 != 0; iVar2 += -1) { *puVar5 = 0; puVar5 = puVar5 + 1; } ddBltFX[0] = 100; ddBltFX[20] = 0xff00; // DDBLT_WAIT | (trans ? DDBLT_KEYSRC : 0) (0x1000000) (0x8000) (*pIVar1->lpVtbl->Blt) (pIVar1,(LPRECT)&dstRect,fsp->fsSurface,NULL,-(uint)(trans != 0) & 0x8000 | 0x1000000, ddBltFX); return (uint)(FVar3 == FLICNOERROR); } FlicError __cdecl lego::image::Flic_Memory(Flic *fsp) { int iVar1; FlicError FVar2; FVar2 = FLICNOERROR; Flic_FindChunk(fsp); if (fsp->currentframe == 0) { fsp->ringframe = fsp->pointerposition; } iVar1 = fsp->currentframe + 1; fsp->currentframe = iVar1; fsp->overallframe = fsp->overallframe + 1; if (((byte)fsp->userflags & FLICLOOPINGON) == FLICLOOPINGON) { if (iVar1 == (fsp->fsHeader).frames + 1) { fsp->currentframe = 1; fsp->pointerposition = fsp->ringframe; return FLICNOERROR; } } else { if (iVar1 == (fsp->fsHeader).frames + 1) { FVar2 = FLICFINISHED; } } return FVar2; } FlicError __cdecl lego::image::Flic_Load(Flic *fsp) { int iVar1; FlicError FVar2; FVar2 = FLICNOERROR; if (fsp->currentframe == 0) { fsp->ringframe = fsp->pointerposition; } io::File_Read(fsp->fsLoadBuffer,0x10,1,fsp->filehandle); Flic_FindChunk(fsp); iVar1 = fsp->currentframe + 1; fsp->currentframe = iVar1; fsp->overallframe = fsp->overallframe + 1; if (((byte)fsp->userflags & FLICLOOPINGON) == FLICLOOPINGON) { if ((int)(uint)(fsp->fsHeader).frames < iVar1) { io::File_Seek(fsp->filehandle,fsp->ringframe,0); fsp->pointerposition = fsp->ringframe; fsp->currentframe = 0; return FLICNOERROR; } } else { if ((int)(uint)(fsp->fsHeader).frames < iVar1) { FVar2 = FLICFINISHED; } } return FVar2; } FlicError __cdecl lego::image::Flic_FindChunk(Flic *fsp) { short sVar1; int iVar2; bool bVar3; int iVar4; FlicUserFlags FVar5; int iVar6; int *piVar7; FVar5 = fsp->userflags & FLICMEMORY; if (FVar5 == FLICMEMORY) { piVar7 = (int *)fsp->rambufferhandle; } else { piVar7 = (int *)fsp->fsLoadBuffer; } iVar2 = fsp->pointerposition; if (FVar5 == FLICMEMORY) { iVar6 = *(int *)((int)piVar7 + iVar2); piVar7 = (int *)((int)piVar7 + iVar2); bVar3 = false; while (fsp->pointerposition < (fsp->fsHeader).size) { sVar1 = *(short *)(piVar7 + 1); if (sVar1 == 0xb) { Flic_LoadPalette64(fsp); iVar4 = fsp->pointerposition + *piVar7; LAB_00484688: fsp->pointerposition = iVar4; LAB_0048468e: piVar7 = (int *)((int)piVar7 + *piVar7); iVar6 += *piVar7; } else { if (sVar1 == 0x4b4c) { Flic_LoadPointers(fsp); fsp->pointerposition = fsp->pointerposition + *piVar7; goto LAB_0048468e; } if (sVar1 != -0xe06) { iVar4 = *piVar7 + fsp->pointerposition; goto LAB_00484688; } Flic_FrameChunk(fsp); bVar3 = true; } if (bVar3) { fsp->pointerposition = iVar2 + iVar6; return FLICNOERROR; } } } else { iVar6 = *piVar7; bVar3 = false; do { if ((fsp->fsHeader).size <= fsp->pointerposition) break; sVar1 = *(short *)(piVar7 + 1); if (sVar1 == 0xb) { Flic_LoadPalette64(fsp); LAB_00484704: iVar4 = fsp->pointerposition + *piVar7; fsp->pointerposition = iVar4; LAB_00484719: io::File_Seek(fsp->filehandle,iVar4,SEEK_SET); piVar7 = (int *)fsp->fsLoadBuffer; io::File_Read(piVar7,0x10,1,fsp->filehandle); iVar6 += *piVar7; } else { if (sVar1 == 0x4b4c) { Flic_LoadPointers(fsp); goto LAB_00484704; } if (sVar1 != -0xe06) { iVar4 = *piVar7 + fsp->pointerposition; fsp->pointerposition = iVar4; goto LAB_00484719; } Flic_FrameChunk(fsp); bVar3 = true; } } while (!bVar3); } fsp->pointerposition = iVar2 + iVar6; return FLICNOERROR; } BOOL __cdecl lego::image::Flic_FrameChunk(Flic *fsp) { byte bVar1; char cVar2; uint size; int *piVar3; char buff [128]; if (((byte)fsp->userflags & FLICMEMORY) == FLICMEMORY) { bVar1 = (fsp->rambufferhandle + fsp->pointerposition)[6]; piVar3 = (int *)(fsp->rambufferhandle + fsp->pointerposition + 0x10); fsp->pointerposition = fsp->pointerposition + 0x10; if ('\0' < (char)bVar1) { while (fsp->pointerposition < (fsp->fsHeader).size) { fsp->fsSource = piVar3; Flic_DoChunk(fsp); fsp->pointerposition = fsp->pointerposition + *piVar3; piVar3 = (int *)((int)piVar3 + *piVar3); bVar1 -= 1; if ((char)bVar1 < '\x01') { return TRUE; } } } } else { piVar3 = (int *)fsp->fsLoadBuffer; cVar2 = *(char *)((int)piVar3 + 6); size = *piVar3 - 0x10; if (fsp->fsLoadBufferSize < (int)size) { if (piVar3 != NULL) { io::Mem_Free(piVar3); } fsp->fsLoadBufferSize = size; piVar3 = (int *)io::Mem_Alloc(size); fsp->fsLoadBuffer = piVar3; if (piVar3 == NULL) { std::sprintf(buff,"Flic Not Enough Memory"); return 0; } } io::File_Read(piVar3,size,1,fsp->filehandle); fsp->pointerposition = fsp->pointerposition + 0x10; while (('\0' < cVar2 && (fsp->pointerposition < (fsp->fsHeader).size))) { fsp->fsSource = piVar3; Flic_DoChunk(fsp); fsp->pointerposition = fsp->pointerposition + *piVar3; piVar3 = (int *)((int)piVar3 + *piVar3); cVar2 += -1; } } return TRUE; } // sort out chunk type FlicError __cdecl lego::image::Flic_DoChunk(Flic *fsp) { FlicError FVar1; int iVar2; FVar1 = FLICNOERROR; iVar2 = (int)*(short *)((int)fsp->fsSource + 4); if (iVar2 < 8) { if (iVar2 == 7) { switchD_0048492b_caseD_1b: Flic_DeltaWord(fsp); return FLICFINISHED; } if (iVar2 == 4) { Flic_Palette256(fsp); return FLICFINISHED; } } else { if (iVar2 < 0x5345) { if (iVar2 != 0x5344) { if (false) { return FLICNOERROR; } switch(iVar2) { case 0xb: nerps::funcs::NERPFunc__True((int *)fsp); return FLICFINISHED; case 0xc: nerps::funcs::NERPFunc__True((int *)fsp); return FLICFINISHED; case 0xd: nerps::funcs::NERPFunc__True((int *)fsp); return FLICFINISHED; default: return FLICNOERROR; case 0xf: case 0x19: Flic_BrunDepack(fsp); return FLICFINISHED; case 0x10: Flic_Copy(fsp); return FLICFINISHED; case 0x1b: goto switchD_0048492b_caseD_1b; } } } else { if (iVar2 != 0x5555) { return FLICNOERROR; } nerps::funcs::NERPFunc__False((int *)fsp); } FVar1 = FLICFINISHED; } return FVar1; } // Function to load pointers for each frame of flic. FlicError __cdecl lego::image::Flic_LoadPointers(Flic *fsp) { uint size; uint *buffer; char buff [256]; if (((byte)fsp->userflags & FLICMEMORY) != FLICMEMORY) { buffer = (uint *)fsp->fsLoadBuffer; size = *buffer; if (fsp->fsLoadBufferSize < (int)size) { if (buffer != NULL) { io::Mem_Free(buffer); } fsp->fsLoadBufferSize = size; buffer = (uint *)io::Mem_Alloc(size); fsp->fsLoadBuffer = buffer; if (buffer == NULL) { std::sprintf(buff,"Flic Not Enough Memory"); return FLICNOERROR; } } io::File_Seek(fsp->filehandle,fsp->pointerposition,SEEK_SET); io::File_Read(buffer,size,1,fsp->filehandle); } return FLICNOERROR; } // Function to load an 8 bit palette. FlicError __cdecl lego::image::Flic_LoadPalette64(Flic *fsp) { uint size; uint *buffer; char buff [128]; if (((byte)fsp->userflags & FLICMEMORY) != FLICMEMORY) { buffer = (uint *)fsp->fsLoadBuffer; size = *buffer; if (fsp->fsLoadBufferSize < (int)size) { if (buffer != NULL) { io::Mem_Free(buffer); } fsp->fsLoadBufferSize = size; buffer = (uint *)io::Mem_Alloc(size); fsp->fsLoadBuffer = buffer; if (buffer == NULL) { std::sprintf(buff,"Flic Not Enough Memory"); return FLICFINISHED; } } io::File_Seek(fsp->filehandle,fsp->pointerposition,SEEK_SET); io::File_Read(buffer,size,1,fsp->filehandle); } return FLICNOERROR; } BOOL __cdecl lego::image::Flic_Copy(Flic *fsp) { if (fsp->fsBitPlanes == 0x10) { // FlicCopyHiColorFlic(fsp) => return; util::logf_removed((char *)fsp); return TRUE; } if (fsp->fsDisplayMode == FLICMODE_BYTEPERPIXEL) { // FlicCopyBytePerPixel(fsp) => return; util::logf_removed((char *)fsp); } if (fsp->fsDisplayMode == FLICMODE_HICOLOR) { // FlicCopyHiColor(fsp) => return; util::logf_removed((char *)fsp); } return TRUE; } BOOL __cdecl lego::image::FlicBRunDepackHiColor(Flic *fsp) { byte n; byte bVar1; ushort uVar2; uint uVar3; uint uVar4; ushort *puVar5; byte *pbVar6; byte *pbVar7; int local_8; uint local_4; pbVar6 = (byte *)((int)fsp->fsSource + 7); if (*(ushort *)&fsp->fsYsize != 0) { local_4 = (uint)*(ushort *)&fsp->fsYsize; local_8 = 0; do { uVar2 = *(ushort *)&fsp->fsXsize; uVar3 = (uint)uVar2; puVar5 = (ushort *)((int)fsp->fsSPtr + (fsp->fsPitch >> 1) * local_8 * 2); while (uVar2 != 0) { bVar1 = *pbVar6; uVar4 = (uint)bVar1; pbVar7 = pbVar6 + 1; if (bVar1 < 0x80) { n = *pbVar7; uVar3 -= uVar4; pbVar7 = pbVar6 + 2; if (bVar1 != 0) { do { uVar2 = getFlicCol(n,fsp); *puVar5 = uVar2; puVar5 = puVar5 + 1; uVar4 -= 1; } while (uVar4 != 0); } } else { uVar4 = 0x100 - uVar4; uVar3 -= uVar4; if ((short)uVar4 != 0) { uVar4 &= 0xffff; do { bVar1 = *pbVar7; pbVar7 = pbVar7 + 1; uVar2 = getFlicCol(bVar1,fsp); *puVar5 = uVar2; puVar5 = puVar5 + 1; uVar4 -= 1; } while (uVar4 != 0); } } pbVar6 = pbVar7; uVar2 = (ushort)uVar3; } local_8 += 1; pbVar6 = pbVar6 + 1; local_4 -= 1; } while (local_4 != 0); } return TRUE; } BOOL __cdecl lego::image::FlicBRunDepackHiColorFlic32k(Flic *fsp) { ushort uVar1; short sVar2; Flic *pFVar3; ushort uVar4; uint uVar5; uint uVar6; ushort *puVar7; ushort *puVar8; ushort *puVar9; short sVar10; pFVar3 = fsp; fsp = NULL; sVar2 = *(short *)&pFVar3->fsYsize; puVar8 = (ushort *)((int)pFVar3->fsSource + 7); if (0 < sVar2) { uVar5 = 0; do { sVar10 = *(short *)&pFVar3->fsXsize; puVar7 = (ushort *)((int)pFVar3->fsSPtr + (pFVar3->fsPitch >> 1) * uVar5 * 2); while (0 < sVar10) { uVar4 = (ushort)*(byte *)puVar8; puVar9 = (ushort *)((int)puVar8 + 1); if (uVar4 < 0x80) { uVar1 = *puVar9; sVar10 -= uVar4; puVar8 = (ushort *)((int)puVar8 + 3); uVar5 = (uVar1 & 0xffe0) << 1; if (uVar4 != 0) { uVar6 = (uint)uVar4; do { if (pFVar3->is15bit == 0) { uVar4 = (ushort)uVar5; } else { uVar4 = (ushort)((uVar5 & 0xffff) >> 1); } *puVar7 = uVar4 | uVar1 & 0x1f; puVar7 = puVar7 + 1; uVar6 -= 1; } while (uVar6 != 0); } } else { uVar4 = 0x100 - uVar4; sVar10 -= uVar4; puVar8 = puVar9; if (uVar4 != 0) { uVar5 = (uint)uVar4; do { uVar4 = *puVar9; puVar9 = puVar9 + 1; uVar6 = (uVar4 & 0xffe0) << 1; if (pFVar3->is15bit == 0) { uVar1 = (ushort)uVar6; } else { uVar1 = (ushort)((uVar6 & 0xffff) >> 1); } *puVar7 = uVar1 | uVar4 & 0x1f; puVar7 = puVar7 + 1; uVar5 -= 1; puVar8 = puVar9; } while (uVar5 != 0); } } } puVar8 = (ushort *)((int)puVar8 + 1); fsp = (Flic *)((int)&fsp->userflags + 1); uVar5 = (uint)fsp & 0xffff; } while ((int)uVar5 < (int)sVar2); } return TRUE; } BOOL __cdecl lego::image::Flic_BrunDepack(Flic *fsp) { ushort uVar1; uVar1 = (fsp->fsHeader).depth; if (uVar1 == 8) { if (fsp->fsDisplayMode == FLICMODE_BYTEPERPIXEL) { // FlicBRunDepackBytePerPixel(fsp) => return TRUE; nerps::funcs::NERPFunc__True((int *)fsp); } if (fsp->fsDisplayMode == FLICMODE_HICOLOR) { FlicBRunDepackHiColor(fsp); return TRUE; } } else { if (uVar1 == 0x10) { if ((fsp->fsHeader).magic == 0xaf43) { FlicBRunDepackHiColorFlic32k(fsp); return TRUE; } // FlicBRunDepackHiColorFlic(fsp) => return TRUE; nerps::funcs::NERPFunc__True((int *)fsp); } } return TRUE; } int __cdecl lego::nerps::funcs::NERPFunc__True(int *stack) { return TRUE; } void __cdecl lego::image::FlicCreateHiColorTable(Flic *fsp) { ColourRGBPacked *pCVar1; ushort *puVar2; int iVar3; iVar3 = 0x100; pCVar1 = fsp->fsPalette256; puVar2 = fsp->fsPalette64k; do { iVar3 += -1; *puVar2 = (ushort)(((uint)pCVar1->green | (pCVar1->red & 0xffff003e) << 5) << 5) | (ushort)(pCVar1->blue >> 1); pCVar1 = pCVar1 + 1; puVar2 = puVar2 + 1; } while (iVar3 != 0); fsp->fsPalette64k[0] = 0; return; } BOOL __cdecl lego::image::Flic_Palette256(Flic *fsp) { byte bVar1; byte *pbVar2; byte *pbVar3; ColourRGBPacked *pCVar4; uint uVar5; int iVar6; short sVar7; pCVar4 = fsp->fsPalette256; pbVar2 = (byte *)((int)fsp->fsSource + 8); for (sVar7 = *(short *)((int)fsp->fsSource + 6); sVar7 != 0; sVar7 += -1) { pbVar3 = pbVar2 + 2; uVar5 = (uint)pbVar2[1]; pCVar4 = pCVar4 + *pbVar2; if (pbVar2[1] == 0) { sVar7 = 1; uVar5 = 0x100; pCVar4 = fsp->fsPalette256; } iVar6 = uVar5 * 3; if ((short)iVar6 != 0) { do { bVar1 = *pbVar3; pbVar3 = pbVar3 + 1; pCVar4->red = bVar1 >> 2; pCVar4 = (ColourRGBPacked *)&pCVar4->green; iVar6 += -1; } while (iVar6 != 0); } pbVar2 = pbVar3; } if (fsp->fsDisplayMode == FLICMODE_HICOLOR) { FlicCreateHiColorTable(fsp); } return TRUE; } void __cdecl lego::util::logf_removed(char *message,...) { return; } void __cdecl lego::image::FlicDeltaWordHiColor(Flic *fsp) { void **ppvVar1; byte bVar2; byte bVar3; ushort uVar4; ushort uVar5; uint uVar6; short sVar7; short sVar8; ushort *puVar9; ushort *puVar10; ushort *puVar11; uint local_10; byte local_4; Flic *fsp_00; fsp_00 = fsp; ppvVar1 = &fsp->fsSource; fsp = NULL; sVar8 = *(short *)((int)*ppvVar1 + 6); puVar10 = (ushort *)((int)*ppvVar1 + 8); sVar7 = sVar8; while( true ) { while( true ) { if (sVar7 == 0) { return; } uVar5 = *puVar10; puVar9 = (ushort *)(((uint)fsp & 0xffff) * fsp_00->fsPitch + (int)fsp_00->fsSPtr); uVar4 = uVar5 >> 0xc & 0xc; if (uVar4 != 0xc) break; puVar10 = puVar10 + 1; fsp = (Flic *)((int)fsp - (uint)uVar5); } if (uVar4 == 4) break; if (uVar4 == 8) { local_4 = *(byte *)puVar10; puVar10 = puVar10 + 1; } uVar5 = *puVar10; puVar10 = puVar10 + 1; if (uVar5 != 0) { local_10 = (uint)uVar5; puVar11 = puVar10; do { bVar3 = *(byte *)((int)puVar11 + 1); uVar6 = (uint)bVar3; puVar10 = puVar11 + 1; puVar9 = puVar9 + *(byte *)puVar11; if ((bVar3 & 0x80) == 0) { if (bVar3 != 0) { do { bVar3 = *(byte *)puVar10; bVar2 = *(byte *)((int)puVar10 + 1); puVar10 = puVar10 + 1; uVar5 = getFlicCol(bVar3,fsp_00); *puVar9 = uVar5; uVar5 = getFlicCol(bVar2,fsp_00); puVar9[1] = uVar5; puVar9 = puVar9 + 2; uVar6 -= 1; } while (uVar6 != 0); } } else { bVar3 = *(byte *)((int)puVar11 + 3); bVar2 = *(byte *)puVar10; puVar10 = puVar11 + 2; if ((short)(0x100 - uVar6) != 0) { uVar6 = 0x100 - uVar6 & 0xffff; do { uVar5 = getFlicCol(bVar2,fsp_00); *puVar9 = uVar5; uVar5 = getFlicCol(bVar3,fsp_00); puVar9[1] = uVar5; puVar9 = puVar9 + 2; uVar6 -= 1; } while (uVar6 != 0); } } local_10 -= 1; puVar11 = puVar10; sVar7 = sVar8; } while (local_10 != 0); } if (uVar4 == 8) { uVar5 = getFlicCol(local_4,fsp_00); *puVar9 = uVar5; } sVar8 = sVar7 + -1; fsp = (Flic *)((int)&fsp->userflags + 1); sVar7 = sVar8; } return; } // WARNING: Could not reconcile some variable overlaps void __cdecl lego::image::FlicDeltaWordHiColorFlic32k(Flic *fsp) { void **ppvVar1; byte bVar2; ushort uVar3; bool bVar4; short sVar5; Flic *pFVar6; ushort uVar7; uint uVar8; short sVar9; uint uVar10; ushort *puVar11; ushort *puVar12; ushort *puVar13; uint local_10; uint local_8; pFVar6 = fsp; ppvVar1 = &fsp->fsSource; fsp = NULL; sVar9 = *(short *)((int)*ppvVar1 + 6); puVar11 = (ushort *)((int)*ppvVar1 + 8); sVar5 = sVar9; while( true ) { while( true ) { if (sVar9 == 0) { return; } uVar3 = *puVar11; uVar8 = (uint)uVar3; puVar13 = (ushort *)(((uint)fsp & 0xffff) * pFVar6->fsPitch + (int)pFVar6->fsSPtr); uVar7 = uVar3 >> 0xc & 0xc; if (uVar7 != 0xc) break; puVar11 = puVar11 + 1; fsp = (Flic *)((int)fsp - uVar8); } if (uVar7 == 4) break; bVar4 = false; if (uVar7 == 8) { if (pFVar6->is15bit != 0) { uVar8 = uVar3 >> 1 & 0x7ff0 | uVar8 & 0x1f; } puVar11 = puVar11 + 1; bVar4 = true; local_8 = uVar8; } uVar3 = *puVar11; puVar11 = puVar11 + 1; if (uVar3 != 0) { local_10 = (uint)uVar3; puVar12 = puVar11; do { bVar2 = *(byte *)((int)puVar12 + 1); uVar8 = (uint)bVar2; puVar11 = puVar12 + 1; puVar13 = puVar13 + *(byte *)puVar12; if ((bVar2 & 0x80) == 0) { if (bVar2 != 0) { do { uVar3 = *puVar11; puVar11 = puVar11 + 1; uVar10 = (uVar3 & 0xffe0) << 1; if (pFVar6->is15bit == 0) { uVar7 = (ushort)uVar10; } else { uVar7 = (ushort)((uVar10 & 0xffff) >> 1); } *puVar13 = uVar7 | uVar3 & 0x1f; puVar13 = puVar13 + 1; uVar8 -= 1; } while (uVar8 != 0); } } else { uVar3 = *puVar11; puVar11 = puVar12 + 2; uVar10 = (uVar3 & 0xffe0) << 1; if ((short)(0x100 - uVar8) != 0) { uVar8 = 0x100 - uVar8 & 0xffff; do { if (pFVar6->is15bit == 0) { uVar7 = (ushort)uVar10; } else { uVar7 = (ushort)((uVar10 & 0xffff) >> 1); } *puVar13 = uVar7 | uVar3 & 0x1f; puVar13 = puVar13 + 1; uVar8 -= 1; } while (uVar8 != 0); } } local_10 -= 1; puVar12 = puVar11; sVar9 = sVar5; } while (local_10 != 0); } if (bVar4) { *(undefined *)puVar13 = (undefined)local_8; } fsp = (Flic *)((int)&fsp->userflags + 1); sVar9 += -1; sVar5 = sVar9; } return; } BOOL __cdecl lego::image::Flic_DeltaWord(Flic *fsp) { ushort uVar1; uVar1 = (fsp->fsHeader).depth; if (uVar1 == 8) { if (fsp->fsDisplayMode == FLICMODE_BYTEPERPIXEL) { // FlicDeltaWordBytePerPixel(fsp) => return; util::logf_removed((char *)fsp); } if (fsp->fsDisplayMode == FLICMODE_HICOLOR) { FlicDeltaWordHiColor(fsp); return TRUE; } } else { if (uVar1 == 0x10) { uVar1 = (fsp->fsHeader).magic; if (uVar1 == 0x1234) { // FlicDeltaWordHiColorDZ(fsp) => return; util::logf_removed((char *)fsp); return TRUE; } if (uVar1 == 0xaf43) { FlicDeltaWordHiColorFlic32k(fsp); return TRUE; } // FlicDeltaWordHiColorFlic(fsp) => return; util::logf_removed((char *)fsp); } } return TRUE; } // MACRO: #define FHCOL(n) getFlicCol(n,fsp) ushort __cdecl lego::image::getFlicCol(byte n,Flic *fsp) { return fsp->fsPalette64k[n]; } uint __cdecl lego::image::Flic_GetHeight(Flic *fsp) { return fsp->fsYsize; } TextWindow * __cdecl lego::front::TextWindow_Create(Font *font,Area2F *area,uint size) { TextWindow *textWnd; void *pvVar1; int iVar2; TextWindow *pTVar3; textWnd = (TextWindow *)io::Mem_Alloc(0x830); if (textWnd != NULL) { pTVar3 = textWnd; for (iVar2 = 0x20c; iVar2 != 0; iVar2 += -1) { pTVar3->font = NULL; pTVar3 = (TextWindow *)&pTVar3->windowSize; } textWnd->font = font; (textWnd->windowSize).x = area->x; (textWnd->windowSize).y = area->y; (textWnd->windowSize).width = area->width; (textWnd->windowSize).height = area->height; pvVar1 = io::Mem_Alloc(size); textWnd->windowBuffer = pvVar1; textWnd->bufferSize = size; TextWindow_EnableCentering(textWnd,1); } return textWnd; } void __cdecl lego::front::TextWindow_EnableCentering(TextWindow *textWnd,BOOL enable) { if (enable != 0) { textWnd->flags = textWnd->flags | 4; return; } textWnd->flags = textWnd->flags & 0xfffffffb; return; } void __cdecl lego::front::TextWindow_Remove(TextWindow *textWnd) { io::Mem_Free(textWnd->windowBuffer); io::Mem_Free(textWnd); return; } void __cdecl lego::front::TextWindow_ChangePosition(TextWindow *textWnd,int xpos,int ypos) { (textWnd->windowSize).x = (float)xpos; (textWnd->windowSize).y = (float)ypos; return; } void __cdecl lego::front::TextWindow_ChangeSize(TextWindow *textWnd,uint width,uint height) { (textWnd->windowSize).width = (float)(ulonglong)width; (textWnd->windowSize).height = (float)(ulonglong)height; return; } void __cdecl lego::front::TextWindow_PagePrintF(TextWindow *textWnd,int page,char *format,...) { TextWindow_VPrintF(textWnd,page,format,&stack0x00000010); return; } void __cdecl lego::front::TextWindow_PrintF(TextWindow *textWnd,char *format,...) { TextWindow_VPrintF(textWnd,0,format,&stack0x0000000c); return; } void __cdecl lego::front::TextWindow_VPrintF(TextWindow *textWnd,int page,char *format,va_list argptr) { uint length; uint index; int pageIndex; uint uVar1; char buff [1024]; pageIndex = 0; length = std::vsprintf(buff,format,argptr); index = 0; if (length != 0) { do { if (pageIndex == page) break; if (buff[index] == '\a') { pageIndex += 1; } index += 1; } while (index < length); } if (index != length) { for (; index < length; index += 1) { *(char *)((int)textWnd->windowBuffer + textWnd->bufferEnd) = buff[index]; uVar1 = textWnd->bufferEnd + 1; textWnd->bufferEnd = uVar1; if (uVar1 == textWnd->bufferSize) { textWnd->bufferEnd = 0; textWnd->flags = textWnd->flags | 1; } } } return; } void __cdecl lego::front::TextWindow_PrintFOverlay(TextWindow *textWnd,BOOL oneFrame,char *format,...) { char cVar1; uint uVar2; uint uVar3; undefined4 *puVar4; char *pcVar5; char *pcVar6; undefined4 *puVar7; char local_400 [1024]; std::vsprintf(local_400,format,&stack0x00000010); uVar2 = 0xffffffff; pcVar5 = local_400; do { pcVar6 = pcVar5; if (uVar2 == 0) break; uVar2 -= 1; pcVar6 = pcVar5 + 1; cVar1 = *pcVar5; pcVar5 = pcVar6; } while (cVar1 != '\0'); uVar2 = ~uVar2; puVar4 = (undefined4 *)(pcVar6 + -uVar2); puVar7 = (undefined4 *)textWnd->secondBuffer; for (uVar3 = uVar2 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar7 = *puVar4; puVar4 = puVar4 + 1; puVar7 = puVar7 + 1; } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar4; puVar4 = (undefined4 *)((int)puVar4 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } if (oneFrame == 0) { textWnd->displayDelay = 25.0; } else { textWnd->displayDelay = 0.0; } textWnd->flags = textWnd->flags | 2; return; } BOOL __cdecl lego::front::TextWindow_Update (TextWindow *textWnd,uint posFromEnd,float elapsed,int *out_lowestPoint) { float fVar1; byte c; uint uVar2; float fVar3; uint uVar4; uint uVar5; BOOL BVar6; uint *puVar7; uint uVar8; int iVar9; ulonglong uVar10; longlong lVar11; uint local_414; uint *local_410; uint *local_40c; uint auStack1028 [257]; uVar8 = 0; local_414 = 0; local_410 = NULL; if (out_lowestPoint != NULL) { *out_lowestPoint = 0; } uVar10 = __ftol((float10)(textWnd->windowSize).height); textWnd->linesCapacity = (int)((uVar10 & 0xffffffff) / (ulonglong)textWnd->font->fontHeight); if ((textWnd->flags & 2) != 0) { BVar6 = TextWindow_UpdateOverlay(textWnd,elapsed,out_lowestPoint); return BVar6; } uVar5 = textWnd->bufferSize; if (((textWnd->flags & 1) != 0) && (local_40c = (uint *)textWnd->linesCount, local_40c != NULL)) { puVar7 = textWnd->lines; do { uVar4 = *puVar7 - textWnd->bufferEnd; if ((0 < (int)uVar4) && ((int)uVar4 < (int)uVar5)) { uVar5 = uVar4; local_414 = *puVar7; } puVar7 = puVar7 + 1; local_40c = (uint *)((int)local_40c - 1); } while (local_40c != NULL); } textWnd->linesCount = 0; textWnd->lines[0] = local_414; textWnd->linesCount = textWnd->linesCount + 1; if (local_414 != textWnd->bufferEnd) { do { c = *(byte *)(local_414 + (int)textWnd->windowBuffer); if (c == '\a') break; if (c == '\n') { textWnd->lines[textWnd->linesCount] = local_414 + 1; uVar5 = textWnd->linesCount; auStack1028[uVar5] = uVar8; textWnd->linesCount = uVar5 + 1; local_410 = NULL; uVar8 = 0; } else { // int std::isspace(int c) if (std::globals::_pcharwidth < 2) { uVar5 = *(byte *)(std::globals::_pctype + c) & C1_SPACE; } else { uVar5 = std::_isctype((uint)c,C1_SPACE); } if (uVar5 != 0) { local_410 = NULL; textWnd->lines[textWnd->linesCount] = local_414 + 1; auStack1028[textWnd->linesCount] = uVar8; } uVar5 = lego::image::Font_GetCharWidth(textWnd->font,c); local_410 = (uint *)((int)local_410 + uVar5); fVar3 = (float)(uVar8 + uVar5); fVar1 = (textWnd->windowSize).width; uVar8 = uVar8 + uVar5; if ((ushort)((ushort)(fVar3 < fVar1) << 8 | (ushort)(fVar3 == fVar1) << 0xe) == 0) { textWnd->linesCount = textWnd->linesCount + 1; uVar8 = (uint)local_410; } } local_414 += 1; if (textWnd->bufferSize <= local_414) { local_414 = 0; } } while (local_414 != textWnd->bufferEnd); } textWnd->lines[textWnd->linesCount] = local_414; uVar5 = textWnd->linesCount; iVar9 = textWnd->linesCapacity; auStack1028[uVar5] = uVar8; uVar8 = (uVar5 - iVar9) + 1; uVar4 = 0; if (uVar8 == 0) { posFromEnd = 0; } else { posFromEnd %= uVar8; } if (uVar5 != 0) { local_40c = auStack1028; local_410 = textWnd->lines; do { local_40c = local_40c + 1; local_410 = local_410 + 1; lVar11 = __ftol((float10)(textWnd->windowSize).x); local_414 = (uint)lVar11; if ((*(byte *)&textWnd->flags & 4) != 0) { auStack1028[0] = 0; lVar11 = __ftol(((float10)(textWnd->windowSize).width - (float10)(ulonglong)*local_40c) * (float10)0.5); local_414 += (int)lVar11; } uVar8 = textWnd->linesCapacity; if (uVar8 < uVar5) { if ((uVar4 < (uVar5 - posFromEnd) - uVar8) || (uVar5 - posFromEnd <= uVar4)) { if (uVar5 <= uVar8) goto LAB_004858e9; iVar9 = 0; } else { uVar2 = textWnd->font->fontHeight; lVar11 = __ftol((float10)(textWnd->windowSize).y); iVar9 = ((posFromEnd + uVar4 + uVar8) - uVar5) * uVar2 + (int)lVar11; } } else { LAB_004858e9: uVar8 = textWnd->font->fontHeight; lVar11 = __ftol((float10)(textWnd->windowSize).y); iVar9 = uVar8 * uVar4 + (int)lVar11; } if ((out_lowestPoint != NULL) && (*out_lowestPoint < iVar9)) { *out_lowestPoint = iVar9; } if ((iVar9 != 0) && (uVar8 = local_410[-1], uVar8 != *local_410)) { do { uVar5 = lego::image::Font_OutputChar (textWnd->font,local_414,iVar9, *(char *)(uVar8 + (int)textWnd->windowBuffer),1); local_414 += uVar5; uVar8 += 1; if (uVar8 == textWnd->bufferSize + 1) { uVar8 = 0; } } while (uVar8 != *local_410); } uVar5 = textWnd->linesCount; uVar4 += 1; } while (uVar4 < uVar5); } if (out_lowestPoint != NULL) { *out_lowestPoint = *out_lowestPoint + textWnd->font->fontHeight; } return 0; } BOOL __cdecl lego::front::TextWindow_UpdateOverlay(TextWindow *textWnd,float elapsed,int *out_lowestPoint) { float fVar1; uint uVar2; float fVar3; byte c; uint uVar4; int iVar5; int iVar6; undefined *puVar7; int iVar8; longlong lVar9; int *local_820; uint local_81c; int local_818; uint local_810; int *local_80c; BOOL local_804; int local_800 [255]; int aiStack1028 [2]; undefined local_3fc [1020]; iVar5 = 0; iVar8 = 0; iVar6 = 0; c = textWnd->secondBuffer[0]; local_810 = 0; local_804 = 0; local_800[0] = 0; local_81c = 1; if (c != 0) { local_80c = local_800 + 1; local_820 = (int *)0x1; puVar7 = local_3fc; do { if (c == 10) { *(int *)(puVar7 + -4) = iVar8; local_81c += 1; *local_80c = (int)local_820; local_80c = local_80c + 1; puVar7 = puVar7 + 4; iVar6 = 0; iVar8 = 0; } else { // int std::isspace(int c) if (std::globals::_pcharwidth < 2) { uVar4 = *(byte *)(std::globals::_pctype + c) & C1_SPACE; } else { uVar4 = std::_isctype((uint)c,C1_SPACE); } if (uVar4 != 0) { *(int *)(puVar7 + -4) = iVar8; iVar6 = 0; *local_80c = (int)local_820; } uVar4 = lego::image::Font_GetCharWidth(textWnd->font,c); iVar6 += uVar4; fVar3 = (float)(iVar8 + uVar4); fVar1 = (textWnd->windowSize).width; iVar8 = iVar8 + uVar4; if ((ushort)((ushort)(fVar3 < fVar1) << 8 | (ushort)(fVar3 == fVar1) << 0xe) == 0) { local_81c += 1; puVar7 = puVar7 + 4; local_80c = local_80c + 1; iVar8 = iVar6; } } iVar5 = local_810 + 1; local_820 = (int *)((int)local_820 + 1); c = textWnd->secondBuffer[local_810 + 1]; local_810 = iVar5; } while (c != 0); } aiStack1028[local_81c] = iVar8; local_800[local_81c] = iVar5; local_810 = 0; if (local_81c != 0) { local_820 = local_800; do { local_820 = local_820 + 1; lVar9 = __ftol((float10)(textWnd->windowSize).x); local_818 = (int)lVar9; if ((*(byte *)&textWnd->flags & 4) != 0) { lVar9 = __ftol(((float10)(textWnd->windowSize).width - (float10)(ulonglong)*(uint *)(local_3fc + local_810 * 4 + -4)) * (float10)0.5 ); local_818 += (int)lVar9; } uVar4 = textWnd->linesCapacity; if (uVar4 < local_81c) { if ((local_810 < local_81c - uVar4) || (local_81c <= local_810)) { if (local_81c <= uVar4) goto LAB_00485b9f; iVar8 = 0; } else { uVar2 = textWnd->font->fontHeight; lVar9 = __ftol((float10)(textWnd->windowSize).y); iVar8 = ((local_810 - local_81c) + uVar4) * uVar2 + (int)lVar9; local_804 = 1; } } else { LAB_00485b9f: uVar4 = textWnd->font->fontHeight; lVar9 = __ftol((float10)(textWnd->windowSize).y); iVar8 = uVar4 * local_810 + (int)lVar9; } if ((out_lowestPoint != NULL) && (*out_lowestPoint < iVar8)) { *out_lowestPoint = iVar8; } if (iVar8 != 0) { iVar6 = *local_820; for (iVar5 = local_800[local_810]; iVar5 != iVar6; iVar5 += 1) { uVar4 = lego::image::Font_OutputChar (textWnd->font,local_818,iVar8,textWnd->secondBuffer[iVar5],1); local_818 += uVar4; } } local_810 += 1; } while (local_810 < local_81c); } fVar1 = textWnd->displayDelay - elapsed; textWnd->displayDelay = fVar1; if (fVar1 < 0.0) { textWnd->flags = textWnd->flags & 0xfffffffd; } return local_804; } void __cdecl lego::front::TextWindow_Clear(TextWindow *textWnd) { uint uVar1; uint uVar2; int iVar3; undefined4 *puVar4; uVar2 = textWnd->bufferSize; puVar4 = (undefined4 *)textWnd->windowBuffer; for (uVar1 = uVar2 >> 2; uVar1 != 0; uVar1 -= 1) { *puVar4 = 0; puVar4 = puVar4 + 1; } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar4 = 0; puVar4 = (undefined4 *)((int)puVar4 + 1); } puVar4 = (undefined4 *)textWnd->secondBuffer; for (iVar3 = 0x100; iVar3 != 0; iVar3 += -1) { *puVar4 = 0; puVar4 = puVar4 + 1; } textWnd->linesCount = 0; textWnd->bufferEnd = 0; textWnd->flags = textWnd->flags & 0xfffffffe; return; } void __cdecl lego::front::TextWindow_GetInfo(TextWindow *textWnd,uint *out_linesCount,uint *out_linesCapacity) { *out_linesCount = textWnd->linesCount; *out_linesCapacity = textWnd->linesCapacity; return; } void __cdecl lego::input::Keys_Initialise(void) { int iVar1; Key_Globs *pKVar2; pKVar2 = &globs::keyGlobs; for (iVar1 = 0x100; iVar1 != 0; iVar1 += -1) { pKVar2->keyName[0] = NULL; pKVar2 = (Key_Globs *)(pKVar2->keyName + 1); } globs::keyGlobs.keyName[1] = "KEY_ESCAPE"; globs::keyGlobs.keyName[2] = "KEY_ONE"; globs::keyGlobs.keyName[3] = "KEY_TWO"; globs::keyGlobs.keyName[4] = "KEY_THREE"; globs::keyGlobs.keyName[5] = "KEY_FOUR"; globs::keyGlobs.keyName[6] = "KEY_FIVE"; globs::keyGlobs.keyName[7] = "KEY_SIX"; globs::keyGlobs.keyName[8] = "KEY_SEVEN"; globs::keyGlobs.keyName[9] = "KEY_EIGHT"; globs::keyGlobs.keyName[10] = "KEY_NINE"; globs::keyGlobs.keyName[11] = "KEY_ZERO"; globs::keyGlobs.keyName[12] = "KEY_MINUS"; globs::keyGlobs.keyName[13] = "KEY_EQUALS"; globs::keyGlobs.keyName[14] = "KEY_BACKSPACE"; globs::keyGlobs.keyName[15] = "KEY_TAB"; globs::keyGlobs.keyName[16] = "KEY_Q"; globs::keyGlobs.keyName[17] = "KEY_W"; globs::keyGlobs.keyName[18] = "KEY_E"; globs::keyGlobs.keyName[19] = "KEY_R"; globs::keyGlobs.keyName[20] = "KEY_T"; globs::keyGlobs.keyName[21] = "KEY_Y"; globs::keyGlobs.keyName[22] = "KEY_U"; globs::keyGlobs.keyName[23] = "KEY_I"; globs::keyGlobs.keyName[24] = "KEY_O"; globs::keyGlobs.keyName[25] = "KEY_P"; globs::keyGlobs.keyName[26] = "KEY_LEFTBRACE"; globs::keyGlobs.keyName[27] = "KEY_RIGHTBRACE"; globs::keyGlobs.keyName[28] = "KEY_RETURN"; globs::keyGlobs.keyName[29] = "KEY_LEFTCTRL"; globs::keyGlobs.keyName[30] = "KEY_A"; globs::keyGlobs.keyName[31] = "KEY_S"; globs::keyGlobs.keyName[32] = "KEY_D"; globs::keyGlobs.keyName[33] = "KEY_F"; globs::keyGlobs.keyName[34] = "KEY_G"; globs::keyGlobs.keyName[35] = "KEY_H"; globs::keyGlobs.keyName[36] = "KEY_J"; globs::keyGlobs.keyName[37] = "KEY_K"; globs::keyGlobs.keyName[38] = "KEY_L"; globs::keyGlobs.keyName[39] = "KEY_SEMICOLON"; globs::keyGlobs.keyName[40] = "KEY_AT"; globs::keyGlobs.keyName[41] = "KEY_RSINGLEQUOTE"; globs::keyGlobs.keyName[42] = "KEY_LEFTSHIFT"; globs::keyGlobs.keyName[43] = "KEY_HASH"; globs::keyGlobs.keyName[44] = "KEY_Z"; globs::keyGlobs.keyName[45] = "KEY_X"; globs::keyGlobs.keyName[46] = "KEY_C"; globs::keyGlobs.keyName[47] = "KEY_V"; globs::keyGlobs.keyName[48] = "KEY_B"; globs::keyGlobs.keyName[49] = "KEY_N"; globs::keyGlobs.keyName[50] = "KEY_M"; globs::keyGlobs.keyName[51] = "KEY_LEFTARROW"; globs::keyGlobs.keyName[52] = "KEY_RIGHTARROW"; globs::keyGlobs.keyName[53] = "KEY_QUESTIONMARK"; globs::keyGlobs.keyName[54] = "KEY_RIGHTSHIFT"; globs::keyGlobs.keyName[55] = "KEYPAD_ASTERISK"; globs::keyGlobs.keyName[56] = "KEY_ALT"; globs::keyGlobs.keyName[57] = "KEY_SPACE"; globs::keyGlobs.keyName[58] = "KEY_CAPLOCK"; globs::keyGlobs.keyName[59] = "KEY_F1"; globs::keyGlobs.keyName[60] = "KEY_F2"; globs::keyGlobs.keyName[61] = "KEY_F3"; globs::keyGlobs.keyName[62] = "KEY_F4"; globs::keyGlobs.keyName[63] = "KEY_F5"; globs::keyGlobs.keyName[64] = "KEY_F6"; globs::keyGlobs.keyName[65] = "KEY_F7"; globs::keyGlobs.keyName[66] = "KEY_F8"; globs::keyGlobs.keyName[67] = "KEY_F9"; globs::keyGlobs.keyName[68] = "KEY_F10"; globs::keyGlobs.keyName[69] = "KEYPAD_NUMLOCK"; globs::keyGlobs.keyName[70] = "KEY_SCROLLLOCK"; globs::keyGlobs.keyName[71] = "KEYPAD_7"; globs::keyGlobs.keyName[72] = "KEYPAD_8"; globs::keyGlobs.keyName[73] = "KEYPAD_9"; globs::keyGlobs.keyName[74] = "KEYPAD_MINUS"; globs::keyGlobs.keyName[75] = "KEYPAD_4"; globs::keyGlobs.keyName[76] = "KEYPAD_5"; globs::keyGlobs.keyName[77] = "KEYPAD_6"; globs::keyGlobs.keyName[78] = "KEYPAD_PLUS"; globs::keyGlobs.keyName[79] = "KEYPAD_1"; globs::keyGlobs.keyName[80] = "KEYPAD_2"; globs::keyGlobs.keyName[81] = "KEYPAD_3"; globs::keyGlobs.keyName[82] = "KEYPAD_0"; globs::keyGlobs.keyName[83] = "KEYPAD_DELETE"; globs::keyGlobs.keyName[86] = "KEY_BACKSLASH"; globs::keyGlobs.keyName[87] = "KEY_F11"; globs::keyGlobs.keyName[88] = "KEY_F12"; globs::keyGlobs.keyName[156] = "KEYPAD_ENTER"; globs::keyGlobs.keyName[157] = "KEY_RIGHTCTRL"; globs::keyGlobs.keyName[181] = "KEYPAD_FORWARDSLASH"; globs::keyGlobs.keyName[183] = "KEY_PRINTSCREEN"; globs::keyGlobs.keyName[184] = "KEY_ALTGR"; globs::keyGlobs.keyName[199] = "KEY_HOME"; globs::keyGlobs.keyName[200] = "KEY_CURSORUP"; globs::keyGlobs.keyName[201] = "KEY_PGUP"; globs::keyGlobs.keyName[203] = "KEY_CURSORLEFT"; globs::keyGlobs.keyName[205] = "KEY_CURSORRIGHT"; globs::keyGlobs.keyName[207] = "KEY_END"; globs::keyGlobs.keyName[208] = "KEY_CURSORDOWN"; globs::keyGlobs.keyName[209] = "KEY_PGDN"; globs::keyGlobs.keyName[210] = "KEY_INSERT"; globs::keyGlobs.keyName[211] = "KEY_DELETE"; return; } BOOL __cdecl lego::input::Key_Find(char *name,Keys8 *out_keyCode) { char *_Str1; int iVar1; Keys8 KVar2; Key_Globs *pKVar3; KVar2 = KEY__NONE; pKVar3 = &globs::keyGlobs; do { _Str1 = *(char **)((FileCheck_Globs *)pKVar3)->loadedList; if (_Str1 != NULL) { iVar1 = std::_stricmp(_Str1,name); if (iVar1 == 0) { *out_keyCode = KVar2; return 1; } } pKVar3 = (Key_Globs *)(((FileCheck_Globs *)pKVar3)->loadedList + 4); KVar2 += KEY_ESCAPE; } while (pKVar3 < &globs::checkGlobs); return 0; } void __cdecl lego::draw::Draw_Initialise(Area2F *window) { globs::drawGlobs.flags |= 1; Draw_SetClipWindow(window); return; } void __cdecl lego::draw::Draw_SetClipWindow(Area2F *window) { float fVar1; HRESULT HVar2; int iVar3; DDSURFACEDESC2 *pDVar4; DDSURFACEDESC2 desc; globs::drawGlobs.clipStart.x = 0.0; globs::drawGlobs.clipStart.y = 0.0; if (window != NULL) { if ((ushort)((ushort)(window->x < 0.0) << 8 | (ushort)(window->x == 0.0) << 0xe) == 0) { globs::drawGlobs.clipStart.x = window->x; } if ((ushort)((ushort)(window->y < 0.0) << 8 | (ushort)(window->y == 0.0) << 0xe) == 0) { globs::drawGlobs.clipStart.y = window->y; } } pDVar4 = &desc; for (iVar3 = 0x1f; iVar3 != 0; iVar3 += -1) { pDVar4->dwSize = 0; pDVar4 = (DDSURFACEDESC2 *)&pDVar4->dwFlags; } desc.dwSize = 0x7c; HVar2 = (*(code *)(globs::directDrawGlobs.bSurf)->lpVtbl->GetSurfaceDesc) (globs::directDrawGlobs.bSurf,&desc); if (HVar2 == 0) { globs::drawGlobs.clipEnd.x = (float)(ulonglong)desc.dwWidth; globs::drawGlobs.clipEnd.y = (float)(ulonglong)desc.dwHeight; if (window != NULL) { fVar1 = window->width + window->x; if (fVar1 < globs::drawGlobs.clipEnd.x) { globs::drawGlobs.clipEnd.x = fVar1; } fVar1 = window->height + window->y; if (fVar1 < globs::drawGlobs.clipEnd.y) { globs::drawGlobs.clipEnd.y = fVar1; return; } } } return; } void __cdecl lego::draw::Draw_GetClipWindow(Area2F *out_window) { out_window->x = globs::drawGlobs.clipStart.x; out_window->y = globs::drawGlobs.clipStart.y; out_window->width = globs::drawGlobs.clipEnd.x - globs::drawGlobs.clipStart.x; out_window->height = globs::drawGlobs.clipEnd.y - globs::drawGlobs.clipStart.y; return; } void __cdecl lego::draw::Draw_LineListEx (Point2F *fromList,Point2F *toList,uint count,float r,float g,float b,DrawEffect effect) { IDirectDrawSurface4 *surface; BOOL BVar1; uint uVar2; int y2; int x2; int y1; int iVar3; float *pfVar4; longlong lVar5; uint colour; surface = globs::directDrawGlobs.bSurf; BVar1 = Draw_LockSurface(globs::directDrawGlobs.bSurf,effect); if (BVar1 != 0) { uVar2 = Draw_GetColour(r,g,b); if (count != 0) { pfVar4 = &fromList->y; iVar3 = (int)toList - (int)fromList; do { colour = uVar2; lVar5 = __ftol((float10)*(float *)(iVar3 + (int)pfVar4)); y2 = (int)lVar5; lVar5 = __ftol((float10)toList->x); x2 = (int)lVar5; lVar5 = __ftol((float10)*pfVar4); y1 = (int)lVar5; lVar5 = __ftol((float10)pfVar4[-1]); Draw_LineActual((int)lVar5,y1,x2,y2,colour); pfVar4 = pfVar4 + 2; toList = toList + 1; count -= 1; } while (count != 0); } Draw_UnlockSurface(surface); } return; } void __cdecl lego::draw::Draw_RectListEx(Area2F *rectList,uint count,float r,float g,float b,DrawEffect effect) { int iVar1; IDirectDrawSurface4 *surface; BOOL BVar2; uint uVar3; int iVar4; float10 extraout_ST0; longlong lVar5; longlong lVar6; longlong lVar7; float local_18; float local_10; float local_c; surface = globs::directDrawGlobs.bSurf; BVar2 = Draw_LockSurface(globs::directDrawGlobs.bSurf,effect); if (BVar2 != 0) { uVar3 = Draw_GetColour(r,g,b); if (count != 0) { effect = (DrawEffect)rectList; b = (float)count; do { local_10 = *(float *)effect; local_c = *(float *)(effect + 4); local_18 = local_10 + *(float *)(effect + 8); if (local_10 < globs::drawGlobs.clipStart.x) { local_10 = globs::drawGlobs.clipStart.x; } if (local_c < globs::drawGlobs.clipStart.y) { local_c = globs::drawGlobs.clipStart.y; } if (globs::drawGlobs.clipEnd.x <= local_18) { local_18 = globs::drawGlobs.clipEnd.x - 1.0; } lVar5 = __ftol((float10)local_18); lVar6 = __ftol(extraout_ST0); lVar7 = __ftol((float10)local_c); iVar4 = (int)lVar7; if (iVar4 < (int)lVar6) { lVar7 = __ftol((float10)local_10); iVar1 = (int)lVar7; do { for (; iVar1 < (int)lVar5; iVar1 = iVar1 + 1) { (*globs::drawGlobs.drawPixelFunc)(iVar1,iVar4,uVar3); } iVar4 += 1; iVar1 = (int)lVar7; } while (iVar4 < (int)lVar6); } effect += 0x10; b = (float)((int)b + -1); } while (b != 0.0); } Draw_UnlockSurface(surface); } return; } void __cdecl lego::draw::Draw_RectList2Ex(Draw_Rect *rectList,uint count,DrawEffect effect) { int iVar1; IDirectDrawSurface4 *surface; BOOL BVar2; uint uVar3; float *pfVar4; int iVar5; float10 extraout_ST0; longlong lVar6; longlong lVar7; longlong lVar8; float local_18; float local_10; float local_c; surface = globs::directDrawGlobs.bSurf; BVar2 = Draw_LockSurface(globs::directDrawGlobs.bSurf,effect); if (BVar2 != 0) { if (count != 0) { pfVar4 = &rectList->g; rectList = (Draw_Rect *)count; do { local_10 = pfVar4[-5]; local_c = pfVar4[-4]; local_18 = pfVar4[-3]; uVar3 = Draw_GetColour(pfVar4[-1],*pfVar4,pfVar4[1]); local_18 = local_10 + local_18; if (local_10 < globs::drawGlobs.clipStart.x) { local_10 = globs::drawGlobs.clipStart.x; } if (local_c < globs::drawGlobs.clipStart.y) { local_c = globs::drawGlobs.clipStart.y; } if (globs::drawGlobs.clipEnd.x <= local_18) { local_18 = globs::drawGlobs.clipEnd.x - 1.0; } lVar6 = __ftol((float10)local_18); lVar7 = __ftol(extraout_ST0); lVar8 = __ftol((float10)local_c); iVar5 = (int)lVar8; if (iVar5 < (int)lVar7) { lVar8 = __ftol((float10)local_10); iVar1 = (int)lVar8; do { for (; iVar1 < (int)lVar6; iVar1 = iVar1 + 1) { (*globs::drawGlobs.drawPixelFunc)(iVar1,iVar5,uVar3); } iVar5 += 1; iVar1 = (int)lVar8; } while (iVar5 < (int)lVar7); } pfVar4 = pfVar4 + 7; rectList = (Draw_Rect *)((int)&rectList[-1].b + 3); } while (rectList != NULL); } Draw_UnlockSurface(surface); } return; } float10 __cdecl lego::draw::Draw_DotCircle (Point2F *pos,uint radius,uint dots,float r,float g,float b,DrawEffect effect) { IDirectDrawSurface4 *surface; BOOL BVar1; uint uVar2; uint uVar3; float10 extraout_ST0; float10 fVar4; unkbyte10 extraout_ST0_00; float10 extraout_ST0_01; ulonglong uVar5; ulonglong uVar6; surface = globs::directDrawGlobs.bSurf; BVar1 = Draw_LockSurface(globs::directDrawGlobs.bSurf,effect); fVar4 = extraout_ST0; if (BVar1 != 0) { uVar2 = Draw_GetColour(r,g,b); uVar3 = 0; if (dots != 0) { do { fVar4 = (float10)fsin((float10)(ulonglong)uVar3 * (float10)(6.283185 / (float)(ulonglong)dots)); uVar5 = __ftol(fVar4 * (float10)(ulonglong)radius + (float10)pos->x); fVar4 = (float10)fcos(extraout_ST0_00); uVar6 = __ftol(fVar4 * (float10)(ulonglong)radius + (float10)pos->y); if ((((globs::drawGlobs.clipStart.x <= (float)(uVar5 & 0xffffffff)) && (globs::drawGlobs.clipStart.y <= (float)(uVar6 & 0xffffffff))) && ((float)(uVar5 & 0xffffffff) < globs::drawGlobs.clipEnd.x)) && ((float)(uVar6 & 0xffffffff) < globs::drawGlobs.clipEnd.y)) { (*globs::drawGlobs.drawPixelFunc)((int)uVar5,(int)uVar6,uVar2); } uVar3 += 1; } while (uVar3 < dots); } Draw_UnlockSurface(surface); fVar4 = extraout_ST0_01; } return fVar4; } uint __cdecl lego::draw::Draw_GetColour(float r,float g,float b) { char cVar1; char cVar2; byte bVar3; uint uVar4; longlong lVar5; longlong lVar6; longlong lVar7; uVar4 = 0; if (globs::drawGlobs.bpp != 8) { lVar5 = __ftol((float10)r * (float10)255.0); cVar1 = (char)globs::drawGlobs.redBits; cVar2 = (char)globs::drawGlobs.greenBits; bVar3 = (byte)globs::drawGlobs.blueBits; lVar6 = __ftol((float10)g * (float10)255.0); lVar7 = __ftol((float10)b * (float10)255.0); uVar4 = ((uint)lVar5 >> (8U - cVar1 & 0x1f)) << (cVar2 + bVar3 & 0x1f) | ((uint)lVar6 >> (8U - cVar2 & 0x1f)) << (bVar3 & 0x1f) | (uint)lVar7 >> (8 - bVar3 & 0x1f); } return uVar4; } BOOL __cdecl lego::draw::Draw_LockSurface(IDirectDrawSurface4 *surface,DrawEffect effect) { HRESULT HVar1; uint uVar2; BOOL BVar3; int iVar4; uint uVar5; DDSURFACEDESC2 *pDVar6; DDSURFACEDESC2 desc; pDVar6 = &desc; for (iVar4 = 0x1f; iVar4 != 0; iVar4 += -1) { pDVar6->dwSize = 0; pDVar6 = (DDSURFACEDESC2 *)&pDVar6->dwFlags; } desc.dwSize = 0x7c; HVar1 = (*surface->lpVtbl->Lock)(surface,NULL,&desc,1,NULL); if (HVar1 == 0) { globs::drawGlobs.buffer = desc.lpSurface; uVar5 = 0; globs::drawGlobs.pitch = desc.lPitch; globs::drawGlobs.redMask = desc.ddpfPixelFormat.dwRBitMask; globs::drawGlobs.greenMask = desc.ddpfPixelFormat.dwGBitMask; globs::drawGlobs.blueMask = desc.ddpfPixelFormat.dwBBitMask; globs::drawGlobs.bpp = desc.ddpfPixelFormat.dwRGBBitCount; globs::drawGlobs.blueBits = 0; globs::drawGlobs.greenBits = 0; globs::drawGlobs.redBits = 0; if (desc.ddpfPixelFormat.dwRGBBitCount != 0) { do { uVar2 = 1 << ((byte)uVar5 & 0x1f); if ((uVar2 & desc.ddpfPixelFormat.dwRBitMask) != 0) { globs::drawGlobs.redBits += 1; } if ((uVar2 & desc.ddpfPixelFormat.dwGBitMask) != 0) { globs::drawGlobs.greenBits += 1; } if ((uVar2 & desc.ddpfPixelFormat.dwBBitMask) != 0) { globs::drawGlobs.blueBits += 1; } uVar5 += 1; } while (uVar5 < desc.ddpfPixelFormat.dwRGBBitCount); } BVar3 = Draw_SetDrawPixelFunc(effect); if (BVar3 != 0) { return TRUE; } Draw_UnlockSurface(surface); } return 0; } void __cdecl lego::draw::Draw_UnlockSurface(IDirectDrawSurface4 *surface) { (*surface->lpVtbl->Unlock)(surface,NULL); globs::drawGlobs.drawPixelFunc = NULL; globs::drawGlobs.buffer = NULL; globs::drawGlobs.pitch = 0; globs::drawGlobs.bpp = 0; globs::drawGlobs.redMask = 0; globs::drawGlobs.greenMask = 0; globs::drawGlobs.blueMask = 0; return; } BOOL __cdecl lego::draw::Draw_SetDrawPixelFunc(DrawEffect effect) { if (globs::drawGlobs.bpp == 8) { globs::drawGlobs.drawPixelFunc = Draw_Pixel8; return DrawEffect_XOR; } if (globs::drawGlobs.bpp != 0x10) { if (globs::drawGlobs.bpp == 0x18) { globs::drawGlobs.drawPixelFunc = Draw_Pixel24; return DrawEffect_XOR; } if (globs::drawGlobs.bpp == 0x20) { globs::drawGlobs.drawPixelFunc = Draw_Pixel32; return DrawEffect_XOR; } globs::drawGlobs.drawPixelFunc = NULL; return DrawEffect_None; } if (effect == DrawEffect_XOR) { globs::drawGlobs.drawPixelFunc = Draw_Pixel16XOR; return effect; } if (effect == DrawEffect_HalfTrans) { globs::drawGlobs.drawPixelFunc = Draw_Pixel16HalfTrans; return DrawEffect_XOR; } globs::drawGlobs.drawPixelFunc = Draw_Pixel16; return DrawEffect_XOR; } void __cdecl lego::draw::Draw_LineActual(int x1,int y1,int x2,int y2,uint colour) { bool bVar1; uint uVar2; int iVar3; int iVar4; int iVar5; int iVar6; int iVar7; uint uVar8; int iVar9; uint local_10; int local_4; iVar4 = y1; iVar3 = x1; uVar8 = x2 - x1 >> 0x1f; iVar7 = (x2 - x1 ^ uVar8) - uVar8; uVar8 = y2 - y1 >> 0x1f; iVar5 = (y2 - y1 ^ uVar8) - uVar8; bVar1 = iVar7 < iVar5; if (bVar1) { iVar6 = iVar7 - iVar5; iVar9 = iVar7 * 2 - iVar5; local_4 = iVar5; } else { iVar6 = iVar5 - iVar7; iVar9 = iVar5 * 2 - iVar7; local_4 = iVar7; iVar7 = iVar5; } local_10 = 1; y1 = 1; x1 = ZEXT14(!bVar1); local_4 += 1; uVar8 = (uint)bVar1; if (x2 < iVar3) { y1 = -1; x1 = -x1; } if (y2 < iVar4) { uVar8 = -uVar8; local_10 = 0xffffffff; } x2 = iVar3; y2 = iVar4; if (0 < local_4) { do { if ((((globs::drawGlobs.clipStart.x <= (float)x2) && (globs::drawGlobs.clipStart.y <= (float)y2)) && ((float)x2 < globs::drawGlobs.clipEnd.x)) && ((float)y2 < globs::drawGlobs.clipEnd.y)) { (*globs::drawGlobs.drawPixelFunc)(x2,y2,colour); } uVar2 = local_10; iVar3 = y1; iVar4 = iVar6; if (iVar9 < 0) { uVar2 = uVar8; iVar3 = x1; iVar4 = iVar7; } x2 += iVar3; iVar9 += iVar4 * 2; y2 += uVar2; local_4 += -1; } while (local_4 != 0); } return; } // 8bit Pixel Routine void __cdecl lego::draw::Draw_Pixel8(int x,int y,uint value) { *(undefined *)(y * globs::drawGlobs.pitch + x + (int)globs::drawGlobs.buffer) = (undefined)value; return; } // 16bit (565) Pixel Routine (normal) void __cdecl lego::draw::Draw_Pixel16(int x,int y,uint value) { *(undefined2 *)((int)globs::drawGlobs.buffer + x * 2 + y * globs::drawGlobs.pitch) = (undefined2)value; return; } // 16bit (565) Pixel Routine (XOR) void __cdecl lego::draw::Draw_Pixel16XOR(int x,int y,uint value) { ushort *puVar1; puVar1 = (ushort *)((int)globs::drawGlobs.buffer + x * 2 + y * globs::drawGlobs.pitch); *puVar1 = *puVar1 ^ (ushort)value; return; } // 16bit (565) Pixel Routine (HalfTrans) void __cdecl lego::draw::Draw_Pixel16HalfTrans(int x,int y,uint value) { ushort *puVar1; ushort uVar2; ushort uVar3; puVar1 = (ushort *)((int)globs::drawGlobs.buffer + x * 2 + y * globs::drawGlobs.pitch); uVar2 = *puVar1; uVar3 = (ushort)value; *puVar1 = (((ushort)globs::drawGlobs.greenMask & uVar2) >> 1 & 0x7fe0) + (((ushort)globs::drawGlobs.greenMask & uVar3) >> 1 & 0x7fe0) & (ushort)globs::drawGlobs.greenMask | ((uVar3 & (ushort)globs::drawGlobs.blueMask) >> 1) + ((uVar2 & (ushort)globs::drawGlobs.blueMask) >> 1) & (ushort)globs::drawGlobs.blueMask | (uVar3 >> 1 & 0x7800) + (uVar2 >> 1 & 0x7800) & (ushort)globs::drawGlobs.redMask; return; } // 24bit Pixel Routine void __cdecl lego::draw::Draw_Pixel24(int x,int y,uint value) { uint *puVar1; puVar1 = (uint *)((int)globs::drawGlobs.buffer + x * 3 + y * globs::drawGlobs.pitch); *puVar1 = value << 8 | *puVar1 & 0xff; return; } // 32bit Pixel Routine void __cdecl lego::draw::Draw_Pixel32(int x,int y,uint value) { *(uint *)((int)globs::drawGlobs.buffer + x * 4 + y * globs::drawGlobs.pitch) = value; return; } Lws_Info * __cdecl lego::gfx::Lws_Parse(char *fname,BOOL looping) { char *pcVar1; int iVar2; float fVar3; char cVar4; byte bVar5; ushort uVar6; File *file; byte *pbVar7; int iVar8; byte *pbVar9; char *pcVar10; Lws_Node *pLVar11; int iVar12; Lws_KeyInfo *pLVar13; float *pfVar14; ushort *puVar15; uint uVar16; uint uVar17; Lws_Node *pLVar18; Lws_Info *scene; char *pcVar19; undefined4 *puVar20; Lws_Info *pLVar21; undefined4 *puVar22; bool bVar23; float10 fVar24; void *local_968; uint local_964; uint local_960; Lws_Node *local_958; byte *local_954; byte *local_950; char *local_94c; char *local_948; char *local_944; char *local_940; char *local_93c; char *local_938; char *local_934; char *local_930; char local_904 [260]; char local_800 [1024]; char local_400 [1024]; scene = NULL; std::sprintf(local_904,"%s.%s",fname,"lws"); file = io::File_Open(local_904,"r"); if (file != NULL) { io::File_GetLine(local_800,0x400,file); uVar16 = 0xffffffff; pcVar19 = local_800; do { if (uVar16 == 0) break; uVar16 -= 1; cVar4 = *pcVar19; pcVar19 = pcVar19 + 1; } while (cVar4 != '\0'); pbVar9 = (byte *)(local_800 + (~uVar16 & 0xffff)); io::File_GetLine((char *)pbVar9,0x400 - (~uVar16 & 0xffff),file); pcVar19 = "LWSC"; pbVar7 = (byte *)local_800; do { bVar5 = *pbVar7; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_00486d70: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00486d75; } if (bVar5 == 0) break; bVar5 = pbVar7[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_00486d70; pbVar7 = pbVar7 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_00486d75: if (iVar8 == 0) { pcVar19 = "1"; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_00486da8: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00486dad; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_00486da8; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_00486dad: if (iVar8 == 0) { local_964 = 0; local_960 = 0; pLVar18 = NULL; pcVar19 = local_904; pcVar10 = local_904; cVar4 = local_904[0]; while (cVar4 != '\0') { if (cVar4 == '\\') { pcVar19 = pcVar10; } pcVar1 = pcVar10 + 1; pcVar10 = pcVar10 + 1; cVar4 = *pcVar1; } pcVar19[pcVar19 != local_904] = '\0'; scene = (Lws_Info *)io::Mem_Alloc(0x38); pLVar21 = scene; for (iVar8 = 0xe; iVar8 != 0; iVar8 += -1) { *(undefined4 *)pLVar21 = 0; pLVar21 = (Lws_Info *)&pLVar21->fps; } if (local_904[0] == '\0') { scene->filePath = NULL; } else { pcVar19 = util::Util_StrCpy(local_904); scene->filePath = pcVar19; } scene->nodeListSize = 10; scene->referenceCount = 1; if (looping != 0) { scene->flags = scene->flags | 1; } pLVar11 = (Lws_Node *)io::Mem_Alloc(0x208); scene->nodeList = pLVar11; local_968 = io::Mem_Alloc((uint)scene->nodeListSize << 1); pcVar19 = io::File_GetLine(local_800,0x400,file); while (pcVar19 != NULL) { uVar16 = 0xffffffff; pcVar19 = local_800; do { pcVar10 = pcVar19; if (uVar16 == 0) break; uVar16 -= 1; pcVar10 = pcVar19 + 1; cVar4 = *pcVar19; pcVar19 = pcVar10; } while (cVar4 != '\0'); uVar16 = ~uVar16; puVar20 = (undefined4 *)(pcVar10 + -uVar16); puVar22 = (undefined4 *)local_400; for (uVar17 = uVar16 >> 2; uVar17 != 0; uVar17 -= 1) { *puVar22 = *puVar20; puVar20 = puVar20 + 1; puVar22 = puVar22 + 1; } for (uVar16 &= 3; uVar16 != 0; uVar16 -= 1) { *(undefined *)puVar22 = *(undefined *)puVar20; puVar20 = (undefined4 *)((int)puVar20 + 1); puVar22 = (undefined4 *)((int)puVar22 + 1); } iVar8 = util::Util_WSTokenise(local_400,(char **)&local_954); if (iVar8 != 0) { if (pLVar18 == NULL) { pcVar19 = "FirstFrame"; pbVar9 = local_954; do { bVar5 = *pcVar19; bVar23 = bVar5 < *pbVar9; if (bVar5 != *pbVar9) { LAB_00486f0b: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00486f10; } if (bVar5 == 0) break; bVar5 = ((byte *)pcVar19)[1]; bVar23 = bVar5 < pbVar9[1]; if (bVar5 != pbVar9[1]) goto LAB_00486f0b; pcVar19 = (char *)((byte *)pcVar19 + 2); pbVar9 = pbVar9 + 2; } while (bVar5 != 0); iVar8 = 0; LAB_00486f10: if (iVar8 == 0) { iVar8 = std::atoi((char *)local_950); scene->firstFrame = (ushort)iVar8; } pcVar19 = "LastFrame"; pbVar9 = local_954; do { bVar5 = *pcVar19; bVar23 = bVar5 < *pbVar9; if (bVar5 != *pbVar9) { LAB_00486f55: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00486f5a; } if (bVar5 == 0) break; bVar5 = ((byte *)pcVar19)[1]; bVar23 = bVar5 < pbVar9[1]; if (bVar5 != pbVar9[1]) goto LAB_00486f55; pcVar19 = (char *)((byte *)pcVar19 + 2); pbVar9 = pbVar9 + 2; } while (bVar5 != 0); iVar8 = 0; LAB_00486f5a: if (iVar8 == 0) { iVar8 = std::atoi((char *)local_950); scene->lastFrame = (ushort)iVar8; } if (scene->lastFrame == 0) { scene->lastFrame = 1; } pcVar19 = "FramesPerSecond"; pbVar9 = local_954; do { bVar5 = *pcVar19; bVar23 = bVar5 < *pbVar9; if (bVar5 != *pbVar9) { LAB_00486fb3: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00486fb8; } if (bVar5 == 0) break; bVar5 = ((byte *)pcVar19)[1]; bVar23 = bVar5 < pbVar9[1]; if (bVar5 != pbVar9[1]) goto LAB_00486fb3; pcVar19 = (char *)((byte *)pcVar19 + 2); pbVar9 = pbVar9 + 2; } while (bVar5 != 0); iVar8 = 0; LAB_00486fb8: if (iVar8 == 0) { fVar24 = std::atof((char *)local_950); scene->fps = (float)fVar24; } pcVar19 = "AddNullObject"; pbVar9 = local_954; do { bVar5 = *pcVar19; bVar23 = bVar5 < *pbVar9; if (bVar5 != *pbVar9) { LAB_00486fff: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00487004; } if (bVar5 == 0) break; bVar5 = ((byte *)pcVar19)[1]; bVar23 = bVar5 < pbVar9[1]; if (bVar5 != pbVar9[1]) goto LAB_00486fff; pcVar19 = (char *)((byte *)pcVar19 + 2); pbVar9 = pbVar9 + 2; } while (bVar5 != 0); iVar8 = 0; LAB_00487004: if (iVar8 != 0) { pcVar19 = "LoadObject"; pbVar9 = local_954; do { bVar5 = *pcVar19; bVar23 = bVar5 < *pbVar9; if (bVar5 != *pbVar9) { LAB_00487033: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00487038; } if (bVar5 == 0) break; bVar5 = ((byte *)pcVar19)[1]; bVar23 = bVar5 < pbVar9[1]; if (bVar5 != pbVar9[1]) goto LAB_00487033; pcVar19 = (char *)((byte *)pcVar19 + 2); pbVar9 = pbVar9 + 2; } while (bVar5 != 0); iVar8 = 0; LAB_00487038: if (iVar8 != 0) goto LAB_004877aa; } if (scene->nodeCount == scene->nodeListSize) { uVar6 = scene->nodeListSize + 10; scene->nodeListSize = uVar6; pLVar18 = (Lws_Node *)io::Mem_ReAlloc(scene->nodeList,(uint)uVar6 * 0x34); scene->nodeList = pLVar18; local_968 = io::Mem_ReAlloc(local_968,(uint)scene->nodeListSize << 1); } *(undefined2 *)((int)local_968 + (uint)scene->nodeCount * 2) = 0; pLVar18 = scene->nodeList + scene->nodeCount; local_958 = pLVar18; pLVar11 = pLVar18; for (iVar8 = 0xd; iVar8 != 0; iVar8 += -1) { pLVar11->name = NULL; pLVar11 = (Lws_Node *)&pLVar11->reference; } pcVar19 = "AddNullObject"; pbVar9 = local_954; do { bVar5 = *pcVar19; bVar23 = bVar5 < *pbVar9; if (bVar5 != *pbVar9) { LAB_004870eb: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_004870f0; } if (bVar5 == 0) break; bVar5 = ((byte *)pcVar19)[1]; bVar23 = bVar5 < pbVar9[1]; if (bVar5 != pbVar9[1]) goto LAB_004870eb; pcVar19 = (char *)((byte *)pcVar19 + 2); pbVar9 = pbVar9 + 2; } while (bVar5 != 0); iVar8 = 0; LAB_004870f0: if (iVar8 == 0) { pLVar18->flags = pLVar18->flags | 1; pcVar19 = util::Util_StrCpy(local_800 + 0xe); pLVar18->name = pcVar19; iVar8 = std::_strnicmp(pcVar19,"SFX",3); if ((iVar8 == 0) && (iVar8 = std::_strnicmp(pLVar18->name + 3,",",1), iVar8 == 0)) { pLVar18->flags = pLVar18->flags | 2; scene->triggerCount = scene->triggerCount + 1; } } else { uVar16 = 0xffffffff; pcVar19 = local_800; do { pcVar10 = pcVar19; if (uVar16 == 0) break; uVar16 -= 1; pcVar10 = pcVar19 + 1; cVar4 = *pcVar19; pcVar19 = pcVar10; } while (cVar4 != '\0'); uVar16 = ~uVar16; puVar20 = (undefined4 *)(pcVar10 + -uVar16); puVar22 = (undefined4 *)local_400; for (uVar17 = uVar16 >> 2; uVar17 != 0; uVar17 -= 1) { *puVar22 = *puVar20; puVar20 = puVar20 + 1; puVar22 = puVar22 + 1; } for (uVar16 &= 3; uVar16 != 0; uVar16 -= 1) { *(undefined *)puVar22 = *(undefined *)puVar20; puVar20 = (undefined4 *)((int)puVar20 + 1); puVar22 = (undefined4 *)((int)puVar22 + 1); } iVar8 = util::Util_Tokenise(local_800,(char **)&local_954,"\\"); pcVar19 = util::Util_StrIStr((char *)(&local_958)[iVar8],".lwo"); if (pcVar19 != NULL) { *pcVar19 = '\0'; } pcVar19 = util::Util_StrCpy((char *)(&local_958)[iVar8]); pLVar18->name = pcVar19; } iVar8 = scene->nodeCount - 1; if (-1 < iVar8) { pLVar11 = scene->nodeList + iVar8; do { bVar5 = pLVar11->flags & 1; if (((bVar5 != 0) && ((pLVar18->flags & 1) != 0)) || ((bVar5 == 0 && ((pLVar18->flags & 1) == 0)))) { pbVar9 = (byte *)pLVar11->name; pbVar7 = (byte *)pLVar18->name; do { bVar5 = *pbVar7; bVar23 = bVar5 < *pbVar9; if (bVar5 != *pbVar9) { LAB_00487222: iVar12 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00487227; } if (bVar5 == 0) break; bVar5 = pbVar7[1]; bVar23 = bVar5 < pbVar9[1]; if (bVar5 != pbVar9[1]) goto LAB_00487222; pbVar7 = pbVar7 + 2; pbVar9 = pbVar9 + 2; } while (bVar5 != 0); iVar12 = 0; LAB_00487227: pLVar18 = local_958; if (iVar12 == 0) { local_958->reference = scene->nodeList[iVar8].reference + 1; break; } } iVar8 += -1; pLVar11 = pLVar11 + -1; } while (-1 < iVar8); } } else { if (local_964 == 0) { if (local_960 == 0) { pcVar19 = "ObjectMotion"; pbVar9 = local_954; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_00487586: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_0048758b; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_00487586; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_0048758b: if (iVar8 == 0) { local_964 = 1; } else { pcVar19 = "ObjDissolve"; pbVar9 = local_954; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_004875c7: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_004875cc; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_004875c7; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_004875cc: if (iVar8 == 0) { pcVar19 = "(envelope)"; pbVar9 = local_950; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_00487603: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00487608; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_00487603; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_00487608: if (iVar8 == 0) { local_960 = 1; } else { fVar24 = std::atof((char *)local_950); globs::lwsGlobs.staticDissolveLevel[globs::lwsGlobs.staticDissolveCount] = (float)fVar24; pLVar18->dissolveLevel = globs::lwsGlobs.staticDissolveLevel + globs::lwsGlobs.staticDissolveCount; globs::lwsGlobs.staticDissolveCount += 1; pLVar18->dissolveLevel = NULL; } } else { pcVar19 = "ParentObject"; pbVar9 = local_954; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_00487680: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00487685; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_00487680; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_00487685: if (iVar8 == 0) { iVar8 = std::atoi((char *)local_950); *(short *)((int)local_968 + (uint)scene->nodeCount * 2) = (short)iVar8; } else { pcVar19 = "PivotPoint"; pbVar9 = local_954; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_004876d8: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_004876dd; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_004876d8; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_004876dd: if (iVar8 == 0) { fVar24 = std::atof((char *)local_950); (pLVar18->pivotVector).x = (float)-fVar24; fVar24 = std::atof(local_94c); (pLVar18->pivotVector).y = (float)-fVar24; fVar24 = std::atof(local_948); (pLVar18->pivotVector).z = (float)-fVar24; } else { pcVar19 = "UnseenByCamera"; pbVar9 = local_954; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_00487747: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_0048774c; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_00487747; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_0048774c: if ((iVar8 == 0) && (iVar8 = std::atoi((char *)local_950), iVar8 == 1)) { pLVar18->flags = pLVar18->flags | 4; } else { pcVar19 = "ShadowOptions"; pbVar9 = local_954; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_00487797: iVar8 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_0048779c; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_00487797; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); iVar8 = 0; LAB_0048779c: if (iVar8 == 0) { pLVar18 = NULL; scene->nodeCount = scene->nodeCount + 1; } } } } } } } else { if (local_960 != 1) { if (local_960 == 2) { uVar16 = std::atoi((char *)local_950); pLVar18->dissolveCount = (ushort)uVar16; pfVar14 = (float *)io::Mem_Alloc((uVar16 & 0xffff) * 4 + 4); pLVar18->dissolveLevel = pfVar14; puVar15 = (ushort *)io::Mem_Alloc((uint)pLVar18->dissolveCount * 2 + 2); pLVar18->dissolveFrame = puVar15; } else { uVar16 = (int)(local_960 - 3) / 2; if ((ushort)uVar16 < pLVar18->dissolveCount) { uVar17 = (int)local_960 >> 0x1f; if (((local_960 ^ uVar17) - uVar17 & 1 ^ uVar17) == uVar17) { iVar8 = std::atoi((char *)local_950); pLVar18->dissolveFrame[uVar16 & 0xffff] = (ushort)iVar8; } else { uVar16 &= 0xffff; fVar24 = std::atof((char *)local_950); pLVar18->dissolveLevel[uVar16] = (float)fVar24; if (pLVar18->dissolveLevel[uVar16] < 0.0) { pLVar18->dissolveLevel[uVar16] = 0.0; } fVar3 = pLVar18->dissolveLevel[uVar16]; if ((ushort)((ushort)(fVar3 < 1.0) << 8 | (ushort)(fVar3 == 1.0) << 0xe) == 0) { pLVar18->dissolveLevel[uVar16] = 1.0; } pLVar18->dissolveLevel[uVar16] = 1.0 - pLVar18->dissolveLevel[uVar16]; } } } } pcVar19 = "EndBehavior"; pbVar9 = local_954; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_00487541: uVar16 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_00487546; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_00487541; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); uVar16 = 0; LAB_00487546: local_960 = local_960 + 1; if (uVar16 == 0) { local_960 = uVar16; } } } else { if (local_964 != 1) { if (local_964 == 2) { uVar16 = std::atoi((char *)local_950); pLVar18->keyCount = (ushort)uVar16; pLVar13 = (Lws_KeyInfo *)io::Mem_Alloc(((uVar16 & 0xffff) + 1) * 0x28); pLVar18->keyList = pLVar13; } else { uVar16 = (int)(local_964 - 3) / 2; if ((ushort)uVar16 < pLVar18->keyCount) { uVar17 = (int)local_964 >> 0x1f; if (((local_964 ^ uVar17) - uVar17 & 1 ^ uVar17) == uVar17) { iVar8 = std::atoi((char *)local_950); pLVar18->keyList[uVar16 & 0xffff].frame = (ushort)iVar8; } else { uVar16 &= 0xffff; fVar24 = std::atof((char *)local_950); pLVar18->keyList[uVar16].position.x = (float)fVar24; fVar24 = std::atof(local_94c); pLVar18->keyList[uVar16].position.y = (float)fVar24; fVar24 = std::atof(local_948); pLVar18->keyList[uVar16].position.z = (float)fVar24; fVar24 = std::atof(local_944); pLVar18->keyList[uVar16].hpb.x = (float)(fVar24 * (float10)0.005555556 * (float10)3.141593); fVar24 = std::atof(local_940); pLVar18->keyList[uVar16].hpb.y = (float)(fVar24 * (float10)0.005555556 * (float10)3.141593); fVar24 = std::atof(local_93c); pLVar18->keyList[uVar16].hpb.z = (float)(fVar24 * (float10)0.005555556 * (float10)3.141593); fVar24 = std::atof(local_938); pLVar18->keyList[uVar16].scale.x = (float)fVar24; fVar24 = std::atof(local_934); pLVar18->keyList[uVar16].scale.y = (float)fVar24; fVar24 = std::atof(local_930); pLVar18->keyList[uVar16].scale.z = (float)fVar24; } } } } pcVar19 = "EndBehavior"; pbVar9 = local_954; do { bVar5 = *pbVar9; bVar23 = bVar5 < (byte)*pcVar19; if (bVar5 != *pcVar19) { LAB_004873f6: uVar16 = (1 - (uint)bVar23) - (uint)(bVar23 != 0); goto LAB_004873fb; } if (bVar5 == 0) break; bVar5 = pbVar9[1]; bVar23 = bVar5 < ((byte *)pcVar19)[1]; if (bVar5 != ((byte *)pcVar19)[1]) goto LAB_004873f6; pbVar9 = pbVar9 + 2; pcVar19 = (char *)((byte *)pcVar19 + 2); } while (bVar5 != 0); uVar16 = 0; LAB_004873fb: local_964 = local_964 + 1; if (uVar16 == 0) { local_964 = uVar16; } } } } LAB_004877aa: pcVar19 = io::File_GetLine(local_800,0x400,file); } iVar8 = 0; if (scene->nodeCount != 0) { iVar12 = 0; do { pbVar9 = scene->nodeList->padding1 + iVar12 + -9; if (*(ushort *)(pbVar9 + 0x24) != 1) { iVar2 = *(int *)(pbVar9 + 0x18) + (uint)*(ushort *)(pbVar9 + 0x24) * 0x28; if (*(ushort *)(iVar2 + -4) < scene->lastFrame) { *(ushort *)(iVar2 + 0x24) = scene->lastFrame; puVar20 = (undefined4 *) (*(int *)(pbVar9 + 0x18) + (uint)*(ushort *)(pbVar9 + 0x24) * 0x28); *puVar20 = puVar20[-10]; puVar20[1] = puVar20[-9]; puVar20[2] = puVar20[-8]; iVar2 = *(int *)(pbVar9 + 0x18) + (uint)*(ushort *)(pbVar9 + 0x24) * 0x28; *(undefined4 *)(iVar2 + 0xc) = *(undefined4 *)(iVar2 + -0x1c); *(undefined4 *)(iVar2 + 0x10) = *(undefined4 *)(iVar2 + -0x18); *(undefined4 *)(iVar2 + 0x14) = *(undefined4 *)(iVar2 + -0x14); iVar2 = *(int *)(pbVar9 + 0x18) + (uint)*(ushort *)(pbVar9 + 0x24) * 0x28; *(undefined4 *)(iVar2 + 0x18) = *(undefined4 *)(iVar2 + -0x10); *(undefined4 *)(iVar2 + 0x1c) = *(undefined4 *)(iVar2 + -0xc); *(undefined4 *)(iVar2 + 0x20) = *(undefined4 *)(iVar2 + -8); *(short *)(pbVar9 + 0x24) = *(short *)(pbVar9 + 0x24) + 1; } } iVar8 += 1; iVar12 += 0x34; } while (iVar8 < (int)(uint)scene->nodeCount); } iVar8 = 0; if (scene->nodeCount != 0) { iVar12 = 0; do { pbVar9 = scene->nodeList->padding1 + iVar12 + -9; if (*(ushort *)(pbVar9 + 0x26) != 0) { puVar15 = (ushort *)(*(int *)(pbVar9 + 0x20) + (uint)*(ushort *)(pbVar9 + 0x26) * 2); if (puVar15[-1] < scene->lastFrame) { *puVar15 = scene->lastFrame; puVar20 = (undefined4 *) (*(int *)(pbVar9 + 0x1c) + (uint)*(ushort *)(pbVar9 + 0x26) * 4); *puVar20 = puVar20[-1]; *(short *)(pbVar9 + 0x26) = *(short *)(pbVar9 + 0x26) + 1; } } iVar8 += 1; iVar12 += 0x34; } while (iVar8 < (int)(uint)scene->nodeCount); } uVar16 = (uint)scene->nodeCount; iVar8 = uVar16 - 1; if (-1 < iVar8) { puVar15 = (ushort *)((int)local_968 + iVar8 * 2); iVar8 *= 0x34; do { pLVar18 = (Lws_Node *)(scene->nodeList->padding1 + iVar8 + -9); if (*puVar15 == 0) { pLVar18->next = scene->masterNode; scene->masterNode = pLVar18; } else { pLVar11 = scene->nodeList + (*puVar15 - 1); pLVar18->next = pLVar11->childList; pLVar11->childList = pLVar18; } iVar8 += -0x34; puVar15 = puVar15 + -1; uVar16 -= 1; } while (uVar16 != 0); } io::Mem_Free(local_968); Lws_SetupSoundTriggers(scene); } } io::File_Close(file); } return scene; } void __cdecl lego::gfx::Lws_Initialise (char *sharedDir,LwsFindSFXIDFunc FindSFXID,LwsPlaySample3DFunc PlaySample3D, LwsSoundEnabledFunc SoundEnabled) { char cVar1; uint uVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; undefined4 *puVar7; if (sharedDir != NULL) { uVar2 = 0xffffffff; pcVar6 = sharedDir; do { if (uVar2 == 0) break; uVar2 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); uVar3 = ~uVar2 - 1; if (sharedDir[(uVar3 & 0xffff) - 1] != '\\') { uVar3 = ~uVar2; } uVar3 &= 0xffff; globs::lwsGlobs.sharedDir = (char *)io::Mem_Alloc(uVar3 + 1); uVar2 = 0xffffffff; do { pcVar6 = sharedDir; if (uVar2 == 0) break; uVar2 -= 1; pcVar6 = sharedDir + 1; cVar1 = *sharedDir; sharedDir = pcVar6; } while (cVar1 != '\0'); uVar2 = ~uVar2; puVar5 = (undefined4 *)(pcVar6 + -uVar2); puVar7 = (undefined4 *)globs::lwsGlobs.sharedDir; for (uVar4 = uVar2 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar7 = *puVar5; puVar5 = puVar5 + 1; puVar7 = puVar7 + 1; } for (uVar2 &= 3; uVar2 != 0; uVar2 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } globs::lwsGlobs.sharedDir[uVar3 - 1] = '\\'; globs::lwsGlobs.sharedDir[uVar3] = '\0'; } globs::lwsGlobs.FindSFXIDFunc = FindSFXID; globs::lwsGlobs.SoundEnabledFunc = SoundEnabled; globs::lwsGlobs.PlaySample3DFunc = PlaySample3D; return; } void __cdecl lego::gfx::Lws_Shutdown(void) { uint uVar1; uint uVar2; uVar2 = 0; if (globs::lwsGlobs.meshPathCount != 0) { uVar1 = 0; do { io::Mem_Free(globs::lwsGlobs.meshPathList[uVar1].path); uVar2 += 1; uVar1 = uVar2 & 0xffff; } while (uVar1 < globs::lwsGlobs.meshPathCount); } uVar2 = 0; if (globs::lwsGlobs.meshPathCountShared != 0) { uVar1 = 0; do { io::Mem_Free(globs::lwsGlobs.meshPathListShared[uVar1].path); uVar2 += 1; uVar1 = uVar2 & 0xffff; } while (uVar1 < globs::lwsGlobs.meshPathCountShared); } return; } uint __cdecl lego::gfx::Lws_GetFrameCount(Lws_Info *scene) { return (uint)scene->lastFrame; } void __cdecl lego::gfx::Lws_SetupSoundTriggers(Lws_Info *scene) { Lws_Node *pLVar1; char cVar2; byte bVar3; ushort uVar4; ushort uVar5; Lws_SoundTrigger *pLVar6; int iVar7; BOOL BVar8; char *pcVar9; uint uVar10; uint uVar11; undefined4 *puVar12; ushort *puVar13; char *pcVar14; undefined4 *puVar15; char **ppcVar16; uint uStack2052; char *local_800; char *local_7fc; char *apcStack2040 [254]; undefined4 local_400 [256]; if (globs::lwsGlobs.FindSFXIDFunc == NULL) { scene->triggerCount = 0; } else { bVar3 = 0; if (scene->triggerCount != 0) { pLVar6 = (Lws_SoundTrigger *)io::Mem_Alloc((uint)scene->triggerCount * 0xd0); scene->triggerList = pLVar6; uVar5 = 0; if (scene->nodeCount != 0) { do { pLVar1 = scene->nodeList + uVar5; if ((scene->nodeList[uVar5].flags & 2) != 0) { pLVar6 = scene->triggerList + bVar3; pLVar1->triggerIndex = bVar3; bVar3 += 1; uVar10 = 0xffffffff; pcVar9 = pLVar1->name; do { pcVar14 = pcVar9; if (uVar10 == 0) break; uVar10 -= 1; pcVar14 = pcVar9 + 1; cVar2 = *pcVar9; pcVar9 = pcVar14; } while (cVar2 != '\0'); uVar10 = ~uVar10; puVar12 = (undefined4 *)(pcVar14 + -uVar10); puVar15 = local_400; for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar15 = *puVar12; puVar12 = puVar12 + 1; puVar15 = puVar15 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } iVar7 = util::Util_Tokenise((char *)local_400,&local_800,","); pLVar6->count = (short)iVar7 - 2; BVar8 = (*globs::lwsGlobs.FindSFXIDFunc)(local_7fc,&pLVar6->sfxID); if (((globs::mainGlobs.flags & MAIN_FLAG_REDUCESAMPLES) != MAIN_FLAG_NONE) && (BVar8 == 0)) { pLVar6->sfxID = 0; } uStack2052 = 0; if (pLVar6->count != 0) { ppcVar16 = apcStack2040; puVar13 = pLVar6->frameEndList; do { pcVar9 = std::strstr(*ppcVar16,"-"); iVar7 = std::atoi(*ppcVar16); uVar4 = (ushort)iVar7; puVar13[-0x19] = uVar4; if (pcVar9 != NULL) { iVar7 = std::atoi(pcVar9 + 1); uVar4 = (ushort)iVar7; } *puVar13 = uVar4; uStack2052 += 1; puVar13 = puVar13 + 1; ppcVar16 = ppcVar16 + 1; } while (uStack2052 < pLVar6->count); } } uVar5 += 1; if (scene->nodeCount <= uVar5) { return; } } while( true ); } } } return; } void __cdecl lego::gfx::Lws_LoadMeshes(Lws_Info *scene,IDirect3DRMFrame3 *parent) { Lws_Node *node; IDirect3DRMFrame3 *pIVar1; undefined4 local_4; local_4 = 0; pIVar1 = (IDirect3DRMFrame3 *)io::Mem_Alloc((uint)scene->nodeCount << 2); node = scene->masterNode; scene->frameList = pIVar1; for (; node != NULL; node = node->next) { Lws_CreateFrames(scene,node,parent,(ushort *)&local_4); Lws_LoadNodes(scene,node); } Lws_SetTime(scene,0.0); return; } Lws_Info * __cdecl lego::gfx::Lws_Clone(Lws_Info *scene,IDirect3DRMFrame3 *parent) { Lws_Node *pLVar1; Lws_Info *scene_00; IDirect3DRMFrame3 *pIVar2; uint uVar3; Mesh *mesh; int iVar4; Lws_Info *pLVar5; undefined4 unaff_EBP; Lws_Info *pLVar6; Lws_Info *pLVar7; IDirect3DRMFrame3Vtbl *pIVar8; int *piVar9; int local_50 [2]; undefined4 local_48; undefined auStack68 [40]; int *piStack28; code **ppcStack16; undefined auStack4 [4]; scene_00 = (Lws_Info *)io::Mem_Alloc(0x38); local_48 = 0; pLVar5 = scene; if (scene->clonedFrom != NULL) { pLVar5 = scene->clonedFrom; } pLVar6 = scene_00; for (iVar4 = 0xe; iVar4 != 0; iVar4 += -1) { *(undefined4 *)pLVar6 = 0; pLVar6 = (Lws_Info *)&pLVar6->fps; } pLVar6 = pLVar5; pLVar7 = scene_00; for (iVar4 = 0xe; iVar4 != 0; iVar4 += -1) { *(undefined4 *)pLVar7 = *(undefined4 *)pLVar6; pLVar6 = (Lws_Info *)&pLVar6->fps; pLVar7 = (Lws_Info *)&pLVar7->fps; } scene_00->referenceCount = 1; pIVar2 = (IDirect3DRMFrame3 *)io::Mem_Alloc((uint)scene_00->nodeCount << 2); pLVar1 = scene_00->masterNode; scene_00->frameList = pIVar2; for (; pLVar1 != NULL; pLVar1 = pLVar1->next) { Lws_CreateFrames(scene_00,pLVar1,parent,(ushort *)&local_48); } scene = NULL; if (scene_00->nodeCount != 0) { do { uVar3 = (uint)scene & 0xffff; pLVar1 = scene_00->nodeList + uVar3; piVar9 = local_50; pIVar8 = pLVar5->frameList[uVar3].lpVtbl; (**(code **)(pIVar8->QueryInterface + 0x5c))(pIVar8); pIVar8 = pLVar5->frameList[uVar3].lpVtbl; (**(code **)(pIVar8->QueryInterface + 0x74))(pIVar8,unaff_EBP,&local_48); (**(code **)(*piVar9 + 8))(piVar9); pIVar8 = scene_00->frameList[uVar3].lpVtbl; (**(code **)(pIVar8->QueryInterface + 0x38))(pIVar8,0,&stack0xffffffa8); if ((pLVar1->flags & 1) == 0) { pIVar8 = pLVar5->frameList[pLVar1->frameIndex].lpVtbl; (**(code **)(pIVar8->QueryInterface + 0x80))(pIVar8,auStack68); piVar9 = local_50; (**(code **)(pIVar8->QueryInterface + 0x80))(pIVar8,piVar9,auStack4); (**(code **)*ppcStack16)(ppcStack16,&idl::IID_IDirect3DRMUserVisual,&stack0xffffff9c); (**(code **)(*piStack28 + 8))(piStack28); mesh = (Mesh *)(**(code **)(*piVar9 + 0x1c))(piVar9); (**(code **)(pIVar8->QueryInterface + 8))(pIVar8); Mesh_Clone(mesh,(IDirect3DRMFrame3 *)scene_00->frameList[pLVar1->frameIndex].lpVtbl); } scene = (Lws_Info *)((int)&scene->firstFrame + 1); } while ((ushort)scene < scene_00->nodeCount); } scene_00->clonedFrom = pLVar5; pLVar5->referenceCount = pLVar5->referenceCount + 1; Lws_SetTime(scene_00,0.0); return scene_00; } void __cdecl lego::gfx::Lws_SetTime(Lws_Info *scene,float time) { Lws_Node *node; float fVar1; Lws_Info *scene_00; Lws_Info *pLVar2; ushort uVar3; float10 fVar4; scene_00 = scene; scene->lastTime = scene->time; if ((scene->flags & 1) == 0) { pLVar2 = (Lws_Info *)(uint)scene->lastFrame; fVar1 = (float)(int)pLVar2; if ((ushort)((ushort)(time < fVar1) << 8 | (ushort)(time == fVar1) << 0xe) == 0) { scene->time = fVar1; scene = pLVar2; } else { scene->time = time; scene = pLVar2; } } else { fVar4 = (float10)time; time = (float)(uint)scene->lastFrame; fVar4 = std::fmod(fVar4,(float10)(int)time); scene_00->time = (float)fVar4; } uVar3 = 0; if (scene_00->nodeCount != 0) { do { node = scene_00->nodeList + uVar3; if (1 < scene_00->nodeList[uVar3].keyCount) { fVar4 = Lws_FindPrevKey(node,scene_00->time,(ushort *)&scene); time = (float)fVar4; Lws_InterpolateKeys(scene_00,node,(ushort)scene,time); } if (1 < node->dissolveCount) { fVar4 = Lws_FindPrevDissolve(node,scene_00->time,(ushort *)&scene); time = (float)fVar4; Lws_InterpolateDissolve(scene_00,node,(ushort)scene,time); } Lws_AnimateTextures(scene_00,node); Lws_HandleTrigger(scene_00,node); uVar3 += 1; } while (uVar3 < scene_00->nodeCount); } return; } float10 __cdecl lego::gfx::Lws_FindPrevKey(Lws_Node *node,float time,ushort *prev) { float fVar1; uint uVar2; uint uVar3; uint uVar4; uint uVar5; float10 fVar6; uVar2 = 0; uVar5 = (uint)node->keyCount; while( true ) { uVar4 = uVar2; uVar3 = (uVar5 + uVar4) / 2; uVar2 = (uint)node->keyList[uVar3].frame; if ((ushort)uVar3 == (ushort)uVar4) break; fVar1 = (float)uVar2; uVar2 = uVar3; if ((ushort)((ushort)(fVar1 < time) << 8 | (ushort)(fVar1 == time) << 0xe) == 0) { uVar2 = uVar4; uVar5 = uVar3; } } fVar6 = (float10)uVar2; *prev = (ushort)uVar3; return ((float10)time - fVar6) / ((float10)(uint)node->keyList[uVar3 + 1].frame - fVar6); } // WARNING: Restarted to delay deadcode elimination for space: stack void __cdecl lego::gfx::Lws_AnimateTextures(Lws_Info *scene,Lws_Node *node) { Mesh *mesh; IDirect3DRMFrame3Vtbl *pIVar1; int *piStack20; code **ppcStack16; int local_4; if ((node->flags & 1) == 0) { ppcStack16 = NULL; pIVar1 = scene->frameList[node->frameIndex].lpVtbl; piStack20 = &local_4; (**(code **)(pIVar1->QueryInterface + 0x80))(pIVar1); (**(code **)(pIVar1->QueryInterface + 0x80))(pIVar1,&ppcStack16); (**(code **)*ppcStack16)(ppcStack16,&idl::IID_IDirect3DRMUserVisual); (**(code **)(local_4 + 8))(&local_4); mesh = (Mesh *)(**(code **)(pIVar1->QueryInterface + 0x1c))(pIVar1); (*(code *)piStack20[2])(&piStack20); Mesh_SetTextureTime2(mesh,scene->time); } return; } void __cdecl lego::gfx::Lws_HandleTrigger(Lws_Info *scene,Lws_Node *node) { ushort *puVar1; IDirect3DRMFrame3Vtbl *frame; Lws_Node *pLVar2; BOOL BVar3; uint uVar4; uint loop; Lws_SoundTrigger *pLVar5; uint uVar6; pLVar2 = node; if ((node->flags & 2) != 0) { puVar1 = &node->frameIndex; node = NULL; frame = scene->frameList[*puVar1].lpVtbl; pLVar5 = scene->triggerList + pLVar2->triggerIndex; if (pLVar5->count != 0) { do { uVar6 = (uint)node & 0xffff; loop = (uint)(pLVar5->frameStartList[uVar6] != pLVar5->frameEndList[uVar6]); BVar3 = Lws_KeyPassed(scene,(uint)pLVar5->frameStartList[uVar6]); if ((BVar3 != 0) && (BVar3 = (*globs::lwsGlobs.SoundEnabledFunc)(), BVar3 != 0)) { uVar4 = (*globs::lwsGlobs.PlaySample3DFunc) ((IDirect3DRMFrame3 *)frame,pLVar5->sfxID,loop,TRUE,NULL); pLVar5->loopUID[uVar6] = uVar4; } if ((loop != 0) && (BVar3 = Lws_KeyPassed(scene,(uint)pLVar5->frameEndList[uVar6]), BVar3 != 0)) { snd::Sound3D_StopSound(pLVar5->loopUID[uVar6]); } node = (Lws_Node *)((int)&node->name + 1); } while ((ushort)node < pLVar5->count); } } return; } BOOL __cdecl lego::gfx::Lws_KeyPassed(Lws_Info *scene,uint key) { Lws_Info *pLVar1; Lws_Info *pLVar2; float fVar3; Lws_Info *pLVar4; uint uVar5; pLVar1 = (Lws_Info *)scene->lastTime; pLVar2 = (Lws_Info *)scene->time; fVar3 = (float)(ulonglong)key; uVar5 = Lws_GetFrameCount(scene); pLVar4 = pLVar2; if ((ushort)((ushort)((float)pLVar1 < (float)pLVar2) << 8 | (ushort)((float)pLVar1 == (float)pLVar2) << 0xe) == 0) { pLVar4 = pLVar1; } scene = pLVar2; if ((float)pLVar1 < (float)pLVar2) { scene = pLVar1; } if (0.5 <= ((float)pLVar4 - (float)scene) / (float)(ulonglong)uVar5) { if ((fVar3 >= (float)pLVar4) || ((ushort)((ushort)(fVar3 < (float)scene) << 8 | (ushort)(fVar3 == (float)scene) << 0xe) != 0) ) { return TRUE; } } else { if (((ushort)((ushort)(fVar3 < (float)pLVar4) << 8 | (ushort)(fVar3 == (float)pLVar4) << 0xe) != 0) && ((float)scene <= fVar3)) { return TRUE; } } return 0; } float10 __cdecl lego::gfx::Lws_FindPrevDissolve(Lws_Node *node,float time,ushort *prev) { ushort uVar1; ushort uVar2; ushort uVar3; uVar1 = node->dissolveCount; uVar3 = 1; if (uVar1 < 2) { *prev = uVar1 - 1; return (float10)0.0; } do { uVar2 = node->dissolveFrame[uVar3]; if (time <= (float)(uint)uVar2) { *prev = uVar3 - 1; return ((float10)time - (float10)(uint)node->dissolveFrame[(ushort)(uVar3 - 1)]) / ((float10)(uint)uVar2 - (float10)(uint)node->dissolveFrame[(ushort)(uVar3 - 1)]); } uVar3 += 1; } while (uVar3 < uVar1); *prev = uVar1 - 1; return (float10)0.0; } void __cdecl lego::gfx::Lws_InterpolateDissolve(Lws_Info *scene,Lws_Node *node,ushort prev,float delta) { float level; uint uVar1; uVar1 = (uint)prev; level = node->dissolveLevel[uVar1]; if (uVar1 == node->dissolveCount - 1) { Lws_SetDissolveLevel(scene,node,level); return; } Lws_SetDissolveLevel(scene,node,(node->dissolveLevel[uVar1 + 1] - level) * delta + level); return; } void __cdecl lego::gfx::Lws_SetDissolveLevel(Lws_Info *scene,Lws_Node *node,float level) { Mesh *mesh; D3DRMGroupIndex DVar1; D3DRMGroupIndex groupID; code **unaff_EDI; IDirect3DRMFrame3Vtbl *pIVar2; int *value; IDirect3DRMFrame3Vtbl *pIVar3; undefined4 uStack20; undefined local_4 [4]; pIVar2 = scene->frameList[node->frameIndex].lpVtbl; uStack20 = 0; pIVar3 = pIVar2; (**(code **)(pIVar2->QueryInterface + 0x80))(pIVar2,local_4); value = (int *)&stack0xfffffff0; (**(code **)(pIVar2->QueryInterface + 0x80))(pIVar2,value,local_4); (**(code **)*unaff_EDI)(unaff_EDI,&idl::IID_IDirect3DRMUserVisual,&uStack20); (**(code **)(pIVar3->QueryInterface + 8))(pIVar3); mesh = (Mesh *)(**(code **)(*value + 0x1c))(value); (**(code **)(pIVar2->QueryInterface + 8))(pIVar2); DVar1 = Mesh_GetGroupCount(mesh); groupID = D3DRMGROUP_0; if (DVar1 != D3DRMGROUP_0) { do { Mesh_SetGroupMaterialValues(mesh,groupID,(float)value,Mesh_Colour_Alpha); groupID += 1; } while (groupID < DVar1); } return; } void __cdecl lego::gfx::Lws_InterpolateKeys(Lws_Info *scene,Lws_Node *node,ushort key,float delta) { int iVar1; Lws_KeyInfo *pLVar2; Lws_KeyInfo *pLVar3; Vector3F local_24; Vector3F local_18; Vector3F local_c; pLVar3 = node->keyList; iVar1 = key + 1; pLVar2 = pLVar3 + key; local_18.x = (pLVar2->position).x + (pLVar3[iVar1].position.x - (pLVar2->position).x) * delta; local_18.y = (pLVar3[iVar1].position.y - (pLVar2->position).y) * delta + (pLVar2->position).y; local_18.z = (pLVar3[iVar1].position.z - (pLVar2->position).z) * delta + (pLVar2->position).z; local_24.x = (pLVar2->scale).x + (pLVar2[1].scale.x - (pLVar2->scale).x) * delta; local_24.y = (pLVar2[1].scale.y - (pLVar2->scale).y) * delta + (pLVar2->scale).y; local_24.z = (pLVar2[1].scale.z - (pLVar2->scale).z) * delta + (pLVar2->scale).z; local_c.x = (pLVar2->hpb).x + (pLVar2[1].hpb.x - (pLVar2->hpb).x) * delta; local_c.y = (pLVar2[1].hpb.y - (pLVar2->hpb).y) * delta + (pLVar2->hpb).y; local_c.z = (pLVar2[1].hpb.z - (pLVar2->hpb).z) * delta + (pLVar2->hpb).z; Lws_SetupNodeTransform(scene,node,&local_18,&local_c,&local_24); return; } void __cdecl lego::gfx::Lws_SetupNodeTransform (Lws_Info *scene,Lws_Node *node,Vector3F *pos,Vector3F *hpb,Vector3F *scale) { float *pfVar1; float fVar2; Lws_Node *pLVar3; float fVar4; IDirect3DRMFrame3Vtbl *pIVar5; float fVar6; float fVar7; float fVar8; float fVar9; float fVar10; float10 fVar11; float10 fVar12; float10 fVar13; float10 fVar14; float10 fVar15; float10 fVar16; undefined4 unaff_retaddr; float local_48; float local_44; float local_40; float local_3c; float local_38; undefined4 local_34; float local_30; float local_2c; float local_28; undefined4 local_24; float local_20; float local_1c; float local_18; undefined4 local_14; float local_10; int *local_c; float local_8; undefined4 local_4; pIVar5 = scene->frameList[node->frameIndex].lpVtbl; if ((node->flags & 4) == 0) { fVar11 = (float10)fsin((float10)hpb->z); fVar12 = (float10)fsin((float10)hpb->y); fVar13 = (float10)fcos((float10)hpb->z); fVar14 = (float10)fsin((float10)hpb->x); fVar6 = (node->pivotVector).x; fVar15 = (float10)fcos((float10)hpb->x); fVar16 = (float10)fcos((float10)hpb->y); local_3c = scale->x * (float)fVar11; fVar9 = scale->x * (float)fVar13; fVar2 = (float)fVar14; pLVar3 = (Lws_Node *)(float)fVar15; local_44 = scale->y * (float)fVar13; fVar4 = (float)(fVar12 * (float10)local_3c); hpb = (Vector3F *)(float)fVar16; local_3c = (float)hpb * local_3c; local_48 = (float)fVar12 * local_44; fVar7 = (node->pivotVector).y; fVar8 = (node->pivotVector).z; fVar10 = -(scale->y * (float)fVar11); local_40 = (float)((float10)fVar2 * (float10)fVar4 + fVar15 * (float10)fVar9); local_38 = (float)((float10)(float)pLVar3 * (float10)fVar4 + -(fVar14 * (float10)fVar9)); pfVar1 = &scale->z; scale = (Vector3F *)(scale->z * (float)hpb); local_1c = -(*pfVar1 * (float)fVar12); local_20 = fVar2 * (float)scale; local_18 = (float)pLVar3 * (float)scale; local_2c = (float)hpb * local_44; local_30 = fVar2 * local_48 + (float)pLVar3 * fVar10; local_28 = -(fVar2 * fVar10) + (float)pLVar3 * local_48; local_34 = 0; local_24 = 0; local_10 = fVar7 * local_30 + fVar6 * local_40 + fVar8 * local_20 + pos->x; local_c = (int *)(fVar7 * local_2c + fVar6 * local_3c + fVar8 * local_1c + pos->y); local_8 = fVar7 * local_28 + fVar6 * local_38 + fVar8 * local_18 + pos->z; local_14 = 0; local_4 = 0x3f800000; node = pLVar3; } else { (**(code **)(pIVar5->QueryInterface + 0x5c))(pIVar5,&node); (**(code **)(pIVar5->QueryInterface + 0x74))(pIVar5,unaff_retaddr,&local_48); (**(code **)(*local_c + 8))(local_c); node = NULL; local_40 = local_40 * scale->x; local_2c = scale->y * local_2c; local_18 = scale->z * local_18; local_10 = pos->x; local_c = (int *)pos->y; local_8 = pos->z; } (**(code **)(pIVar5->QueryInterface + 0x38))(pIVar5,0,&local_40); return; } Mesh * __cdecl lego::gfx::Lws_LoadMesh(char *baseDir,char *fname,IDirect3DRMFrame3 *frame,BOOL noTextures) { char cVar1; Mesh *pMVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; char *pcVar7; undefined4 *puVar8; char filenameBuffer [260]; if (baseDir == NULL) { uVar3 = 0xffffffff; pcVar6 = fname; do { pcVar7 = pcVar6; if (uVar3 == 0) break; uVar3 -= 1; pcVar7 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar7; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar7 + -uVar3); puVar8 = (undefined4 *)filenameBuffer; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar8 = *puVar5; puVar5 = puVar5 + 1; puVar8 = puVar8 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } } else { std::sprintf(filenameBuffer,"%s%s",baseDir,fname); } pMVar2 = Lws_SearchMeshPathList (globs::lwsGlobs.meshPathList,globs::lwsGlobs.meshPathCount,filenameBuffer); if (pMVar2 != NULL) { Mesh_Clone(pMVar2,frame); return pMVar2; } pMVar2 = Mesh_Load(filenameBuffer,frame,noTextures); if (pMVar2 != NULL) { Lws_AddMeshPathEntry (globs::lwsGlobs.meshPathList,&globs::lwsGlobs.meshPathCount,filenameBuffer,pMVar2); return pMVar2; } if (globs::lwsGlobs.sharedDir != NULL) { std::sprintf(filenameBuffer,"%s%s",globs::lwsGlobs.sharedDir,fname); pMVar2 = Lws_SearchMeshPathList (globs::lwsGlobs.meshPathListShared,globs::lwsGlobs.meshPathCountShared,fname ); if (pMVar2 != NULL) { Mesh_Clone(pMVar2,frame); return pMVar2; } pMVar2 = Mesh_Load(filenameBuffer,frame,noTextures); if (pMVar2 != NULL) { Lws_AddMeshPathEntry (globs::lwsGlobs.meshPathListShared,&globs::lwsGlobs.meshPathCountShared,fname, pMVar2); return pMVar2; } } return NULL; } Mesh * __cdecl lego::gfx::Lws_SearchMeshPathList(Lws_MeshPath *list,uint count,char *path) { uint uVar1; int iVar2; uint uVar3; uVar3 = 0; if (count == 0) { return NULL; } uVar1 = 0; do { iVar2 = std::_stricmp(path,list[uVar1].path); if (iVar2 == 0) { return list[uVar3 & 0xffff].mesh; } uVar3 += 1; uVar1 = uVar3 & 0xffff; } while (uVar1 < count); return NULL; } void __cdecl lego::gfx::Lws_AddMeshPathEntry(Lws_MeshPath *ref_list,uint *ref_count,char *path,Mesh *mesh) { char *pcVar1; pcVar1 = util::Util_StrCpy(path); ref_list[*ref_count].path = pcVar1; ref_list[*ref_count].mesh = mesh; *ref_count = *ref_count + 1; return; } // WARNING: Type propagation algorithm not settling void __cdecl lego::gfx::Lws_CreateFrames (Lws_Info *scene,Lws_Node *node,IDirect3DRMFrame3 *parent,ushort *ref_frameCount) { byte *pbVar1; Lws_Node *node_00; uint uVar2; int iVar3; IDirect3DRMFrame3 *unaff_EBP; byte *pbVar4; undefined4 *puVar5; IDirect3DRMFrame3 local_444; undefined4 auStack1088 [5]; undefined4 uStack1068; undefined4 uStack1048; undefined4 uStack1040; undefined4 uStack1036; undefined4 uStack1032; undefined4 uStack1028; byte abStack1024 [1024]; (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateFrame) (globs::mainGlobs.lpD3DRM,parent,(IDirect3DRMFrame3 **)&local_444); if ((node->flags & 4) != 0) { puVar5 = auStack1088; for (iVar3 = 0x10; iVar3 != 0; iVar3 += -1) { *puVar5 = 0; puVar5 = puVar5 + 1; } uStack1032 = 0; uStack1036 = 0; uStack1040 = 0; uStack1028 = 0x3f800000; uStack1048 = 0x3f800000; uStack1068 = 0x3f800000; auStack1088[0] = 0x3f800000; (**(code **)(*(int *)local_444 + 0x38))(local_444,0,auStack1088); } scene->frameList[*ref_frameCount].lpVtbl = local_444; node->frameIndex = *ref_frameCount; *ref_frameCount = *ref_frameCount + 1; std::sprintf((char *)abStack1024,"%s_%0.2i",node->name,(uint)node->reference); pbVar4 = abStack1024; while (abStack1024[0] != 0) { // int std::isgraph(int c) // (or close enough to this?) if (std::globals::_pcharwidth < 2) { // C1_ALPHA | C1_BLANK | C1_PUNCT | C1_DIGIT | C1_LOWER | C1_UPPER (0x100 | 0x40 | 0x10 // | 0x4 | 0x2 | 0x1) uVar2 = std::globals::_pctype[*pbVar4] & 0x157; } else { uVar2 = std::_isctype((uint)*pbVar4,0x157); } if (uVar2 == 0) { *pbVar4 = 0x5f; } pbVar1 = pbVar4 + 1; pbVar4 = pbVar4 + 1; abStack1024[0] = *pbVar1; } (**(code **)(*(int *)local_444 + 0x20))(local_444,abStack1024); for (node_00 = node->childList; node_00 != NULL; node_00 = node_00->next) { Lws_CreateFrames(scene,node_00,unaff_EBP,ref_frameCount); } return; } void __cdecl lego::gfx::Lws_LoadNodes(Lws_Info *scene,Lws_Node *node) { IDirect3DRMFrame3Vtbl *frame; Lws_Node *node_00; Mesh *pMVar1; frame = scene->frameList[node->frameIndex].lpVtbl; if (node->keyCount == 1) { Lws_SetAbsoluteKey(scene,node,0); } if (((node->flags & 1) == 0) && (pMVar1 = Lws_LoadMesh(scene->filePath,node->name,(IDirect3DRMFrame3 *)frame,0), pMVar1 != NULL )) { if ((node->flags & 4) != 0) { pMVar1->flags = pMVar1->flags | 0x1000000; } if ((node->dissolveLevel != NULL) && (node->dissolveCount == 0)) { Lws_SetDissolveLevel(scene,node,*node->dissolveLevel); node->dissolveLevel = NULL; } } for (node_00 = node->childList; node_00 != NULL; node_00 = node_00->next) { Lws_LoadNodes(scene,node_00); } return; } void __cdecl lego::gfx::Lws_SetAbsoluteKey(Lws_Info *scene,Lws_Node *node,ushort key) { Lws_KeyInfo *pos; pos = node->keyList + key; Lws_SetupNodeTransform(scene,node,&pos->position,&pos->hpb,&pos->scale); return; } void __cdecl lego::gfx::Lws_Free(Lws_Info *scene) { Lws_Info *pLVar1; uint uVar2; ushort uVar3; do { pLVar1 = scene->clonedFrom; uVar2 = scene->referenceCount - 1; scene->referenceCount = uVar2; if (uVar2 == 0) { uVar3 = 0; if (scene->nodeCount != 0) { do { Lws_FreeNode(scene,scene->nodeList + uVar3); uVar3 += 1; } while (uVar3 < scene->nodeCount); } if (scene->clonedFrom == NULL) { io::Mem_Free(scene->nodeList); io::Mem_Free(scene->filePath); if (scene->triggerCount != 0) { io::Mem_Free(scene->triggerList); } } io::Mem_Free(scene->frameList); io::Mem_Free(scene); } scene = pLVar1; } while (pLVar1 != NULL); return; } void __cdecl lego::gfx::Lws_FreeNode(Lws_Info *scene,Lws_Node *node) { Mesh *mesh; code **unaff_EDI; IDirect3DRMFrame3Vtbl *pIVar1; int *piVar2; IDirect3DRMFrame3Vtbl *pIVar3; undefined local_4 [4]; if ((node->flags & 1) == 0) { pIVar1 = scene->frameList[node->frameIndex].lpVtbl; pIVar3 = pIVar1; (**(code **)(pIVar1->QueryInterface + 0x80))(pIVar1,local_4); piVar2 = (int *)&stack0xfffffff0; (**(code **)(pIVar1->QueryInterface + 0x80))(pIVar1,piVar2,local_4); (**(code **)*unaff_EDI)(unaff_EDI,&idl::IID_IDirect3DRMUserVisual,&stack0xffffffec); (**(code **)(pIVar3->QueryInterface + 8))(pIVar3); mesh = (Mesh *)(**(code **)(*piVar2 + 0x1c))(piVar2); (**(code **)(pIVar1->QueryInterface + 8))(pIVar1); Mesh_Remove(mesh,(IDirect3DRMFrame3 *)scene->frameList[node->frameIndex].lpVtbl); } if ((scene->clonedFrom == NULL) && (scene->referenceCount == 0)) { io::Mem_Free(node->name); io::Mem_Free(node->keyList); if (node->dissolveCount != 0) { io::Mem_Free(node->dissolveLevel); io::Mem_Free(node->dissolveFrame); } } return; } BOOL __cdecl lego::snd::Sound_Initialise(BOOL nosound) { BOOL BVar1; globs::soundGlobs.initialised = ZEXT14(nosound == 0); globs::soundGlobs.loopCDTrack = -1; if (nosound != 0) { globs::soundGlobs.loopCDTrack = -1; return 1; } BVar1 = Sound3D_Initialise(globs::mainGlobs.hWnd); return (uint)(BVar1 != 0); } BOOL __cdecl lego::snd::Sound_IsInitialised(void) { if ((globs::soundGlobs.initialised != 0) && (globs::sound3DGlobs.intialised != 0)) { return TRUE; } return 0; } BOOL __cdecl lego::snd::Sound_PlayCDTrack(uint track,SoundMode mode,SoundCDStopCallback stopCallback) { BOOL BVar1; BVar1 = globs::soundGlobs.initialised; if (globs::soundGlobs.initialised != 0) { if (mode == SoundMode_Loop) { globs::soundGlobs.loopCDTrack = TRUE; } globs::soundGlobs.currTrack = track; globs::soundGlobs.CDStopCallback = stopCallback; BVar1 = Play_CDTrack(track); } return BVar1; } BOOL __cdecl lego::snd::Sound_StopCD(void) { BOOL BVar1; if (globs::soundGlobs.initialised != 0) { BVar1 = Stop_CDTrack(); return BVar1; } return 0; } void __cdecl lego::snd::Sound_Update(BOOL cdtrack) { uint uVar1; DWORD DVar2; BOOL BVar3; uVar1 = globs::soundGlobs.s_Update_lastUpdate; if ((((globs::soundGlobs.initialised != 0) && (DVar2 = timeGetTime(), uVar1 = globs::soundGlobs.s_Update_lastUpdate, globs::soundGlobs.s_Update_lastUpdate + 4000 < DVar2)) && (uVar1 = DVar2, cdtrack != 0)) && (BVar3 = Status_CDTrack(globs::soundGlobs.currTrack), BVar3 == 0)) { if (globs::soundGlobs.loopCDTrack != 0) { Restart_CDTrack(globs::soundGlobs.currTrack); } if (globs::soundGlobs.CDStopCallback != NULL) { (*globs::soundGlobs.CDStopCallback)(); } } globs::soundGlobs.s_Update_lastUpdate = uVar1; return; } // WARNING: Could not reconcile some variable overlaps // This function will open a wave input file and prepare it for reading, // so the data can be easily // read with WaveReadFile. Returns 0 if successful, the error code if not. // pszFileName - Input filename to load. // phmmioIn - Pointer to handle which will be used // for further mmio routines. // ppwfxInfo - Ptr to ptr to WaveFormatEx structure // with all info about the file. int __cdecl lego::snd::WaveOpenFile (void *fileData,uint fileSize,HMMIO *out_phmmioIn,WAVEFORMATEX **out_ppwfxInfo, MMCKINFO *out_pckInRIFF) { WAVEFORMATEX **ppWVar1; MMCKINFO *pmmckiParent; HMMIO hmmio; LONG LVar2; WAVEFORMATEX *pWVar3; uint uVar4; int iVar5; MMRESULT MVar6; _MMIOINFO *p_Var7; undefined4 local_6c; DWORD local_68; DWORD local_64; undefined4 local_60; _MMCKINFO local_5c; _MMIOINFO local_48; *out_ppwfxInfo = NULL; p_Var7 = &local_48; for (iVar5 = 0x12; iVar5 != 0; iVar5 += -1) { p_Var7->dwFlags = 0; p_Var7 = (_MMIOINFO *)&p_Var7->fccIOProc; } // "MEM " local_48.fccIOProc = 0x204d454d; local_48.pchBuffer = (HPSTR)fileData; local_48.cchBuffer = fileSize; hmmio = mmioOpenA(NULL,(LPMMIOINFO)&local_48,0x10000); pmmckiParent = out_pckInRIFF; if (hmmio == NULL) { MVar6 = 0xe100; } else { MVar6 = mmioDescend(hmmio,(LPMMCKINFO)out_pckInRIFF,NULL,0); if (MVar6 == 0) { if ((pmmckiParent->ckid == 0x46464952) && (pmmckiParent->fccType == 0x45564157)) { local_5c.ckid = 0x20746d66; MVar6 = mmioDescend(hmmio,(LPMMCKINFO)&local_5c,pmmckiParent,0x10); if (MVar6 != 0) goto LAB_004890e9; if (0xf < local_5c.cksize) { LVar2 = mmioRead(hmmio,(HPSTR)&local_6c,0x10); if (LVar2 != 0x10) { MVar6 = 0xe102; goto LAB_004890e9; } if ((short)local_6c == 1) { fileData = NULL; } else { LVar2 = mmioRead(hmmio,(HPSTR)&fileData,2); if (LVar2 != 2) { MVar6 = 0xe102; goto LAB_004890e9; } } pWVar3 = (WAVEFORMATEX *)GlobalAlloc(0,((uint)fileData & 0xffff) + 0x12); *out_ppwfxInfo = pWVar3; if (pWVar3 == NULL) { MVar6 = 0xe000; goto LAB_004890e9; } *(undefined4 *)pWVar3 = local_6c; pWVar3->nSamplesPerSec = local_68; pWVar3->nAvgBytesPerSec = local_64; *(undefined4 *)&pWVar3->nBlockAlign = local_60; (*out_ppwfxInfo)->cbSize = (WORD)fileData; if (((WORD)fileData == 0) || (uVar4 = mmioRead(hmmio,(HPSTR)(*out_ppwfxInfo + 1),(uint)fileData & 0xffff), uVar4 == ((uint)fileData & 0xffff))) { MVar6 = mmioAscend(hmmio,(LPMMCKINFO)&local_5c,0); if (MVar6 == 0) { *out_phmmioIn = hmmio; return 0; } goto LAB_004890e9; } } } MVar6 = 0xe101; } } LAB_004890e9: ppWVar1 = out_ppwfxInfo; if (*out_ppwfxInfo != NULL) { GlobalFree(*out_ppwfxInfo); *ppWVar1 = NULL; } if (hmmio != NULL) { mmioClose(hmmio,0); hmmio = NULL; } *out_phmmioIn = hmmio; return MVar6; } uint __cdecl lego::snd::GetWaveAvgBytesPerSec(char *pszFileName) { HMMIO hmmio; MMRESULT MVar1; LONG LVar2; uint uVar3; PCMWAVEFORMAT local_38; _MMCKINFO local_28; _MMCKINFO local_14; uVar3 = 0; hmmio = mmioOpenA(pszFileName,NULL,0); if (hmmio != NULL) { MVar1 = mmioDescend(hmmio,(LPMMCKINFO)&local_28,NULL,0); // "RIFF", "WAVE" if (((MVar1 == 0) && (local_28.ckid == L'\x46464952')) && (local_28.fccType == L'\x45564157')) { // "fmt " local_14.ckid = L'\x20746d66'; MVar1 = mmioDescend(hmmio,(LPMMCKINFO)&local_14,(MMCKINFO *)&local_28,0x10); if ((MVar1 == 0) && (0xf < local_14.cksize)) { LVar2 = mmioRead(hmmio,(HPSTR)&local_38,0x10); if (LVar2 == 0x10) { uVar3 = local_38.wf.nAvgBytesPerSec; } } } if (hmmio != NULL) { mmioClose(hmmio,0); } } return uVar3; } // WARNING: Could not reconcile some variable overlaps int __cdecl lego::snd::WaveOpenFile2 (char *pszFileName,HMMIO *out_phmmioIn,WAVEFORMATEX **out_ppwfxInfo, MMCKINFO *out_pckInRIFF) { WAVEFORMATEX **ppWVar1; MMCKINFO *pmmckiParent; HMMIO hmmio; LONG LVar2; WAVEFORMATEX *pWVar3; uint uVar4; MMRESULT MVar5; undefined4 local_24; DWORD local_20; DWORD local_1c; undefined4 local_18; _MMCKINFO local_14; *out_ppwfxInfo = NULL; hmmio = mmioOpenA(pszFileName,NULL,0x10000); pmmckiParent = out_pckInRIFF; if (hmmio == NULL) { MVar5 = 0xe100; } else { MVar5 = mmioDescend(hmmio,(LPMMCKINFO)out_pckInRIFF,NULL,0); if (MVar5 == 0) { if ((pmmckiParent->ckid == L'\x46464952') && (pmmckiParent->fccType == L'\x45564157')) { local_14.ckid = L'\x20746d66'; MVar5 = mmioDescend(hmmio,(LPMMCKINFO)&local_14,pmmckiParent,0x10); if (MVar5 != 0) goto LAB_00489343; if (0xf < local_14.cksize) { LVar2 = mmioRead(hmmio,(HPSTR)&local_24,0x10); if (LVar2 != 0x10) { MVar5 = 0xe102; goto LAB_00489343; } if ((short)local_24 == 1) { pszFileName = NULL; } else { LVar2 = mmioRead(hmmio,(HPSTR)&pszFileName,2); if (LVar2 != 2) { MVar5 = 0xe102; goto LAB_00489343; } } pWVar3 = (WAVEFORMATEX *)GlobalAlloc(0,((uint)pszFileName & 0xffff) + 0x12); *out_ppwfxInfo = pWVar3; if (pWVar3 == NULL) { MVar5 = 0xe000; goto LAB_00489343; } *(undefined4 *)pWVar3 = local_24; pWVar3->nSamplesPerSec = local_20; pWVar3->nAvgBytesPerSec = local_1c; *(undefined4 *)&pWVar3->nBlockAlign = local_18; (*out_ppwfxInfo)->cbSize = (WORD)pszFileName; if (((WORD)pszFileName == 0) || (uVar4 = mmioRead(hmmio,(HPSTR)(*out_ppwfxInfo + 1),(uint)pszFileName & 0xffff), uVar4 == ((uint)pszFileName & 0xffff))) { MVar5 = mmioAscend(hmmio,(LPMMCKINFO)&local_14,0); if (MVar5 == 0) { *out_phmmioIn = hmmio; return 0; } goto LAB_00489343; } } } MVar5 = 0xe101; } } LAB_00489343: ppWVar1 = out_ppwfxInfo; if (*out_ppwfxInfo != NULL) { GlobalFree(*out_ppwfxInfo); *ppWVar1 = NULL; } if (hmmio != NULL) { mmioClose(hmmio,0); hmmio = NULL; } *out_phmmioIn = hmmio; return MVar5; } // This routine has to be called before WaveReadFile as it searchs for the chunk to descend into for // reading, that is, the 'data' chunk. For simplicity, this used to be in the open routine, but was // taken out and moved to a separate routine so there was more control on the chunks that are before // the data chunk, such as 'fact', etc... int __cdecl lego::snd::WaveStartDataRead(HMMIO *phmmioIn,MMCKINFO *pckIn,MMCKINFO *pckInRIFF) { MMRESULT MVar1; mmioSeek(*phmmioIn,pckInRIFF->dwDataOffset + 4,0); pckIn->ckid = L'\x61746164'; MVar1 = mmioDescend(*phmmioIn,(LPMMCKINFO)pckIn,pckInRIFF,0x10); return MVar1; } // This will read wave data from the wave file. Makre sure we're descended into // the data chunk, else this will fail bigtime! // hmmioIn - Handle to mmio. // cbRead - # of bytes to read. // pbDest - Destination buffer to put bytes. // cbActualRead- # of bytes actually read. int __cdecl lego::snd::WaveReadFile(HMMIO hmmioIn,uint cbRead,byte *pbDest,MMCKINFO *pckIn,uint *cbActualRead) { byte bVar1; MMRESULT MVar2; uint uVar3; byte *pbVar4; uint uVar5; _MMIOINFO local_48; MVar2 = mmioGetInfo(hmmioIn,(LPMMIOINFO)&local_48,0); uVar3 = (uint)(MVar2 != 0); if (uVar3 == 0) { uVar3 = pckIn->cksize; if (uVar3 < cbRead) { cbRead = uVar3; } uVar5 = 0; pckIn->cksize = uVar3 - cbRead; pbVar4 = (byte *)local_48.pchEndRead; if (cbRead != 0) { do { if ((byte *)local_48.pchNext == pbVar4) { uVar3 = mmioAdvance(hmmioIn,(LPMMIOINFO)&local_48,0); if (uVar3 != 0) goto LAB_00489456; pbVar4 = (byte *)local_48.pchEndRead; if (local_48.pchNext == local_48.pchEndRead) { *cbActualRead = 0; return 0xe103; } } bVar1 = *local_48.pchNext; local_48.pchNext = (HPSTR)((byte *)local_48.pchNext + 1); pbDest[uVar5] = bVar1; uVar5 += 1; } while (uVar5 < cbRead); } uVar3 = mmioSetInfo(hmmioIn,(LPCMMIOINFO)&local_48,0); if (uVar3 == 0) { *cbActualRead = cbRead; return 0; } } LAB_00489456: *cbActualRead = 0; return uVar3; } // This will close the wave file openned with WaveOpenFile. // phmmioIn - Pointer to the handle to input MMIO. // ppwfxSrc - Pointer to pointer to WaveFormatEx structure. // // Returns 0 if successful, non-zero if there was a warning. int __cdecl lego::snd::WaveCloseReadFile(HMMIO *phmmio,WAVEFORMATEX **ppwfxSrc) { if (*ppwfxSrc != NULL) { GlobalFree(*ppwfxSrc); *ppwfxSrc = NULL; } if (*phmmio != NULL) { mmioClose(*phmmio,0); *phmmio = NULL; } return 0; } BOOL __cdecl lego::snd::Restart_CDTrack(int track) { CHAR local_64 [100]; wsprintfA(local_64,"play cdaudio from %i",track + 1); globs::soundGlobs.mciErr = mciSendStringA(local_64,globs::mciReturn,200,NULL); if (globs::soundGlobs.mciErr != 0) { ReportCDError(); return 0; } return TRUE; } void __cdecl lego::snd::ReportCDError(void) { mciGetErrorStringA(globs::soundGlobs.mciErr,globs::mciReturn,200); return; } BOOL __cdecl lego::snd::Status_CDTrack(int track) { int iVar1; char buff [100]; std::sprintf(buff,"status cdaudio mode"); globs::soundGlobs.mciErr = mciSendStringA(buff,globs::mciReturn,200,NULL); iVar1 = std::_stricmp(globs::mciReturn,"stopped"); if (iVar1 != 0) { std::sprintf(buff,"status cdaudio current track"); globs::soundGlobs.mciErr = mciSendStringA(buff,globs::mciReturn,200,NULL); iVar1 = std::atoi(globs::mciReturn); if (iVar1 <= track + 1) { return TRUE; } } ReportCDError(); return 0; } BOOL __cdecl lego::snd::Play_CDTrack(int track) { globs::soundGlobs.mciErr = mciSendStringA("open cdaudio",globs::mciReturn,200,NULL); if (globs::soundGlobs.mciErr == 0) { globs::soundGlobs.mciErr = mciSendStringA("set cdaudio time format tmsf",globs::mciReturn,200,NULL); if (globs::soundGlobs.mciErr == 0) { Restart_CDTrack(track); if (globs::soundGlobs.mciErr == 0) { return 1; } } } ReportCDError(); return 0; } BOOL __cdecl lego::snd::Stop_CDTrack(void) { globs::soundGlobs.mciErr = mciSendStringA("stop cdaudio",globs::mciReturn,200,NULL); if (globs::soundGlobs.mciErr == 0) { globs::soundGlobs.mciErr = mciSendStringA("close cdaudio",globs::mciReturn,200,NULL); if (globs::soundGlobs.mciErr == 0) { return TRUE; } } ReportCDError(); return 0; } void __cdecl lego::io::Mem_Initialise(void) { Mem_HandleFlags *pMVar1; pMVar1 = &globs::memGlobs.handleList[0].flags; do { pMVar1[-1] = MEMORY_HANDLE_FLAG_NONE; *pMVar1 = MEMORY_HANDLE_FLAG_NONE; pMVar1 = pMVar1 + 2; } while (pMVar1 < &DAT_005498a4); return; } uint __cdecl lego::io::Mem_AllocHandle(uint size) { Mem_HandleFlags *pMVar1; void *pvVar2; uint uVar3; uVar3 = 0; pMVar1 = &globs::memGlobs.handleList[0].flags; do { if ((*(byte *)pMVar1 & MEMORY_HANDLE_FLAG_USED) == 0) { pvVar2 = Mem_Alloc(size); globs::memGlobs.handleList[uVar3].addr = pvVar2; globs::memGlobs.handleList[uVar3].flags = globs::memGlobs.handleList[uVar3].flags | 1; return uVar3; } pMVar1 = pMVar1 + 2; uVar3 += 1; } while (pMVar1 < &DAT_005498a4); return 0xffffffff; } void __cdecl lego::io::Mem_FreeHandle(uint handle) { if ((handle < 2000) && ((*(byte *)&globs::memGlobs.handleList[handle].flags & 1) != 0)) { Mem_Free(globs::memGlobs.handleList[handle].addr); globs::memGlobs.handleList[handle].addr = NULL; globs::memGlobs.handleList[handle].flags = MEMORY_HANDLE_FLAG_NONE; } return; } void * __cdecl lego::io::Mem_AddressHandle(uint handle) { if ((handle < 2000) && ((*(byte *)&globs::memGlobs.handleList[handle].flags & 1) != 0)) { return globs::memGlobs.handleList[handle].addr; } return NULL; } IDirect3DRMMaterial2 * __cdecl lego::gfx::Material_Create (float emissiveRed,float emissiveGreen,float emissiveBlue,float specularRed, float specularGreen,float specularBlue,float power) { HRESULT HVar1; HVar1 = (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateMaterial) (globs::mainGlobs.lpD3DRM,power,(IDirect3DRMMaterial2 **)&power); if (HVar1 == 0) { // IDirect3DRMMaterial2->SetEmissive(this, float r, float g, float b) (**(code **)((int)*(IDirect3DRMMaterial2 *)power + 0x34)) ((IDirect3DRMMaterial2 *)power,emissiveRed,emissiveGreen,emissiveBlue); // IDirect3DRMMaterial2->SetSpecular(this, float r, float g, float b) (**(code **)((int)*(IDirect3DRMMaterial2 *)power + 0x30)) ((IDirect3DRMMaterial2 *)power,specularRed,specularGreen,specularBlue); return (IDirect3DRMMaterial2 *)power; } return NULL; } AnimClone * __cdecl lego::gfx::AnimClone_Register (IDirect3DRMAnimationSet2 *animSet,IDirect3DRMFrame3 *root,uint frameCount) { uint *data; AnimClone *actFrame; IDirect3DRMFrame3 **ppIVar1; AnimClone dummyActFrame; actFrame = (AnimClone *)io::Mem_Alloc(0x20); actFrame->clonedFrom = NULL; actFrame->animSet = animSet; actFrame->scene = NULL; actFrame->lws = 0; actFrame->root = root; (*root->lpVtbl->AddRef)((IUnknown *)root); data = &actFrame->partCount; *data = 0; actFrame->frameCount = (uint)root; AnimClone_WalkTree(root,0,AnimClone_FrameCountCallback,data); ppIVar1 = (IDirect3DRMFrame3 **)io::Mem_Alloc(*data << 2); actFrame->partArray = ppIVar1; AnimClone_WalkTree(root,0,AnimClone_SetupFrameArrayCallback,&stack0xffffffdc); return actFrame; } AnimClone * __cdecl lego::gfx::AnimClone_RegisterLws(void *struct38,IDirect3DRMFrame3 *rmFrame3,undefined4 field1c) { uint *data; AnimClone *pAVar1; IDirect3DRMFrame3 **ppIVar2; AnimClone dummyActFrame; pAVar1 = (AnimClone *)io::Mem_Alloc(0x20); pAVar1->clonedFrom = NULL; pAVar1->animSet = NULL; pAVar1->scene = (Lws_Info *)struct38; pAVar1->lws = 1; pAVar1->root = rmFrame3; (*rmFrame3->lpVtbl->AddRef)((IUnknown *)rmFrame3); data = &pAVar1->partCount; *data = 0; pAVar1->frameCount = (uint)rmFrame3; AnimClone_WalkTree(rmFrame3,0,AnimClone_FrameCountCallback,data); ppIVar2 = (IDirect3DRMFrame3 **)io::Mem_Alloc(*data << 2); pAVar1->partArray = ppIVar2; AnimClone_WalkTree(rmFrame3,0,AnimClone_SetupFrameArrayCallback,&stack0xffffffdc); return pAVar1; } AnimClone * __cdecl lego::gfx::AnimClone_Make(AnimClone *lastActFrameRes,IDirect3DRMFrame3 *parent,uint *out_frameCount) { IDirect3DRMFrame3 **lplpD3DRMFrame; AnimClone *pAVar1; Lws_Info *pLVar2; IDirect3DRMFrame3 **ppIVar3; int iVar4; AnimClone *pAVar5; AnimClone *pAVar6; uint *unaff_retaddr; pAVar1 = (AnimClone *)io::Mem_Alloc(0x20); iVar4 = 8; pAVar5 = lastActFrameRes; pAVar6 = pAVar1; if (lastActFrameRes->lws == 0) { for (; iVar4 != 0; iVar4 += -1) { pAVar6->clonedFrom = NULL; pAVar6 = (AnimClone *)&pAVar6->scene; } // IDirect3DRMAnimationSet2->SetTime(IDirect3DRMAnimationSet2* this, float rvTime) (*(code *)lastActFrameRes->animSet->lpVtbl->SetTime)(lastActFrameRes->animSet,0.0); pAVar1->animSet = NULL; pAVar1->clonedFrom = lastActFrameRes; lplpD3DRMFrame = &pAVar1->root; // IDirect3DRM3->CreateFrame(this, IDirect3DRMFrame3* lpD3DRMFrame, IDirect3DRMFrame3** // lplpD3DRMFrame) (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateFrame) (globs::mainGlobs.lpD3DRM,parent,lplpD3DRMFrame); ppIVar3 = (IDirect3DRMFrame3 **)io::Mem_Alloc(lastActFrameRes->partCount << 2); pAVar1->partArray = ppIVar3; AnimClone_CreateCopy(lastActFrameRes->root,*lplpD3DRMFrame,lastActFrameRes->lws); pAVar1->partCount = lastActFrameRes->partCount; if (unaff_retaddr != NULL) { *unaff_retaddr = lastActFrameRes->frameCount; } AnimClone_WalkTree(*lplpD3DRMFrame,0,AnimClone_SetupFrameArrayCallback,&stack0xffffffd4); } else { for (; iVar4 != 0; iVar4 += -1) { pAVar6->clonedFrom = pAVar5->clonedFrom; pAVar5 = (AnimClone *)&pAVar5->scene; pAVar6 = (AnimClone *)&pAVar6->scene; } pLVar2 = Lws_Clone(lastActFrameRes->scene,parent); pAVar1->scene = pLVar2; pAVar1->clonedFrom = NULL; if (out_frameCount != NULL) { *out_frameCount = lastActFrameRes->frameCount; return pAVar1; } } return pAVar1; } void __cdecl lego::gfx::AnimClone_Remove(AnimClone *actFrameRes) { uint uVar1; if (actFrameRes != NULL) { if (actFrameRes->clonedFrom == NULL) { if (actFrameRes->lws == 0) { (*actFrameRes->animSet->lpVtbl->Release)((IUnknown *)actFrameRes->animSet); (*actFrameRes->root->lpVtbl->Release)((IUnknown *)actFrameRes->root); } else { Lws_Free(actFrameRes->scene); } } if (actFrameRes->lws == 0) { uVar1 = 0; if (actFrameRes->partCount != 0) { do { (*actFrameRes->partArray[uVar1]->lpVtbl->Release) ((IUnknown *)actFrameRes->partArray[uVar1]); uVar1 += 1; } while (uVar1 < actFrameRes->partCount); } io::Mem_Free(actFrameRes->partArray); } io::Mem_Free(actFrameRes); } return; } // This function performs the same accessor, // shared between 3 different structure types. // uint __cdecl Flic_GetWidth(ImageFlic* fsp); // BOOL __cdecl AnimClone_IsLws(AnimClone* clone); // uint __cdecl Flocks_GetNumSubdata(Flocks* flocksData); BOOL __cdecl lego::gfx::AnimClone_IsLws__Flic_GetWidth(AnimClone *clone) { return clone->lws; } void __cdecl lego::gfx::AnimClone_SetTime(AnimClone *clone,float time,float *out_oldTime) { AnimClone *pAVar1; uint uVar2; Matrix4F local_40; pAVar1 = clone->clonedFrom; if (pAVar1 == NULL) { if (clone->lws != 0) { Lws_SetTime(clone->scene,time); return; } (*(code *)clone->animSet->lpVtbl->SetTime)(clone->animSet,time); } else { if (pAVar1->lws == 0) { (*(code *)pAVar1->animSet->lpVtbl->SetTime)(pAVar1->animSet,time); } else { Lws_SetTime(pAVar1->scene,time); } uVar2 = 0; if (clone->partCount != 0) { do { (*pAVar1->partArray[uVar2]->lpVtbl->GetParent) (pAVar1->partArray[uVar2],(IDirect3DRMFrame3 **)&time); (*pAVar1->partArray[uVar2]->lpVtbl->GetTransform) (pAVar1->partArray[uVar2],(IDirect3DRMFrame3 *)time,&local_40); (**(code **)((int)*(IDirect3DRMFrame3 *)time + 8))((IUnknown *)time); (*clone->partArray[uVar2]->lpVtbl->AddTransform) (clone->partArray[uVar2],D3DRMCOMBINE_REPLACE,&local_40); uVar2 += 1; } while (uVar2 < clone->partCount); } if (out_oldTime != NULL) { if (pAVar1->lws != 0) { Lws_SetTime(pAVar1->scene,*out_oldTime); return; } (*(code *)pAVar1->animSet->lpVtbl->SetTime)(pAVar1->animSet,*out_oldTime); return; } } return; } BOOL __cdecl lego::gfx::AnimClone_FrameCountCallback(IDirect3DRMFrame3 *frame,int *lpFramesCount) { *lpFramesCount = *lpFramesCount + 1; return 0; } BOOL __cdecl lego::gfx::AnimClone_SetupFrameArrayCallback(IDirect3DRMFrame3 *frame,AnimClone *actFrameRes) { actFrameRes->partArray[actFrameRes->partCount] = frame; actFrameRes->partCount = actFrameRes->partCount + 1; return 0; } BOOL __cdecl lego::gfx::AnimClone_WalkTree (IDirect3DRMFrame3 *frame,uint level,AnimCloneWalkTreeCallback Callback, IDirect3DRMFrame3 *data) { uint level_00; IDirect3DRMFrame3 *pIVar1; AnimCloneWalkTreeCallback Callback_00; IDirect3DRMFrame3 *data_00; int iVar2; HRESULT HVar3; uint uVar4; BOOL BVar5; uint index; BOOL local_8; data_00 = data; Callback_00 = Callback; pIVar1 = frame; local_8 = 0; iVar2 = (*Callback)(frame,data); if (iVar2 != 0) { return 1; } // IDirect3DRMFrame3->GetChildren(this, IDirect3DRMFrameArray** lplpChildren) HVar3 = (*pIVar1->lpVtbl->GetChildren)(pIVar1,(IDirect3DRMFrameArray **)&frame); if (HVar3 == 0) { // DWORD IDirect3DRMFrameArray->GetSize(this) uVar4 = (*frame->lpVtbl->Clone)((IDirect3DRMFrameArray *)frame); index = 0; if (uVar4 != 0) { level_00 = level + 1; do { // IDirect3DRMFrameArray->GetElement(this, DWORD index, IDirect3DRMFrame** // lplpD3DRMFrame) (*frame->lpVtbl->AddDestroyCallback) ((IDirect3DRMFrameArray *)frame,index,(IUnknown **)&Callback); // IDirect3DRMFrame->QueryInterface(this, IID_IDirect3DRMFrame3, IDirect3DRMFrame3** // lplpOut) (**(code **)*(IUnknown *)Callback)((IUnknown *)Callback,&idl::IID_IDirect3DRMFrame3,&data); // IDirect3DRMFrame->Release(this) (**(code **)((int)*(IUnknown *)Callback + 8))((IUnknown *)Callback); BVar5 = AnimClone_WalkTree(data,level_00,Callback_00,data_00); if (BVar5 != 0) { local_8 = 1; (*data->lpVtbl->Release)((IUnknown *)data); break; } (*data->lpVtbl->Release)((IUnknown *)data); index += 1; } while (index < uVar4); } (*frame->lpVtbl->Release)((IUnknown *)frame); } return local_8; } void __cdecl lego::gfx::AnimClone_CreateCopy(IDirect3DRMFrame3 *orig,IDirect3DRMFrame3 *clone,BOOL lws) { IDirect3DRMFrame3 *this; IDirect3DRMFrame3 *this_00; BOOL lws_00; LPCSTR lpName; HRESULT HVar1; uint uVar2; LPVOID *unaff_EBP; IID *unaff_ESI; DWORD index; IUnknown *unaff_EDI; IDirect3DRMFrameArray *in_stack_00000014; Matrix4F local_40; lws_00 = lws; this_00 = clone; this = orig; if ((IDirect3DRMFrame3 *)lws == NULL) { AnimClone_ReferenceVisuals(orig,clone); } else { AnimClone_CloneLwsMesh(orig,clone); } // IDirect3DRMFrame3->GetName(this, DWORD* lpdwSize, LPSTR lpName) (*this->lpVtbl->GetName)(this,(LPDWORD)&orig,NULL); if (orig != NULL) { lpName = (LPCSTR)io::Mem_Alloc((uint)orig); // IDirect3DRMFrame3->GetName(this, DWORD* lpdwSize, LPSTR lpName) (*this->lpVtbl->GetName)(this,(LPDWORD)&orig,lpName); // IDirect3DRMFrame3->SetName(this, LPCSTR lpName) (*this_00->lpVtbl->SetName)(this_00,lpName); io::Mem_Free(lpName); } // IDirect3DRMFrame3->GetParent(this, IDirect3DRMFrame3** lplpParent) (*this->lpVtbl->GetParent)(this,(IDirect3DRMFrame3 **)&lws); // IDirect3DRMFrame3->GetTransform(this, IDirect3DRMFrame3* lpRefFrame, Matrix4F** // rmMatrix) (*this->lpVtbl->GetTransform)(this,(IDirect3DRMFrame3 *)lws,(Matrix4F **)&local_40); // IDirect3DRMFrame3->Release(this) // (this = GetParent) (**(code **)((int)*(IDirect3DRMFrame3 *)lws + 8))((IDirect3DRMFrame3 *)lws); // IDirect3DRMFrame3->AddTransform(this, TD3DRMCombineType rctCombine, Matrix4F* // rmMatrix) (*this_00->lpVtbl->AddTransform)(this_00,D3DRMCOMBINE_REPLACE,&local_40); // IDirect3DRMFrame3->GetChildren(this, IDirect3DRMFrameArray** lplpChildren) HVar1 = (*this->lpVtbl->GetChildren)(this,(IDirect3DRMFrameArray **)&clone); if (HVar1 == 0) { // DWORD IDirect3DRMFrameArray->GetSize(this) uVar2 = (*clone->lpVtbl->Clone)((IUnknown *)clone,unaff_EDI,unaff_ESI,unaff_EBP); index = 0; if (uVar2 != 0) { do { // IDirect3DRMFrameArray->GetElement(this, DWORD index, IDirect3DRMFrame** // lplpD3DRMFrame) (*in_stack_00000014->lpVtbl->GetElement)(in_stack_00000014,index,(IUnknown **)&local_40); // IDirect3DRMFrame->QueryInterface(this, IID_IDirect3DRMFrame3, IDirect3DRMFrame3** // lplpOut) (*(*(IDirect3DRMFrame3Vtbl **)local_40.values[0][0])->QueryInterface) ((IUnknown *)local_40.values[0][0],&idl::IID_IDirect3DRMFrame3, (IDirect3DRMFrame3 **)(local_40.values + 2)); // IDirect3DRMFrame->Release(this) (*(*(IDirect3DRMFrame3Vtbl **)local_40.values[0][0])->Release) ((IUnknown *)local_40.values[0][0]); // IDirect3DRM3->CreateFrame(this, IDirect3DRMFrame3* lpD3DRMFrame, IDirect3DRMFrame3** // lplpD3DRMFrame) (*(globs::mainGlobs.lpD3DRM)->lpVtbl->CreateFrame) (globs::mainGlobs.lpD3DRM,this_00,(IDirect3DRMFrame3 **)&local_40); AnimClone_CreateCopy ((IDirect3DRMFrame3 *)local_40.values[0][1], (IDirect3DRMFrame3 *)local_40.values[0][0],lws_00); (*(*(IDirect3DRMFrame3Vtbl **)local_40.values[0][0])->Release) ((IUnknown *)local_40.values[0][0]); (*(*(IDirect3DRMFrame3Vtbl **)local_40.values[0][1])->Release) ((IUnknown *)local_40.values[0][1]); index += 1; } while (index < uVar2); } (*in_stack_00000014->lpVtbl->Release)((IUnknown *)in_stack_00000014); } return; } void __cdecl lego::gfx::AnimClone_CloneLwsMesh(IDirect3DRMFrame3 *rmFrame3,IDirect3DRMFrame3 *param_2) { IDirect3DRMFrame3 *pIVar1; HRESULT HVar2; Mesh *mesh; IDirect3DRMVisual **ppIVar3; IDirect3DRMFrame3 *pIVar4; IDirect3DRMUserVisual *local_14; IDirect3DRMVisual *local_10 [4]; pIVar1 = rmFrame3; // IDirect3DRMFrame3->GetVisuals(this, DWORD* lpdwCount, IDirect3DRMVisualArray** // lplpVisuals) // (NOTE: lightalloy's implementation is missing an argument) (*rmFrame3->lpVtbl->GetVisuals)(rmFrame3,(DWORD *)&rmFrame3,NULL); if (rmFrame3 != NULL) { // IDirect3DRMFrame3->GetVisuals(this, DWORD* lpdwCount, IDirect3DRMVisualArray** // lplpVisuals) // (NOTE: lightalloy's implementation is missing an argument) (*pIVar1->lpVtbl->GetVisuals)(pIVar1,(DWORD *)&rmFrame3,local_10); pIVar1 = param_2; pIVar4 = NULL; if (rmFrame3 != NULL) { ppIVar3 = local_10; do { HVar2 = (*(*ppIVar3)->lpVtbl->QueryInterface) (*ppIVar3,&idl::IID_IDirect3DRMUserVisual,&local_14); if (HVar2 == 0) { mesh = (Mesh *)(*local_14->lpVtbl->GetAppData)((IUnknown *)local_14); Mesh_Clone(mesh,pIVar1); } pIVar4 = (IDirect3DRMFrame3 *)((int)&pIVar4->lpVtbl + 1); ppIVar3 = ppIVar3 + 1; } while (pIVar4 < rmFrame3); } } return; } void __cdecl lego::gfx::AnimClone_ReferenceVisuals(IDirect3DRMFrame3 *orig,IDirect3DRMFrame3 *clone) { IDirect3DRMFrame3 *pIVar1; IDirect3DRMFrame3 *pIVar2; IDirect3DRMVisual **ppIVar3; IDirect3DRMVisual *local_10 [4]; pIVar1 = orig; (*orig->lpVtbl->GetVisuals)(orig,(DWORD *)&orig,NULL); if (orig != NULL) { (*pIVar1->lpVtbl->GetVisuals)(pIVar1,(DWORD *)&orig,local_10); pIVar1 = clone; pIVar2 = NULL; if (orig != NULL) { ppIVar3 = local_10; do { (*pIVar1->lpVtbl->AddVisual)(pIVar1,*ppIVar3); pIVar2 = (IDirect3DRMFrame3 *)((int)&pIVar2->lpVtbl + 1); ppIVar3 = ppIVar3 + 1; } while (pIVar2 < orig); } } return; } void __cdecl lego::image::BMP_Parse(BITMAP_FILE_INFO_STRUCT *data,uint size,D3DRMImage *istruct) { byte bVar1; D3DRMPaletteEntry *pDVar2; int iVar3; DWORD DVar4; D3DRMPaletteEntry *pDVar5; uint uVar6; DWORD DVar7; D3DRMPaletteEntry *pDVar8; if ((data->bmi).biBitCount == 8) { DVar7 = (data->bmi).biClrUsed; if (DVar7 == 0) { DVar7 = 0x100; } pDVar2 = (D3DRMPaletteEntry *)io::Mem_Alloc(0x400); pDVar5 = pDVar2; for (iVar3 = 0x100; iVar3 != 0; iVar3 += -1) { *pDVar5 = (D3DRMPaletteEntry)0x0; pDVar5 = pDVar5 + 1; } pDVar5 = (D3DRMPaletteEntry *)data->bmiColors; pDVar8 = pDVar2; for (DVar4 = DVar7; DVar4 != 0; DVar4 -= 1) { *pDVar8 = *pDVar5; pDVar5 = pDVar5 + 1; pDVar8 = pDVar8 + 1; } istruct->rgb = 0; istruct->red_mask = 0xfc; istruct->green_mask = 0xfc; istruct->blue_mask = 0xfc; istruct->alpha_mask = 0xfc; istruct->palette_size = DVar7; pDVar5 = pDVar2; if (0 < (int)DVar7) { do { bVar1 = pDVar5->red; pDVar5->red = pDVar5->blue; pDVar5->blue = bVar1; DVar7 -= 1; pDVar5 = pDVar5 + 1; } while (DVar7 != 0); } istruct->palette = pDVar2; } else { istruct->rgb = 1; istruct->palette_size = 0; istruct->palette = NULL; } istruct->width = (data->bmi).biWidth; istruct->height = (data->bmi).biHeight; uVar6 = (uint)(data->bmi).biBitCount; istruct->depth = uVar6; if (false) { switchD_00489faf_caseD_9: iVar3 = 0; } else { switch(uVar6) { case 8: iVar3 = 1; break; default: goto switchD_00489faf_caseD_9; case 0xf: case 0x10: iVar3 = 2; break; case 0x18: iVar3 = 3; break; case 0x20: iVar3 = 4; } } istruct->bytes_per_line = iVar3 * istruct->width + 3U & 0xfffffffc; DVar7 = (data->hdr).bfOffBits; istruct->aspecty = 1; istruct->aspectx = 1; istruct->buffer1 = (byte *)((int)data->bmiColors + (DVar7 - 0x36)); istruct->buffer2 = NULL; return; } void __cdecl lego::image::BMP_Cleanup(D3DRMImage *istruct) { if (istruct->palette != NULL) { io::Mem_Free(istruct->palette); } return; } void __cdecl lego::debug::SE(char *error,char *errorDesc) { std::sprintf(globs::dxbugGlobs.DXErrorString, "A DirectX error was set in module %s at line no %i.\nError : %s (code %i)\nDX Module : %s\nError Description : %s\n" ,globs::dxbugGlobs.file,globs::dxbugGlobs.line,error,globs::dxbugGlobs.errnum, globs::constant::DXModuleName[globs::dxbugGlobs.DXModuleNameNumber],errorDesc); return; } HRESULT __cdecl lego::debug::Error_SetDXError(HRESULT err,int DXModule,char *File,int Line) { globs::dxbugGlobs.errnum = err; if ((DXModule < 1) || (globs::dxbugGlobs.DXModuleNameNumber = DXModule, 7 < DXModule)) { globs::dxbugGlobs.DXModuleNameNumber = 0; } globs::dxbugGlobs.line = Line; globs::dxbugGlobs.DXNumErrorsSet += 1; globs::dxbugGlobs.file = File; switch(DXModule) { case 2: if (err < -0x7fffbffe) { if (err == -0x7fffbfff) { SE("DIERR_UNSUPPORTED", "The function called is not supported at this time.\nThis value is equal to the E_NOTIMPL\nstandard COM return value." ); return -0x7fffbfff; } if (err == -0x7ffffff6) { SE("E_PENDING","Data is not yet availabe."); return -0x7ffffff6; } } else { if (err < -0x7fffbffa) { if (err == -0x7fffbffb) { SE("DIERR_GENERIC", "An undetermined error occurred inside the DirectInput subsystem.\nThis value is equal to the E_FAIL standard\nCOM return value." ); return -0x7fffbffb; } if (err == -0x7fffbffe) { SE("DIERR_NOINTERFACE", "The specified interface is not supported by\nthe object. This value is equal to the E_NOINTERFACE\nstandard COM return value." ); return -0x7fffbffe; } } else { if (err < -0x7ffbfeab) { if (err == -0x7ffbfeac) { SE("DIERR_DEVICENOTREG", "The device or device instance is not registered with\nDirectInput. This value is equal to the\nREGDB_E_CLASSNOTREG standard COM return value." ); return -0x7ffbfeac; } if (err == -0x7ffbfef0) { SE("DIERR_NOAGGREGATION","This object does not support aggregation."); return -0x7ffbfef0; } } else { if (err < -0x7ff8fffd) { if (err == -0x7ff8fffe) { SE("DIERR_NOTFOUND","The requested object does not exist."); return -0x7ff8fffe; } switch(err) { case -0x7ffbfdff: SE("DIERR_DEVICEFULL","The device is full."); return err; case -0x7ffbfdfe: SE("DIERR_MOREDATA","Not all the requested information fitted into the buffer"); return err; case -0x7ffbfdfd: SE("DIERR_NOTDOWNLOADED","The effect is not downloaded"); return err; case -0x7ffbfdfc: SE("DIERR_HASEFFECTS", "The device cannot be reinitialized because there\nare still effects attached to it" ); return err; case -0x7ffbfdfb: SE("DIERR_NOTEXCLUSIVEACQUIRED", "The operation cannot be performed unless the device\nis acquired in DISCL_EXCLUSIVE mode." ); return err; case -0x7ffbfdfa: SE("DIERR_INCOMPLETEEFFECT", "The effect could not be downloaded because essential\ninformation is missing. For example, no axes have\nbeen associated with the effect, or no type-specific\ninformation has been supplied" ); return err; case -0x7ffbfdf9: SE("DIERR_NOTBUFFERED", "The device is not buffered.\nSet the DIPROP_BUFFERSIZE property to enable buffering" ); return err; case -0x7ffbfdf8: SE("DIERR_EFFECTPLAYING", "The parameters were updated in memory but were not\ndownloaded to the device because the device does not\nsupport updating an effect while it is still playing." ); return err; } } else { if (err < -0x7ff8fff3) { if (err == -0x7ff8fff4) { SE("DIERR_NOTACQUIRED", "The operation cannot be performed unless\nthe device is acquired."); return -0x7ff8fff4; } if (err == -0x7ff8fffb) { SE("DIERR_HANDLEEXISTS", "The device already has an event notification associated\nwith it. This value is equal to the E_ACCESSDENIED\nstandard COM return value." ); return -0x7ff8fffb; } } else { if (err < -0x7ff8ffea) { if (err == -0x7ff8ffeb) { SE("DIERR_NOTINITIALIZED","This object has not been initialized."); return -0x7ff8ffeb; } if (err == -0x7ff8fff2) { SE("DIERR_OUTOFMEMORY", "The DirectInput subsystem couldn\'t allocate\nsufficient memory to complete the call.\nThis value is equal to the E_OUTOFMEMORY\nstandard COM return value." ); return -0x7ff8fff2; } } else { if (err < -0x7ff8ffa8) { if (err == -0x7ff8ffa9) { SE("DIERR_INVALIDPARAM", "An invalid parameter was passed to the returning function, or the object was not in a state that permitted the function to be called. This value is equal to the E_INVALIDARG standard COM return value." ); return -0x7ff8ffa9; } if (err == -0x7ff8ffe2) { SE("DIERR_INPUTLOST", "Access to the input device has been lost. It must be reacquired."); return -0x7ff8ffe2; } } else { if (err < -0x7ff8ff55) { if (err == -0x7ff8ff56) { SE("DIERR_ACQUIRED", "The operation cannot be performed while\nthe device is acquired."); return -0x7ff8ff56; } if (err == -0x7ff8ff89) { SE("DIERR_BADDRIVERVER", "The object could not be created due to an\nincompatible driver version or mismatched or\nincomplete driver components." ); return -0x7ff8ff89; } } else { if (err < -0x7ff8fb7e) { if (err == -0x7ff8fb7f) { SE("DIERR_BETADIRECTINPUTVERSION", "The application was written for an unsupported\nprerelease version of DirectInput." ); return -0x7ff8fb7f; } if (err == -0x7ff8fb82) { SE("DIERR_OLDDIRECTINPUTVERSION", "The application requires a newer version of DirectInput."); return -0x7ff8fb82; } } else { if (err < 1) { if (err == 0) { SE("DI_OK", "The operation completed successfully.\nThis value is equal to the S_OK standard\nCOM return value." ); return 0; } if (err == -0x7ff8fb21) { SE("DIERR_ALREADYINITIALIZED","This object is already initialized"); return -0x7ff8fb21; } } else { if (true) { switch(err) { case 1: SE("DI_BUFFEROVERFLOW", "The device buffer overflowed and some input was lost.\nThis value is equal to the S_FALSE\nstandard COM return value." ); return err; case 2: SE("DI_POLLEDDEVICE", "The device is a polled device.\nAs a result, device buffering will not collect\nany data and event notifications will not be signaled\nuntil the IDirectInputDevice2::Poll method is called." ); return err; case 3: SE("DI_DOWNLOADSKIPPED", "The parameters of the effect were successfully updated,\nbut the effect could not be downloaded because the associated\ndevice was not acquired in exclusive mode." ); return err; case 4: SE("DI_EFFECTRESTARTED", "The effect was stopped,\nthe parameters were updated,\nand the effect was restarted." ); return err; case 8: SE("DI_TRUNCATED", "The parameters of the effect were successfully updated,\nbut some of them were beyond the capabilities of the\ndevice and were truncated to the nearest supported value." ); return err; case 0xc: SE("DI_TRUNCATEDANDRESTARTED", "Equal to DI_EFFECTRESTARTED | DI_TRUNCATED"); return err; } } } } } } } } } } } } break; case 3: if (err < -0x7fffbffa) { if (err == -0x7fffbffb) { SE("DDERR_GENERIC","There is an undefined error condition."); return -0x7fffbffb; } if (err == -0x7fffbfff) { SE("DDERR_UNSUPPORTED","The operation is not supported."); return -0x7fffbfff; } } else { if (err < -0x7ff8fff1) { if (err == -0x7ff8fff2) { SE("DDERR_OUTOFMEMORY","DirectDraw does not have enough\nmemory to perform the operation." ); return -0x7ff8fff2; } if (err == -0x7ffbfe10) { SE("DDERR_NOTINITIALIZED", "An attempt was made to call an interface method\nof a DirectDraw object created by CoCreateInstance before\nthe object was initialized." ); return -0x7ffbfe10; } } else { if (err < -0x7789fffa) { if (err == -0x7789fffb) { SE("DDERR_ALREADYINITIALIZED","The object has already been initialized."); return -0x7789fffb; } if (err == -0x7ff8ffa9) { SE("DDERR_INVALIDPARAMS", "One or more of the parameters passed to the\nmethod are incorrect."); return -0x7ff8ffa9; } } else { if (err < -0x7789ffeb) { if (err == -0x7789ffec) { SE("DDERR_CANNOTDETACHSURFACE", "A surface cannot be detached from another\nrequested surface."); return -0x7789ffec; } if (err == -0x7789fff6) { SE("DDERR_CANNOTATTACHSURFACE", "A surface cannot be attached to\nanother requested surface."); return -0x7789fff6; } } else { if (err < -0x7789ffc8) { if (err == -0x7789ffc9) { SE("DDERR_EXCEPTION", "An exception was encountered while performing the requested operation."); return -0x7789ffc9; } if (err == -0x7789ffd8) { SE("DDERR_CURRENTLYNOTAVAIL","No support is currently available."); return -0x7789ffd8; } } else { if (err < -0x7789ffa0) { if (err == -0x7789ffa1) { SE("DDERR_INCOMPATIBLEPRIMARY", "The primary surface creation request does\nnot match with the existing primary surface." ); return -0x7789ffa1; } if (err == -0x7789ffa6) { SE("DDERR_HEIGHTALIGN", "The height of the provided rectangle is not\na multiple of the required alignment." ); return -0x7789ffa6; } } else { if (err < -0x7789ff91) { if (err == -0x7789ff92) { SE("DDERR_INVALIDCLIPLIST","DirectDraw does not support the provided clip list." ); return -0x7789ff92; } if (err == -0x7789ff9c) { SE("DDERR_INVALIDCAPS", "One or more of the capability bits passed to\nthe callback function are incorrect." ); return -0x7789ff9c; } } else { if (err < -0x7789ff7d) { if (err == -0x7789ff7e) { SE("DDERR_INVALIDOBJECT", "DirectDraw received a pointer that was an\ninvalid DirectDraw object."); return -0x7789ff7e; } if (err == -0x7789ff88) { SE("DDERR_INVALIDMODE","DirectDraw does not support the requested mode."); return -0x7789ff88; } } else { if (err < -0x7789ff69) { if (err == -0x7789ff6a) { SE("DDERR_INVALIDRECT","The provided rectangle was invalid."); return -0x7789ff6a; } if (err == -0x7789ff6f) { SE("DDERR_INVALIDPIXELFORMAT","The pixel format was invalid as specified."); return -0x7789ff6f; } } else { if (err < -0x7789ff55) { if (err == -0x7789ff56) { SE("DDERR_NO3D","No 3-D hardware or emulation is present."); return -0x7789ff56; } if (err == -0x7789ff60) { SE("DDERR_LOCKEDSURFACES", "One or more surfaces are locked, causing the failure of\nthe requested operation." ); return -0x7789ff60; } } else { if (err < -0x7789ff32) { if (err == -0x7789ff33) { SE("DDERR_NOCLIPLIST","No clip list is available."); return -0x7789ff33; } if (err == -0x7789ff4c) { SE("DDERR_NOALPHAHW", "No alpha acceleration hardware is present or\navailable, causing the failure of\nthe requested operation." ); return -0x7789ff4c; } } else { if (err < -0x7789ff23) { if (err == -0x7789ff24) { SE("DDERR_NOCOLORKEYHW", "The operation cannot be carried out because there is\nno hardware support for the destination color key." ); return -0x7789ff24; } if (err == -0x7789ff2e) { SE("DDERR_NOCOLORCONVHW", "The operation cannot be carried out because no\ncolor-conversion hardware is present or available." ); return -0x7789ff2e; } if (err == -0x7789ff2c) { SE("DDERR_NOCOOPERATIVELEVELSET", "A create function is called without the\nIDirectDraw2::SetCooperativeLevel method being called." ); return -0x7789ff2c; } if (err == -0x7789ff29) { SE("DDERR_NOCOLORKEY", "The surface does not currently have a color key."); return -0x7789ff29; } } else { if (err < -0x7789ff1e) { if (err == -0x7789ff1f) { SE("DDERR_NOEXCLUSIVEMODE", "The operation requires the application to have exclusive mode,\nbut the application does not have exclusive mode." ); return -0x7789ff1f; } if (err == -0x7789ff22) { SE("DDERR_NODIRECTDRAWSUPPORT", "DirectDraw support is not possible\nwith the current display driver." ); return -0x7789ff22; } } else { if (err < -0x7789ff0f) { if (err == -0x7789ff10) { SE("DDERR_NOGDI","No GDI is present."); return -0x7789ff10; } if (err == -0x7789ff1a) { SE("DDERR_NOFLIPHW","Flipping visible surfaces is not supported.") ; return -0x7789ff1a; } } else { if (err < -0x7789ff00) { if (err == -0x7789ff01) { SE("DDERR_NOTFOUND","The requested item was not found."); return -0x7789ff01; } if (err == -0x7789ff06) { SE("DDERR_NOMIRRORHW", "The operation cannot be carried out because no mirroring\nhardware is present or available." ); return -0x7789ff06; } } else { if (err < -0x7789fee7) { if (err == -0x7789fee8) { SE("DDERR_NORASTEROPHW", "The operation cannot be carried out because no appropriate\nraster operation hardware is present or available." ); return -0x7789fee8; } if (err == -0x7789fefc) { SE("DDERR_NOOVERLAYHW", "The operation cannot be carried out because no\noverlay hardware is present or available." ); return -0x7789fefc; } } else { if (err < -0x7789fec9) { if (err == -0x7789feca) { SE("DDERR_NOSTRETCHHW", "The operation cannot be carried out because\nthere is no hardware support for stretching." ); return -0x7789feca; } if (err == -0x7789fede) { SE("DDERR_NOROTATIONHW", "The operation cannot be carried out because\nno rotation hardware is present or available." ); return -0x7789fede; } } else { if (err < -0x7789feb5) { if (err == -0x7789feb6) { SE("DDERR_NOTEXTUREHW", "The operation cannot be carried out because no\ntexture-mapping hardware is present or available." ); return -0x7789feb6; } if (err == -0x7789fec4) { SE("DDERR_NOT4BITCOLOR", "The DirectDrawSurface object is not using a 4-bit color palette\nand the requested operation requires a 4-bit color palette." ); return -0x7789fec4; } if (err == -0x7789fec3) { SE("DDERR_NOT4BITCOLORINDEX", "The DirectDrawSurface object is not using a 4-bit color index\npalette and the requested operation requires a\n4-bit color index palette." ); return -0x7789fec3; } if (err == -0x7789fec0) { SE("DDERR_NOT8BITCOLOR", "The DirectDrawSurface object is not using an 8-bit color\npalette and the requested operation requires\nan 8-bit color palette." ); return -0x7789fec0; } } else { if (err < -0x7789feab) { if (err == -0x7789feac) { SE("DDERR_NOZBUFFERHW", "The operation to create a z-buffer in display memory\nor to perform a blit using a z-buffer cannot be\ncarried out because there is no hardware support\nfor z-buffers." ); return -0x7789feac; } if (err == -0x7789feb1) { SE("DDERR_NOVSYNCHW", "The operation cannot be carried out because\nthere is no hardware support for vertical\nblank synchronized operations." ); return -0x7789feb1; } } else { if (err < -0x7789fe97) { if (err == -0x7789fe98) { SE("DDERR_OUTOFCAPS", "The hardware needed for the requested\noperation has already been allocated." ); return -0x7789fe98; } if (err == -0x7789fea2) { SE("DDERR_NOZOVERLAYHW", "The overlay surfaces cannot be z-layered based on the\nz-order because the hardware does not support\nz-ordering of overlays." ); return -0x7789fea2; } } else { if (err < -0x7789fe6f) { if (err == -0x7789fe70) { SE("DDERR_COLORKEYNOTSET", "No source color key is specified for this operation." ); return -0x7789fe70; } if (true) { switch(err) { case -0x7789fe84: SE("DDERR_OUTOFVIDEOMEMORY", "DirectDraw does not have enough display\nmemory to perform the operation." ); return err; case -0x7789fe82: SE("DDERR_OVERLAYCANTCLIP", "The hardware does not support clipped overlays.") ; return err; case -0x7789fe80: SE("DDERR_OVERLAYCOLORKEYONLYONEACTIVE", "An attempt was made to have more than one\ncolor key active on an overlay." ); return err; case -0x7789fe7d: SE("DDERR_PALETTEBUSY", "Access to this palette is refused because\nthe palette is locked by another thread." ); return err; } } } else { if (err < -0x7789fe5b) { if (err == -0x7789fe5c) { SE("DDERR_SURFACEALREADYDEPENDENT", "An attempt was made to make a surface a dependency\nof another surface to which it is\nalready dependent." ); return -0x7789fe5c; } if (err == -0x7789fe66) { SE("DDERR_SURFACEALREADYATTACHED", "An attempt was made to attach a surface to another\nsurface to which it is already attached." ); return -0x7789fe66; } } else { if (err < -0x7789fe4c) { if (err == -0x7789fe4d) { SE("DDERR_CANTLOCKSURFACE", "Access to this surface is refused because an\nattempt was made to lock the primary\nsurface without DCI support." ); return -0x7789fe4d; } if (err == -0x7789fe52) { SE("DDERR_SURFACEBUSY", "Access to the surface is refused because\nthe surface is locked by another thread." ); return -0x7789fe52; } } else { if (err < -0x7789fe3d) { if (err == -0x7789fe3e) { SE("DDERR_SURFACELOST", "Access to the surface is refused because the surface\nmemory is gone. The DirectDrawSurface object representing this\nsurface should have the IDirectDrawSurface3::Restore\nmethod called on it." ); return -0x7789fe3e; } if (err == -0x7789fe48) { SE("DDERR_SURFACEISOBSCURED", "Access to the surface is refused\nbecause the surface is obscured." ); return -0x7789fe48; } } else { if (err < -0x7789fe29) { if (err == -0x7789fe2a) { SE("DDERR_TOOBIGHEIGHT", "The height requested by DirectDraw is too large." ); return -0x7789fe2a; } if (err == -0x7789fe34) { SE("DDERR_SURFACENOTATTACHED", "The requested surface is not attached."); return -0x7789fe34; } } else { if (err < -0x7789fe15) { if (err == -0x7789fe16) { SE("DDERR_TOOBIGWIDTH", "The width requested by DirectDraw\nis too large." ); return -0x7789fe16; } if (err == -0x7789fe20) { SE("DDERR_TOOBIGSIZE", "The size requested by DirectDraw is too large.\nHowever, the individual height and\nwidth are OK." ); return -0x7789fe20; } } else { if (err < -0x7789fdf7) { if (err == -0x7789fdf8) { SE("DDERR_UNSUPPORTEDMASK", "The bitmask in the pixel format requested\nis not supported by DirectDraw." ); return -0x7789fdf8; } if (err == -0x7789fe02) { SE("DDERR_UNSUPPORTEDFORMAT", "The FourCC format requested is\nnot supported by DirectDraw." ); return -0x7789fe02; } } else { if (err < -0x7789fde3) { if (err == -0x7789fde4) { SE("DDERR_WASSTILLDRAWING", "The previous blit operation that is transferring\ninformation to or from this\nsurface is incomplete." ); return -0x7789fde4; } if (err == -0x7789fde7) { SE("DDERR_VERTICALBLANKINPROGRESS", "A vertical blank is in progress."); return -0x7789fde7; } } else { if (err < -0x7789fd89) { if (err == -0x7789fd8a) { SE("DDERR_NONONLOCALVIDME", "An attempt was made to allocate non-local video\nmemory from a device that does not support non-local\nvideo memory" ); return -0x7789fd8a; } if (true) { switch(err) { case -0x7789fdd0: SE("DDERR_XALIGN", "The provided rectangle was not horizontally\naligned on a required boundary." ); return err; case -0x7789fdcf: SE("DDERR_INVALIDDIRECTDRAWGUID", "The globally unique identifier (GUID) passed to the\nDirectDrawCreate function is not a valid DirectDraw\ndriver identifier." ); return err; case -0x7789fdce: SE("DDERR_DIRECTDRAWALREADYCREATED", "A DirectDraw object representing this driver\nhas already been created for this process." ); return err; case -0x7789fdcd: SE("DDERR_NODIRECTDRAWHW", "Hardware-only DirectDraw object creation is not possible;\nthe driver does not support any hardware." ); return err; case -0x7789fdcc: SE("DDERR_PRIMARYSURFACEALREADYEXISTS", "This process has already created a primary surface." ); return err; case -0x7789fdcb: SE("DDERR_NOEMULATION", "Software emulation is not available."); return err; case -0x7789fdca: SE("DDERR_REGIONTOOSMALL", "The region passed to the\nIDirectDrawClipper::GetClipList\nmethod is too small." ); return err; case -0x7789fdc9: SE("DDERR_CLIPPERISUSINGHWND", "An attempt was made to set a clip list for a\nDirectDrawClipper object that is already monitoring\na window handle." ); return err; case -0x7789fdc8: SE("DDERR_NOCLIPPERATTACHED", "No DirectDrawClipper object is attached\nto the surface object." ); return err; case -0x7789fdc7: SE("DDERR_NOHWND", "Clipper notification requires a window handle,\nor no window handle has been previously set as\nthe cooperative level window handle." ); return err; case -0x7789fdc6: SE("DDERR_HWNDSUBCLASSED", "DirectDraw is prevented from restoring state\nbecause the DirectDraw cooperative level window\nhandle has been subclassed." ); return err; case -0x7789fdc5: SE("DDERR_HWNDALREADYSET", "The DirectDraw cooperative level window handle\nhas already been set. It cannot be reset while the process\nhas surfaces or palettes created." ); return err; case -0x7789fdc4: SE("DDERR_NOPALETTEATTACHED", "No palette object is attached to this surface."); return err; case -0x7789fdc3: SE("DDERR_NOPALETTEHW", "There is no hardware support for 16- or 256-color palettes." ); return err; case -0x7789fdc2: SE("DDERR_BLTFASTCANTCLIP", "A DirectDrawClipper object is attached to a source\nsurface that has passed into a call to the\nIDirectDrawSurface3::BltFast method." ); return err; case -0x7789fdc1: SE("DDERR_NOBLTHW", "No blitter hardware is present."); return err; case -0x7789fdc0: SE("DDERR_NODDROPSHW", "No DirectDraw raster operation (ROP) hardware is available." ); return err; case -0x7789fdbf: SE("DDERR_OVERLAYNOTVISIBLE", "The IDirectDrawSurface3::GetOverlayPosition method\nis called on a hidden overlay." ); return err; case -0x7789fdbe: SE("DDERR_NOOVERLAYDEST", "The IDirectDrawSurface3::GetOverlayPosition method is called\non an overlay that the IDirectDrawSurface3::UpdateOverlay method\nhas not been called on to establish a destination." ); return err; case -0x7789fdbd: SE("DDERR_INVALIDPOSITION", "The position of the overlay on the destination is no longer legal." ); return err; case -0x7789fdbc: SE("DDERR_NOTAOVERLAYSURFACE", "An overlay component is called for a non-overlay surface." ); return err; case -0x7789fdbb: SE("DDERR_EXCLUSIVEMODEALREADYSET", "An attempt was made to set the cooperative level\nwhen it was already set to exclusive." ); return err; case -0x7789fdba: SE("DDERR_NOTFLIPPABLE", "An attempt has been made to flip\na surface that cannot be flipped." ); return err; case -0x7789fdb9: SE("DDERR_CANTDUPLICATE", "Primary and 3-D surfaces, or surfaces that\nare implicitly created, cannot be duplicated." ); return err; case -0x7789fdb8: SE("DDERR_NOTLOCKED", "An attempt is made to unlock a\nsurface that was not locked." ); return err; case -0x7789fdb7: SE("DDERR_CANTCREATEDC", "Windows cannot create any more device\ncontexts (DCs)." ); return err; case -0x7789fdb6: SE("DDERR_NODC", "No DC has ever been created for this surface."); return err; case -0x7789fdb5: SE("DDERR_WRONGMODE", "This surface cannot be restored because it\nwas created in a different mode." ); return err; case -0x7789fdb4: SE("DDERR_IMPLICITLYCREATED", "The surface cannot be restored because\nit is an implicitly created surface." ); return err; case -0x7789fdb3: SE("DDERR_NOTPALETTIZED", "The surface being used is not a\npalette-based surface." ); return err; case -0x7789fdb2: SE("DDERR_UNSUPPORTEDMODE", "The display is currently in\nan unsupported mode." ); return err; case -0x7789fdb1: SE("DDERR_NOMIPMAPHW", "The operation cannot be carried out because no mipmap\ntexture mapping hardware is present or available." ); return err; case -0x7789fdb0: SE("DDERR_INVALIDSURFACETYPE", "The requested operation could not be performed\nbecause the surface was of the wrong type." ); return err; case -0x7789fda8: SE("DDERR_NOOPTIMIZEH", "The device does not support optimized surfaces"); return err; case -0x7789fda7: SE("DDERR_NOTLOADE", "The surface is an optimized surface,\nbut it has not yet been allocated any memory" ); return err; case -0x7789fd94: SE("DDERR_DCALREADYCREATED", "A device context (DC) has already been returned\nfor this surface. Only one DC can be retrieved for each surface." ); return err; } } } else { if (err < -0x7789fd6b) { if (err == -0x7789fd6c) { SE("DDERR_CANTPAGEUNLOCK", "An attempt to page unlock a surface failed.\nPage unlock will not work on a display-memory\nsurface or an emulated primary surface." ); return -0x7789fd6c; } if (err == -0x7789fd80) { SE("DDERR_CANTPAGELOCK", "An attempt to page lock a surface failed.\nPage lock will not work on a display-memory surface or\nan emulated primary surface." ); return -0x7789fd80; } } else { if (err < -0x7789fd4d) { if (err == -0x7789fd4e) { SE("DDERR_MOREDAT", "There is more data available than the\nspecified buffer size can hold" ); return -0x7789fd4e; } if (err == -0x7789fd58) { SE("DDERR_NOTPAGELOCKED", "An attempt is made to page unlock a\nsurface with no outstanding page locks." ); return -0x7789fd58; } } else { if (err == -0x7789fd49) { SE("DDERR_VIDEONOTACTIV", "The video port is not active"); return -0x7789fd49; } if (err == -0x7789fd45) { SE("DDERR_DEVICEDOESNTOWNSURFAC", "Surfaces created by one direct draw device cannot\nbe used directly by another direct draw device" ); return -0x7789fd45; } if (err == 0) { SE("DD_OK","The request completed successfully." ); return 0; } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } break; case 4: SE("Unknown","Error handling is unsupported in this module"); case 5: SE("Unknown","Error handling is unsupported in this module"); case 6: SE("Unknown","Error handling is unsupported in this module"); case 1: if (err < 1) { if (err == 0) { SE("D3DRM_OK","No error."); return 0; } if (true) { switch(err) { case -0x7789fcf3: SE("D3DRMERR_BADOBJECT","Object expected in argument."); return err; case -0x7789fcf2: SE("D3DRMERR_BADTYPE","Bad argument type passed."); return err; case -0x7789fcf1: SE("D3DRMERR_BADALLOC","Out of memory."); return err; case -0x7789fcf0: SE("D3DRMERR_FACEUSED","Face already used in a mesh."); return err; case -0x7789fcef: SE("D3DRMERR_NOTFOUND","Object not found in specified place."); return err; case -0x7789fcee: SE("D3DRMERR_NOTDONEYET","Unimplemented."); return err; case -0x7789fced: SE("D3DRMERR_FILENOTFOUND","File cannot be opened."); return err; case -0x7789fcec: SE("D3DRMERR_BADFILE","Data file is corrupt."); return err; case -0x7789fceb: SE("D3DRMERR_BADDEVICE","Device is not compatible with renderer."); return err; case -0x7789fcea: SE("D3DRMERR_BADVALUE","Bad argument value passed."); return err; case -0x7789fce9: SE("D3DRMERR_BADMAJORVERSION","Bad DLL major version."); return err; case -0x7789fce8: SE("D3DRMERR_BADMINORVERSION","Bad DLL minor version."); return err; case -0x7789fce7: SE("D3DRMERR_UNABLETOEXECUTE","Unable to carry out procedure."); return err; case -0x7789fce4: SE("D3DRMERR_PENDING", "The data required to supply the requested\ninformation has not finished loading."); return err; case -0x7789fce3: SE("D3DRMERR_NOTENOUGHDATA", "Not enough data has been loaded to\nperform the requested operation."); return err; case -0x7789fce2: SE("D3DRMERR_REQUESTTOOLARGE", "An attempt was made to set a level\nof detail in a progressive mesh greater than the maximum available." ); return err; case -0x7789fce1: SE("D3DRMERR_REQUESTTOOSMALL", "An attempt was made to set the minimum\nrendering detail of a progressive mesh smaller than\nthe detail in the base mesh\n(the minimum for rendering)." ); return err; case -0x7789fce0: SE("D3DRMERR_CONNECTIONLOST", "Data connection was lost during a load,\nclone, or duplicate."); return err; case -0x7789fcdc: SE("D3DRMERR_BOXNOTSET", "An attempt was made to access a bounding box\n(for example, with IDirect3DRMFrame2::GetBox)\nwhen no bounding box was set on the frame." ); return err; case -0x7789fcdb: SE("D3DRMERR_BADPMDATA", "The data in the X File is corrupted.\nThe conversion to a progressive mesh succeeded but\nproduced an invalid progressive mesh in\nthe X File." ); return err; } } } break; case 7: SE("QUERY_INTERFACE","The requested interface could not be obtained"); return err; default: SE("Unknown","An error in an unknown DirectX module/object was raised"); return err; } SE("UNKNOWN ERROR","Invalid error code specified"); return err; } void __cdecl lego::debug::Error_Initialise(void) { globs::errorGlobs.dumpFile = NULL; globs::errorGlobs.loadLogFile = NULL; globs::errorGlobs.loadErrorLogFile = NULL; globs::errorGlobs.redundantLogFile = NULL; globs::errorGlobs.fullScreen = 0; return; } void __cdecl lego::debug::Error_FullScreen(BOOL on) { globs::errorGlobs.fullScreen = on; return; } void __cdecl lego::debug::Error_CloseLog(void) { if (globs::errorGlobs.dumpFile != NULL) { io::File_Close(globs::errorGlobs.dumpFile); } if (globs::errorGlobs.loadLogFile != NULL) { io::File_Close(globs::errorGlobs.loadLogFile); } if (globs::errorGlobs.loadErrorLogFile != NULL) { io::File_Close(globs::errorGlobs.loadErrorLogFile); } globs::errorGlobs.dumpFile = NULL; globs::errorGlobs.loadLogFile = NULL; globs::errorGlobs.loadErrorLogFile = NULL; return; } void __cdecl lego::debug::Error_Shutdown(void) { Error_CloseLog(); globs::errorGlobs.redundantLogFile = io::File_Open(globs::errorGlobs.redundantLogName,"w"); if (globs::errorGlobs.redundantLogFile != NULL) { io::File_CheckRedundantFiles(globs::errorGlobs.loadLogName); io::File_Close(globs::errorGlobs.redundantLogFile); } return; } char * __cdecl lego::registry::Registry_GetKeyFromPath(char *path,char *out_str) { char cVar1; *out_str = '\0'; cVar1 = *path; while ((cVar1 != '\0' && (cVar1 != '\\'))) { path = path + 1; *out_str = cVar1; out_str = out_str + 1; cVar1 = *path; } if (*path == '\\') { path = path + 1; } *out_str = '\0'; return path; } BOOL __cdecl lego::registry::Registry_GetValue (char *path,char *key,RegistryType dataType,char *out_data,uint dataSize) { BOOL BVar1; BVar1 = Registry_GetValue_Recursive((HKEY)HKEY_LOCAL_MACHINE,path,key,dataType,out_data,dataSize); return BVar1; } BOOL __cdecl lego::registry::Registry_GetValue_Recursive (HKEY parent,char *path,char *key,RegistryType dataType,char *out_data,uint dataSize) { char *path_00; LSTATUS LVar1; HKEY pHVar2; HKEY local_68; char str [100]; path_00 = Registry_GetKeyFromPath(path,str); if (str[0] != '\0') { // Open the key and recurse RegCreateKeyA(parent,str,&local_68); if (local_68 == NULL) { return (BOOL)local_68; } pHVar2 = (HKEY)Registry_GetValue_Recursive(local_68,path_00,key,dataType,out_data,dataSize); RegCloseKey(local_68); return (BOOL)pHVar2; } path = NULL; // REG_NONE (0x0) if (dataType != REGISTRY_STRING_VALUE) { // REG_SZ (0x1) if (dataType != REGISTRY_DWORD_VALUE) { return (BOOL)NULL; } LVar1 = RegQueryValueExA(parent,key,NULL,(LPDWORD)&path,(LPBYTE)out_data,&dataSize); return (BOOL)(HKEY)(uint)(LVar1 == 0); } LVar1 = RegQueryValueExA(parent,key,NULL,(LPDWORD)&path,(LPBYTE)out_data,&dataSize); return (BOOL)(HKEY)(uint)(LVar1 == 0); } BOOL __cdecl lego::wad::GetFileName(FILE *f,char *out_str) { char cVar1; int iVar2; iVar2 = std::fgetc(f); cVar1 = (char)iVar2; while (cVar1 != '\0') { *out_str = (char)iVar2; out_str = out_str + 1; iVar2 = std::fgetc(f); cVar1 = (char)iVar2; } *out_str = '\0'; return TRUE; } // WARNING: Function: _alloca4k replaced with injection: alloca_probe // Open the wad and map in the file data. // Returns a handle to the wad file. int __cdecl lego::wad::Wad_Load(char *fName) { char cVar1; int wadNo; FILE *stream; Wad *pWVar2; size_t sVar3; char **ppcVar4; BOOL BVar5; char *pcVar6; WadEntry *pWVar7; int iVar8; uint uVar9; uint uVar10; int iVar11; undefined4 *puVar12; char *pcVar13; undefined4 *puVar14; bool bVar15; size_t sVar16; FILE *pFVar17; char acStack4100 [4]; char acStack4096 [4092]; undefined4 uStack4; uStack4 = 0x48b7aa; iVar11 = 0; wadNo = Wad_GetFreeWadSlot(); if (wadNo != -1) { stream = std::fopen(fName,"rb"); pWVar2 = Wad_Get(wadNo); pWVar2->fWad = stream; if (stream != NULL) { pWVar2 = Wad_Get(wadNo); pWVar2->active = 1; sVar3 = std::fread(acStack4100,1,4,stream); if (sVar3 != 4) { std::fclose(stream); return -1; } iVar8 = 4; bVar15 = true; pcVar6 = acStack4100; pcVar13 = "WWAD"; do { if (iVar8 == 0) break; iVar8 += -1; bVar15 = *pcVar6 == *pcVar13; pcVar6 = pcVar6 + 1; pcVar13 = pcVar13 + 1; } while (bVar15); if (!bVar15) { std::fclose(stream); return -1; } sVar16 = 4; sVar3 = 1; pFVar17 = stream; pWVar2 = Wad_Get(wadNo); sVar3 = std::fread(&pWVar2->numFiles,sVar3,sVar16,pFVar17); if (sVar3 != 4) { std::fclose(stream); return -1; } pWVar2 = Wad_Get(wadNo); ppcVar4 = (char **)io::Mem_Alloc(pWVar2->numFiles << 2); pWVar2 = Wad_Get(wadNo); pWVar2->wadNames = ppcVar4; pWVar2 = Wad_Get(wadNo); ppcVar4 = (char **)io::Mem_Alloc(pWVar2->numFiles << 2); pWVar2 = Wad_Get(wadNo); pWVar2->fileNames = ppcVar4; pWVar2 = Wad_Get(wadNo); if ((pWVar2->wadNames != NULL) && (pWVar2 = Wad_Get(wadNo), pWVar2->fileNames != NULL)) { pWVar2 = Wad_Get(wadNo); uVar9 = pWVar2->numFiles; pWVar2 = Wad_Get(wadNo); ppcVar4 = pWVar2->wadNames; for (uVar9 &= 0x3fffffff; uVar9 != 0; uVar9 -= 1) { *ppcVar4 = NULL; ppcVar4 = ppcVar4 + 1; } for (iVar8 = 0; iVar8 != 0; iVar8 += -1) { *(undefined *)ppcVar4 = 0; ppcVar4 = (char **)((int)ppcVar4 + 1); } pWVar2 = Wad_Get(wadNo); uVar9 = pWVar2->numFiles; pWVar2 = Wad_Get(wadNo); ppcVar4 = pWVar2->fileNames; for (uVar9 &= 0x3fffffff; uVar9 != 0; uVar9 -= 1) { *ppcVar4 = NULL; ppcVar4 = ppcVar4 + 1; } for (iVar8 = 0; iVar8 != 0; iVar8 += -1) { *(undefined *)ppcVar4 = 0; ppcVar4 = (char **)((int)ppcVar4 + 1); } pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { BVar5 = GetFileName(stream,acStack4096); if (BVar5 == 0) { pWVar2 = Wad_Get(wadNo); if (pWVar2->wadNames != NULL) { iVar11 = 0; pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { pWVar2 = Wad_Get(wadNo); if (pWVar2->wadNames[iVar11] != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames[iVar11]); } iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames); } pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->fileNames); } std::fclose(stream); return -1; } uVar9 = 0xffffffff; pcVar6 = acStack4096; do { if (uVar9 == 0) break; uVar9 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); pcVar6 = (char *)io::Mem_Alloc(~uVar9); pWVar2 = Wad_Get(wadNo); pWVar2->wadNames[iVar11] = pcVar6; pWVar2 = Wad_Get(wadNo); uVar9 = 0xffffffff; pcVar6 = acStack4096; do { pcVar13 = pcVar6; if (uVar9 == 0) break; uVar9 -= 1; pcVar13 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar13; } while (cVar1 != '\0'); uVar9 = ~uVar9; puVar12 = (undefined4 *)(pcVar13 + -uVar9); puVar14 = (undefined4 *)pWVar2->wadNames[iVar11]; for (uVar10 = uVar9 >> 2; uVar10 != 0; uVar10 -= 1) { *puVar14 = *puVar12; puVar12 = puVar12 + 1; puVar14 = puVar14 + 1; } for (uVar9 &= 3; uVar9 != 0; uVar9 -= 1) { *(undefined *)puVar14 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar14 = (undefined4 *)((int)puVar14 + 1); } pWVar2 = Wad_Get(wadNo); io::File_Error("%s\n",pWVar2->wadNames[iVar11]); iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } iVar11 = 0; pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { BVar5 = GetFileName(stream,acStack4096); if (BVar5 == 0) { pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames != NULL) { iVar11 = 0; pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { pWVar2 = Wad_Get(wadNo); if (pWVar2->wadNames[iVar11] != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames[iVar11]); } iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames); } pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames != NULL) { iVar11 = 0; pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames[iVar11] != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->fileNames[iVar11]); } iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->fileNames); std::fclose(stream); return -1; } goto LAB_0048be6d; } uVar9 = 0xffffffff; pcVar6 = acStack4096; do { if (uVar9 == 0) break; uVar9 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); pcVar6 = (char *)io::Mem_Alloc(~uVar9); pWVar2 = Wad_Get(wadNo); pWVar2->fileNames[iVar11] = pcVar6; pWVar2 = Wad_Get(wadNo); uVar9 = 0xffffffff; pcVar6 = acStack4096; do { pcVar13 = pcVar6; if (uVar9 == 0) break; uVar9 -= 1; pcVar13 = pcVar6 + 1; cVar1 = *pcVar6; pcVar6 = pcVar13; } while (cVar1 != '\0'); uVar9 = ~uVar9; puVar12 = (undefined4 *)(pcVar13 + -uVar9); puVar14 = (undefined4 *)pWVar2->fileNames[iVar11]; for (uVar10 = uVar9 >> 2; uVar10 != 0; uVar10 -= 1) { *puVar14 = *puVar12; puVar12 = puVar12 + 1; puVar14 = puVar14 + 1; } for (uVar9 &= 3; uVar9 != 0; uVar9 -= 1) { *(undefined *)puVar14 = *(undefined *)puVar12; puVar12 = (undefined4 *)((int)puVar12 + 1); puVar14 = (undefined4 *)((int)puVar14 + 1); } pWVar2 = Wad_Get(wadNo); io::File_Error("%s\n",pWVar2->fileNames[iVar11]); iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } pWVar2 = Wad_Get(wadNo); pWVar7 = (WadEntry *)io::Mem_Alloc(pWVar2->numFiles << 4); pWVar2 = Wad_Get(wadNo); pWVar2->wadEntries = pWVar7; pWVar2 = Wad_Get(wadNo); if (pWVar2->wadEntries == NULL) { pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames != NULL) { iVar11 = 0; pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { pWVar2 = Wad_Get(wadNo); if (pWVar2->wadNames[iVar11] != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames[iVar11]); } iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames); } pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames != NULL) { iVar11 = 0; pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames[iVar11] != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->fileNames[iVar11]); } iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->fileNames); } std::fclose(stream); return -1; } pFVar17 = stream; pWVar2 = Wad_Get(wadNo); sVar3 = pWVar2->numFiles << 4; sVar16 = 1; pWVar2 = Wad_Get(wadNo); sVar3 = std::fread(pWVar2->wadEntries,sVar16,sVar3,pFVar17); pWVar2 = Wad_Get(wadNo); if (sVar3 == pWVar2->numFiles << 4) { return wadNo; } pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames != NULL) { iVar11 = 0; pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { pWVar2 = Wad_Get(wadNo); if (pWVar2->wadNames[iVar11] != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames[iVar11]); } iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames); } pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames != NULL) { iVar11 = 0; pWVar2 = Wad_Get(wadNo); if (0 < pWVar2->numFiles) { do { pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames[iVar11] != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->fileNames[iVar11]); } iVar11 += 1; pWVar2 = Wad_Get(wadNo); } while (iVar11 < pWVar2->numFiles); } pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->fileNames); } pWVar2 = Wad_Get(wadNo); if (pWVar2->wadEntries != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadEntries); } LAB_0048be6d: std::fclose(stream); return -1; } std::fclose(stream); pWVar2 = Wad_Get(wadNo); if (pWVar2->wadNames != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->wadNames); } pWVar2 = Wad_Get(wadNo); if (pWVar2->fileNames != NULL) { pWVar2 = Wad_Get(wadNo); io::Mem_Free(pWVar2->fileNames); } } } return -1; } Wad * __cdecl lego::wad::Wad_Get(int wadNo) { return globs::wadGlobs.wads + wadNo; } int __cdecl lego::wad::Wad_FileLength(int wadNo,int fileNo) { Wad *pWVar1; pWVar1 = Wad_Get(wadNo); return pWVar1->wadEntries[fileNo].decompressedLength; } int __cdecl lego::wad::Wad_FileCompressedLength(int wadNo,int fileNo) { Wad *pWVar1; pWVar1 = Wad_Get(wadNo); return pWVar1->wadEntries[fileNo].fileLength; } int __cdecl lego::wad::Wad_FindFreeFileHandle(void) { int iVar1; int *piVar2; iVar1 = 0; piVar2 = &globs::wadGlobs.fileHandles[0].active; do { if (*piVar2 == 0) { return iVar1; } piVar2 = piVar2 + 4; iVar1 += 1; } while ((int)piVar2 < 0x576ce4); return -1; } int __cdecl lego::wad::Wad_IsFileInWad(char *fName,int opt_wadNo) { Wad *pWVar1; int iVar2; int iVar3; if (opt_wadNo != -1) { iVar3 = _Wad_IsFileInWad(fName,opt_wadNo); return iVar3; } iVar3 = 9; while ((pWVar1 = Wad_Get(iVar3), pWVar1->active == 0 || (iVar2 = _Wad_IsFileInWad(fName,iVar3), iVar2 == -1))) { iVar3 += -1; if (iVar3 < 0) { return -1; } } return iVar2; } int __cdecl lego::wad::_Wad_IsFileInWad(char *fName,int wadNo) { int iVar1; int iVar2; iVar2 = 0; if (globs::wadGlobs.wads[wadNo].numFiles < 1) { return -1; } do { iVar1 = std::_stricmp(globs::wadGlobs.wads[wadNo].wadNames[iVar2],fName); if (iVar1 == 0) { return iVar2; } iVar2 += 1; } while (iVar2 < globs::wadGlobs.wads[wadNo].numFiles); return -1; } int __cdecl lego::wad::Wad_GetFreeWadSlot(void) { int *piVar1; int iVar2; int iVar3; Wad *pWVar4; iVar3 = 0; piVar1 = &globs::wadGlobs.wads[0].active; do { if (*piVar1 == 0) { pWVar4 = globs::wadGlobs.wads + iVar3; for (iVar2 = 9; iVar2 != 0; iVar2 += -1) { pWVar4->fName = NULL; pWVar4 = (Wad *)&pWVar4->active; } return iVar3; } piVar1 = piVar1 + 9; iVar3 += 1; } while ((int)piVar1 < 0x57666c); return -1; } int __cdecl lego::wad::_Wad_FileOpen(char *fName,int wadNo) { int iVar1; int fileNo; uint size; void *out_buffer; Wad *pWVar2; size_t sVar3; int offset; size_t count; int origin; FILE *stream; int wadNo_00; iVar1 = Wad_FindFreeFileHandle(); wadNo_00 = wadNo; if (iVar1 == -1) { return -1; } fileNo = Wad_IsFileInWad(fName,wadNo); if (fileNo == -1) { return -1; } size = Wad_FileCompressedLength(wadNo_00,fileNo); out_buffer = io::Mem_Alloc(size); if (out_buffer == NULL) { return -1; } origin = 0; pWVar2 = Wad_Get(wadNo_00); offset = pWVar2->wadEntries[fileNo].addr; pWVar2 = Wad_Get(wadNo_00); std::fseek(pWVar2->fWad,offset,origin); pWVar2 = Wad_Get(wadNo_00); stream = pWVar2->fWad; count = 1; sVar3 = Wad_FileCompressedLength(wadNo_00,fileNo); sVar3 = std::fread(out_buffer,sVar3,count,stream); if (sVar3 != 1) { io::Mem_Free(out_buffer); return -1; } pWVar2 = Wad_Get(wadNo_00); wadNo = (int)out_buffer; if ((*(byte *)&pWVar2->wadEntries[fileNo].compression & 2) != 0) { wadNo = 0; rnc::RNC_Uncompress(out_buffer,(void **)&wadNo); io::Mem_Free(out_buffer); } globs::wadGlobs.fileHandles[iVar1].data = (void *)wadNo; globs::wadGlobs.fileHandles[iVar1].active = 1; globs::wadGlobs.fileHandles[iVar1].wadNo = wadNo_00; globs::wadGlobs.fileHandles[iVar1].fileNo = fileNo; return iVar1; } int __cdecl lego::wad::Wad_FileOpen(char *fName,int opt_wadNo) { Wad *pWVar1; int iVar2; int iVar3; if (opt_wadNo != -1) { iVar3 = _Wad_FileOpen(fName,opt_wadNo); return iVar3; } iVar3 = 9; while ((pWVar1 = Wad_Get(iVar3), pWVar1->active == 0 || (iVar2 = _Wad_FileOpen(fName,iVar3), iVar2 == -1))) { iVar3 += -1; if (iVar3 < 0) { return -1; } } return iVar2; } void __cdecl lego::wad::Wad_FileClose(int handle) { if (globs::wadGlobs.fileHandles[handle].active != 0) { io::Mem_Free(globs::wadGlobs.fileHandles[handle].data); globs::wadGlobs.fileHandles[handle].active = 0; } return; } void * __cdecl lego::wad::Wad_FileGetPointer(int handle) { if (globs::wadGlobs.fileHandles[handle].active != 0) { return globs::wadGlobs.fileHandles[handle].data; } return NULL; } int __cdecl lego::wad::Wad_hLength(int handle) { int iVar1; iVar1 = Wad_FileLength(globs::wadGlobs.fileHandles[handle].wadNo, globs::wadGlobs.fileHandles[handle].fileNo); return iVar1; } void * __cdecl lego::wad::Wad_hData(int handle) { void *pvVar1; pvVar1 = Wad_FileGetPointer(handle); return pvVar1; } char * __cdecl lego::lw::lwExtractString(char *str1,char *str2,uint *out_pos,uint *out_len) { char cVar1; int iVar2; uint uVar3; uint uVar4; size_t _MaxCount; char *pcVar5; uVar3 = 0xffffffff; pcVar5 = str1; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); uVar3 = ~uVar3; uVar4 = 0xffffffff; pcVar5 = str2; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); _MaxCount = ~uVar4 - 1; if (((uVar3 != 1) && (_MaxCount != 0)) && (uVar4 = 0, uVar3 != 1)) { do { iVar2 = std::_strnicmp(str1,str2,_MaxCount); if (iVar2 == 0) { if (out_pos != NULL) { *out_pos = uVar4; } if (out_len != NULL) { *out_len = _MaxCount; } return str1; } uVar4 += 1; str1 = str1 + 1; } while (uVar4 < uVar3 - 1); return NULL; } return NULL; } char * __cdecl lego::lw::stringAlloc(char *str) { char cVar1; undefined4 *puVar2; uint uVar3; uint uVar4; undefined4 *puVar5; char *pcVar6; undefined4 *puVar7; uVar3 = 0xffffffff; pcVar6 = str; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); uVar4 = ~uVar3 + (~uVar3 & 1); puVar2 = (undefined4 *)io::Mem_Alloc(uVar4); puVar5 = puVar2; for (uVar3 = uVar4 >> 2; uVar3 != 0; uVar3 -= 1) { *puVar5 = 0; puVar5 = puVar5 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar5 = 0; puVar5 = (undefined4 *)((int)puVar5 + 1); } uVar3 = 0xffffffff; do { pcVar6 = str; if (uVar3 == 0) break; uVar3 -= 1; pcVar6 = str + 1; cVar1 = *str; str = pcVar6; } while (cVar1 != '\0'); uVar3 = ~uVar3; puVar5 = (undefined4 *)(pcVar6 + -uVar3); puVar7 = puVar2; for (uVar4 = uVar3 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar7 = *puVar5; puVar5 = puVar5 + 1; puVar7 = puVar7 + 1; } for (uVar3 &= 3; uVar3 != 0; uVar3 -= 1) { *(undefined *)puVar7 = *(undefined *)puVar5; puVar5 = (undefined4 *)((int)puVar5 + 1); puVar7 = (undefined4 *)((int)puVar7 + 1); } return (char *)puVar2; } // Defaults to "PLANAR" on failure to parse uint __cdecl lego::lw::texMapType(char *shapeName) { char cVar1; int iVar2; uint uVar3; uint uVar4; char **ppcVar5; char *pcVar6; char *tTypes [3]; tTypes[0] = "PLANAR"; tTypes[1] = "CYLINDRICAL"; tTypes[2] = "SPHERICAL"; uVar4 = 0; ppcVar5 = tTypes; do { uVar3 = 0xffffffff; pcVar6 = *ppcVar5; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *pcVar6; pcVar6 = pcVar6 + 1; } while (cVar1 != '\0'); iVar2 = std::_strnicmp(shapeName,*ppcVar5,~uVar3 - 1); if (iVar2 == 0) break; uVar4 += 1; ppcVar5 = ppcVar5 + 1; } while (uVar4 < 3); if (uVar4 == 3) { uVar4 = 0; } return uVar4; } void __cdecl lego::lw::surfFree(LWSURFACE *srf,BOOL flag) { if (srf->srfName != NULL) { io::Mem_Free(srf->srfName); } if (srf->srfPath != NULL) { io::Mem_Free(srf->srfPath); } if (srf->srfNextSurf != NULL) { surfFree(srf->srfNextSurf,1); } if (flag != 0) { io::Mem_Free(srf); } return; } BOOL __cdecl lego::lw::LWD3D(byte **p,float *f) { byte *pbVar1; *(byte *)((int)f + 3) = **p; pbVar1 = *p; *p = pbVar1 + 1; *(byte *)((int)f + 2) = pbVar1[1]; pbVar1 = *p; *p = pbVar1 + 1; *(byte *)((int)f + 1) = pbVar1[1]; pbVar1 = *p; *p = pbVar1 + 1; *(byte *)f = pbVar1[1]; *p = *p + 1; return TRUE; } // WARNING: Could not reconcile some variable overlaps BOOL __cdecl lego::lw::PNTSprc(File *file,LWSIZE *sizeData,int csize,float **verts,BOOL dflag) { float *pfVar1; int iVar2; float local_120; float fStack284; undefined uStack280; undefined local_117; undefined2 uStack278; byte *local_114; byte *local_110; uint local_10c; char local_108 [260]; iVar2 = 0; local_120 = (float)(uint)local_120._0_1_; fStack284 = 0.0; uStack280 = 0; local_117 = 0; local_114 = (byte *)io::Mem_Alloc(csize + 0x10); local_110 = local_114; io::File_Read(local_114,csize,1,file); sizeData->lwVertCount = csize / 0xc; if (verts != NULL) { pfVar1 = (float *)io::Mem_Alloc(csize + 4); *verts = pfVar1; if (0 < csize) { local_10c = (csize + 0xbU) / 0xc; do { LWD3D(&local_114,&local_120); LWD3D(&local_114,&fStack284); LWD3D(&local_114,(float *)&uStack280); *pfVar1 = local_120; pfVar1[1] = fStack284; pfVar1[2] = (float)CONCAT22(uStack278,CONCAT11(local_117,uStack280)); pfVar1 = pfVar1 + 3; if (dflag != 0) { std::sprintf(local_108,"Point %d > %f %f %f\n",iVar2,(double)local_120,(double)fStack284); } iVar2 += 1; local_10c -= 1; } while (local_10c != 0); } } io::Mem_Free(local_110); return TRUE; } BOOL __cdecl lego::lw::CRVSprc(File *file,int csize,BOOL dflag) { ushort uVar1; ushort *out_buffer; uint uVar2; ushort *puVar3; int iVar4; out_buffer = (ushort *)io::Mem_Alloc(csize + 0x10); io::File_Read(out_buffer,csize,1,file); puVar3 = out_buffer; if (0 < csize) { do { uVar1 = *puVar3 * 0x100 + (*puVar3 >> 8); puVar3 = puVar3 + 1; iVar4 = csize + -2; if (uVar1 != 0) { uVar2 = (uint)uVar1; puVar3 = puVar3 + uVar2; do { iVar4 += -2; uVar2 -= 1; } while (uVar2 != 0); } csize = iVar4 + -4; puVar3 = puVar3 + 2; } while (0 < csize); } io::Mem_Free(out_buffer); return TRUE; } BOOL __cdecl lego::lw::POLSprc(File *file,LWSIZE *sizeData,LWPOLY **polys,int csize,BOOL dflag) { char cVar1; ushort *out_buffer; LWPOLY *pLVar2; ushort *puVar3; uint uVar4; int iVar5; uint uVar6; ushort uVar7; ushort uVar8; LWPOLY *pLVar9; undefined4 *puVar10; LWPOLY *pLVar11; char *pcVar12; char *pcVar13; char *pcVar14; undefined4 *puVar15; ushort *local_150; uint local_14c; char local_140 [64]; char local_100 [256]; out_buffer = (ushort *)io::Mem_Alloc(csize + 0x10); io::File_Read(out_buffer,csize,1,file); uVar8 = 0; local_150 = out_buffer; uVar7 = 0; if (0 < csize) { do { uVar7 = *local_150 * 0x100 + (*local_150 >> 8); local_150 = local_150 + 1; csize += -2; if (polys != NULL) { if (uVar8 == 0) { pLVar2 = (LWPOLY *)io::Mem_Alloc(0xc); *polys = pLVar2; } else { uVar4 = (uint)uVar8; pLVar2 = (LWPOLY *)io::Mem_Alloc((uVar4 + 1) * 0xc); pLVar9 = *polys; pLVar11 = pLVar2; for (iVar5 = uVar4 * 3; iVar5 != 0; iVar5 += -1) { pLVar11->plyCount = pLVar9->plyCount; pLVar9 = (LWPOLY *)&pLVar9->plySurface; pLVar11 = (LWPOLY *)&pLVar11->plySurface; } for (iVar5 = 0; iVar5 != 0; iVar5 += -1) { *(undefined *)&pLVar11->plyCount = *(undefined *)&pLVar9->plyCount; pLVar9 = (LWPOLY *)((int)&pLVar9->plyCount + 1); pLVar11 = (LWPOLY *)((int)&pLVar11->plyCount + 1); } io::Mem_Free(*polys); *polys = pLVar2; pLVar2 = pLVar2 + uVar4; } local_14c = (uint)uVar7; puVar3 = (ushort *)io::Mem_Alloc(local_14c * 2); if (dflag != 0) { std::sprintf(local_100,"Poly %d, Vertex Count %d > ",(uint)uVar8,local_14c); } pLVar2->plyCount = local_14c; pLVar2->plyData = puVar3; if (uVar7 != 0) { do { uVar7 = *local_150 * 0x100 + (*local_150 >> 8); if (dflag != 0) { std::sprintf(local_140,"%d ",(uint)uVar7); uVar4 = 0xffffffff; pcVar13 = local_140; do { pcVar12 = pcVar13; if (uVar4 == 0) break; uVar4 -= 1; pcVar12 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar12; } while (cVar1 != '\0'); uVar4 = ~uVar4; iVar5 = -1; pcVar13 = local_100; do { pcVar14 = pcVar13; if (iVar5 == 0) break; iVar5 += -1; pcVar14 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar14; } while (cVar1 != '\0'); puVar10 = (undefined4 *)(pcVar12 + -uVar4); puVar15 = (undefined4 *)(pcVar14 + -1); for (uVar6 = uVar4 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar15 = *puVar10; puVar10 = puVar10 + 1; puVar15 = puVar15 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar10; puVar10 = (undefined4 *)((int)puVar10 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } } *puVar3 = uVar7; puVar3 = puVar3 + 1; local_150 = local_150 + 1; csize += -2; local_14c -= 1; } while (local_14c != 0); } uVar4 = (uint)(byte)*local_150 * 0x100 + -1 + (uint)(*local_150 >> 8) & 0xffff; pLVar2->plySurface = uVar4; if (dflag != 0) { std::sprintf(local_140,"Surface :- %d\n",uVar4); uVar4 = 0xffffffff; pcVar13 = local_140; do { pcVar12 = pcVar13; if (uVar4 == 0) break; uVar4 -= 1; pcVar12 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar12; } while (cVar1 != '\0'); uVar4 = ~uVar4; iVar5 = -1; pcVar13 = local_100; do { pcVar14 = pcVar13; if (iVar5 == 0) break; iVar5 += -1; pcVar14 = pcVar13 + 1; cVar1 = *pcVar13; pcVar13 = pcVar14; } while (cVar1 != '\0'); puVar10 = (undefined4 *)(pcVar12 + -uVar4); puVar15 = (undefined4 *)(pcVar14 + -1); for (uVar6 = uVar4 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar15 = *puVar10; puVar10 = puVar10 + 1; puVar15 = puVar15 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar15 = *(undefined *)puVar10; puVar10 = (undefined4 *)((int)puVar10 + 1); puVar15 = (undefined4 *)((int)puVar15 + 1); } } } csize += -2; uVar8 += 1; local_150 = local_150 + 1; uVar7 = uVar8; } while (0 < csize); } sizeData->lwPolyCount = (uint)uVar7; io::Mem_Free(out_buffer); return TRUE; } BOOL __cdecl lego::lw::SRFSprc(File *file,LWSIZE *sizeData,LWSURFLIST **srfl,int csize,uint *srflCount,BOOL dflag ) { char cVar1; undefined4 *out_buffer; undefined4 *puVar2; char **ppcVar3; uint uVar4; uint uVar5; int iVar6; uint uVar7; undefined4 *puVar8; char **ppcVar9; undefined4 *puVar10; undefined4 *puVar11; char **ppcVar12; uint local_224; LWSURFLIST *local_220; char local_200 [512]; uVar7 = 0; local_224 = 0; out_buffer = (undefined4 *)io::Mem_Alloc(csize + 0x10); io::File_Read(out_buffer,csize,1,file); if (srfl != NULL) { local_220 = (LWSURFLIST *)io::Mem_Alloc(8); local_220->srflCount = 0; local_220->srflName = NULL; } puVar10 = out_buffer; if (0 < csize) { do { if (dflag != 0) { std::sprintf(local_200,"Surface %d > %s\n",local_224,puVar10); } uVar4 = 0xffffffff; puVar8 = puVar10; do { if (uVar4 == 0) break; uVar4 -= 1; cVar1 = *(char *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); } while (cVar1 != '\0'); uVar4 = ~uVar4; if ((uVar4 & 1) != 0) { uVar4 += 1; } if (srfl != NULL) { puVar2 = (undefined4 *)io::Mem_Alloc(uVar4); ppcVar3 = (char **)io::Mem_Alloc(uVar7 + 4); puVar8 = puVar10; puVar11 = puVar2; for (uVar5 = uVar4 >> 2; uVar5 != 0; uVar5 -= 1) { *puVar11 = *puVar8; puVar8 = puVar8 + 1; puVar11 = puVar11 + 1; } for (uVar5 = uVar4 & 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar11 = *(undefined *)puVar8; puVar8 = (undefined4 *)((int)puVar8 + 1); puVar11 = (undefined4 *)((int)puVar11 + 1); } if (uVar7 != 0) { ppcVar9 = local_220->srflName; ppcVar12 = ppcVar3; for (uVar5 = uVar7 >> 2; uVar5 != 0; uVar5 -= 1) { *ppcVar12 = *ppcVar9; ppcVar9 = ppcVar9 + 1; ppcVar12 = ppcVar12 + 1; } for (iVar6 = 0; iVar6 != 0; iVar6 += -1) { *(undefined *)ppcVar12 = *(undefined *)ppcVar9; ppcVar9 = (char **)((int)ppcVar9 + 1); ppcVar12 = (char **)((int)ppcVar12 + 1); } io::Mem_Free(local_220->srflName); } *(undefined4 **)((int)ppcVar3 + uVar7) = puVar2; local_220->srflName = ppcVar3; *srfl = local_220; local_220->srflCount = local_224 + 1; } local_224 += 1; uVar7 += 4; *srflCount = local_224; puVar10 = (undefined4 *)((int)puVar10 + uVar4); csize -= uVar4; } while (0 < csize); } io::Mem_Free(out_buffer); return TRUE; } // WARNING: Could not reconcile some variable overlaps BOOL __cdecl lego::lw::SURFprc(File *file,LWSIZE *sizeData,LWSURFACE **surf,int csize,BOOL dflag) { char cVar1; float fVar2; char *pcVar3; LWSURFACE *pLVar4; char *pcVar5; int iVar6; LWTEXMAPTYPE LVar7; LWSURFACE *pLVar8; int iVar9; uint uVar10; uint uVar11; LWTEXFLAGS LVar12; LWSRFFLAGS LVar13; char **shapeName; undefined4 *puVar14; int iVar15; LWSURFACE *pLVar16; char **ppcVar17; char **ppcVar18; char *pcVar19; char *pcVar20; undefined4 *puVar21; char **local_50c; LWSURFACE *local_508; uint local_504; char local_500; undefined4 local_4ff; undefined4 local_4fb; undefined local_4f7; char **local_4f4; int local_4f0; char *local_4ec; char *local_4e8; char *local_4e4; char *local_4e0; char *local_4dc; char *local_4d8; char *local_4d4; uint local_4d0; int local_4cc; char *local_4c8 [4]; char *local_4b8; char *local_4b4; char *local_4b0; char *local_4ac [4]; char *local_49c; char *local_498; char *local_494; char *local_490; char *local_48c; char *local_488; uint local_484; char local_480 [511]; undefined uStack641; undefined4 local_280 [32]; char local_200 [512]; local_4ff = 0; local_4fb = 0; local_500 = '\0'; local_4f7 = 0; pcVar3 = (char *)io::Mem_Alloc(csize + 0x10); local_4ec = pcVar3; io::File_Read(pcVar3,csize,1,file); uVar10 = sizeData->lwSurfaceCount; pLVar4 = local_508; local_504 = uVar10; if (surf != NULL) { if (uVar10 == 0) { pLVar4 = (LWSURFACE *)io::Mem_Alloc(0x54); *surf = pLVar4; pLVar8 = pLVar4; for (iVar9 = 0x15; iVar9 != 0; iVar9 += -1) { pLVar8->srfName = NULL; pLVar8 = (LWSURFACE *)&pLVar8->srfNextSurf; } local_508 = pLVar4; pcVar5 = stringAlloc(pcVar3); pLVar4->srfName = pcVar5; } else { pLVar4 = (LWSURFACE *)io::Mem_Alloc((uVar10 + 1) * 0x54); pLVar8 = *surf; pLVar16 = pLVar4; for (uVar11 = uVar10 * 0x15 & 0x3fffffff; uVar11 != 0; uVar11 -= 1) { pLVar16->srfName = pLVar8->srfName; pLVar8 = (LWSURFACE *)&pLVar8->srfNextSurf; pLVar16 = (LWSURFACE *)&pLVar16->srfNextSurf; } for (iVar9 = 0; iVar9 != 0; iVar9 += -1) { *(undefined *)&pLVar16->srfName = *(undefined *)&pLVar8->srfName; pLVar8 = (LWSURFACE *)((int)&pLVar8->srfName + 1); pLVar16 = (LWSURFACE *)((int)&pLVar16->srfName + 1); } io::Mem_Free(*surf); *surf = pLVar4; pLVar4 = pLVar4 + uVar10; pLVar8 = pLVar4; for (iVar9 = 0x15; iVar9 != 0; iVar9 += -1) { pLVar8->srfName = NULL; pLVar8 = (LWSURFACE *)&pLVar8->srfNextSurf; } local_508 = pLVar4; pcVar3 = stringAlloc(local_4ec); pLVar4->srfName = pcVar3; pcVar3 = local_4ec; } } if (dflag != 0) { std::sprintf(local_200,"Surface %d :- %s"); } uVar10 = 0xffffffff; pcVar5 = pcVar3; do { if (uVar10 == 0) break; uVar10 -= 1; cVar1 = *pcVar5; pcVar5 = pcVar5 + 1; } while (cVar1 != '\0'); uVar10 = ~uVar10; if ((uVar10 & 1) != 0) { uVar10 += 1; } iVar9 = csize - uVar10; pcVar3 = pcVar3 + uVar10; do { if (iVar9 < 1) { sizeData->lwSurfaceCount = sizeData->lwSurfaceCount + 1; io::Mem_Free(local_4ec); return TRUE; } std::strncpy(&local_500,pcVar3,4); local_4cc = (*(ushort *)(pcVar3 + 4) & 0xff) * 0x100 + (uint)(*(ushort *)(pcVar3 + 4) >> 8); std::sprintf(local_200," %s (%d)"); shapeName = (char **)(pcVar3 + 6); iVar6 = std::_strnicmp(&local_500,"TIMG",4); if (iVar6 == 0) { uVar10 = 0xffffffff; ppcVar17 = shapeName; do { ppcVar18 = ppcVar17; if (uVar10 == 0) break; uVar10 -= 1; ppcVar18 = (char **)((int)ppcVar17 + 1); cVar1 = *(char *)ppcVar17; ppcVar17 = ppcVar18; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_200; do { pcVar5 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); puVar14 = (undefined4 *)((int)ppcVar18 - uVar10); puVar21 = (undefined4 *)(pcVar5 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } if (surf != NULL) { uVar10 = 0xffffffff; ppcVar17 = shapeName; do { ppcVar18 = ppcVar17; if (uVar10 == 0) break; uVar10 -= 1; ppcVar18 = (char **)((int)ppcVar17 + 1); cVar1 = *(char *)ppcVar17; ppcVar17 = ppcVar18; } while (cVar1 != '\0'); uVar10 = ~uVar10; puVar14 = (undefined4 *)((int)ppcVar18 - uVar10); puVar21 = local_280; for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } pcVar3 = lwExtractString((char *)local_280,"(sequence)",&local_4d0,&local_484); if (pcVar3 != NULL) { LVar12 = pLVar4->srfTexFlags; *(undefined *)((int)local_280 + (local_4d0 - 1)) = 0; pLVar4->srfTexFlags = LVar12 | TFM_SEQUENCE; } pcVar3 = stringAlloc((char *)local_280); pLVar4->srfPath = pcVar3; } } else { iVar6 = std::_strnicmp(&local_500,"COLR",4); if (iVar6 == 0) { std::sprintf(local_480," RGBA %d,%d,%d,%d"); uVar10 = 0xffffffff; pcVar5 = local_480; do { pcVar20 = pcVar5; if (uVar10 == 0) break; uVar10 -= 1; pcVar20 = pcVar5 + 1; cVar1 = *pcVar5; pcVar5 = pcVar20; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar5 = local_200; do { pcVar19 = pcVar5; if (iVar6 == 0) break; iVar6 += -1; pcVar19 = pcVar5 + 1; cVar1 = *pcVar5; pcVar5 = pcVar19; } while (cVar1 != '\0'); puVar14 = (undefined4 *)(pcVar20 + -uVar10); puVar21 = (undefined4 *)(pcVar19 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } if (surf != NULL) { (pLVar4->srfCol).colRed = *(byte *)shapeName; (pLVar4->srfCol).colGreen = pcVar3[7]; (pLVar4->srfCol).colBlue = pcVar3[8]; (pLVar4->srfCol).colAlpha = pcVar3[9]; } } else { iVar6 = std::_strnicmp(&local_500,"CTEX",4); if (iVar6 == 0) { uVar10 = 0xffffffff; ppcVar17 = shapeName; do { ppcVar18 = ppcVar17; if (uVar10 == 0) break; uVar10 -= 1; ppcVar18 = (char **)((int)ppcVar17 + 1); cVar1 = *(char *)ppcVar17; ppcVar17 = ppcVar18; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_200; do { pcVar5 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); puVar14 = (undefined4 *)((int)ppcVar18 - uVar10); puVar21 = (undefined4 *)(pcVar5 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } if (surf != NULL) { LVar7 = texMapType((char *)shapeName); pLVar4->srfTexType = LVar7; } } else { iVar6 = std::_strnicmp(&local_500,"TTEX",4); if (iVar6 == 0) { uVar10 = 0xffffffff; ppcVar17 = shapeName; do { ppcVar18 = ppcVar17; if (uVar10 == 0) break; uVar10 -= 1; ppcVar18 = (char **)((int)ppcVar17 + 1); cVar1 = *(char *)ppcVar17; ppcVar17 = ppcVar18; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_200; do { pcVar5 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); puVar14 = (undefined4 *)((int)ppcVar18 - uVar10); puVar21 = (undefined4 *)(pcVar5 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } if (surf != NULL) { pLVar8 = (LWSURFACE *)io::Mem_Alloc(0x54); pLVar4->srfNextSurf = pLVar8; pLVar4 = pLVar8; for (iVar6 = 0x15; iVar6 != 0; iVar6 += -1) { pLVar4->srfName = NULL; pLVar4 = (LWSURFACE *)&pLVar4->srfNextSurf; } local_508 = pLVar8; LVar7 = texMapType((char *)shapeName); pLVar8->srfTexType = LVar7; pLVar4 = pLVar8; } } else { iVar6 = std::_strnicmp(&local_500,"TFLG",4); if (iVar6 == 0) { local_4f4 = NULL; if (surf != NULL) { LVar12 = (uint)(*(ushort *)shapeName >> 8) + (*(ushort *)shapeName & 0xff) * 0x100 & 0xffff; local_4c8[0] = "Axis_x"; local_508->srfTexFlags = local_508->srfTexFlags | LVar12; local_4c8[1] = "Axis_y"; local_4c8[2] = "Axis_z"; local_4c8[3] = "World Coord"; local_4b8 = "Negative Image"; local_4b4 = "Pixel Blending"; local_4b0 = "Anti Aliasing"; std::sprintf(local_480,"%xH - "); local_50c = local_4c8; local_4f0 = 0; local_504 = 8; do { if ((LVar12 & 1 << ((byte)local_4f0 & 0x1f)) != 0) { if ((short)local_4f4 != 0) { uVar10 = 0xffffffff; pcVar3 = ","; do { pcVar5 = pcVar3; if (uVar10 == 0) break; uVar10 -= 1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_480; do { pcVar20 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar20 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar20; } while (cVar1 != '\0'); puVar14 = (undefined4 *)(pcVar5 + -uVar10); puVar21 = (undefined4 *)(pcVar20 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } } local_4f4 = (char **)((int)local_4f4 + 1); uVar10 = 0xffffffff; pcVar3 = *local_50c; do { pcVar5 = pcVar3; if (uVar10 == 0) break; uVar10 -= 1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_480; do { pcVar20 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar20 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar20; } while (cVar1 != '\0'); puVar14 = (undefined4 *)(pcVar5 + -uVar10); puVar21 = (undefined4 *)(pcVar20 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } } local_4f0 += 1; local_50c = local_50c + 1; local_504 -= 1; } while (local_504 != 0); LAB_0048d1d2: uVar10 = 0xffffffff; pcVar3 = local_480; do { pcVar5 = pcVar3; if (uVar10 == 0) break; uVar10 -= 1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_200; do { pcVar20 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar20 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar20; } while (cVar1 != '\0'); puVar14 = (undefined4 *)(pcVar5 + -uVar10); puVar21 = (undefined4 *)(pcVar20 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; pLVar4 = local_508, uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } } } else { iVar6 = std::_strnicmp(&local_500,"FLAG",4); if (iVar6 == 0) { local_50c = NULL; if (surf != NULL) { local_4ac[0] = "Luminous"; LVar13 = (uint)(*(ushort *)shapeName >> 8) + (*(ushort *)shapeName & 0xff) * 0x100 & 0xffff; local_4ac[1] = "Outline"; local_4ac[2] = "Smoothing"; local_4ac[3] = "Color Highlights"; local_49c = "Color Filter"; local_498 = "Opaque Edge"; local_494 = "Transparent Edge"; local_490 = "Sharp Terminator"; local_48c = "Double Sided"; local_488 = "Additive"; local_508->srfFlags = LVar13; std::sprintf(local_480,"%xH - "); local_4f4 = local_4ac; local_504 = 0; local_4f0 = 10; do { if ((LVar13 & 1 << ((byte)local_504 & 0x1f)) != 0) { if ((short)local_50c != 0) { uVar10 = 0xffffffff; pcVar3 = ","; do { pcVar5 = pcVar3; if (uVar10 == 0) break; uVar10 -= 1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_480; do { pcVar20 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar20 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar20; } while (cVar1 != '\0'); puVar14 = (undefined4 *)(pcVar5 + -uVar10); puVar21 = (undefined4 *)(pcVar20 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } } local_50c = (char **)((int)local_50c + 1); uVar10 = 0xffffffff; pcVar3 = *local_4f4; do { pcVar5 = pcVar3; if (uVar10 == 0) break; uVar10 -= 1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_480; do { pcVar20 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar20 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar20; } while (cVar1 != '\0'); puVar14 = (undefined4 *)(pcVar5 + -uVar10); puVar21 = (undefined4 *)(pcVar20 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } } local_504 += 1; local_4f4 = local_4f4 + 1; local_4f0 += -1; } while (local_4f0 != 0); goto LAB_0048d1d2; } } else { iVar6 = std::_strnicmp(&local_500,"TSIZ",4); if (iVar6 == 0) { if (surf != NULL) { local_50c = shapeName; LWD3D((byte **)&local_50c,(float *)&local_4dc); LWD3D((byte **)&local_50c,(float *)&local_4d8); LWD3D((byte **)&local_50c,(float *)&local_4d4); std::sprintf(local_480," (%f,%f,%f)"); (pLVar4->srfTexSize).tdX = (float)local_4dc; (pLVar4->srfTexSize).tdY = (float)local_4d8; (pLVar4->srfTexSize).tdZ = (float)local_4d4; LAB_0048d369: uVar10 = 0xffffffff; pcVar3 = local_480; do { pcVar5 = pcVar3; if (uVar10 == 0) break; uVar10 -= 1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_200; do { pcVar20 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar20 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar20; } while (cVar1 != '\0'); puVar14 = (undefined4 *)(pcVar5 + -uVar10); puVar21 = (undefined4 *)(pcVar20 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } } } else { iVar6 = std::_strnicmp(&local_500,"TCTR",4); if ((iVar6 == 0) && (surf != NULL)) { local_50c = shapeName; LWD3D((byte **)&local_50c,(float *)&local_4e8); LWD3D((byte **)&local_50c,(float *)&local_4e4); LWD3D((byte **)&local_50c,(float *)&local_4e0); std::sprintf(local_480," (%f,%f,%f)"); (pLVar4->srfTexCentre).tdX = (float)local_4e8; (pLVar4->srfTexCentre).tdY = (float)local_4e4; (pLVar4->srfTexCentre).tdZ = (float)local_4e0; goto LAB_0048d369; } } } } } } } } iVar15 = 0; iVar6 = std::_strnicmp(&local_500,"TRAN",4); if (iVar6 == 0) { iVar15 = 1; } else { iVar6 = std::_strnicmp(&local_500,"DIFF",4); if (iVar6 == 0) { iVar15 = 2; } else { iVar6 = std::_strnicmp(&local_500,"LUMI",4); if (iVar6 == 0) { iVar15 = 3; } else { iVar6 = std::_strnicmp(&local_500,"REFL",4); if (iVar6 == 0) { iVar15 = 4; } else { iVar6 = std::_strnicmp(&local_500,"SPEC",4); if (iVar6 == 0) { iVar15 = 5; } else { iVar6 = std::_strnicmp(&local_500,"GLOS",4); if (iVar6 == 0) { iVar15 = 6; } } } } } } if ((iVar15 != 0) && (surf != NULL)) { local_504 = (uint)(*(ushort *)shapeName >> 8) + (*(ushort *)shapeName & 0xff) * 0x100 & 0xffff ; fVar2 = (float)local_504 * 0.00390625; switch(iVar15) { case 1: pLVar4->srfTransparent = fVar2; break; case 2: pLVar4->srfDiffuse = fVar2; break; case 3: pLVar4->srfLuminous = fVar2; break; case 4: pLVar4->srfReflect = fVar2; break; case 5: pLVar4->srfSpecular = fVar2; break; case 6: pLVar4->srfSpecPower = fVar2; } std::sprintf(local_480,"%f"); uVar10 = 0xffffffff; pcVar3 = local_480; do { pcVar5 = pcVar3; if (uVar10 == 0) break; uVar10 -= 1; pcVar5 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar5; } while (cVar1 != '\0'); uVar10 = ~uVar10; iVar6 = -1; pcVar3 = local_200; do { pcVar20 = pcVar3; if (iVar6 == 0) break; iVar6 += -1; pcVar20 = pcVar3 + 1; cVar1 = *pcVar3; pcVar3 = pcVar20; } while (cVar1 != '\0'); puVar14 = (undefined4 *)(pcVar5 + -uVar10); puVar21 = (undefined4 *)(pcVar20 + -1); for (uVar11 = uVar10 >> 2; uVar11 != 0; uVar11 -= 1) { *puVar21 = *puVar14; puVar14 = puVar14 + 1; puVar21 = puVar21 + 1; } for (uVar10 &= 3; uVar10 != 0; uVar10 -= 1) { *(undefined *)puVar21 = *(undefined *)puVar14; puVar14 = (undefined4 *)((int)puVar14 + 1); puVar21 = (undefined4 *)((int)puVar21 + 1); } } pcVar3 = (char *)((int)shapeName + local_4cc); iVar9 += -6 - local_4cc; } while( true ); } BOOL __cdecl lego::lw::LoadLWOB(char *fn,LWSIZE *sd,float **verts,LWPOLY **polys,LWSURFACE **surfs, File **out_fileUV,BOOL dflag) { File *f; LWSIZE *sizeData; BOOL BVar1; File *pFVar2; int iVar3; int iVar4; char *pcVar5; uint uVar6; byte *pbVar7; LWSURFACE *pLVar8; char **ppcVar9; uint local_534; uint local_530; LWSURFLIST *local_52c; uint local_528; char local_524; undefined4 local_523; undefined4 local_51f; undefined local_51b; uint local_518; uint local_514; char *local_510; File *local_50c; LWSIZE *local_508; LWSURFACE *local_504; char filenameLwo [256]; char buff [1024]; local_523 = 0; local_51f = 0; local_524 = '\0'; local_51b = 0; local_530 = 0; std::sprintf(filenameLwo,"%s.lwo",fn); f = io::File_Open(filenameLwo,"rb"); if (f == NULL) { return 0; } local_50c = f; sizeData = (LWSIZE *)io::Mem_Alloc(0xc); sizeData->lwSurfaceCount = 0; sizeData->lwPolyCount = 0; sizeData->lwVertCount = 0; local_508 = sizeData; if (out_fileUV != NULL) { std::sprintf(filenameLwo,"%s.uv",fn); BVar1 = io::File_Exists(filenameLwo); if (BVar1 == 0) { *out_fileUV = NULL; } else { pFVar2 = io::File_Open(filenameLwo,"rb"); *out_fileUV = pFVar2; } } io::File_Read(&local_524,4,1,f); iVar3 = std::_stricmp(&local_524,"FORM"); if (iVar3 == 0) { io::File_Read(&local_518,4,1,f); local_518 = ((local_518 & 0xff00) + (local_518 & 0xff) * 0x10000) * 0x100 + (local_518 >> 0x10 & 0xff) * 0x100 + (local_518 >> 0x18); io::File_Read(&local_524,4,1,f); iVar3 = std::_stricmp(&local_524,"LWOB"); if (iVar3 == 0) { for (iVar3 = local_518 - 4; 0 < iVar3; iVar3 += -8 - local_534) { io::File_Read(&local_524,4,1,f); io::File_Read(&local_534,4,1,f); local_534 = ((local_534 & 0xff00) + (local_534 & 0xff) * 0x10000) * 0x100 + (local_534 >> 0x10 & 0xff) * 0x100 + (local_534 >> 0x18); if (dflag != 0) { std::sprintf(buff,"LW OBJECT %s %d\n",&local_524,local_534); } iVar4 = std::_stricmp(&local_524,"PNTS"); if (iVar4 == 0) { PNTSprc(f,sizeData,local_534,verts,dflag); } else { iVar4 = std::_stricmp(&local_524,"SRFS"); if (iVar4 == 0) { SRFSprc(f,sizeData,&local_52c,local_534,&local_530,dflag); } else { iVar4 = std::_stricmp(&local_524,"SURF"); if (iVar4 == 0) { SURFprc(f,sizeData,surfs,local_534,dflag); } else { iVar4 = std::_stricmp(&local_524,"CRVS"); if (iVar4 == 0) { CRVSprc(f,local_534,dflag); } else { iVar4 = std::_stricmp(&local_524,"POLS"); if (iVar4 == 0) { POLSprc(f,sizeData,polys,local_534,dflag); } else { io::File_Seek(f,local_534,SEEK_CUR); } } } } } } local_528 = sizeData->lwSurfaceCount; if (((surfs != NULL) && (local_52c != NULL)) && (sizeData != NULL)) { local_504 = (LWSURFACE *)io::Mem_Alloc(local_530 * 0x54); pLVar8 = local_504; for (uVar6 = local_530 * 0x15 & 0x3fffffff; uVar6 != 0; uVar6 -= 1) { pLVar8->srfName = NULL; pLVar8 = (LWSURFACE *)&pLVar8->srfNextSurf; } for (iVar3 = 0; iVar3 != 0; iVar3 += -1) { *(undefined *)&pLVar8->srfName = 0; pLVar8 = (LWSURFACE *)((int)&pLVar8->srfName + 1); } local_514 = 0; if (local_530 != 0) { pbVar7 = &(local_504->srfCol).colGreen; do { uVar6 = 0; local_510 = local_52c->srflName[local_514]; if (local_528 != 0) { iVar3 = 0; LAB_0048d940: iVar4 = std::_stricmp(*(char **)((*surfs)->srfTCLR + iVar3 + -0x10),local_510); if (iVar4 != 0) goto code_r0x0048d95e; pLVar8 = *surfs + uVar6; ppcVar9 = (char **)(pbVar7 + -0xd); for (iVar3 = 0x15; f = local_50c, iVar3 != 0; iVar3 += -1) { *ppcVar9 = pLVar8->srfName; pLVar8 = (LWSURFACE *)&pLVar8->srfNextSurf; ppcVar9 = ppcVar9 + 1; } } LAB_0048d990: if (uVar6 == local_528) { pcVar5 = stringAlloc("Default"); *(char **)(pbVar7 + -0xd) = pcVar5; pbVar7[-1] = 0xff; *pbVar7 = 0xff; pbVar7[1] = 0xff; local_528 = local_530; } pbVar7 = pbVar7 + 0x54; local_514 += 1; sizeData = local_508; } while (local_514 < local_530); } pLVar8 = local_504; io::Mem_Free(*surfs); *surfs = pLVar8; } sizeData->lwSurfaceCount = local_528; if (sd != NULL) { sd->lwVertCount = sizeData->lwVertCount; sd->lwPolyCount = sizeData->lwPolyCount; sd->lwSurfaceCount = sizeData->lwSurfaceCount; } io::Mem_Free(sizeData); if (local_530 != 0) { uVar6 = 0; if (local_530 != 0) { do { io::Mem_Free(local_52c->srflName[uVar6]); uVar6 += 1; } while (uVar6 < local_530); } io::Mem_Free(local_52c->srflName); io::Mem_Free(local_52c); } io::File_Close(f); return TRUE; } } io::Mem_Free(sizeData); io::File_Close(f); std::sprintf(buff,"Error in Lightwave file %s",fn); return 0; code_r0x0048d95e: uVar6 += 1; iVar3 += 0x54; if (local_528 <= uVar6) goto LAB_0048d990; goto LAB_0048d940; } BOOL __cdecl lego::lw::LoadAppObj(char *fn,APPOBJ **out_ao,BOOL flag) { APPOBJ *pAVar1; char *pcVar2; BOOL BVar3; int iVar4; char path [128]; pAVar1 = (APPOBJ *)io::Mem_Alloc(0x20); *out_ao = pAVar1; for (iVar4 = 8; iVar4 != 0; iVar4 += -1) { pAVar1->aoPath = NULL; pAVar1 = (APPOBJ *)&pAVar1->aoSize; } std::_splitpath(fn,NULL,path,NULL,NULL); pcVar2 = stringAlloc(path); (*out_ao)->aoPath = pcVar2; pAVar1 = *out_ao; BVar3 = LoadLWOB(fn,&pAVar1->aoSize,&pAVar1->aoVerts,&pAVar1->aoPoly,&pAVar1->aoSurface, &pAVar1->aoFileUV,flag); if (BVar3 != 0) { return TRUE; } io::Mem_Free((*out_ao)->aoPath); io::Mem_Free(*out_ao); return 0; } BOOL __cdecl lego::lw::FreeLWOB(APPOBJ *ao) { uint uVar1; LWSURFACE *srf; int iVar2; if (ao != NULL) { if (ao->aoFileUV != NULL) { io::File_Close(ao->aoFileUV); } srf = ao->aoSurface; if (srf != NULL) { for (uVar1 = (ao->aoSize).lwSurfaceCount; uVar1 != 0; uVar1 -= 1) { surfFree(srf,0); srf = srf + 1; } io::Mem_Free(ao->aoSurface); } if (ao->aoPoly != NULL) { uVar1 = (ao->aoSize).lwPolyCount; if (uVar1 != 0) { iVar2 = 0; do { io::Mem_Free(*(void **)((int)&ao->aoPoly->plyData + iVar2)); iVar2 += 0xc; uVar1 -= 1; } while (uVar1 != 0); } io::Mem_Free(ao->aoPoly); } io::Mem_Free(ao->aoVerts); io::Mem_Free(ao->aoPath); io::Mem_Free(ao); return TRUE; } return 0; } float10 __cdecl std::atof(char *str) { byte bVar1; uint uVar2; undefined *puVar3; int iVar4; byte *pbVar5; while( true ) { // int std::isspace(int c) if (globals::_pcharwidth < 2) { uVar2 = *(byte *)(globals::_pctype + (byte)*str) & C1_SPACE; } else { uVar2 = _isctype((uint)(byte)*str,C1_SPACE); } if (uVar2 == 0) break; str = (char *)((byte *)str + 1); } iVar4 = -1; pbVar5 = (byte *)str; do { if (iVar4 == 0) break; iVar4 += -1; bVar1 = *pbVar5; pbVar5 = pbVar5 + 1; } while (bVar1 != 0); puVar3 = internal::__atof_internal(str); return (float10)*(double *)(puVar3 + 0x10); } int __cdecl std::sprintf(char *out_buffer,char *format,...) { int iVar1; FILE dummyFile; dummyFile._base = out_buffer; dummyFile._ptr = out_buffer; dummyFile._flag = 0x42; dummyFile._cnt = 0x7fffffff; iVar1 = internal::__vfprintf_internal(&dummyFile,format,&stack0x0000000c); dummyFile._cnt += -1; if (-1 < dummyFile._cnt) { *dummyFile._ptr = '\0'; return iVar1; } internal::__fafterwrite_00490b60(0,&dummyFile._ptr); return iVar1; } char * __cdecl std::strstr(char *str,char *strSearch) { char *pcVar1; char *pcVar2; char cVar3; uint uVar4; char cVar5; uint uVar6; char *pcVar7; uint uVar8; uint *puVar9; char *pcVar10; cVar3 = *strSearch; if (cVar3 == '\0') { return (char *)(uint *)str; } if (strSearch[1] == '\0') { uVar4 = (uint)str & 3; while (uVar4 != 0) { if (*str == cVar3) { return (char *)(uint *)str; } if (*str == '\0') { return (char *)NULL; } uVar4 = (uint)(uint *)((int)str + 1) & 3; str = (char *)(uint *)((int)str + 1); } while( true ) { while( true ) { uVar4 = *(uint *)str; uVar8 = uVar4 ^ CONCAT22(CONCAT11(cVar3,cVar3),CONCAT11(cVar3,cVar3)); uVar6 = uVar4 ^ 0xffffffff ^ uVar4 + 0x7efefeff; puVar9 = (uint *)((int)str + 4); if (((uVar8 ^ 0xffffffff ^ uVar8 + 0x7efefeff) & 0x81010100) != 0) break; str = (char *)puVar9; if ((uVar6 & 0x81010100) != 0) { if ((uVar6 & 0x1010100) != 0) { return (char *)NULL; } if ((uVar4 + 0x7efefeff & 0x80000000) == 0) { return (char *)NULL; } } } uVar4 = *(uint *)str; if ((char)uVar4 == cVar3) { return (char *)(uint *)str; } if ((char)uVar4 == '\0') { return (char *)NULL; } cVar5 = (char)(uVar4 >> 8); if (cVar5 == cVar3) { return (char *)(uint *)((int)str + 1); } if (cVar5 == '\0') break; cVar5 = (char)(uVar4 >> 0x10); if (cVar5 == cVar3) { return (char *)(uint *)((int)str + 2); } if (cVar5 == '\0') { return (char *)NULL; } cVar5 = (char)(uVar4 >> 0x18); if (cVar5 == cVar3) { return (char *)(uint *)((int)str + 3); } str = (char *)puVar9; if (cVar5 == '\0') { return (char *)NULL; } } return (char *)NULL; } do { cVar5 = *str; do { while (str = str + 1, cVar5 != cVar3) { if (cVar5 == '\0') { return (char *)NULL; } cVar5 = *str; } cVar5 = *str; pcVar10 = str + 1; pcVar7 = strSearch; } while (cVar5 != strSearch[1]); do { if (pcVar7[2] == '\0') { LAB_0048dd83: return (char *)(uint *)(str + -1); } if (*pcVar10 != pcVar7[2]) break; pcVar1 = pcVar7 + 3; if (*pcVar1 == '\0') goto LAB_0048dd83; pcVar2 = pcVar10 + 1; pcVar7 = pcVar7 + 2; pcVar10 = pcVar10 + 2; } while (*pcVar1 == *pcVar2); } while( true ); } int __cdecl std::atoi(char *str) { int iVar1; iVar1 = internal::__atoi_internal(str); return iVar1; } // ALIAS FOR: free void __cdecl lego::io::Mem_Free(void *buffer) { void *lpMem; byte *pbVar1; int *local_4; lpMem = buffer; if (buffer != NULL) { pbVar1 = (byte *)std::internal::__realloc_free__00491b00 ((undefined *)buffer,&local_4,(uint *)&buffer); if (pbVar1 != NULL) { std::internal::__free_realloc__00491b60((int)local_4,(int)buffer,pbVar1); return; } HeapFree(std::globs::_crt2._heap,0,lpMem); } return; } // ALIAS FOR: malloc void * __cdecl lego::io::Mem_Alloc(uint size) { void *buffer; buffer = std::internal::__malloc_handlermode(size,std::globs::_crt1._handlermode); return buffer; } // ALIAS FOR: realloc void * __cdecl lego::io::Mem_ReAlloc(void *memblock,uint size) { int *piVar1; int **ppiVar2; int iVar3; BOOL BVar4; uint uVar5; uint uVar6; int *piVar7; int *piVar8; int **local_8; int *local_4; if (memblock == NULL) { piVar1 = (int *)Mem_Alloc(size); return piVar1; } if (size == 0) { Mem_Free(memblock); return NULL; } if (size < 0xffffffe1) { if (size == 0) { size = 0x10; } else { size = size + 0xf & 0xfffffff0; } } do { piVar1 = NULL; if (size < 0xffffffe1) { ppiVar2 = (int **)std::internal::__realloc_free__00491b00 ((undefined *)memblock,&local_4,(uint *)&local_8); if (ppiVar2 == NULL) { piVar1 = (int *)HeapReAlloc(std::globs::_crt2._heap,0,memblock,size); goto LAB_0048e0aa; } if (size < std::globs::_crt3.field_0x2038) { iVar3 = std::internal::__realloc__00491f80 ((int)local_4,local_8,ppiVar2,(uint)(int *)(size >> 4)); piVar1 = (int *)memblock; if (iVar3 != 0) goto LAB_0048e03f; piVar1 = std::internal::__malloc__00491bc0((int *)(size >> 4)); if (piVar1 != NULL) { uVar6 = (uint)*(byte *)ppiVar2 << 4; if (size <= (uint)*(byte *)ppiVar2 << 4) { uVar6 = size; } piVar7 = (int *)memblock; piVar8 = piVar1; for (uVar5 = uVar6 >> 2; uVar5 != 0; uVar5 -= 1) { *piVar8 = *piVar7; piVar7 = piVar7 + 1; piVar8 = piVar8 + 1; } for (uVar6 &= 3; uVar6 != 0; uVar6 -= 1) { *(undefined *)piVar8 = *(undefined *)piVar7; piVar7 = (int *)((int)piVar7 + 1); piVar8 = (int *)((int)piVar8 + 1); } std::internal::__free_realloc__00491b60((int)local_4,(int)local_8,(byte *)ppiVar2); goto LAB_0048e03f; } } else { LAB_0048e03f: if (piVar1 != NULL) { return piVar1; } } piVar1 = (int *)HeapAlloc(std::globs::_crt2._heap,0,size); if (piVar1 != NULL) { uVar6 = (uint)*(byte *)ppiVar2 << 4; if (size <= (uint)*(byte *)ppiVar2 << 4) { uVar6 = size; } piVar7 = (int *)memblock; piVar8 = piVar1; for (uVar5 = uVar6 >> 2; uVar5 != 0; uVar5 -= 1) { *piVar8 = *piVar7; piVar7 = piVar7 + 1; piVar8 = piVar8 + 1; } for (uVar6 &= 3; uVar6 != 0; uVar6 -= 1) { *(undefined *)piVar8 = *(undefined *)piVar7; piVar7 = (int *)((int)piVar7 + 1); piVar8 = (int *)((int)piVar8 + 1); } std::internal::__free_realloc__00491b60((int)local_4,(int)local_8,(byte *)ppiVar2); goto LAB_0048e0aa; } } else { LAB_0048e0aa: if (piVar1 != NULL) { return piVar1; } } if (std::globs::_crt1._handlermode == 0) { return piVar1; } BVar4 = std::internal::__call_new_handler(size); if (BVar4 == 0) { return NULL; } } while( true ); } void __cdecl std::qsort(void *base,uint number,uint width,QsortCompare compare) { uint uVar1; int iVar2; byte *a; byte *b; byte *local_100; byte **local_fc; byte **local_f8; int local_f4; byte *local_f0 [30]; byte *local_78 [30]; if ((number < 2) || (width == 0)) { return; } local_100 = (byte *)((number - 1) * width + (int)base); local_fc = local_f0; local_f8 = local_78; local_f4 = 0; LAB_0048e134: uVar1 = (uint)((int)local_100 - (int)base) / width + 1; if (8 < uVar1) { internal::__memswap((byte *)((int)base + (uVar1 >> 1) * width),(byte *)base,width); b = local_100 + width; a = (byte *)base; LAB_0048e1ae: a = a + width; if (a <= local_100) goto code_r0x0048e1b8; goto LAB_0048e1c8; } internal::__qsort((byte *)base,local_100,width,compare); goto LAB_0048e155; code_r0x0048e1b8: iVar2 = (*compare)(a,base); if (iVar2 < 1) goto LAB_0048e1ae; LAB_0048e1c8: do { b = b + -width; if (b <= base) break; iVar2 = (*compare)(b,base); } while (-1 < iVar2); if (a <= b) { internal::__memswap(a,b,width); goto LAB_0048e1ae; } internal::__memswap((byte *)base,b,width); if ((int)(b + (-1 - (int)base)) < (int)local_100 - (int)a) { if (a < local_100) { *local_f8 = a; *local_fc = local_100; local_f4 += 1; local_f8 = local_f8 + 1; local_fc = local_fc + 1; } if ((byte *)((int)base + width) < b) { local_100 = b + -width; goto LAB_0048e134; } } else { if ((byte *)((int)base + width) < b) { *local_f8 = (byte *)base; *local_fc = b + -width; local_f4 += 1; local_f8 = local_f8 + 1; local_fc = local_fc + 1; } base = a; if (a < local_100) goto LAB_0048e134; } LAB_0048e155: local_f4 += -1; local_f8 = local_f8 + -1; local_fc = local_fc + -1; if (local_f4 < 0) { return; } local_100 = *local_fc; base = *local_f8; goto LAB_0048e134; } // Library Function - Single Match // Name: __ftol // Library: Visual Studio longlong __ftol(float10 param_1) { return (longlong)ROUND(param_1); } float10 __cdecl std::acos(float10 x) { float10 fVar1; double dVar2; dVar2 = (double)x; internal::__fpmath_FUN_00492328(dVar2); fVar1 = internal::__fpmath_acos_FUN_0048e36d(dVar2); return fVar1; } void __cdecl std::srand(uint seed) { globals::g_rand = seed; return; } int __cdecl std::rand(void) { globals::g_rand = globals::g_rand * 0x343fd + 0x269ec3; return (int)globals::g_rand >> 0x10 & 0x7fff; } float10 __cdecl std::fmod(float10 x,float10 y) { float10 fVar1; fVar1 = internal::__cintrindisp2(x,y); return fVar1; } int __cdecl std::vsprintf(char *buffer,char *format,va_list argptr) { int iVar1; FILE dummyFile; dummyFile._base = buffer; dummyFile._ptr = buffer; dummyFile._flag = 0x42; dummyFile._cnt = 0x7fffffff; iVar1 = internal::__vfprintf_internal(&dummyFile,format,argptr); dummyFile._cnt += -1; if (-1 < dummyFile._cnt) { *dummyFile._ptr = '\0'; return iVar1; } internal::__fafterwrite_00490b60(0,&dummyFile._ptr); return iVar1; } // WARNING: This is an inlined function // WARNING: Unable to track spacebase fully for stack void * std::_alloca4k(uint size) { undefined *puVar1; void *unaff_retaddr; puVar1 = &stack0x00000004; if (0xfff < size) { do { puVar1 = puVar1 + -0x1000; size -= 0x1000; } while (0xfff < size); } *(void **)(puVar1 + (-4 - size)) = unaff_retaddr; return unaff_retaddr; } // This function appears implicitly in a few locations. float10 __cdecl std::floor(double x) { double dVar1; uint new; int iVar2; float10 fVar3; new = _control87(null_ARRAY_004b0d20[0],0xffff); if ((x._6_2_ & 0x7ff0) != 0x7ff0) { fVar3 = internal::__std_unk_round_internal__00493410(x); dVar1 = (double)fVar3; if ((dVar1 != x) && ((new & 0x20) == 0)) { fVar3 = internal::__fpmath_enum2_FUN_00493480(0x10,_FPMATH_floor,x,dVar1,new); return fVar3; } _control87(new,0xffff); return (float10)dVar1; } iVar2 = internal::__fpmath_FUN_00493d40(x); if (0 < iVar2) { if (iVar2 < 3) { _control87(new,0xffff); return (float10)x; } if (iVar2 == 3) { fVar3 = internal::__fpmath_enum1_FUN_00493430(_FPMATH_floor,x,new); return fVar3; } } fVar3 = internal::__fpmath_enum2_FUN_00493480(8,_FPMATH_floor,x,x - -1.0,new); return fVar3; } int __cdecl std::toupper(int c) { int iVar1; uint uVar2; LPCWSTR pWVar3; int iVar4; uint local_8 [2]; iVar1 = c; if (globs::_crt1.DAT_0054a180 == 0) { if ((0x60 < c) && (c < 0x7b)) { return c - 0x20; } } else { if (c < 0x100) { // int std::islower(int c) if (globals::_pcharwidth < 2) { uVar2 = *(byte *)(globals::_pctype + c) & C1_LOWER; } else { uVar2 = _isctype(c,C1_LOWER); } if (uVar2 == 0) { return iVar1; } } if ((*(byte *)((int)globals::_pctype + (iVar1 >> 8 & 0xffU) * 2 + 1) & 0x80) == 0) { c = c & 0xffff0000U | iVar1 & 0xffU; pWVar3 = (LPCWSTR)0x1; } else { c = c & 0xff000000U | (uint)CONCAT11((char)iVar1,(char)((uint)iVar1 >> 8)); pWVar3 = (LPCWSTR)0x2; } iVar4 = internal::__uprlwr__00493f60 (globs::_crt1.DAT_0054a180,0x200,(char *)&c,pWVar3,(LPWSTR)local_8,3,0); if (iVar4 == 0) { return iVar1; } if (iVar4 == 1) { return local_8[0] & 0xff; } c = (local_8[0] >> 8 & 0xff) << 8 | local_8[0] & 0xff; } return c; } void __cdecl std::exit(int status) { internal::__std_exit_FUN_0048e7b0(status,0,0); return; } float10 __cdecl std::sqrt(double x) { uint uVar1; undefined4 in_ECX; uint extraout_EDX; undefined in_ZF; float10 extraout_ST0; float10 extraout_ST0_00; float10 fVar2; float10 extraout_ST0_01; float10 fVar3; ushort in_FPUControlWord; ushort in_FPUStatusWord; uint uVar4; internal::__fload_withFB(in_ECX,(int)&x); uVar4 = extraout_EDX & 0xffff0000 | (uint)in_FPUControlWord; fVar2 = extraout_ST0; if ((bool)in_ZF) { if ((((ulonglong)x & 0xfffff00000000) == 0) && (x._0_4_ == 0)) { fVar3 = globs::_crt3.field_0x203c; if (((ulonglong)x & 0x8000000000000000) == 0) goto LAB_0048e8be; } else { internal::__fpmath_FUN_004922cc(x._4_4_); fVar3 = extraout_ST0_01; } LAB_0048e91b: if (globs::_crt1.DAT_0054a0c8 == 0) { fVar2 = internal::__startOneArgErrorHandling("sqrt",_FPMATH_sqrt,uVar4); return fVar2; } } else { uVar1 = x._4_4_; if (in_FPUControlWord != 0x27f) { uVar1 = internal::__fpmath_FUN_004922b5(uVar4); fVar2 = extraout_ST0_00; } if ((uVar1 & 0x80000000) == 0) { fVar2 = SQRT(fVar2); } else { fVar3 = globs::_crt3.field_0x203c; if ((((uVar1 & 0x7ff00000) != 0) || ((uVar1 & 0xfffff) != 0)) || (x._0_4_ != 0)) goto LAB_0048e91b; } LAB_0048e8be: fVar3 = fVar2; if (globs::_crt1.DAT_0054a0c8 == 0) { if ((((short)uVar4 != 0x27f) && ((uVar4 & 0x20) != 0)) && ((in_FPUStatusWord & 0x20) != 0)) { fVar2 = internal::__startOneArgErrorHandling("sqrt",_FPMATH_sqrt,uVar4); return fVar2; } return fVar2; } } return fVar3; } float10 __cdecl std::fabs(double x) { uint new; int iVar1; float10 fVar2; new = _control87(0x133f,0xffff); if ((x._6_2_ & 0x7ff0) != 0x7ff0) { _control87(new,0xffff); return (float10)(double)((ulonglong)x & 0x7fffffffffffffff); } iVar1 = internal::__fpmath_FUN_00493d40(x); if (iVar1 == 1) { _control87(new,0xffff); return (float10)x; } if (iVar1 == 2) { _control87(new,0xffff); return -(float10)x; } if (iVar1 != 3) { fVar2 = internal::__fpmath_enum2_FUN_00493480(8,_FPMATH_fabs,x,x - -1.0,new); return fVar2; } fVar2 = internal::__fpmath_enum1_FUN_00493430(_FPMATH_fabs,x,new); return fVar2; } // Library Function - Single Match // Name: _strncpy // Library: Visual Studio 1998 Release char * __cdecl std::strncpy(char *_Dest,char *_Source,size_t _Count) { uint uVar1; uint uVar2; char cVar3; uint uVar4; uint *puVar5; if (_Count == 0) { return _Dest; } puVar5 = (uint *)_Dest; if (((uint)_Source & 3) != 0) { while( true ) { cVar3 = *_Source; _Source = (char *)((int)_Source + 1); *(char *)puVar5 = cVar3; puVar5 = (uint *)((int)puVar5 + 1); _Count -= 1; if (_Count == 0) { return _Dest; } if (cVar3 == '\0') break; if (((uint)_Source & 3) == 0) { uVar4 = _Count >> 2; goto joined_r0x0048ea6e; } } do { if (((uint)puVar5 & 3) == 0) { uVar4 = _Count >> 2; if (uVar4 == 0) goto LAB_0048eaab; goto LAB_0048eb19; } *(undefined *)puVar5 = 0; puVar5 = (uint *)((int)puVar5 + 1); _Count -= 1; } while (_Count != 0); return _Dest; } uVar4 = _Count >> 2; if (uVar4 != 0) { do { uVar1 = *(uint *)_Source; uVar2 = *(uint *)_Source; _Source = (char *)((int)_Source + 4); if (((uVar1 ^ 0xffffffff ^ uVar1 + 0x7efefeff) & 0x81010100) != 0) { if ((char)uVar2 == '\0') { *puVar5 = 0; joined_r0x0048eb15: while( true ) { uVar4 -= 1; puVar5 = puVar5 + 1; if (uVar4 == 0) break; LAB_0048eb19: *puVar5 = 0; } cVar3 = '\0'; _Count &= 3; if (_Count != 0) goto LAB_0048eaab; return _Dest; } if ((char)(uVar2 >> 8) == '\0') { *puVar5 = uVar2 & 0xff; goto joined_r0x0048eb15; } if ((uVar2 & 0xff0000) == 0) { *puVar5 = uVar2 & 0xffff; goto joined_r0x0048eb15; } if ((uVar2 & 0xff000000) == 0) { *puVar5 = uVar2; goto joined_r0x0048eb15; } } *puVar5 = uVar2; puVar5 = puVar5 + 1; uVar4 -= 1; joined_r0x0048ea6e: } while (uVar4 != 0); _Count &= 3; if (_Count == 0) { return _Dest; } } do { cVar3 = *_Source; _Source = (char *)((int)_Source + 1); *(char *)puVar5 = cVar3; puVar5 = (uint *)((int)puVar5 + 1); if (cVar3 == '\0') { while (_Count -= 1, _Count != 0) { LAB_0048eaab: *(char *)puVar5 = cVar3; puVar5 = (uint *)((int)puVar5 + 1); } return _Dest; } _Count -= 1; } while (_Count != 0); return _Dest; } int __cdecl std::_finite(double x) { return (uint)((x._6_2_ & 0x7ff0) != 0x7ff0); } int __cdecl std::sscanf(char *buffer,char *format,...) { char cVar1; int iVar2; uint uVar3; FILE file; uVar3 = 0xffffffff; file._base = buffer; file._ptr = buffer; do { if (uVar3 == 0) break; uVar3 -= 1; cVar1 = *buffer; buffer = buffer + 1; } while (cVar1 != '\0'); file._cnt = ~uVar3 - 1; file._flag = 0x49; iVar2 = vfscanf(&file,format,&stack0x0000000c); return iVar2; } // (probably) float10 __cdecl std::ceil(double x) { double dVar1; uint new; int iVar2; float10 fVar3; new = _control87(null_ARRAY_004b0d38[2],0xffff); if ((x._6_2_ & 0x7ff0) != 0x7ff0) { fVar3 = internal::__std_unk_round_internal__00493410(x); dVar1 = (double)fVar3; if ((dVar1 != x) && ((new & 0x20) == 0)) { fVar3 = internal::__fpmath_enum2_FUN_00493480(0x10,_FPMATH_ceil,x,dVar1,new); return fVar3; } _control87(new,0xffff); return (float10)dVar1; } iVar2 = internal::__fpmath_FUN_00493d40(x); if (0 < iVar2) { if (iVar2 < 3) { _control87(new,0xffff); return (float10)x; } if (iVar2 == 3) { fVar3 = internal::__fpmath_enum1_FUN_00493430(_FPMATH_ceil,x,new); return fVar3; } } fVar3 = internal::__fpmath_enum2_FUN_00493480(8,_FPMATH_ceil,x,x - -1.0,new); return fVar3; } // Library Function - Single Match // Name: __alldiv // Library: Visual Studio longlong __alldiv(longlong param_1,longlong param_2) { ulonglong uVar1; uint uVar2; int iVar3; uint uVar4; uint uVar5; bool bVar6; char cVar7; cVar7 = param_1 < 0; if ((bool)cVar7) { param_1 = CONCAT44(-(uint)((uint)param_1 != 0) - param_1._4_4_,-(uint)param_1); } param_1._4_4_ = (uint)((ulonglong)param_1 >> 0x20); uVar2 = param_2._4_4_; if (param_2 < 0) { cVar7 += '\x01'; uVar2 = -(uint)((uint)param_2 != 0) - param_2._4_4_; param_2 = CONCAT44(uVar2,-(uint)param_2); } param_2._4_4_ = (uint)((ulonglong)param_2 >> 0x20); uVar1 = param_1; if (uVar2 == 0) { uVar2 = param_1._4_4_ / (uint)param_2; iVar3 = (int)(((ulonglong)param_1._4_4_ % (param_2 & 0xffffffffU) << 0x20 | param_1 & 0xffffffffU) / (param_2 & 0xffffffffU)); } else { do { uVar4 = uVar2 & 1; uVar2 >>= 1; param_2._0_4_ = (uint)param_2 >> 1 | (uint)(uVar4 != 0) << 0x1f; uVar5 = (uint)(uVar1 >> 0x21); uVar4 = (uint)uVar1 >> 1 | (uint)((uVar1 & 0x100000000) != 0) << 0x1f; uVar1 = CONCAT44(uVar5,uVar4); } while (uVar2 != 0); uVar1 = CONCAT44(uVar5,uVar4) / (ulonglong)(uint)param_2; iVar3 = (int)uVar1; uVar1 = (param_2 & 0xffffffffU) * (uVar1 & 0xffffffff); uVar2 = (uint)(uVar1 >> 0x20); if (((CARRY4(uVar2,iVar3 * param_2._4_4_)) || ((ulonglong)param_1 < (uVar1 & 0xffffffff | (ulonglong)(uVar2 + iVar3 * param_2._4_4_) << 0x20))) || ((false && ((uint)param_1 < (uint)uVar1)))) { iVar3 += -1; } uVar2 = 0; } if (cVar7 == '\x01') { bVar6 = iVar3 != 0; iVar3 = -iVar3; uVar2 = -(uint)bVar6 - uVar2; } return CONCAT44(uVar2,iVar3); } void * __cdecl std::operator_new(uint size) { void *pvVar1; pvVar1 = internal::__malloc_handlermode(size,1); return pvVar1; } int __cdecl std::fclose(FILE *stream) { int iVar1; int iVar2; iVar2 = -1; if ((stream->_flag & 0x40U) != 0) { stream->_flag = 0; return -1; } if ((stream->_flag & 0x83U) != 0) { iVar2 = internal::fflush(stream); internal::__ffree__004950b0(stream); iVar1 = internal::__fdclose__00494fd0(stream->_file); if (iVar1 < 0) { stream->_flag = 0; return -1; } if (stream->_tmpfname != NULL) { lego::io::Mem_Free(stream->_tmpfname); stream->_tmpfname = NULL; } } stream->_flag = 0; return iVar2; } FILE * __cdecl std::fopen(LPCSTR filename,char *mode) { FILE *pFVar1; pFVar1 = _fsopen(filename,mode,SH_DENYNO); return pFVar1; } BOOL __cdecl std::_isctype(int c,uint desc) { int iVar1; LCID LVar2; uint local_4; if (c + 1U < 0x101) { return globals::_pctype[c] & desc; } if ((*(byte *)((int)globals::_pctype + (c >> 8 & 0xffU) * 2 + 1) & 0x80) == 0) { c &= 0xffff00ff; iVar1 = 1; } else { c = c & 0xff000000U | (uint)CONCAT11((char)c,(char)((uint)c >> 8)); iVar1 = 2; } LVar2 = internal::__ctype_internal(1,(LPCSTR)&c,iVar1,(LPWORD)&local_4,0,0); if (LVar2 == 0) { return 0; } return local_4 & 0xffff & desc; } // Library Function - Single Match // Name: _strncmp // Libraries: Visual Studio 1998 Debug, Visual Studio 1998 Release int __cdecl std::strncmp(char *_Str1,char *_Str2,size_t _MaxCount) { char cVar1; char cVar2; byte bVar3; size_t sVar4; int iVar5; uint uVar6; char *pcVar7; char *pcVar8; bool bVar9; sVar4 = _MaxCount; pcVar7 = _Str1; if (_MaxCount != 0) { do { if (sVar4 == 0) break; sVar4 -= 1; cVar1 = *pcVar7; pcVar7 = pcVar7 + 1; } while (cVar1 != '\0'); iVar5 = _MaxCount - sVar4; do { pcVar7 = _Str2; pcVar8 = _Str1; if (iVar5 == 0) break; iVar5 += -1; pcVar8 = _Str1 + 1; pcVar7 = _Str2 + 1; cVar1 = *_Str2; cVar2 = *_Str1; _Str2 = pcVar7; _Str1 = pcVar8; } while (cVar1 == cVar2); bVar3 = pcVar7[-1]; uVar6 = 0; bVar9 = bVar3 == pcVar8[-1]; if (bVar3 < (byte)pcVar8[-1] || bVar9) { if (bVar9) { return 0; } uVar6 = 0xfffffffe; } _MaxCount = ~uVar6; } return _MaxCount; } long __cdecl std::ftell(FILE *stream) { uint uVar1; uint uVar2; char *pcVar3; int iVar4; DWORD DVar5; char *pcVar6; int iVar7; char *pcVar8; DWORD local_8; DWORD local_4; uVar1 = stream->_file; if (stream->_cnt < 0) { stream->_cnt = 0; } local_4 = internal::__fdread__00496ec0(uVar1,0,1); if ((int)local_4 < 0) { return 0xffffffff; } uVar2 = stream->_flag; if ((uVar2 & 0x108) == 0) { return local_4 - stream->_cnt; } pcVar8 = stream->_ptr; pcVar3 = stream->_base; local_8 = (int)pcVar8 - (int)pcVar3; iVar4 = (int)uVar1 >> 5; if ((uVar2 & 3) == 0) { if ((uVar2 & 0x80) == 0) { globs::_crt1.errno = 0x16; return 0xffffffff; } } else { pcVar6 = pcVar3; if ((*(byte *)((int)globs::_crt2._handlesTable_0076edc0[iVar4] + (uVar1 & 0x1f) * 8 + 4) & 0x80) != 0) { for (; pcVar6 < pcVar8; pcVar6 = pcVar6 + 1) { if (*pcVar6 == '\n') { local_8 += 1; } } } } if (local_4 == 0) { return local_8; } if ((*(byte *)&stream->_flag & 1) == 0) goto LAB_0048f6e5; if (stream->_cnt == 0) { return local_4; } pcVar8 = pcVar8 + (stream->_cnt - (int)pcVar3); iVar7 = (uVar1 & 0x1f) * 8; if ((*(byte *)(iVar7 + 4 + (int)globs::_crt2._handlesTable_0076edc0[iVar4]) & 0x80) != 0) { DVar5 = internal::__fdread__00496ec0(uVar1,0,2); if (DVar5 == local_4) { pcVar6 = stream->_base; pcVar3 = pcVar6 + (int)pcVar8; for (; pcVar6 < pcVar3; pcVar6 = pcVar6 + 1) { if (*pcVar6 == '\n') { pcVar8 = pcVar8 + 1; } } if ((stream->_flag & 0x2000U) != 0) { LAB_0048f6dc: pcVar8 = pcVar8 + 1; } } else { internal::__fdread__00496ec0(uVar1,local_4,0); if (((pcVar8 < (char *)0x201) && ((stream->_flag & 8U) != 0)) && ((stream->_flag & 0x400U) == 0)) { pcVar8 = (char *)0x200; } else { pcVar8 = (char *)stream->_bufsiz; } if ((*(byte *)(iVar7 + 4 + (int)globs::_crt2._handlesTable_0076edc0[iVar4]) & 4) != 0) goto LAB_0048f6dc; } } local_4 -= (int)pcVar8; LAB_0048f6e5: return local_4 + local_8; } int __cdecl std::fseek(FILE *stream,long offset,int origin) { uint uVar1; long lVar2; DWORD DVar3; if (((stream->_flag & 0x83U) != 0) && (((origin == 0 || (origin == 1)) || (origin == 2)))) { stream->_flag = stream->_flag & 0xffffffef; if (origin == 1) { lVar2 = ftell(stream); offset += lVar2; origin = 0; } internal::fflush(stream); uVar1 = stream->_flag; if ((uVar1 & 0x80) == 0) { if ((((uVar1 & 1) != 0) && ((uVar1 & 8) != 0)) && ((uVar1 & 0x400) == 0)) { stream->_bufsiz = 0x200; } } else { stream->_flag = uVar1 & 0xfffffffc; } DVar3 = internal::__fdread__00496ec0(stream->_file,offset,origin); return (DVar3 != 0xffffffff) - 1; } globs::_crt1.errno = EINVAL; return -1; } size_t __cdecl std::fwrite(void *out_buffer,size_t size,size_t count,FILE *stream) { FILE *stream_00; FILE *pFVar1; int iVar2; FILE *pFVar3; uint uVar4; FILE *pFVar5; FILE *pFVar6; undefined4 *puVar7; undefined4 *puVar8; stream_00 = stream; pFVar5 = (FILE *)(count * size); if (pFVar5 == NULL) { return 0; } pFVar6 = pFVar5; if ((stream->_flag & 0x10cU) == 0) { stream = (FILE *)0x1000; } else { stream = (FILE *)stream->_bufsiz; } do { uVar4 = stream_00->_flag & 0x108; if ((uVar4 == 0) || (pFVar1 = (FILE *)stream_00->_cnt, pFVar1 == NULL)) { if (pFVar6 < stream) { // WARNING: Load size is inaccurate uVar4 = internal::__fafterwrite_00490b60((int)*out_buffer,&stream_00->_ptr); if (uVar4 == 0xffffffff) goto LAB_0048f8f4; stream = (FILE *)stream_00->_bufsiz; out_buffer = (void *)((int)out_buffer + 1); pFVar6 = (FILE *)((int)&pFVar6[-1]._tmpfname + 3); if ((int)stream < 1) { stream = (FILE *)0x1; } } else { if ((uVar4 != 0) && (iVar2 = internal::fflush(stream_00), iVar2 != 0)) { LAB_0048f8f4: return (uint)((int)pFVar5 - (int)pFVar6) / size; } pFVar1 = pFVar6; if (stream != NULL) { pFVar1 = (FILE *)((int)pFVar6 - (uint)pFVar6 % (uint)stream); } pFVar3 = (FILE *)internal::__fdwrite__00496f80 (stream_00->_file,(char *)out_buffer,(char *)pFVar1); if (pFVar3 == (FILE *)0xffffffff) { LAB_0048f8d9: stream_00->_flag = stream_00->_flag | 0x20; return (uint)((int)pFVar5 - (int)pFVar6) / size; } pFVar6 = (FILE *)((int)pFVar6 - (int)pFVar3); out_buffer = (void *)((int)out_buffer + (int)pFVar3); if (pFVar3 < pFVar1) goto LAB_0048f8d9; } } else { if (pFVar6 < pFVar1) { pFVar1 = pFVar6; } pFVar6 = (FILE *)((int)pFVar6 - (int)pFVar1); puVar7 = (undefined4 *)out_buffer; puVar8 = (undefined4 *)stream_00->_ptr; for (uVar4 = (uint)pFVar1 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar8 = *puVar7; puVar7 = puVar7 + 1; puVar8 = puVar8 + 1; } for (uVar4 = (uint)pFVar1 & 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar8 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar8 = (undefined4 *)((int)puVar8 + 1); } out_buffer = (void *)((int)out_buffer + (int)pFVar1); stream_00->_cnt = stream_00->_cnt - (int)pFVar1; stream_00->_ptr = (char *)((int)&pFVar1->_ptr + (int)stream_00->_ptr); } if (pFVar6 == NULL) { return count; } } while( true ); } int __cdecl std::remove(LPCSTR filename) { BOOL BVar1; uint error_value; BVar1 = DeleteFileA(filename); if (BVar1 == 0) { error_value = GetLastError(); } else { error_value = 0; } if (error_value != 0) { internal::__set_doserrno(error_value); return -1; } return 0; } int __cdecl std::_chmod(LPCSTR filename,int pmode) { DWORD DVar1; BOOL BVar2; DVar1 = GetFileAttributesA(filename); if (DVar1 != INVALID_FILE_ATTRIBUTES) { if ((pmode & FILE_ATTRIBUTE_NORMAL) == 0) { DVar1 |= 1; } else { DVar1 &= 0xfffffffe; } BVar2 = SetFileAttributesA(filename,DVar1); if (BVar2 != 0) { return 0; } } DVar1 = GetLastError(); internal::__set_doserrno(DVar1); return -1; } int __cdecl std::_mkdir(LPCSTR dirname) { BOOL BVar1; uint error_value; BVar1 = CreateDirectoryA(dirname,NULL); if (BVar1 == 0) { error_value = GetLastError(); } else { error_value = 0; } if (error_value != 0) { internal::__set_doserrno(error_value); return -1; } return 0; } HANDLE __cdecl std::_findfirst32(LPCSTR filename,_finddata32_t *fileinfo) { char cVar1; HANDLE pvVar2; DWORD DVar3; int iVar4; uint uVar5; uint uVar6; undefined4 *puVar7; char *pcVar8; char *pcVar9; undefined4 *puVar10; _WIN32_FIND_DATAA local_140; pvVar2 = FindFirstFileA(filename,(LPWIN32_FIND_DATAA)&local_140); if (pvVar2 == (HANDLE)0xffffffff) { DVar3 = GetLastError(); if (true) { switch(DVar3) { case 2: case 3: case 0x12: globs::_crt1.errno = 2; return (HANDLE)0xffffffff; case 8: globs::_crt1.errno = 0xc; return (HANDLE)0xffffffff; } } globs::_crt1.errno = 0x16; return (HANDLE)0xffffffff; } fileinfo->attrib = -(uint)(local_140.dwFileAttributes != 0x80) & local_140.dwFileAttributes; iVar4 = internal::__unk_ftime__0048fc30(&local_140.ftCreationTime); fileinfo->time_create = iVar4; iVar4 = internal::__unk_ftime__0048fc30(&local_140.ftLastAccessTime); fileinfo->time_access = iVar4; iVar4 = internal::__unk_ftime__0048fc30(&local_140.ftLastWriteTime); fileinfo->time_write = iVar4; uVar5 = 0xffffffff; pcVar8 = local_140.cFileName; do { pcVar9 = pcVar8; if (uVar5 == 0) break; uVar5 -= 1; pcVar9 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar9; } while (cVar1 != '\0'); uVar5 = ~uVar5; fileinfo->size = local_140.nFileSizeLow; puVar7 = (undefined4 *)(pcVar9 + -uVar5); puVar10 = (undefined4 *)fileinfo->name; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } return pvVar2; } int __cdecl std::_findnext32(HANDLE handle,_finddata32_t *fileinfo) { char cVar1; BOOL BVar2; DWORD DVar3; int iVar4; uint uVar5; uint uVar6; undefined4 *puVar7; char *pcVar8; char *pcVar9; undefined4 *puVar10; _WIN32_FIND_DATAA local_140; BVar2 = FindNextFileA(handle,(LPWIN32_FIND_DATAA)&local_140); if (BVar2 == 0) { DVar3 = GetLastError(); if (true) { switch(DVar3) { case 2: case 3: case 0x12: globs::_crt1.errno = ENOENT; return -1; case 8: globs::_crt1.errno = ENOMEM; return -1; } } globs::_crt1.errno = EINVAL; return -1; } fileinfo->attrib = -(uint)(local_140.dwFileAttributes != 0x80) & local_140.dwFileAttributes; iVar4 = internal::__unk_ftime__0048fc30(&local_140.ftCreationTime); fileinfo->time_create = iVar4; iVar4 = internal::__unk_ftime__0048fc30(&local_140.ftLastAccessTime); fileinfo->time_access = iVar4; iVar4 = internal::__unk_ftime__0048fc30(&local_140.ftLastWriteTime); fileinfo->time_write = iVar4; uVar5 = 0xffffffff; pcVar8 = local_140.cFileName; do { pcVar9 = pcVar8; if (uVar5 == 0) break; uVar5 -= 1; pcVar9 = pcVar8 + 1; cVar1 = *pcVar8; pcVar8 = pcVar9; } while (cVar1 != '\0'); uVar5 = ~uVar5; fileinfo->size = local_140.nFileSizeLow; puVar7 = (undefined4 *)(pcVar9 + -uVar5); puVar10 = (undefined4 *)fileinfo->name; for (uVar6 = uVar5 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar5 &= 3; uVar5 != 0; uVar5 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } return 0; } int __cdecl std::_findclose(HANDLE handle) { BOOL BVar1; BVar1 = FindClose(handle); if (BVar1 == 0) { globs::_crt1.errno = 0x16; return -1; } return 0; } char * __cdecl std::_getcwd(char *out_buffer,int maxlen) { char *pcVar1; pcVar1 = _getdcwd(0,out_buffer,maxlen); return pcVar1; } size_t __cdecl std::fread(void *out_buffer,size_t size,size_t count,FILE *stream) { FILE *file; FILE *pFVar1; char *pcVar2; int iVar3; uint uVar4; FILE *pFVar5; FILE *pFVar6; undefined4 *puVar7; FILE *pFVar8; undefined4 *puVar9; file = stream; pFVar5 = (FILE *)(count * size); if (pFVar5 == NULL) { return 0; } pFVar6 = pFVar5; if ((stream->_flag & 0x10cU) == 0) { stream = (FILE *)0x1000; pFVar8 = (FILE *)0x1000; } else { pFVar8 = (FILE *)stream->_bufsiz; stream = pFVar8; } do { if (((file->_flag & 0x10cU) == 0) || (pFVar1 = (FILE *)file->_cnt, pFVar1 == NULL)) { if (pFVar6 < pFVar8) { iVar3 = internal::__fpeekc(file); if (iVar3 == -1) { return (uint)((int)pFVar5 - (int)pFVar6) / size; } *(char *)out_buffer = (char)iVar3; pFVar8 = (FILE *)file->_bufsiz; out_buffer = (void *)((int)out_buffer + 1); iVar3 = -1; stream = pFVar8; } else { pFVar1 = pFVar6; if (pFVar8 != NULL) { pFVar1 = (FILE *)((int)pFVar6 - (uint)pFVar6 % (uint)pFVar8); } pcVar2 = internal::__fdread(file->_file,(char *)out_buffer,(DWORD)pFVar1); if (pcVar2 == NULL) { file->_flag = file->_flag | 0x10; return (uint)((int)pFVar5 - (int)pFVar6) / size; } if (pcVar2 == (char *)0xffffffff) { file->_flag = file->_flag | 0x20; return (uint)((int)pFVar5 - (int)pFVar6) / size; } iVar3 = -(int)pcVar2; out_buffer = (void *)((int)out_buffer + (int)pcVar2); } } else { if (pFVar6 < pFVar1) { pFVar1 = pFVar6; } iVar3 = -(int)pFVar1; puVar7 = (undefined4 *)file->_ptr; puVar9 = (undefined4 *)out_buffer; for (uVar4 = (uint)pFVar1 >> 2; uVar4 != 0; uVar4 -= 1) { *puVar9 = *puVar7; puVar7 = puVar7 + 1; puVar9 = puVar9 + 1; } for (uVar4 = (uint)pFVar1 & 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar9 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar9 = (undefined4 *)((int)puVar9 + 1); } out_buffer = (void *)((int)out_buffer + (int)pFVar1); file->_cnt = file->_cnt - (int)pFVar1; file->_ptr = (char *)((int)&pFVar1->_ptr + (int)file->_ptr); pFVar8 = stream; } pFVar6 = (FILE *)((int)&pFVar6->_ptr + iVar3); if (pFVar6 == NULL) { return count; } } while( true ); } int __cdecl std::fgetc(FILE *stream) { byte bVar1; int iVar2; uint uVar3; iVar2 = stream->_cnt + -1; stream->_cnt = iVar2; if (-1 < iVar2) { bVar1 = *stream->_ptr; stream->_ptr = stream->_ptr + 1; return (uint)bVar1; } uVar3 = internal::__fpeekc(stream); return uVar3; } char * __cdecl std::fgets(char *str,int numChars,FILE *stream) { int iVar1; uint uVar2; int iVar3; char *pcVar4; if (numChars < 1) { return NULL; } iVar3 = numChars + -1; pcVar4 = str; if (iVar3 != 0) { while( true ) { iVar1 = stream->_cnt + -1; stream->_cnt = iVar1; if (iVar1 < 0) { uVar2 = internal::__fpeekc(stream); } else { uVar2 = (uint)(byte)*stream->_ptr; stream->_ptr = stream->_ptr + 1; } if (uVar2 == 0xffffffff) break; *pcVar4 = (char)uVar2; pcVar4 = pcVar4 + 1; if ((char)uVar2 == '\n') goto LAB_00490176; iVar3 += -1; if (iVar3 == 0) { *pcVar4 = '\0'; return str; } } if (pcVar4 == str) { return NULL; } } LAB_00490176: *pcVar4 = '\0'; return str; } int __cdecl std::vfprintf(FILE *stream,char *format,va_list argptr) { BOOL BVar1; int iVar2; BVar1 = internal::__vfprintf__00497790(stream); iVar2 = internal::__vfprintf_internal(stream,format,argptr); internal::__vfprintf__00497830(BVar1,stream); return iVar2; } // Library Function - Single Match // Name: __strcmpi // Libraries: Visual Studio 1998 Debug, Visual Studio 1998 Release int __cdecl std::_stricmp(char *_Str1,char *_Str2) { char cVar1; char cVar2; byte bVar3; byte bVar5; uint uVar4; uint c; if (globs::_crt1.DAT_0054a180 == 0) { uVar4 = 0xff; do { do { cVar2 = (char)uVar4; if (cVar2 == '\0') goto LAB_0049021e; cVar2 = *_Str2; _Str2 = _Str2 + 1; cVar1 = *_Str1; uVar4 = (uint)CONCAT11(cVar1,cVar2); _Str1 = _Str1 + 1; } while ((char)(uVar4 >> 8) == cVar2); bVar3 = cVar1 + 0xbf; bVar3 = bVar3 + (-(bVar3 < 0x1a) & 0x20U) + 0x41; uVar4 = (uint)CONCAT11(cVar2 + 0xbfU + (-((byte)(cVar2 + 0xbfU) < 0x1a) & 0x20U) + 'A',bVar3); bVar5 = (byte)(uVar4 >> 8); } while (bVar3 == bVar5); cVar2 = (bVar3 < bVar5) * -2 + '\x01'; LAB_0049021e: uVar4 = SEXT14(cVar2); } else { c = 0; uVar4 = 0xff; do { do { if ((char)uVar4 == '\0') { return uVar4; } bVar3 = *_Str2; uVar4 = uVar4 & 0xffffff00 | (uint)bVar3; _Str2 = (char *)((byte *)_Str2 + 1); bVar5 = *_Str1; c = c & 0xffffff00 | (uint)bVar5; _Str1 = (char *)((byte *)_Str1 + 1); } while (bVar3 == bVar5); c = tolower(c); uVar4 = tolower(uVar4); } while ((byte)c == (byte)uVar4); uVar4 = (uint)((byte)c < (byte)uVar4); uVar4 = (1 - uVar4) - (uint)(uVar4 != 0); } return uVar4; } char * __cdecl std::_fullpath(char *out_absPath,LPCSTR relPath,uint maxLength) { LPSTR lpBuffer; LPSTR pCVar1; DWORD error_value; char *pcVar2; LPSTR nBufferLength; if ((relPath == NULL) || (*relPath == '\0')) { pcVar2 = _getcwd(out_absPath,maxLength); return pcVar2; } lpBuffer = out_absPath; nBufferLength = (LPSTR)maxLength; if (out_absPath == NULL) { lpBuffer = (LPSTR)lego::io::Mem_Alloc(MAX_PATH); if (lpBuffer == NULL) { globs::_crt1.errno = ENOMEM; return NULL; } nBufferLength = (LPSTR)MAX_PATH; } pCVar1 = (LPSTR)GetFullPathNameA(relPath,(DWORD)nBufferLength,lpBuffer,(LPSTR *)&maxLength); if (pCVar1 < nBufferLength) { if (pCVar1 != NULL) { return lpBuffer; } if (out_absPath == NULL) { lego::io::Mem_Free(lpBuffer); } error_value = GetLastError(); internal::__set_doserrno(error_value); return NULL; } if (out_absPath == NULL) { lego::io::Mem_Free(lpBuffer); } globs::_crt1.errno = ERANGE; return NULL; } int __cdecl std::fscanf(FILE *stream,char *format,...) { int iVar1; iVar1 = vfscanf(stream,format,&stack0x0000000c); return iVar1; } void __cdecl std::_splitpath(char *path,char *drive,char *dir,char *fname,char *ext) { byte *pbVar1; char cVar2; byte bVar3; uint uVar4; int iVar5; byte *pbVar6; size_t sVar7; char *pcVar8; byte *local_4; iVar5 = -1; pcVar8 = path; do { if (iVar5 == 0) break; iVar5 += -1; cVar2 = *pcVar8; pcVar8 = pcVar8 + 1; } while (cVar2 != '\0'); local_4 = NULL; if ((iVar5 == -2) || (path[1] != ':')) { if (drive != NULL) { *drive = '\0'; } } else { if (drive != NULL) { internal::__strncpy(drive,path,2); drive[2] = '\0'; } path = path + 2; } bVar3 = *path; drive = NULL; pbVar6 = (byte *)path; while (bVar3 != 0) { bVar3 = *pbVar6; if ((globs::_crt1.CHAR_ARRAY_0054a2b8[bVar3 + 1] & 4U) == 0) { if ((bVar3 == '/') || (bVar3 == '\\')) { drive = (char *)(pbVar6 + 1); } else { if (bVar3 == '.') { local_4 = pbVar6; } } } else { pbVar6 = pbVar6 + 1; } pbVar1 = pbVar6 + 1; pbVar6 = pbVar6 + 1; bVar3 = *pbVar1; } if ((byte *)drive == NULL) { drive = path; if (dir != NULL) { *dir = '\0'; } } else { if (dir != NULL) { uVar4 = (int)drive - (int)path; if (0xfe < uVar4) { uVar4 = 0xff; } internal::__strncpy(dir,path,uVar4); dir[uVar4] = '\0'; } } if ((local_4 == NULL) || (local_4 < drive)) { if (fname != NULL) { sVar7 = (int)pbVar6 - (int)drive; if (0xfe < sVar7) { sVar7 = 0xff; } internal::__strncpy(fname,drive,sVar7); fname[sVar7] = '\0'; } if (ext != NULL) { *ext = '\0'; } } else { if (fname != NULL) { uVar4 = (int)local_4 - (int)drive; if (0xfe < uVar4) { uVar4 = 0xff; } internal::__strncpy(fname,drive,uVar4); fname[uVar4] = '\0'; } if (ext != NULL) { sVar7 = (int)pbVar6 - (int)local_4; if (0xfe < sVar7) { sVar7 = 0xff; } internal::__strncpy(ext,(char *)local_4,sVar7); ext[sVar7] = '\0'; return; } } return; } // WARNING: Could not reconcile some variable overlaps int __cdecl std::vfscanf(FILE *stream,char *format,va_list argptr) { byte bVar1; int **ppiVar2; va_list *ppcVar3; uint uVar4; int iVar5; uint uVar6; int **c; uint uVar7; byte bVar8; byte *pbVar9; byte *pbVar10; va_list *ppcVar11; char *pcVar12; char *pcVar13; int iVar14; undefined4 *puVar15; va_list *ppcVar16; va_list pcVar17; bool bVar18; ulonglong uVar19; FILE *file; char local_1cd; va_list local_1cc; char local_1c7; char local_1c6; char local_1c5; int local_1c4; char local_1c0; char local_1bf; char local_1be; byte local_1bd; uint local_1bc; va_list *local_1b8; undefined4 local_1b4; int local_1b0; int local_1ac; int local_1a8; va_list local_1a4; byte local_19e; undefined local_19d; undefined8 local_19c; uint local_194; ushort local_18e; int **local_18c; int local_188; uint local_184; undefined4 local_180 [2]; undefined local_175; char local_160; char local_15f [351]; local_1bf = '\0'; local_1cc = NULL; local_1ac = 0; bVar1 = *format; c = local_18c; do { if (bVar1 == 0) { LAB_00494e06: if ((c == (int **)0xffffffff) && ((local_1ac == 0 && (local_1bf == '\0')))) { local_1ac = -1; } return local_1ac; } iVar14 = 0; if (globals::_pcharwidth < 2) { uVar4 = *(byte *)(globals::_pctype + bVar1) & 8; } else { uVar4 = _isctype((uint)bVar1,8); } if (uVar4 != 0) { local_1cc = local_1cc + -1; file = stream; iVar5 = internal::__vfscanf__fgetc_skipws((int *)&local_1cc,stream); internal::__vfscanf__00494f60(iVar5,file); format = format + 1; iVar5 = isspace((uint)(byte)*format); while (iVar5 != 0) { format = (char *)((byte *)format + 1); iVar5 = isspace((uint)(byte)*format); } } if (*format != '%') { local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); if ((int **)(uint)(byte)*format != c) goto LAB_00494ded; pbVar9 = (byte *)(format + 1); if ((*(byte *)((int)globals::_pctype + ((uint)c & 0xff) * 2 + 1) & 0x80) != 0) { local_1cc = local_1cc + 1; uVar4 = internal::__vfscanf__fgetc(stream); if ((byte)format[1] != uVar4) { local_1cc = local_1cc + -1; internal::__vfscanf__00494f60(uVar4,stream); goto LAB_00494ded; } local_1cc = local_1cc + -1; pbVar9 = (byte *)(format + 2); } goto LAB_00494db3; } local_1a4 = NULL; local_1b4 &= 0xffffff00; local_1a8 = 0; local_1b0 = 0; local_1c4 = 0; local_1bd = 0; local_1be = '\0'; local_1c5 = '\0'; local_1cd = '\0'; local_1c0 = '\0'; local_1c7 = '\0'; local_1c6 = '\x01'; local_188 = 0; do { pbVar9 = (byte *)(format + 1); uVar4 = (uint)*pbVar9; if (globals::_pcharwidth < 2) { uVar6 = *(byte *)(globals::_pctype + uVar4) & 4; } else { uVar6 = _isctype(uVar4,4); } if (uVar6 != 0) { local_1b0 += 1; local_1c4 = (uVar4 - 0x30) + local_1c4 * 10; goto switchD_00494330_caseD_46; } if (false) { switchD_00494330_caseD_2b: local_1cd += '\x01'; } else { switch(uVar4) { case 0x2a: local_1c5 += '\x01'; break; default: goto switchD_00494330_caseD_2b; case 0x46: case 0x4e: break; case 0x49: if ((format[2] != '6') || (format[3] != '4')) goto switchD_00494330_caseD_2b; iVar14 += 1; local_19c = 0; pbVar9 = (byte *)(format + 3); break; case 0x4c: local_1c6 += '\x01'; break; case 0x68: local_1c6 += -1; local_1c7 += -1; break; case 0x6c: local_1c6 += '\x01'; case 0x77: local_1c7 += '\x01'; } } switchD_00494330_caseD_46: format = (char *)pbVar9; } while (local_1cd == '\0'); ppiVar2 = (int **)argptr; if (local_1c5 == '\0') { local_1b8 = *(va_list **)argptr; ppiVar2 = (int **)((int)argptr + 4); local_18c = (int **)argptr; } argptr = (va_list)ppiVar2; bVar18 = false; if ((local_1c7 == '\0') && ((*format == 'S' || (local_1c7 = -1, *format == 'C')))) { local_1c7 = '\x01'; } local_1bc = (byte)*format | 0x20; local_188 = iVar14; uVar19 = local_19c; if (local_1bc != 0x6e) { if ((local_1bc == 99) || (local_1bc == 0x7b)) { local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); uVar19 = local_19c; } else { c = (int **)internal::__vfscanf__fgetc_skipws((int *)&local_1cc,stream); uVar19 = local_19c; } } ppcVar11 = local_1b8; uVar4 = local_1bc; local_19c = uVar19; if ((local_1b0 != 0) && (local_1c4 == 0)) { LAB_00494ded: local_1cc = local_1cc + -1; internal::__vfscanf__00494f60((int)c,stream); goto LAB_00494e06; } if (false) { switchD_00494448_caseD_68: if ((int **)(uint)(byte)*format != c) goto LAB_00494ded; local_1bf += -1; if (local_1c5 == '\0') { argptr = (va_list)local_18c; } goto LAB_00494d38; } switch(local_1bc) { case 99: if (local_1b0 == 0) { local_1b0 = 1; local_1c4 += 1; } if ('\0' < local_1c7) { local_1c0 = '\x01'; } pbVar9 = (byte *)globs::_crt4.field_0x3c; break; case 100: case 0x6f: case 0x75: goto switchD_00494448_caseD_64; case 0x65: case 0x66: case 0x67: pcVar12 = &local_160; if (c == (int **)0x2d) { local_160 = '-'; pcVar12 = local_15f; LAB_00494af3: local_1c4 += -1; local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); uVar19 = local_19c; } else { if (c == (int **)0x2b) goto LAB_00494af3; } iVar14 = local_1a8; if ((local_1b0 == 0) || (0x15d < local_1c4)) { local_1c4 = 0x15d; } while( true ) { if (globals::_pcharwidth < 2) { uVar4 = *(byte *)(globals::_pctype + (int)c) & 4; } else { local_19c = uVar19; uVar4 = _isctype((int)c,4); uVar19 = local_19c; } local_19c = uVar19; if ((uVar4 == 0) || (iVar5 = local_1c4 + -1, bVar18 = local_1c4 == 0, local_1c4 = iVar5, bVar18)) break; *pcVar12 = (char)c; pcVar12 = pcVar12 + 1; local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); iVar14 = iVar14 + 1; uVar19 = local_19c; } if ((CHAR___004b0f78 == (char)c) && (iVar5 = local_1c4 + -1, bVar18 = local_1c4 != 0, local_1c4 = iVar5, bVar18)) { local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); *pcVar12 = CHAR___004b0f78; while( true ) { pcVar12 = pcVar12 + 1; if (globals::_pcharwidth < 2) { uVar4 = *(byte *)(globals::_pctype + (int)c) & 4; uVar19 = local_19c; } else { uVar4 = _isctype((int)c,4); uVar19 = local_19c; } if ((uVar4 == 0) || (iVar5 = local_1c4 + -1, bVar18 = local_1c4 == 0, local_1c4 = iVar5, bVar18)) break; *pcVar12 = (char)c; iVar14 += 1; local_1cc = local_1cc + 1; local_19c = uVar19; c = (int **)internal::__vfscanf__fgetc(stream); } } pcVar13 = pcVar12; if ((iVar14 != 0) && (((c == (int **)0x65 || (c == (int **)0x45)) && (iVar5 = local_1c4 + -1, bVar18 = local_1c4 != 0, local_1c4 = iVar5, bVar18)))) { *pcVar12 = 'e'; pcVar13 = pcVar12 + 1; local_1cc = local_1cc + 1; local_19c = uVar19; c = (int **)internal::__vfscanf__fgetc(stream); if (c == (int **)0x2d) { *pcVar13 = '-'; pcVar13 = pcVar12 + 2; LAB_00494c4e: iVar5 = local_1c4 + -1; uVar19 = local_19c; if (local_1c4 != 0) goto LAB_00494c63; } else { if (c == (int **)0x2b) goto LAB_00494c4e; } while( true ) { if (globals::_pcharwidth < 2) { uVar4 = *(byte *)(globals::_pctype + (int)c) & 4; uVar19 = local_19c; } else { uVar4 = _isctype((int)c,4); uVar19 = local_19c; } if ((uVar4 == 0) || (iVar5 = local_1c4 + -1, bVar18 = local_1c4 == 0, local_1c4 = iVar5, bVar18)) break; iVar14 += 1; *pcVar13 = (char)c; pcVar13 = pcVar13 + 1; LAB_00494c63: local_1c4 = iVar5; local_1cc = local_1cc + 1; local_19c = uVar19; c = (int **)internal::__vfscanf__fgetc(stream); } } local_1cc = local_1cc + -1; local_19c = uVar19; internal::__vfscanf__00494f60((int)c,stream); if (iVar14 != 0) { uVar19 = local_19c; if (local_1c5 == '\0') { local_1ac += 1; *pcVar13 = '\0'; (*(code *)PTR___std_FUN_004b0f88)(local_1c6 + -1,local_1b8,&local_160); uVar19 = local_19c; } goto LAB_00494d38; } goto LAB_00494e06; default: goto switchD_00494448_caseD_68; case 0x69: local_1bc = 100; case 0x78: uVar4 = local_1bc; if (c == (int **)0x2d) { local_1be = '\x01'; LAB_00494702: local_1c4 += -1; if ((local_1c4 == 0) && (local_1b0 != 0)) { bVar18 = true; } else { local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); uVar19 = local_19c; } } else { if (c == (int **)0x2b) goto LAB_00494702; } if (c == (int **)0x30) { local_1cc = local_1cc + 1; local_19c = uVar19; c = (int **)internal::__vfscanf__fgetc(stream); if (((char)c == 'x') || ((char)c == 'X')) { local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); uVar4 = 0x78; local_1bc = 0x78; uVar19 = local_19c; } else { local_1a8 = 1; if (uVar4 == 0x78) { local_1cc = local_1cc + -1; internal::__vfscanf__00494f60((int)c,stream); c = (int **)0x30; uVar19 = local_19c; } else { uVar4 = 0x6f; local_1bc = 0x6f; uVar19 = local_19c; } } } goto LAB_004947e4; case 0x6e: pcVar17 = local_1cc; if (local_1c5 != '\0') goto LAB_00494d38; goto LAB_00494aa5; case 0x70: local_1c6 = '\x01'; switchD_00494448_caseD_64: if (c == (int **)0x2d) { local_1be = '\x01'; LAB_004947ba: local_1c4 += -1; if ((local_1c4 == 0) && (local_1b0 != 0)) { bVar18 = true; } else { local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); uVar19 = local_19c; } } else { if (c == (int **)0x2b) goto LAB_004947ba; } LAB_004947e4: pcVar17 = local_1a4; local_19c = uVar19; if (iVar14 == 0) { while (!bVar18) { local_19c = uVar19; if ((uVar4 == 0x78) || (uVar4 == 0x70)) { if (globals::_pcharwidth < 2) { // C1_XDIGIT (0x80) uVar6 = *(byte *)(globals::_pctype + (int)c) & C1_XDIGIT; } else { // C1_XDIGIT (0x80) uVar6 = _isctype((int)c,C1_XDIGIT); uVar19 = local_19c; } if (uVar6 != 0) { pcVar17 = (va_list)((int)pcVar17 << 4); local_19c = uVar19; c = (int **)internal::__hexdigit_subtractalpha((int)c); goto LAB_004949da; } LAB_004949d6: bVar18 = true; local_19c = uVar19; } else { if (globals::_pcharwidth < 2) { uVar6 = *(byte *)(globals::_pctype + (int)c) & 4; } else { uVar6 = _isctype((int)c,4); uVar19 = local_19c; } if (uVar6 == 0) goto LAB_004949d6; local_19c = uVar19; if (uVar4 == 0x6f) { if (0x37 < (int)c) goto LAB_004949d6; pcVar17 = (va_list)((int)pcVar17 << 3); } else { pcVar17 = (va_list)((int)pcVar17 * 10); } } LAB_004949da: if (bVar18) { local_1cc = local_1cc + -1; internal::__vfscanf__00494f60((int)c,stream); uVar19 = local_19c; } else { local_1a8 += 1; pcVar17 = pcVar17 + -0x30 + (int)c; if ((local_1b0 == 0) || (local_1c4 += -1, local_1c4 != 0)) { local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); uVar19 = local_19c; } else { bVar18 = true; uVar19 = local_19c; } } } local_1a4 = pcVar17; if (local_1be != '\0') { local_1a4 = (va_list)-(int)pcVar17; } } else { while( true ) { uVar4 = (uint)uVar19; uVar6 = (uint)(uVar19 >> 0x20); if (bVar18) break; if (local_1bc == 0x78) { if (globals::_pcharwidth < 2) { uVar4 = *(byte *)(globals::_pctype + (int)c) & 0x80; } else { uVar4 = _isctype((int)c,0x80); } if (uVar4 != 0) { uVar19 = internal::__allshl(); c = (int **)internal::__hexdigit_subtractalpha((int)c); goto LAB_004948b1; } LAB_004948ad: bVar18 = true; } else { if (globals::_pcharwidth < 2) { uVar7 = *(byte *)(globals::_pctype + (int)c) & 4; } else { uVar7 = _isctype((int)c,4); } if (uVar7 == 0) goto LAB_004948ad; if (local_1bc == 0x6f) { if (0x37 < (int)c) goto LAB_004948ad; uVar19 = internal::__allshl(); } else { uVar19 = __allmul(uVar4,uVar6,10,0); } } LAB_004948b1: if (bVar18) { local_1cc = local_1cc + -1; internal::__vfscanf__00494f60((int)c,stream); } else { ppiVar2 = c + -0xc; local_1a8 += 1; if ((local_1b0 == 0) || (local_1c4 += -1, local_1c4 != 0)) { local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); uVar19 = uVar19 + (longlong)(int)ppiVar2; } else { bVar18 = true; uVar19 = uVar19 + (longlong)(int)ppiVar2; } } } if (local_1be != '\0') { uVar19 = CONCAT44(-(uVar6 + (uVar4 != 0)),-uVar4); } } iVar14 = local_1a8; if (local_1bc == 0x46) { iVar14 = 0; } if (iVar14 != 0) { if (local_1c5 == '\0') { local_1ac += 1; pcVar17 = local_1a4; iVar14 = local_188; LAB_00494aa5: local_19c._4_4_ = (va_list)(uVar19 >> 0x20); local_19c._0_4_ = (va_list)uVar19; if (iVar14 == 0) { if (local_1c6 == '\0') { *(short *)local_1b8 = (short)pcVar17; } else { *local_1b8 = pcVar17; } } else { *local_1b8 = (va_list)local_19c; local_1b8[1] = local_19c._4_4_; } } goto LAB_00494d38; } goto LAB_00494e06; case 0x73: if ('\0' < local_1c7) { local_1c0 = '\x01'; } pbVar9 = (byte *)globs::_crt4.field_0x34; break; case 0x7b: if ('\0' < local_1c7) { local_1c0 = '\x01'; } pbVar10 = (byte *)(format + 1); pbVar9 = pbVar10; if (*pbVar10 == 0x5e) { pbVar9 = (byte *)(format + 2); format = (char *)pbVar10; break; } goto LAB_004944b3; } local_1bd = 0xff; pbVar10 = (byte *)format; LAB_004944b3: format = (char *)pbVar10; puVar15 = local_180; for (iVar14 = 8; iVar14 != 0; iVar14 += -1) { *puVar15 = 0; puVar15 = puVar15 + 1; } if ((local_1bc == 0x7b) && (*pbVar9 == 0x5d)) { local_1b4 = CONCAT31(local_1b4._1_3_,0x5d); pbVar9 = pbVar9 + 1; local_175 = 0x20; } bVar1 = *pbVar9; while (bVar1 != 0x5d) { pbVar10 = pbVar9 + 1; local_184 = local_184 & 0xffffff00 | (uint)bVar1; if (((bVar1 == 0x2d) && ((byte)local_1b4 != 0)) && (bVar8 = *pbVar10, bVar8 != 0x5d)) { pbVar10 = pbVar9 + 2; if ((byte)local_1b4 < bVar8) { local_194 = local_194 & 0xffffff00 | (uint)bVar8; bVar8 = (byte)local_1b4; } else { local_194 = local_194 & 0xffffff00 | local_1b4 & 0xff; local_1b4 = local_1b4 & 0xffffff00 | (uint)bVar8; } if (bVar8 <= (byte)local_194) { uVar4 = local_1b4 & 0xff; iVar14 = ((local_194 & 0xff) - uVar4) + 1; do { bVar1 = (byte)uVar4; pbVar9 = (byte *)((int)local_180 + (uVar4 >> 3)); uVar4 += 1; iVar14 += -1; *pbVar9 = *pbVar9 | '\x01' << (bVar1 & 7); } while (iVar14 != 0); } local_1b4 &= 0xffffff00; } else { local_1b4 = local_1b4 & 0xffffff00 | (uint)bVar1; pbVar9 = (byte *)((int)local_180 + (uint)(bVar1 >> 3)); *pbVar9 = *pbVar9 | '\x01' << (bVar1 & 7); } pbVar9 = pbVar10; bVar1 = *pbVar10; } if (*pbVar9 == 0) goto LAB_00494e06; if (local_1bc == 0x7b) { format = (char *)pbVar9; } local_1cc = local_1cc + -1; internal::__vfscanf__00494f60((int)c,stream); ppcVar16 = ppcVar11; while( true ) { if ((local_1b0 != 0) && (iVar14 = local_1c4 + -1, bVar18 = local_1c4 == 0, local_1c4 = iVar14, ppcVar3 = ppcVar16, bVar18)) goto LAB_0049469c; local_1cc = local_1cc + 1; c = (int **)internal::__vfscanf__fgetc(stream); if ((c == (int **)0xffffffff) || (bVar1 = (byte)c, ((int)(char)(*(byte *)((int)local_180 + ((int)c >> 3)) ^ local_1bd) & 1 << (bVar1 & 7)) == 0)) break; if (local_1c5 == '\0') { if (local_1c0 == '\0') { *(byte *)ppcVar16 = bVar1; ppcVar16 = (va_list *)((int)ppcVar16 + 1); } else { local_19e = bVar1; if ((*(byte *)((int)globals::_pctype + ((uint)c & 0xff) * 2 + 1) & 0x80) != 0) { local_1cc = local_1cc + 1; iVar14 = internal::__vfscanf__fgetc(stream); local_19d = (undefined)iVar14; } internal::__vfscanf__004990c0(&local_18e,&local_19e,globals::_pcharwidth); *(ushort *)ppcVar16 = local_18e; ppcVar16 = (va_list *)((int)ppcVar16 + 2); } } else { ppcVar11 = (va_list *)((int)ppcVar11 + 1); } } local_1cc = local_1cc + -1; local_1b8 = ppcVar16; internal::__vfscanf__00494f60((int)c,stream); ppcVar3 = local_1b8; LAB_0049469c: local_1b8 = ppcVar3; if (ppcVar11 == ppcVar16) goto LAB_00494e06; uVar19 = local_19c; if ((local_1c5 == '\0') && (local_1ac += 1, local_1bc != 99)) { if (local_1c0 == '\0') { *(undefined *)local_1b8 = 0; } else { *(undefined2 *)local_1b8 = 0; } } LAB_00494d38: local_1bf += '\x01'; pbVar9 = (byte *)(format + 1); local_19c = uVar19; LAB_00494db3: format = (char *)pbVar9; if ((c == (int **)0xffffffff) && ((*format != '%' || (format[1] != 'n')))) goto LAB_00494e06; bVar1 = *format; } while( true ); } int __cdecl std::tolower(int c) { int iVar1; uint uVar2; LPCWSTR pWVar3; int iVar4; uint local_8 [2]; iVar1 = c; if (globs::_crt1.DAT_0054a180 == 0) { if ((0x40 < c) && (c < 0x5b)) { return c + 0x20; } } else { if (c < 0x100) { // int std::isupper(int c) if (globals::_pcharwidth < 2) { uVar2 = *(byte *)(globals::_pctype + c) & C1_UPPER; } else { uVar2 = _isctype(c,C1_UPPER); } if (uVar2 == 0) { return iVar1; } } if ((*(byte *)((int)globals::_pctype + (iVar1 >> 8 & 0xffU) * 2 + 1) & 0x80) == 0) { c = c & 0xffff0000U | iVar1 & 0xffU; pWVar3 = (LPCWSTR)0x1; } else { c = c & 0xff000000U | (uint)CONCAT11((char)iVar1,(char)((uint)iVar1 >> 8)); pWVar3 = (LPCWSTR)0x2; } iVar4 = internal::__uprlwr__00493f60 (globs::_crt1.DAT_0054a180,0x100,(char *)&c,pWVar3,(LPWSTR)local_8,3,0); if (iVar4 == 0) { return iVar1; } if (iVar4 == 1) { return local_8[0] & 0xff; } c = (local_8[0] >> 8 & 0xff) << 8 | local_8[0] & 0xff; } return c; } int __cdecl std::isspace(int c) { uint uVar1; if (1 < globals::_pcharwidth) { // C1_SPACE (0x8) uVar1 = _isctype(c,C1_SPACE); return uVar1; } // C1_SPACE (0x8) return *(byte *)(globals::_pctype + c) & C1_SPACE; } HRESULT Direct3DRMCreate(IUnknown **lplpIDirect3DRM) { HRESULT HVar1; // WARNING: Could not recover jumptable at 0x0049b970. Too many branches // WARNING: Treating indirect jump as call HVar1 = Direct3DRMCreate(lplpIDirect3DRM); return HVar1; } Vector3F * D3DRMVectorRandom(Vector3F *d) { Vector3F *pVVar1; // WARNING: Could not recover jumptable at 0x0049b976. Too many branches // WARNING: Treating indirect jump as call pVVar1 = D3DRMVectorRandom(d); return pVVar1; } Vector3F * D3DRMVectorRotate(Vector3F *r,Vector3F *v,Vector3F *axis,float theta) { Vector3F *pVVar1; // WARNING: Could not recover jumptable at 0x0049b97c. Too many branches // WARNING: Treating indirect jump as call pVVar1 = D3DRMVectorRotate(r,v,axis,theta); return pVVar1; } HRESULT DirectDrawEnumerateA(DDENUMCALLBACKA *lpCallback,LPVOID lpContext) { HRESULT HVar1; // WARNING: Could not recover jumptable at 0x0049b982. Too many branches // WARNING: Treating indirect jump as call HVar1 = DirectDrawEnumerateA(lpCallback,lpContext); return HVar1; } HRESULT DirectDrawCreate(LPGUID lpGUID,IDirectDraw **lplpIDirectDraw,LPUNKNOWN pUnkOuter) { HRESULT HVar1; // WARNING: Could not recover jumptable at 0x0049b988. Too many branches // WARNING: Treating indirect jump as call HVar1 = DirectDrawCreate(lpGUID,lplpIDirectDraw,pUnkOuter); return HVar1; } HRESULT AVIStreamInfoA(IAVIStream *pIAVIStream,AVISTREAMINFOA *pAVIStreamInfoA,LONG lSize) { HRESULT HVar1; // WARNING: Could not recover jumptable at 0x0049b98e. Too many branches // WARNING: Treating indirect jump as call HVar1 = AVIStreamInfoA(pIAVIStream,pAVIStreamInfoA,lSize); return HVar1; } IGetFrame * AVIStreamGetFrameOpen(IAVIStream *pIAVIStream,BITMAPINFOHEADER *lpbiWanted) { IGetFrame *pIVar1; // WARNING: Could not recover jumptable at 0x0049b994. Too many branches // WARNING: Treating indirect jump as call pIVar1 = AVIStreamGetFrameOpen(pIAVIStream,lpbiWanted); return pIVar1; } HRESULT AVIStreamOpenFromFileA (IAVIStream **lplpIAVIStream,LPCSTR szFile,DWORD fccType,LONG lParam,UINT mode, CLSID *pclsidHandler) { HRESULT HVar1; // WARNING: Could not recover jumptable at 0x0049b99a. Too many branches // WARNING: Treating indirect jump as call HVar1 = AVIStreamOpenFromFileA(lplpIAVIStream,szFile,fccType,lParam,mode,pclsidHandler); return HVar1; } ULONG AVIStreamRelease(IAVIStream *pIAVIStream) { ULONG UVar1; // WARNING: Could not recover jumptable at 0x0049b9a0. Too many branches // WARNING: Treating indirect jump as call UVar1 = AVIStreamRelease(pIAVIStream); return UVar1; } LPVOID AVIStreamGetFrame(IGetFrame *pIGetFrame,LONG lPos) { LPVOID pvVar1; // WARNING: Could not recover jumptable at 0x0049b9a6. Too many branches // WARNING: Treating indirect jump as call pvVar1 = AVIStreamGetFrame(pIGetFrame,lPos); return pvVar1; } void AVIFileInit(void) { // WARNING: Could not recover jumptable at 0x0049b9ac. Too many branches // WARNING: Treating indirect jump as call AVIFileInit(); return; } HRESULT DirectInputCreateA(HINSTANCE hInst,DWORD dwVersion,IUnknown **lplpIDirectInput, IUnknown *pUnkOuter) { HRESULT HVar1; // WARNING: Could not recover jumptable at 0x0049ca68. Too many branches // WARNING: Treating indirect jump as call HVar1 = DirectInputCreateA(hInst,dwVersion,lplpIDirectInput,pUnkOuter); return HVar1; } HRESULT DirectSoundCreate(LPGUID lpGuid,IDirectSound **lplpIDirectSound,IUnknown *pUnkOuter) { HRESULT HVar1; // WARNING: Could not recover jumptable at 0x0049ca6e. Too many branches // WARNING: Treating indirect jump as call HVar1 = DirectSoundCreate(lpGuid,lplpIDirectSound,pUnkOuter); return HVar1; } // RNC (Rob Northern Compression) // https://moddingwiki.shikadi.net/wiki/Rob_Northern_Compression uint __cdecl lego::rnc::RNC_Uncompress(void *bufferIn,void **out_bufferOut) { RNCError result; byte *newBufferOut; uint origSize; uint beOrigSize; beOrigSize = *(uint *)((int)bufferIn + 4); origSize = ((beOrigSize & 0xff00) + beOrigSize * 0x10000) * 0x100 + (beOrigSize >> 0x10 & 0xff) * 0x100 + (beOrigSize >> 0x18); if (out_bufferOut == NULL) { return origSize; } newBufferOut = (byte *)io::Mem_Alloc(origSize); if (newBufferOut != NULL) { result = _RNC_Uncompress((RNC_HeaderInfo *)bufferIn,newBufferOut); if (result != RNC_OK) { io::Mem_Free(newBufferOut); return 0; } *out_bufferOut = newBufferOut; return origSize; } return 0; } RNCError __cdecl lego::rnc::_RNC_Uncompress(RNC_HeaderInfo *bufferIn,byte *bufferOut) { RNCError result; int cmp; uint origSize; undefined4 *puVar1; uint beOrigSize; RNCCompression compression; cmp = std::strncmp(bufferIn->signature,"RNC",3); if (cmp != 0) { return RNC_INVALIDFILE; } compression = bufferIn->compression; if (compression == RNC_COMPRESS_STORE) { beOrigSize = bufferIn->beOrigSize; origSize = (((beOrigSize >> 8 & 0xff) + beOrigSize * 0x100) * 0x100 + (beOrigSize >> 0x10 & 0xff)) * 0x100 + (beOrigSize >> 0x18); puVar1 = (undefined4 *)bufferIn->data; // std::memcpy(bufferOut, bufferIn->data, origSize); for (beOrigSize = origSize >> 2; beOrigSize != 0; beOrigSize -= 1) { *(undefined4 *)bufferOut = *puVar1; puVar1 = puVar1 + 1; bufferOut = (byte *)((int)bufferOut + 4); } for (origSize &= 3; origSize != 0; origSize -= 1) { *bufferOut = *(undefined *)puVar1; puVar1 = (undefined4 *)((int)puVar1 + 1); bufferOut = (byte *)((int)bufferOut + 1); } return RNC_OK; } if (compression == RNC_COMPRESS_BEST) { result = RNC_M1_Uncompress(bufferIn,bufferOut); return result; } if (compression != RNC_COMPRESS_FAST) { return RNC_INVALIDCOMPRESSION; } result = RNC_M2_Uncompress(bufferIn,bufferOut); return result; } RNCError __cdecl lego::rnc::RNC_M1_Uncompress(RNC_HeaderInfo *bufferIn,byte *bufferOut) { ushort runDataLength; ushort prevRunOffset; ushort runCopyLength; uint runCount; int i1; int i2; byte *prevOutput; RNC_BitStreamInit(bufferIn,bufferOut); RNC_M1_BitStreamAdvance(2); if (globs::rncGlobs.Output < globs::rncGlobs.OutputEnd) { do { RNC_M1_ReadHuffmanTable(globs::rncGlobs.HuffmanTable_Raw,0x10); RNC_M1_ReadHuffmanTable(globs::rncGlobs.HuffmanTable_Dst,0x10); RNC_M1_ReadHuffmanTable(globs::rncGlobs.HuffmanTable_Len,0x10); runCount = RNC_M1_BitStreamAdvance(0x10); // DECOMPILE FAIL: while (runCount) // otherwise we end up reading a dataRun when there should be no more data!!!!! while( true ) { // DATA RUN runDataLength = RNC_M1_ReadHuffman(globs::rncGlobs.HuffmanTable_Raw); if (runDataLength != 0) { i1 = (ushort)(runDataLength - 1) + 1; do { *globs::rncGlobs.Output = *globs::rncGlobs.Input; globs::rncGlobs.Output = globs::rncGlobs.Output + 1; globs::rncGlobs.Input = globs::rncGlobs.Input + 1; i1 += -1; } while (i1 != 0); } // runCount--; // ushort runCount += 0xffff; globs::rncGlobs.BitBuffer = (((uint)globs::rncGlobs.Input[1] + (uint)globs::rncGlobs.Input[2] * 0x100) * 0x100 + (uint)*globs::rncGlobs.Input << (globs::rncGlobs.BitCount & 0x1f)) + ((1 << (globs::rncGlobs.BitCount & 0x1f)) - 1U & globs::rncGlobs.BitBuffer); if ((short)runCount == 0) break; // COPY RUN prevRunOffset = RNC_M1_ReadHuffman(globs::rncGlobs.HuffmanTable_Dst); prevOutput = globs::rncGlobs.Output + (-1 - (uint)prevRunOffset); runCopyLength = RNC_M1_ReadHuffman(globs::rncGlobs.HuffmanTable_Len); if (runCopyLength != 0xfffe) { i2 = (ushort)(runCopyLength + 1) + 1; do { *globs::rncGlobs.Output = *prevOutput; globs::rncGlobs.Output = globs::rncGlobs.Output + 1; prevOutput = prevOutput + 1; i2 += -1; } while (i2 != 0); } } } while (globs::rncGlobs.Output < globs::rncGlobs.OutputEnd); } return RNC_OK; } RNCError __cdecl lego::rnc::RNC_M2_Uncompress(RNC_HeaderInfo *bufferIn,byte *bufferOut) { short sVar1; ushort uVar2; ushort uVar3; uint uVar4; byte *pbVar5; int iVar6; RNC_BitStreamInit(bufferIn,bufferOut); RNC_M2_BitStreamAdvance(2); if (globs::rncGlobs.Output < globs::rncGlobs.OutputEnd) { do { while( true ) { while( true ) { uVar4 = RNC_M2_BitStreamAdvance(1); sVar1 = (short)uVar4; while (sVar1 == 0) { *globs::rncGlobs.Output = *globs::rncGlobs.Input; globs::rncGlobs.Output = globs::rncGlobs.Output + 1; globs::rncGlobs.Input = globs::rncGlobs.Input + 1; uVar4 = RNC_M2_BitStreamAdvance(1); sVar1 = (short)uVar4; } uVar4 = RNC_M2_BitStreamAdvance(1); if ((short)uVar4 != 0) break; uVar2 = RNC_M2_ReadLengthCode(); if (uVar2 == 9) { uVar4 = RNC_M2_BitStreamAdvance(4); if ((short)(uVar4 * 4) != -0xc) { iVar6 = (uVar4 * 4 + 0x1000b & 0xffff) + 1; do { *globs::rncGlobs.Output = *globs::rncGlobs.Input; globs::rncGlobs.Output = globs::rncGlobs.Output + 1; globs::rncGlobs.Input = globs::rncGlobs.Input + 1; iVar6 += -1; } while (iVar6 != 0); } } else { uVar3 = RNC_M2_ReadOffsetCode(); pbVar5 = globs::rncGlobs.Output + -(uint)uVar3; if (uVar2 != 0) { iVar6 = (ushort)(uVar2 - 1) + 1; do { *globs::rncGlobs.Output = *pbVar5; globs::rncGlobs.Output = globs::rncGlobs.Output + 1; pbVar5 = pbVar5 + 1; iVar6 += -1; } while (iVar6 != 0); } } } uVar4 = RNC_M2_BitStreamAdvance(1); if ((short)uVar4 != 0) break; sVar1 = 2; uVar4 = *globs::rncGlobs.Input + 1; globs::rncGlobs.Input = globs::rncGlobs.Input + 1; LAB_0049ce07: pbVar5 = globs::rncGlobs.Output + -uVar4; if (sVar1 != 0) { iVar6 = (ushort)(sVar1 - 1) + 1; do { *globs::rncGlobs.Output = *pbVar5; globs::rncGlobs.Output = globs::rncGlobs.Output + 1; pbVar5 = pbVar5 + 1; iVar6 += -1; } while (iVar6 != 0); } } uVar4 = RNC_M2_BitStreamAdvance(1); if ((short)uVar4 == 0) { sVar1 = 3; LAB_0049ce02: uVar2 = RNC_M2_ReadOffsetCode(); uVar4 = (uint)uVar2; goto LAB_0049ce07; } sVar1 = *globs::rncGlobs.Input + 8; globs::rncGlobs.Input = globs::rncGlobs.Input + 1; if (sVar1 != 8) goto LAB_0049ce02; RNC_M2_BitStreamAdvance(1); } while (globs::rncGlobs.Output < globs::rncGlobs.OutputEnd); } return RNC_OK; } void __cdecl lego::rnc::RNC_BitStreamInit(RNC_HeaderInfo *bufferIn,byte *bufferOut) { uint beOrigSize; beOrigSize = bufferIn->beOrigSize; globs::rncGlobs.BitCount = 0; globs::rncGlobs.Input = bufferIn->data; globs::rncGlobs.Output = bufferOut; globs::rncGlobs.OutputEnd = bufferOut + (beOrigSize >> 0x18) + (((beOrigSize >> 8 & 0xff) + beOrigSize * 0x100) * 0x100 + (beOrigSize >> 0x10 & 0xff)) * 0x100; return; } uint __cdecl lego::rnc::RNC_M1_BitStreamAdvance(byte bits) { uint result; int k; uint *ptr; uint bitmask; result = 0; bitmask = 1; _bits = (uint)(byte)(bits - 1); if (bits != 0) { k = _bits + 1; ptr = (uint *)globs::rncGlobs.Input; do { if (globs::rncGlobs.BitCount == 0) { globs::rncGlobs.BitBuffer = *ptr; ptr = (uint *)((int)ptr + 2); globs::rncGlobs.BitCount = 0x10; globs::rncGlobs.Input = (byte *)ptr; } if ((globs::rncGlobs.BitBuffer & 1) != 0) { result |= bitmask; } bitmask <<= 1; globs::rncGlobs.BitBuffer >>= 1; globs::rncGlobs.BitCount -= 1; k += -1; } while (k != 0); } return result; } uint __cdecl lego::rnc::RNC_M2_BitStreamAdvance(byte bits) { uint result; byte *ptr; int k; result = 0; _bits = (uint)(byte)(bits - 1); if (bits != 0) { k = _bits + 1; ptr = globs::rncGlobs.Input; do { if (globs::rncGlobs.BitCount == 0) { globs::rncGlobs.ByteBuffer = *ptr; ptr = ptr + 1; globs::rncGlobs.BitCount = 8; globs::rncGlobs.Input = ptr; } result *= 2; if ((globs::rncGlobs.ByteBuffer & 0x80) != 0) { result += 1; } globs::rncGlobs.ByteBuffer <<= 1; globs::rncGlobs.BitCount -= 1; k += -1; } while (k != 0); } return result; } void __cdecl lego::rnc::RNC_M1_ReadHuffmanTable(HuffmanLeaf *table,byte bits) { byte bits2; uint uVar1; ushort *pCount_2; uint k; RNC_M1_HuffmanReset(table,bits); uVar1 = RNC_M1_BitStreamAdvance(5); bits2 = (byte)uVar1; if (bits2 != 0) { if (0x10 < bits2) { bits2 = 0x10; } if (bits2 != 0) { pCount_2 = &table->count_2; k = (uint)bits2; do { uVar1 = RNC_M1_BitStreamAdvance(4); *pCount_2 = (ushort)uVar1; pCount_2 = pCount_2 + 8; k -= 1; } while (k != 0); } RNC_M1_HuffmanAssignValues(table,bits2); } return; } ushort __cdecl lego::rnc::RNC_M1_ReadHuffman(HuffmanLeaf *table) { uint uVar1; byte k; k = 0; for (; (table->count_2 == 0 || (((1 << ((byte)table->count_2 & 0x1f)) - 1U & globs::rncGlobs.BitBuffer) != table->value_2) ); table = table + 1) { k += 1; } RNC_M1_BitStreamAdvance(*(byte *)&table->count_2); if (k < 2) { return (ushort)k; } uVar1 = RNC_M1_BitStreamAdvance(k - 1); return (ushort)uVar1 | (ushort)(1 << (k - 1 & 0x1f)); } ushort __cdecl lego::rnc::RNC_M2_ReadLengthCode(void) { ushort uVar1; uint uVar2; uVar2 = RNC_M2_BitStreamAdvance(1); uVar1 = (short)uVar2 + 4; uVar2 = RNC_M2_BitStreamAdvance(1); if ((short)uVar2 == 0) { return uVar1; } uVar2 = RNC_M2_BitStreamAdvance(1); return (short)uVar2 + -2 + uVar1 * 2; } ushort __cdecl lego::rnc::RNC_M2_ReadOffsetCode(void) { byte bVar1; ushort uVar2; uint uVar3; uVar2 = 0; uVar3 = RNC_M2_BitStreamAdvance(1); if ((short)uVar3 != 0) { uVar3 = RNC_M2_BitStreamAdvance(1); uVar2 = (ushort)uVar3; uVar3 = RNC_M2_BitStreamAdvance(1); if ((short)uVar3 == 0) { if (uVar2 == 0) { uVar3 = RNC_M2_BitStreamAdvance(1); uVar2 = (short)uVar3 + 2; } } else { uVar3 = RNC_M2_BitStreamAdvance(1); uVar2 = (short)uVar3 + uVar2 * 2 | 4; uVar3 = RNC_M2_BitStreamAdvance(1); if ((short)uVar3 == 0) { uVar3 = RNC_M2_BitStreamAdvance(1); uVar2 = (short)uVar3 + uVar2 * 2; } } } bVar1 = *globs::rncGlobs.Input; globs::rncGlobs.Input = globs::rncGlobs.Input + 1; return uVar2 * 0x100 + 1 + (ushort)bVar1; } void __cdecl lego::rnc::RNC_M1_HuffmanReset(HuffmanLeaf *table,byte bits) { int k; _bits = (uint)(byte)(bits - 1); if (bits != 0) { k = _bits + 1; do { table->value_1 = 0; table->count_1 = 0xffff; table->value_2 = 0; table->count_2 = 0; table = table + 1; k += -1; } while (k != 0); } return; } void __cdecl lego::rnc::RNC_M1_HuffmanAssignValues(HuffmanLeaf *table,byte bits) { uint uVar1; ushort k; uint bitmask; uint *pValue_2; uint i; uint value; k = 1; value = 0; bitmask = 0x80000000; do { i = (uint)bits; if (bits != 0) { pValue_2 = &table->value_2; do { if (*(ushort *)(pValue_2 + 1) == k) { uVar1 = RNC_M1_MirrorBits(value / bitmask,(byte)k); *pValue_2 = uVar1; value += bitmask; } pValue_2 = pValue_2 + 4; i -= 1; } while (i != 0); } k += 1; bitmask >>= 1; } while (k < 17); return; } uint __cdecl lego::rnc::RNC_M1_MirrorBits(uint value,byte bits) { uint result; int k; result = 0; _bits = (uint)(byte)(bits - 1); if (bits != 0) { k = _bits + 1; do { result <<= 1; if ((value & 1) != 0) { result |= 1; } value >>= 1; k += -1; } while (k != 0); } return result; } // (ChooseScreenMode) BOOL __cdecl lego::setup::Init_Initialise(BOOL setup,BOOL debug,BOOL best,BOOL window,char *noHALMsg) { bool bVar1; BOOL BVar2; Graphics_DeviceFlags *pGVar3; int iVar4; int iVar5; uint modeIndex; Graphics_Driver *driver; INT_PTR local_4; local_4 = 1; globs::initGlobs.selDriver = NULL; globs::initGlobs.selDevice = NULL; globs::initGlobs.selMode = NULL; globs::initGlobs.wasFullScreen = 1; globs::initGlobs.selFullScreen = 1; globs::initGlobs.validModeCount = 0; Init_AddValidMode(640,480,0x10); if (debug != 0) { Init_AddValidMode(800,600,0x10); Init_AddValidMode(1024,768,0x10); } ddraw::DirectDraw_EnumDrivers(globs::initGlobs.drivers,&globs::initGlobs.driverCount); if (globs::initGlobs.driverCount != 0) { globs::initGlobs.selDriver = globs::initGlobs.drivers; if (best == 0) { if (setup != 0) { local_4 = DialogBoxParamA(globs::mainGlobs.hInst,(LPCSTR)LEGORR_MODESELECTION_DIALOG, globs::mainGlobs.hWnd,Init_DialogProc,0); } } else { bVar1 = false; iVar5 = globs::initGlobs.driverCount - 1; local_4 = 1; globs::initGlobs.selFullScreen = ZEXT14(window == 0); if (-1 < iVar5) { driver = (Graphics_Driver *)((int)&globs::initGlobs + iVar5 * 0x114 + 0xc); LAB_0049d3d2: BVar2 = ddraw::DirectDraw_EnumDevices (driver,globs::initGlobs.devices,&globs::initGlobs.deviceCount); if (BVar2 == 0) { MessageBoxA(NULL,"Please install DirectX version 6 or later","Error",MB_OK); return FALSE; } ddraw::DirectDraw_EnumModes (driver,globs::initGlobs.selFullScreen,globs::initGlobs.modes, &globs::initGlobs.modeCount); modeIndex = 0; if (globs::initGlobs.modeCount != 0) { do { BVar2 = Init_IsValidMode(modeIndex); if (BVar2 != 0) { iVar4 = globs::initGlobs.deviceCount - 1; if (-1 < iVar4) { pGVar3 = &globs::initGlobs.devices[globs::initGlobs.deviceCount - 1].flags; goto LAB_0049d447; } break; } modeIndex += 1; } while (modeIndex < globs::initGlobs.modeCount); } goto LAB_0049d48f; } LAB_0049d4a8: if (!bVar1) { MessageBoxA(NULL,noHALMsg,"Error",MB_OK); return FALSE; } } if (local_4 == 1) { if (globs::initGlobs.selFullScreen != 0) { BVar2 = ddraw::DirectDraw_Setup (1,globs::initGlobs.selDriver,globs::initGlobs.selDevice, globs::initGlobs.selMode,0,0,320,200); return BVar2; } if (globs::initGlobs.selMode == NULL) { BVar2 = ddraw::DirectDraw_Setup(0,NULL,globs::initGlobs.selDevice,NULL,40,40,640,480); return BVar2; } BVar2 = ddraw::DirectDraw_Setup (0,NULL,globs::initGlobs.selDevice,NULL,100,100, (globs::initGlobs.selMode)->width,(globs::initGlobs.selMode)->height); return BVar2; } } return 0; while( true ) { iVar4 += -1; pGVar3 = pGVar3 + -0x45; if (iVar4 < 0) break; LAB_0049d447: if ((*pGVar3 & GRAPHICS_DEVICE_FLAG_HARDWARE) != GRAPHICS_DEVICE_FLAG_NONE) { globs::initGlobs.selMode = globs::initGlobs.modes + modeIndex; bVar1 = true; globs::initGlobs.selDevice = globs::initGlobs.devices + iVar4; globs::initGlobs.selDriver = driver; break; } } LAB_0049d48f: if (bVar1) goto LAB_0049d4a8; iVar5 += -1; driver = driver + -1; if (iVar5 < 0) goto LAB_0049d4a8; goto LAB_0049d3d2; } INT_PTR lego::setup::Init_DialogProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam) { short sVar1; HWND pHVar2; LRESULT LVar3; WPARAM wParam2; BOOL BVar4; short sVar5; uint uVar6; int iVar7; uint outIndex; tagRECT dlgRect; tagRECT desktopRect; char screenModeText [1024]; if (message == WM_INITDIALOG) { pHVar2 = GetDesktopWindow(); GetWindowRect(pHVar2,(LPRECT)&desktopRect); GetWindowRect(hDlg,(LPRECT)&dlgRect); MoveWindow(hDlg,desktopRect.right / 2 - (dlgRect.right - dlgRect.left) / 2, desktopRect.bottom / 2 - (dlgRect.bottom - dlgRect.top) / 2, dlgRect.right - dlgRect.left,dlgRect.bottom - dlgRect.top,1); if (globs::initGlobs.selFullScreen == 0) { iVar7 = LEGORR_ID_WINDOW_RADIOBUTTON; } else { iVar7 = LEGORR_ID_FULLSCREEN_RADIOBUTTON; } pHVar2 = GetDlgItem(hDlg,iVar7); SendMessageA(pHVar2,BM_SETCHECK,BST_CHECKED,0); pHVar2 = GetDlgItem(hDlg,LEGORR_ID_DRIVER_LISTBOX); uVar6 = 0; if (globs::initGlobs.driverCount != 0) { iVar7 = 0x5590bc; do { SendMessageA(pHVar2,LB_ADDSTRING,0,iVar7); uVar6 += 1; iVar7 += 0x114; } while (uVar6 < globs::initGlobs.driverCount); } SendMessageA(pHVar2,LB_SETCURSEL,0,0); SetFocus(pHVar2); Init_HandleWindowButton(hDlg); Init_SetDeviceList(hDlg); Init_SetModeList(hDlg); return 0; } if (message != WM_COMMAND) { return 0; } sVar1 = (short)(wParam >> 0x10); sVar5 = (short)wParam; if (sVar1 == 1) { if (sVar5 == LEGORR_ID_DEVICE_LISTBOX) { LVar3 = SendMessageA((HWND)lParam,LB_GETCURSEL,0,0); globs::initGlobs.selDevice = globs::initGlobs.devices + LVar3; return 1; } if (sVar5 == LEGORR_ID_SCREENMODES_LISTBOX) { wParam2 = SendMessageA((HWND)lParam,LB_GETCURSEL,0,0); SendMessageA((HWND)lParam,LB_GETTEXT,wParam2,(LPARAM)screenModeText); BVar4 = Init_GetMode(screenModeText,&outIndex); if (BVar4 != 0) { globs::initGlobs.selMode = globs::initGlobs.modes + outIndex; return 1; } } else { if (sVar5 == LEGORR_ID_DRIVER_LISTBOX) { LVar3 = SendMessageA((HWND)lParam,LB_GETCURSEL,0,0); globs::initGlobs.selDriver = globs::initGlobs.drivers + LVar3; Init_HandleWindowButton(hDlg); Init_SetModeList(hDlg); Init_SetDeviceList(hDlg); return 1; } } } else { if (sVar1 == 0) { if (sVar5 == LEGORR_ID_WINDOW_RADIOBUTTON) { Init_SetFullScreen(hDlg,0); } if (sVar5 == LEGORR_ID_FULLSCREEN_RADIOBUTTON) { Init_SetFullScreen(hDlg,1); return 1; } if ((sVar5 == IDOK) || (sVar5 == IDCANCEL)) { EndDialog(hDlg,wParam); } } } return 1; } void __cdecl lego::setup::Init_SetFullScreen(HWND hDlg,BOOL on) { HWND hWnd; globs::initGlobs.selFullScreen = on; Init_SetModeList(hDlg); hWnd = GetDlgItem(hDlg,LEGORR_ID_SCREENMODES_LABEL); if (on != 0) { SendMessageA(hWnd,WM_SETTEXT,0,(LPARAM)"Screen Mode"); return; } SendMessageA(hWnd,WM_SETTEXT,0,(LPARAM)"Window Size"); return; } void __cdecl lego::setup::Init_SetModeList(HWND hDlg) { bool bVar1; HWND hCtrl_Screens; int iVar2; BOOL BVar3; HWND hCtrl_OK; Graphics_Mode *pGVar4; uint local_104; char unsupportedMessage [256]; bVar1 = true; hCtrl_Screens = GetDlgItem(hDlg,LEGORR_ID_SCREENMODES_LISTBOX); iVar2 = SendMessageA(hCtrl_Screens,LB_DELETESTRING,0,0); while (iVar2 != -1) { iVar2 = SendMessageA(hCtrl_Screens,LB_DELETESTRING,0,0); } ddraw::DirectDraw_EnumModes (globs::initGlobs.selDriver,globs::initGlobs.selFullScreen,globs::initGlobs.modes, &globs::initGlobs.modeCount); local_104 = 0; if (globs::initGlobs.modeCount != 0) { pGVar4 = globs::initGlobs.modes; do { BVar3 = Init_IsValidMode(local_104); if ((BVar3 != 0) && (SendMessageA(hCtrl_Screens,LB_ADDSTRING,0,(LPARAM)pGVar4->desc), bVar1)) { bVar1 = false; globs::initGlobs.selMode = pGVar4; } local_104 += 1; pGVar4 = pGVar4 + 1; } while (local_104 < globs::initGlobs.modeCount); } hCtrl_OK = GetDlgItem(hDlg,IDOK); if (bVar1) { if (globs::initGlobs.selFullScreen == 0) { iVar2 = main::Main_GetWindowsBitDepth(); std::sprintf(unsupportedMessage,"No supported %i bit modes found",iVar2); } else { std::sprintf(unsupportedMessage,"No supported screen modes found"); } SendMessageA(hCtrl_Screens,LB_ADDSTRING,0,(LPARAM)unsupportedMessage); BVar3 = 0; } else { BVar3 = 1; } EnableWindow(hCtrl_OK,BVar3); SendMessageA(hCtrl_Screens,LB_SETCURSEL,0,0); return; } void __cdecl lego::setup::Init_SetDeviceList(HWND hDlg) { HWND hWnd; int iVar1; BOOL BVar2; WPARAM wParam; WPARAM WVar3; WPARAM local_4; local_4 = 0; hWnd = GetDlgItem(hDlg,LEGORR_ID_DEVICE_LISTBOX); iVar1 = SendMessageA(hWnd,LB_DELETESTRING,0,0); while (iVar1 != -1) { iVar1 = SendMessageA(hWnd,LB_DELETESTRING,0,0); } BVar2 = ddraw::DirectDraw_EnumDevices (globs::initGlobs.selDriver,globs::initGlobs.devices, &globs::initGlobs.deviceCount); if (BVar2 != 0) { WVar3 = 0; wParam = 0; if (globs::initGlobs.deviceCount != 0) { iVar1 = 0x55a64c; do { if ((*(uint *)(iVar1 + 0x100) & 0x2000) != 0) { local_4 = WVar3; } SendMessageA(hWnd,LB_ADDSTRING,0,iVar1); WVar3 += 1; iVar1 += 0x114; wParam = local_4; } while (WVar3 < globs::initGlobs.deviceCount); } globs::initGlobs.selDevice = globs::initGlobs.devices + wParam; SendMessageA(hWnd,LB_SETCURSEL,wParam,0); return; } SendMessageA(hWnd,LB_ADDSTRING,0,(LPARAM)"Error: DirectX6 not installed."); SendMessageA(hWnd,LB_SETCURSEL,0,0); return; } void __cdecl lego::setup::Init_AddValidMode(uint width,uint height,uint depth) { globs::initGlobs.validModes[globs::initGlobs.validModeCount].width = width; globs::initGlobs.validModes[globs::initGlobs.validModeCount].height = height; globs::initGlobs.validModes[globs::initGlobs.validModeCount].bitDepth = depth; globs::initGlobs.validModeCount = globs::initGlobs.validModeCount + 1; return; } BOOL __cdecl lego::setup::Init_IsValidMode(uint modeIndex) { uint *puVar1; uint uVar2; if (globs::initGlobs.validModeCount == 0) { return 1; } uVar2 = 0; if (globs::initGlobs.validModeCount != 0) { puVar1 = &globs::initGlobs.validModes[0].height; do { if (((puVar1[-1] == 0) || (puVar1[-1] == globs::initGlobs.modes[modeIndex].width)) && ((*puVar1 == 0 || (*puVar1 == globs::initGlobs.modes[modeIndex].height)))) { if (puVar1[1] == 0) { return 1; } if (puVar1[1] == globs::initGlobs.modes[modeIndex].bitDepth) { return 1; } } uVar2 += 1; puVar1 = puVar1 + 0x44; } while (uVar2 < globs::initGlobs.validModeCount); } return 0; } BOOL __cdecl lego::setup::Init_GetMode(char *name,uint *out_modeIndex) { byte bVar1; byte *pbVar2; int iVar3; uint uVar4; byte *pbVar5; byte *pbVar6; bool bVar7; uVar4 = 0; if (globs::initGlobs.modeCount == 0) { return 0; } pbVar2 = (byte *)globs::initGlobs.modes[0].desc; pbVar5 = (byte *)name; pbVar6 = pbVar2; LAB_0049dc2b: do { bVar1 = *pbVar2; bVar7 = bVar1 < *pbVar5; if (bVar1 == *pbVar5) { if (bVar1 != 0) { bVar1 = pbVar2[1]; bVar7 = bVar1 < pbVar5[1]; if (bVar1 != pbVar5[1]) goto LAB_0049dc4f; pbVar2 = pbVar2 + 2; pbVar5 = pbVar5 + 2; if (bVar1 != 0) goto LAB_0049dc2b; } iVar3 = 0; } else { LAB_0049dc4f: iVar3 = (1 - (uint)bVar7) - (uint)(bVar7 != 0); } if (iVar3 == 0) { *out_modeIndex = uVar4; return 1; } uVar4 += 1; pbVar2 = pbVar6 + 0x110; pbVar5 = (byte *)name; pbVar6 = pbVar2; if (globs::initGlobs.modeCount <= uVar4) { return 0; } } while( true ); } void __cdecl lego::setup::Init_HandleWindowButton(HWND hDlg) { HWND pHVar1; if ((*(byte *)&(globs::initGlobs.selDriver)->flags & GRAPHICS_DRIVER_FLAG_WINDOWOK) == 0) { globs::initGlobs.wasFullScreen = globs::initGlobs.selFullScreen; Init_SetFullScreen(hDlg,1); pHVar1 = GetDlgItem(hDlg,LEGORR_ID_WINDOW_RADIOBUTTON); SendMessageA(pHVar1,BM_SETCHECK,0,0); EnableWindow(pHVar1,0); pHVar1 = GetDlgItem(hDlg,LEGORR_ID_FULLSCREEN_RADIOBUTTON); SendMessageA(pHVar1,BM_SETCHECK,1,0); } else { pHVar1 = GetDlgItem(hDlg,LEGORR_ID_WINDOW_RADIOBUTTON); EnableWindow(pHVar1,1); if (globs::initGlobs.wasFullScreen == 0) { Init_SetFullScreen(hDlg,0); pHVar1 = GetDlgItem(hDlg,LEGORR_ID_FULLSCREEN_RADIOBUTTON); SendMessageA(pHVar1,BM_SETCHECK,0,0); pHVar1 = GetDlgItem(hDlg,LEGORR_ID_WINDOW_RADIOBUTTON); SendMessageA(pHVar1,BM_SETCHECK,1,0); return; } } return; } // Library Function - Single Match // Name: __strnicmp // Libraries: Visual Studio 1998 Debug, Visual Studio 1998 Release int __cdecl std::_strnicmp(char *_Str1,char *_Str2,size_t _MaxCount) { byte bVar1; byte bVar2; uint c; uint c_00; bool bVar3; if (_MaxCount != 0) { if (globs::_crt1.DAT_0054a180 == 0) { do { bVar2 = *_Str1; bVar1 = *_Str2; if ((bVar2 == 0) || (bVar1 == 0)) break; _Str1 = (char *)((byte *)_Str1 + 1); _Str2 = (char *)((byte *)_Str2 + 1); if ((0x40 < bVar2) && (bVar2 < 0x5b)) { bVar2 += 0x20; } if ((0x40 < bVar1) && (bVar1 < 0x5b)) { bVar1 += 0x20; } bVar3 = bVar2 < bVar1; if (bVar2 != bVar1) goto LAB_0049ddcb; _MaxCount -= 1; } while (_MaxCount != 0); _MaxCount = 0; bVar3 = bVar2 < bVar1; if (bVar2 != bVar1) { LAB_0049ddcb: _MaxCount = 0xffffffff; if (!bVar3) { _MaxCount = 1; } } } else { c_00 = 0; c = 0; do { c = c & 0xffffff00 | (uint)(byte)*_Str1; c_00 = c_00 & 0xffffff00 | (uint)(byte)*_Str2; if ((c == 0) || (c_00 == 0)) break; _Str1 = (char *)((byte *)_Str1 + 1); _Str2 = (char *)((byte *)_Str2 + 1); c_00 = tolower(c_00); c = tolower(c); bVar3 = c < c_00; if (c != c_00) goto LAB_0049de0d; _MaxCount -= 1; } while (_MaxCount != 0); _MaxCount = 0; bVar3 = c < c_00; if (c != c_00) { LAB_0049de0d: _MaxCount = 0xffffffff; if (!bVar3) { _MaxCount = 1; } } } } return _MaxCount; } char * __cdecl std::itoa(int value,char *buffer,int radix) { if ((radix == 10) && (value < 0)) { internal::__itoa__internal(value,buffer,10,1); return buffer; } internal::__itoa__internal(value,buffer,radix,0); return buffer; } char * __cdecl std::_strlwr(char *str) { char *pcVar1; char cVar2; char *pcVar3; uint uVar4; int iVar5; uint uVar6; LPWSTR buffer; undefined4 *puVar7; LPWSTR pWVar8; LPWSTR pWVar9; undefined4 *puVar10; buffer = NULL; if (globs::_crt1.DAT_0054a180 == 0) { pcVar3 = str; if (*str != '\0') { do { cVar2 = *str; if (('@' < cVar2) && (cVar2 < '[')) { *str = cVar2 + ' '; } pcVar1 = str + 1; str = str + 1; } while (*pcVar1 != '\0'); return pcVar3; } } else { uVar4 = internal::__uprlwr__00493f60 (globs::_crt1.DAT_0054a180,0x100,str,(LPCWSTR)0xffffffff,NULL,0,0); if (((uVar4 != 0) && (buffer = (LPWSTR)lego::io::Mem_Alloc(uVar4), buffer != NULL)) && (iVar5 = internal::__uprlwr__00493f60 (globs::_crt1.DAT_0054a180,0x100,str,(LPCWSTR)0xffffffff,buffer,uVar4,0), iVar5 != 0)) { uVar4 = 0xffffffff; pWVar8 = buffer; do { pWVar9 = pWVar8; if (uVar4 == 0) break; uVar4 -= 1; pWVar9 = (LPWSTR)((int)pWVar8 + 1); cVar2 = *(char *)pWVar8; pWVar8 = pWVar9; } while (cVar2 != '\0'); uVar4 = ~uVar4; puVar7 = (undefined4 *)((int)pWVar9 - uVar4); puVar10 = (undefined4 *)str; for (uVar6 = uVar4 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } } lego::io::Mem_Free(buffer); } return str; } char * __cdecl std::_strupr(char *str) { char *pcVar1; char cVar2; char *pcVar3; uint uVar4; int iVar5; uint uVar6; LPWSTR buffer; undefined4 *puVar7; LPWSTR pWVar8; LPWSTR pWVar9; undefined4 *puVar10; buffer = NULL; if (globs::_crt1.DAT_0054a180 == 0) { pcVar3 = str; if (*str != '\0') { do { cVar2 = *str; if (('`' < cVar2) && (cVar2 < '{')) { *str = cVar2 + -0x20; } pcVar1 = str + 1; str = str + 1; } while (*pcVar1 != '\0'); return pcVar3; } } else { uVar4 = internal::__uprlwr__00493f60 (globs::_crt1.DAT_0054a180,0x200,str,(LPCWSTR)0xffffffff,NULL,0,0); if (((uVar4 != 0) && (buffer = (LPWSTR)lego::io::Mem_Alloc(uVar4), buffer != NULL)) && (iVar5 = internal::__uprlwr__00493f60 (globs::_crt1.DAT_0054a180,0x200,str,(LPCWSTR)0xffffffff,buffer,uVar4,0), iVar5 != 0)) { uVar4 = 0xffffffff; pWVar8 = buffer; do { pWVar9 = pWVar8; if (uVar4 == 0) break; uVar4 -= 1; pWVar9 = (LPWSTR)((int)pWVar8 + 1); cVar2 = *(char *)pWVar8; pWVar8 = pWVar9; } while (cVar2 != '\0'); uVar4 = ~uVar4; puVar7 = (undefined4 *)((int)pWVar9 - uVar4); puVar10 = (undefined4 *)str; for (uVar6 = uVar4 >> 2; uVar6 != 0; uVar6 -= 1) { *puVar10 = *puVar7; puVar7 = puVar7 + 1; puVar10 = puVar10 + 1; } for (uVar4 &= 3; uVar4 != 0; uVar4 -= 1) { *(undefined *)puVar10 = *(undefined *)puVar7; puVar7 = (undefined4 *)((int)puVar7 + 1); puVar10 = (undefined4 *)((int)puVar10 + 1); } } lego::io::Mem_Free(buffer); } return str; }