Files
2025-09-29 00:52:08 +02:00

1937 lines
68 KiB
Python
Executable File

// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : stock_controller.sc
// AUTHOR : Ak
// DESCRIPTION : The stock market watcher script
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
USING "rage_builtins.sch"
USING "globals.sch"
USING "commands_script.sch"
USING "commands_misc.sch"
USING "Commands_Player.sch"
USING "finance_control_public.sch"
USING "commands_graphics.sch"
USING "cellphone_public.sch"
USING "finance_modifiers_public.sch"
USING "mission_stat_public.sch"
USING "shrink_stat_tracking.sch"
USING "vehicle_gen_public.sch"
USING "vehicle_public.sch"
CONST_INT UI_HOME_SCREEN 1
CONST_INT UI_LISTING_SCREEN 2
CONST_INT UI_BUY_SCREEN 8
CONST_INT UI_SELL_SCREEN 9
//Update timers.
TIMEOFDAY todNextLogUpdate = INVALID_TIMEOFDAY
TIMEOFDAY todNextTickUpdate = INVALID_TIMEOFDAY
//Cached update frequencies.
INT iTickUpdateMins = -1
INT iSpreeTimer = 0
INT iSpreeCounter = 0
INT iSameStationTick
INT iCurrentStation = -1
#IF IS_DEBUG_BUILD
PROC DEBUG_DUMP_OFFLINE_PRICES_TO_LOG()
DEBUG_STOCK_DUMP_HEADER_CHECK()
SAVE_STRING_TO_NAMED_DEBUG_FILE("---------------------------------------------------\n",g_m_strPath, g_m_strFile)
SAVE_STRING_TO_NAMED_DEBUG_FILE("--------------------Price Log Tick-----------------\n",g_m_strPath, g_m_strFile)
SAVE_STRING_TO_NAMED_DEBUG_FILE("---------------------------------------------------\n",g_m_strPath, g_m_strFile)
TEXT_LABEL_63 dumpstring
dumpstring += "Last running mission tag: "
dumpstring += g_sMissionStatsName
SAVE_STRING_TO_NAMED_DEBUG_FILE(dumpstring, g_m_strPath, g_m_strFile)
dumpstring = ""
//BAWSAQ_LISTING_STRUCT
INT i = 0
REPEAT BS_CO_TOTAL_LISTINGS i
IF !g_BS_Listings[i].bOnlineStock
dumpstring += " ("
dumpstring += i
dumpstring += ") : Price "
SAVE_STRING_TO_NAMED_DEBUG_FILE(dumpstring, g_m_strPath, g_m_strFile)
dumpstring = FLOOR(g_BS_Listings[i].fCurrentPrice)
dumpstring += " \n"
SAVE_STRING_TO_NAMED_DEBUG_FILE(dumpstring, g_m_strPath, g_m_strFile)
ENDIF
dumpstring = ""
ENDREPEAT
SAVE_STRING_TO_NAMED_DEBUG_FILE("---------------------------------------------------\n",g_m_strPath, g_m_strFile)
ENDPROC
#ENDIF
PROC Script_Cleanup()
CPRINTLN(DEBUG_STOCKS, "Stock controller cleaning up.")
TERMINATE_THIS_THREAD()
ENDPROC
FUNC BOOL IS_VEHICLE_STOLEN_SCRIPT_VER(VEHICLE_INDEX vi)
IF g_bInMultiplayer
RETURN IS_VEHICLE_STOLEN(vi)
ENDIF
VEHICLE_GEN_NAME_ENUM v
IF IS_VEHICLE_STORED_VEHGEN_GARAGE_VEHICLE(vi,v) RETURN FALSE ENDIF
IF IS_VEHICLE_IN_TEMP_PLAYER_VEHICLE_ID_LIST(vi) RETURN FALSE ENDIF
IF IS_VEHICLE_IN_TEMP_NPC_VEHICLE_ID_LIST(vi) RETURN FALSE ENDIF
RETURN TRUE
ENDFUNC
PROC VEHICLE_MODEL_KILLED_PED_PARSE(MODEL_NAMES mn,PED_TYPE pt)
CDEBUG3LN(DEBUG_STOCKS, "Parsing a ped being killed by a vehicle.")
// ,// PeopleKilledWith : used by BF
// ,// PeopleKilledWith : used by Brute
// ,// PeopleKilledWith : used by Hijak
// ,// PeopleKilledWith : used by Maibatsu
// ,// PeopleKilledWith : used by Schyster
// ,// PeopleKilledWith : used by Ubermacht
// ,// PeopleKilledWith : used by Vapid
// ,// PeopleKilledWith : used by HVYIndustries
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECPEDKIL)
SWITCH mn
CASE COACH
CASE TAXI
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_BRVECDES_FOR_LST )
BREAK
CASE TANKER
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_BRVECDES_FOR_LTD )
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_BRVECDES_FOR_RON )
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_TANDES )
BREAK
CASE PACKER
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_BRVECDES_FOR_RON )
BREAK
CASE PHANTOM
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_BRVECDES_FOR_LTD )
BREAK
ENDSWITCH
SWITCH GET_MAKE_OF_VEHICLE(mn)
CASE BSICC_HVY
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_KILW_FOR_HVY )
BREAK
CASE BSICC_MAI
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_KILW_FOR_MAI )
SWITCH pt
CASE PEDTYPE_CIVMALE
CASE PEDTYPE_CIVFEMALE
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCIV_FOR_MAI)
CPRINTLN(DEBUG_STOCKS, "Civillian killed BSMF_SM_KILCIV_FOR_MAI")
BREAK
ENDSWITCH
BREAK
CASE BSICC_BRU
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_KILW_FOR_BRU )
BREAK
CASE BSICC_VAP
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_KILW_FOR_VAP )
BREAK
CASE BSICC_BFA
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_KILW_FOR_BFA )
BREAK
CASE BSICC_HJK
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_KILW_FOR_HJK )
BREAK
CASE BSICC_SHT
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_KILW_FOR_SHT )
SWITCH pt
CASE PEDTYPE_CIVMALE
CASE PEDTYPE_CIVFEMALE
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCIV_FOR_SHT)
CPRINTLN(DEBUG_STOCKS, "Civillian killed BSMF_SM_KILCIV_FOR_SHT")
BREAK
ENDSWITCH
BREAK
CASE BSICC_UMA
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_KILW_FOR_UMA )
SWITCH pt
CASE PEDTYPE_CIVMALE
CASE PEDTYPE_CIVFEMALE
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCIV_FOR_UMA)
CPRINTLN(DEBUG_STOCKS, "Civillian killed BSMF_SM_KILCIV_FOR_UMA")
BREAK
ENDSWITCH
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// For when you don't give a crap if a ped is dead/alive/exsistant
PROC ENTITY_EXISTANCE_LIFE_CHECK(ENTITY_INDEX ei)
DOES_ENTITY_EXIST(ei)
IS_ENTITY_DEAD(ei)
ENDPROC
PROC WEAPON_TYPE_KILLED_PED_PARSE(WEAPON_TYPE wt, PED_TYPE pt, MODEL_NAMES model)
CDEBUG3LN(DEBUG_STOCKS, "Parsing a ped being killed by a weapon.")
// Attempt to do company specific weapons.
BAWSAQ_INTERNAL_WEAPON_COMPANY wc = WEAPON_MODEL_PARSE(wt)
IF wc = WEPCO_VOM_FEUER
CDEBUG3LN(DEBUG_STOCKS, "Weapon was made by VOM_FEUER.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILW_FOR_VOM)
ENDIF
SWITCH pt
CASE PEDTYPE_CIVMALE
CASE PEDTYPE_CIVFEMALE
CDEBUG3LN(DEBUG_STOCKS, "Ped is a civilian.")
SWITCH wc
CASE WEPCO_VOM_FEUER
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by VOM_FEUER weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCIV_FOR_VOM)
BREAK
CASE WEPCO_SHREWSBURY
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by SHREWSBURY weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCIV_FOR_SHR)
BREAK
CASE WEPCO_HAWK_AND_LITTLE
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by HAWK_AND_LITTLE weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCIV_FOR_HAL)
BREAK
ENDSWITCH
BREAK
CASE PEDTYPE_CRIMINAL
CDEBUG3LN(DEBUG_STOCKS, "Ped is a criminal.")
SWITCH wc
CASE WEPCO_VOM_FEUER
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by VOM_FEUER weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCRIM_FOR_VOM)
BREAK
CASE WEPCO_SHREWSBURY
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by SHREWSBURY weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCRIM_FOR_SHR)
BREAK
CASE WEPCO_HAWK_AND_LITTLE
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by HAWK_AND_LITTLE weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCRIM_FOR_HAL)
BREAK
ENDSWITCH
BREAK
CASE PEDTYPE_SWAT
CASE PEDTYPE_COP
CDEBUG3LN(DEBUG_STOCKS, "Ped is a cop.")
SWITCH wc
CASE WEPCO_VOM_FEUER
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by VOM_FEUER weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCOP_FOR_VOM)
BREAK
CASE WEPCO_SHREWSBURY
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by SHREWSBURY weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCOP_FOR_SHR)
BREAK
CASE WEPCO_HAWK_AND_LITTLE
CDEBUG3LN(DEBUG_STOCKS, "Ped killed by HAWK_AND_LITTLE weapon.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILCOP_FOR_HAL)
BREAK
ENDSWITCH
BREAK
ENDSWITCH
SWITCH model
CASE S_F_Y_hooker_01
CDEBUG3LN(DEBUG_STOCKS, "Ped was a hooker.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_UGHOK)
BREAK
CASE A_F_M_BodyBuild_01
CASE A_M_M_Beach_02
CASE A_M_Y_MusclBeac_02
CASE A_M_Y_Runner_01
CASE A_M_Y_RoadCyc_01
CASE A_M_Y_Skater_01
CASE A_M_Y_Skater_02
CASE A_M_Y_Sunbathe_01
CASE A_M_Y_Surfer_01
CASE A_M_Y_Yoga_01
CASE S_M_Y_Baywatch_01
CASE S_M_Y_Marine_02
CDEBUG3LN(DEBUG_STOCKS, "Ped was a beach person.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_HPKIL)
BREAK
CASE S_M_Y_Dealer_01
CDEBUG3LN(DEBUG_STOCKS, "Ped was a drug dealer.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DRUGKIL)
BREAK
ENDSWITCH
ENDPROC
PROC WEAPON_TYPE_OBTAINED_PARSE(WEAPON_TYPE wt)
CDEBUG3LN(DEBUG_STOCKS, "Parsing newly obtained weapon.")
// Attempt to do company specific weapons
BAWSAQ_INTERNAL_WEAPON_COMPANY wc = WEAPON_MODEL_PARSE(wt)
SWITCH wc
CASE WEPCO_VOM_FEUER
CDEBUG3LN(DEBUG_STOCKS, "VOM_FEUER weapon obtained.")
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_WEPTAKE_FOR_VOM )
BREAK
CASE WEPCO_SHREWSBURY
CDEBUG3LN(DEBUG_STOCKS, "SHREWSBURY weapon obtained.")
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_WEPTAKE_FOR_SHR )
BREAK
CASE WEPCO_HAWK_AND_LITTLE
CDEBUG3LN(DEBUG_STOCKS, "HAWK_AND_LITTLE weapon obtained.")
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_WEPTAKE_FOR_HAL )
BREAK
ENDSWITCH
ENDPROC
FUNC BOOL WAS_PED_KILLED_BY_PLAYER(ENTITY_INDEX e)
IF NOT NETWORK_HAS_CONTROL_OF_ENTITY(e)
RETURN FALSE
ENDIF
ENTITY_INDEX eb = GET_PED_SOURCE_OF_DEATH(GET_PED_INDEX_FROM_ENTITY_INDEX(e))
IF(GET_ENTITY_FROM_PED_OR_VEHICLE(GET_PLAYER_PED(GET_PLAYER_INDEX())) = eb)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC PED_KILLED_PARSE(ENTITY_INDEX e)
CDEBUG3LN(DEBUG_STOCKS, "Parsing a killed ped.")
PED_INDEX pi = GET_PED_INDEX_FROM_ENTITY_INDEX(e)
//Check if they were damaged by a vehicle.
IF HAS_ENTITY_BEEN_DAMAGED_BY_ANY_VEHICLE(e)
ENTITY_INDEX ei = GET_PED_SOURCE_OF_DEATH(pi)//check for this being a ped done before
IF IS_ENTITY_A_VEHICLE(ei)
MODEL_NAMES mnn = GET_ENTITY_MODEL(ei)
VEHICLE_MODEL_KILLED_PED_PARSE(mnn, GET_PED_TYPE(pi) )
ELSE
WEAPON_TYPE wt = GET_PED_CAUSE_OF_DEATH(pi)
MODEL_NAMES mnn = GET_ENTITY_MODEL(e)
WEAPON_TYPE_KILLED_PED_PARSE(wt, GET_PED_TYPE(pi) ,mnn)
ENDIF
ENDIF
IF IS_ENTITY_ON_FIRE(e)
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_PEDFIREKILL) //because feck it
ENDIF
IF NOT WAS_PED_KILLED_BY_PLAYER(e)
EXIT
ENDIF
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_CRIMCOM)
INT gtr = GET_GAME_TIMER()
INT gtdiff = gtr - iSpreeTimer
iSpreeTimer = gtr
IF gtdiff > 2000
iSpreeCounter = 0
ELSE
++iSpreeCounter
IF iSpreeCounter = 3
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_KILLSPR)
ENDIF
ENDIF
ENDPROC
PROC STOCK_MARKET_MUSIC_MODIFIER_CHECK()
CDEBUG3LN(DEBUG_STOCKS, "Running music modifier checks.")
INT s = GET_PLAYER_RADIO_STATION_INDEX()
// Switch away modifier
// TimesChangedAwayFromRadiostation
IF iCurrentStation != s
IF iSameStationTick > 48 //tick every 5 seconds//so 4 minutes without switch primes switch away
SWITCH GET_RADIO_STATION_CO_BY_INT(iCurrentStation)
CASE RADIO_CO_WEAZEL BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RADCHA_FOR_WZL) BREAK
CASE RADIO_CO_CNT BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RADCHA_FOR_CNT) BREAK
CASE RADIO_CO_RA1 BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RADCHA_FOR_RA1) BREAK
CASE RADIO_CO_RA2 BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RADCHA_FOR_RA2) BREAK
ENDSWITCH
ENDIF
iSameStationTick = 0
iCurrentStation = s
ENDIF
//PRINTLN("STOCK_MARKET_MUSIC_MODIFIER_CHECK\n:")
//IF IS_MOBILE_PHONE_RADIO_ACTIVE() OR (IS_PLAYER_VEH_RADIO_ENABLE())
SWITCH GET_RADIO_STATION_CO_BY_INT(s)
CASE RADIO_CO_WEAZEL BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RAD_FOR_WZL) BREAK
CASE RADIO_CO_CNT BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RAD_FOR_CNT) BREAK
CASE RADIO_CO_RA1 BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RAD_FOR_RA1) BREAK
CASE RADIO_CO_RA2 BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RAD_FOR_RA2) BREAK
CASE RADIO_CO_NONE
//PRINTLN("STOCK_MARKET_MUSIC_MODIFIER_CHECK: unset station with index :",s,"\n")
BREAK
ENDSWITCH
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_RAD_FOR_ZIT)
iSameStationTick++
ENDPROC
PROC VEHICLE_MODEL_STOLEN_PARSE(MODEL_NAMES mn)
CDEBUG3LN(DEBUG_STOCKS, "Parsing stolen vehicle.")
// Check what the make of the vehicle is.
SWITCH GET_MAKE_OF_VEHICLE(mn)
CASE BSICC_HVY BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_HVY) BREAK
CASE BSICC_MAI BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_MAI) BREAK
CASE BSICC_BRU BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_BRU) BREAK
CASE BSICC_VAP BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_VAP) BREAK
CASE BSICC_BFA BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_BFA) BREAK
CASE BSICC_HJK BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_HJK) BREAK
CASE BSICC_SHT BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_SHT) BREAK
CASE BSICC_UMA BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_UMA) BREAK
ENDSWITCH
// Check for taxis/buses/bikes.
SWITCH mn
CASE COACH
CASE TAXI
CASE BMX
CASE SCORCHER
CASE TRIBIKE2
CASE FIXTER
CASE TRIBIKE
CASE CRUISER
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECSTOL_FOR_LST)
BREAK
ENDSWITCH
ENDPROC
PROC INTERMITTANT_PLAYER_CHECK()
CDEBUG1LN(DEBUG_STOCKS, "Running intermittant player checks.")
IF NOT IS_PLAYER_DEAD(GET_PLAYER_INDEX())
INT iwanted = GET_PLAYER_WANTED_LEVEL(GET_PLAYER_INDEX())
IF iwanted = 0
CDEBUG2LN(DEBUG_STOCKS, "The player is not wanted.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_TKNWA)
ENDIF
//Check if the player is in a stolen vehicle.
PED_INDEX p = GET_PLAYER_PED(GET_PLAYER_INDEX())
IF IS_PED_IN_ANY_VEHICLE(p)
VEHICLE_INDEX vi = GET_VEHICLE_PED_IS_IN(p)
IF vi != NULL
CDEBUG2LN(DEBUG_STOCKS, "Noted the player is in a vehicle.")
IF IS_VEHICLE_STOLEN_SCRIPT_VER(vi) /// Needs to be replaced
MODEL_NAMES mn = GET_ENTITY_MODEL(vi)
VEHICLE_MODEL_STOLEN_PARSE(mn)
ENDIF
ENDIF
ENDIF
WAIT(0)
IF NOT IS_ENTITY_DEAD(p)
WEAPON_TYPE w = GET_SELECTED_PED_WEAPON(p)
WEAPON_TYPE_OBTAINED_PARSE(w) // weapon equipped tick
SWITCH w
CASE WEAPONTYPE_MOLOTOV
CASE WEAPONTYPE_PETROLCAN
CDEBUG2LN(DEBUG_STOCKS, "Noted the player is using a fire based weapon.")
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_SP_FIRESTART_M)
BREAK
CASE CHAR_FRANKLIN
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_SP_FIRESTART_F)
BREAK
CASE CHAR_TREVOR
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_SP_FIRESTART_T)
BREAK
ENDSWITCH
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDPROC
PROC VEHICLE_MODEL_DAMAGED_PARSE(MODEL_NAMES mn)
CDEBUG3LN(DEBUG_STOCKS, "Parsing damaged vehicle.")
SWITCH GET_MAKE_OF_VEHICLE(mn)
CASE BSICC_HVY BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECDMG_FOR_HVY) BREAK
CASE BSICC_MAI BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECDMG_FOR_MAI) BREAK
CASE BSICC_BRU BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECDMG_FOR_BRU) BREAK
CASE BSICC_VAP BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECDMG_FOR_VAP) BREAK
CASE BSICC_BFA BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECDMG_FOR_BFA) BREAK
CASE BSICC_HJK BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECDMG_FOR_HJK) BREAK
CASE BSICC_SHT BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECDMG_FOR_SHT) BREAK
CASE BSICC_UMA BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECDMG_FOR_UMA) BREAK
ENDSWITCH
ENDPROC
PROC VEHICLE_MODEL_DESTROYED_PARSE(MODEL_NAMES mn)
CDEBUG3LN(DEBUG_STOCKS, "Parsing destroyed vehicle.")
SWITCH GET_MAKE_OF_VEHICLE(mn)
CASE BSICC_HVY
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_BRVECDES_FOR_HVY)
BREAK
CASE BSICC_MAI
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_BRVECDES_FOR_MAI)
BREAK
CASE BSICC_BRU
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_BRVECDES_FOR_BRU)
BREAK
CASE BSICC_VAP
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_BRVECDES_FOR_VAP)
BREAK
CASE BSICC_BFA
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_BRVECDES_FOR_BFA)
BREAK
CASE BSICC_HJK
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_BRVECDES_FOR_HJK)
BREAK
CASE BSICC_SHT
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_BRVECDES_FOR_SHT)
BREAK
CASE BSICC_UMA
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_BRVECDES_FOR_UMA)
BREAK
ENDSWITCH
IF mn = TAXI
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_TAXDEST)
ENDIF
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_CRIMCOM)
ENDPROC
FUNC BOOL DOES_VEHICLE_ENTITY_HAVE_MODS(VEHICLE_INDEX vehID)
IF GET_VEHICLE_MOD_KIT(vehID) >= 0
IF GET_VEHICLE_MOD(vehID, MOD_SPOILER) != -1
//iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_SPOILER), GET_VEHICLE_MOD(vehID, MOD_SPOILER)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_SKIRT) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_SKIRT), GET_VEHICLE_MOD(vehID, MOD_SKIRT)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_EXHAUST) != -1
//iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_EXHAUST), GET_VEHICLE_MOD(vehID, MOD_EXHAUST)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_CHASSIS) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_CHASSIS), GET_VEHICLE_MOD(vehID, MOD_CHASSIS)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_GRILL) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_GRILL), GET_VEHICLE_MOD(vehID, MOD_GRILL)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_BONNET) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_BONNET), GET_VEHICLE_MOD(vehID, MOD_BONNET)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_ROOF) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_ROOF), GET_VEHICLE_MOD(vehID, MOD_ROOF)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_ENGINE) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_ENGINE), GET_VEHICLE_MOD(vehID, MOD_ENGINE)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_BRAKES) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_BRAKES), GET_VEHICLE_MOD(vehID, MOD_BRAKES)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_GEARBOX) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_GEARBOX), GET_VEHICLE_MOD(vehID, MOD_GEARBOX)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_HORN) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_HORN), GET_VEHICLE_MOD(vehID, MOD_HORN)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_SUSPENSION) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_SUSPENSION), GET_VEHICLE_MOD(vehID, MOD_SUSPENSION)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_ARMOUR) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_ARMOUR), GET_VEHICLE_MOD(vehID, MOD_ARMOUR)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_WHEELS) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_WHEELS), GET_VEHICLE_MOD(vehID, MOD_WHEELS)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_REAR_WHEELS) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_REAR_WHEELS), GET_VEHICLE_MOD(vehID, MOD_REAR_WHEELS)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_BUMPER_F) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_BUMPER_F), GET_VEHICLE_MOD(vehID, MOD_BUMPER_F)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_BUMPER_R) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_BUMPER_R), GET_VEHICLE_MOD(vehID, MOD_BUMPER_R)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_WING_L) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_WING_L), GET_VEHICLE_MOD(vehID, MOD_WING_L)+1)
RETURN TRUE
ENDIF
IF GET_VEHICLE_MOD(vehID, MOD_WING_R) != -1
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_WING_R), GET_VEHICLE_MOD(vehID, MOD_WING_R)+1)
RETURN TRUE
ENDIF
IF IS_TOGGLE_MOD_ON(vehID, MOD_TOGGLE_TURBO)
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_TOGGLE_TURBO), 1)
RETURN TRUE
ENDIF
IF IS_TOGGLE_MOD_ON(vehID, MOD_TOGGLE_XENON_LIGHTS)
// iModValue += GET_CARMOD_MENU_OPTION_COST(GET_CARMOD_MENU_FOR_MOD_SLOT(MOD_TOGGLE_XENON_LIGHTS), 1)
RETURN TRUE
ENDIF
IF NOT GET_VEHICLE_TYRES_CAN_BURST(vehID)
// iModValue += GET_CARMOD_MENU_OPTION_COST(CMM_WHEEL_ACCS, 2)
RETURN TRUE
ENDIF
// iModValue = FLOOR((TO_FLOAT(iModValue)*0.5))
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Performs the AI event queue checks for event needed for stock market modifiers.
PROC STOCK_MODIFIER_CHECK()
IF g_bStockMarketCarModified
g_bStockMarketCarModified = FALSE
SWITCH GET_MAKE_OF_VEHICLE(g_eStockMarketCarModified)
CASE BSICC_HVY
CASE BSICC_MAI
CASE BSICC_BRU
CASE BSICC_VAP
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECMOD_FOR_AUG)
BREAK
CASE BSICC_BFA
CASE BSICC_HJK
CASE BSICC_SHT
CASE BSICC_UMA
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_VECMOD_FOR_LSC)
BREAK
ENDSWITCH
ENDIF
//TODO
//BSMF_DISTDRIV_FOR_BRU,// DistanceDrivenInType : used by Brute
//BSMF_DISTDRIV_FOR_VAP,// DistanceDrivenInType : used by Vapid
//BSMF_DISTDRIV_FOR_MAI,// DistanceDrivenInType : used by Maibatsu
//BSMF_DISTDRIV_FOR_PFI,// DistanceDrivenInType : used by Pfister
//BSMF_DISTDRIV_FOR_HVY,// DistanceDrivenInType : used by HVY
//BSMF_DISTDRIV_FOR_MTL,// DistanceDrivenInType : used by MTL
INT iCount = 0
STRUCT_ENTITY_ID sei
EVENT_NAMES eventType
PED_INDEX eventPed
BOOL checkthisentity = TRUE
REPEAT GET_NUMBER_OF_EVENTS(SCRIPT_EVENT_QUEUE_AI) iCount
eventType = GET_EVENT_AT_INDEX(SCRIPT_EVENT_QUEUE_AI, iCount)
//the event type and then total up
//NATIVE FUNC BOOL GET_EVENT_DATA(SCRIPT_EVENT_QUEUES eventQueue, INT eventIndex, STRUCT &data, INT dataSize)
//use rID
SWITCH (eventType)
CASE EVENT_ENTITY_DESTROYED
//figure out what type of entity
CPRINTLN(DEBUG_STOCKS, "Entity destroyed, parsing for type!")
GET_EVENT_DATA(SCRIPT_EVENT_QUEUE_AI,iCount, sei,SIZE_OF(STRUCT_ENTITY_ID))
ENTITY_EXISTANCE_LIFE_CHECK(sei.EntityId)
//sei.EntityId
checkthisentity = TRUE
IF NETWORK_IS_GAME_IN_PROGRESS()
IF DOES_ENTITY_EXIST(sei.EntityId)
IF NOT NETWORK_HAS_CONTROL_OF_ENTITY(sei.EntityId)
checkthisentity = FALSE
ENDIF
ELSE
checkthisentity = FALSE
ENDIF
ENDIF
IF checkthisentity
IF DOES_ENTITY_EXIST(sei.EntityId)
IF IS_ENTITY_A_PED(sei.EntityId)
CPRINTLN(DEBUG_STOCKS, "Ped killed, parsing for model: ", GET_MODEL_NAME_FOR_DEBUG(GET_ENTITY_MODEL(sei.EntityId)))
PED_KILLED_PARSE(sei.EntityId)
ELIF IS_ENTITY_A_VEHICLE(sei.EntityId)
CPRINTLN(DEBUG_STOCKS, "Vehicle destroyed, parsing for model: ", GET_MODEL_NAME_FOR_DEBUG(GET_ENTITY_MODEL(sei.EntityId)))
IF DOES_VEHICLE_ENTITY_HAVE_MODS(GET_VEHICLE_INDEX_FROM_ENTITY_INDEX(sei.EntityId))
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_BRVECDES_FOR_LSC )
ENDIF
VEHICLE_MODEL_DESTROYED_PARSE(GET_ENTITY_MODEL(sei.EntityId))
ELIF IS_ENTITY_AN_OBJECT(sei.EntityId)
//SCRIPT_ASSERT("Entity destroyed")
SWITCH GET_ENTITY_MODEL(sei.EntityId)
CASE PROP_NEWS_DISP_01A
CASE PROP_NEWS_DISP_02A
CASE PROP_NEWS_DISP_02A_S
CASE PROP_NEWS_DISP_02B
CASE PROP_NEWS_DISP_02C
CASE PROP_NEWS_DISP_02D
CASE PROP_NEWS_DISP_02E
CASE PROP_NEWS_DISP_03A
CASE PROP_NEWS_DISP_03C
CASE PROP_NEWS_DISP_05A
CASE PROP_NEWS_DISP_05A_DOOR
CASE PROP_NEWS_DISP_05A_PAPERS
CASE PROP_NEWS_DISP_06A
CASE PROP_NEWS_DISP_06A_DAM
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_NEWDAM )
BREAK
CASE MAILBOX
CASE PROP_POSTBOX_01A
CASE PROP_POSTBOX_01A_L1
CASE PROP_POSTBOX_01A_L2
CASE PROP_POSTBOX_SS_01A
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_MAILDEST )
BREAK
ENDSWITCH
CPRINTLN(DEBUG_STOCKS, "Object destroyed, parsing for model: ", GET_MODEL_NAME_FOR_DEBUG(GET_ENTITY_MODEL(sei.EntityId)))
ENDIF
ENDIF
ENDIF
BREAK
CASE EVENT_ENTITY_DAMAGED
//figure out what type of entity
//PRINTSTRING("Entity damaged, parsing for type\n")
//PRINTNL()
GET_EVENT_DATA(SCRIPT_EVENT_QUEUE_AI,iCount, sei,SIZE_OF(STRUCT_ENTITY_ID))
ENTITY_EXISTANCE_LIFE_CHECK(sei.EntityId)
checkthisentity = TRUE
IF NETWORK_IS_GAME_IN_PROGRESS()
IF DOES_ENTITY_EXIST(sei.EntityId)
IF NOT NETWORK_HAS_CONTROL_OF_ENTITY(sei.EntityId)
checkthisentity = FALSE
ENDIF
ELSE
checkthisentity = FALSE
ENDIF
ENDIF
IF checkthisentity
IF DOES_ENTITY_EXIST(sei.EntityId)
//sei.EntityId
IF IS_ENTITY_A_PED(sei.EntityId)
//PRINTSTRING("Ped injured, parsing for model: ")
//PRINTSTRING(GET_MODEL_NAME_FOR_DEBUG(GET_ENTITY_MODEL(sei.EntityId)))
//PRINTNL()
eventPed = GET_PED_INDEX_FROM_ENTITY_INDEX(sei.EntityId)
// Keep track of Michael hitting peds for purposes of Shrink dialogue
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL AND eventPed <> PLAYER_PED_ID()
IF (IS_ENTITY_DEAD(sei.EntityId) OR GET_ENTITY_HEALTH(sei.EntityId) < 0.5 * GET_PED_MAX_HEALTH(eventPed))
IF IS_ENTITY_A_PED(sei.EntityId) AND IS_PED_HUMAN(GET_PED_INDEX_FROM_ENTITY_INDEX(sei.EntityId))
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
//PRINT_STRING_WITH_LITERAL_STRING("STRING", "You have RUN OVER A PED. Dr. Friedlander will not be pleased.", DEFAULT_GOD_TEXT_TIME, 1)
SHRINK_ADD_OW_VIOLENCE_TIMESTAMP(SHRINK_VEHICLE_KILLS)
ENDIF
ENDIF
ENDIF
ENDIF
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_CRIMCOM)
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_TOTINJ)
IF IS_ENTITY_ON_FIRE(sei.EntityId)
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_PEDFIRETICK)
ENDIF
ELIF IS_ENTITY_A_VEHICLE(sei.EntityId)
//PRINTSTRING("Vehicle damaged, parsing for model: ")
//PRINTSTRING(GET_MODEL_NAME_FOR_DEBUG(GET_ENTITY_MODEL(sei.EntityId)))
//PRINTNL()
//BAWSAQ_INTERNAL_INCREMENT_MODIFIER(BSMF_VA_DAMAGED)
VEHICLE_MODEL_DAMAGED_PARSE(GET_ENTITY_MODEL(sei.EntityId))
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_CRIMCOM )
ELIF IS_ENTITY_AN_OBJECT(sei.EntityId)
BAWSAQ_INCREMENT_MODIFIER( BSMF_SM_CRIMCOM )
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_STOCKS, "Object damaged, parsing for model: ")
PRINTSTRING(GET_MODEL_NAME_FOR_DEBUG(GET_ENTITY_MODEL(sei.EntityId)))
PRINTNL()
#ENDIF
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDREPEAT
ENDPROC
PROC LCN_UPDATE_SAVED_OFFLINE_PRICES()
CPRINTLN(DEBUG_LCN,"Updating saved offline stock prices.")
// Use current and last UPMs to create new price for each entry.
INT iOfflineCount = 0
INT i
REPEAT BS_CO_TOTAL_LISTINGS i
IF NOT (g_BS_Listings[i].bOnlineStock)
IF (iOfflineCount < MAX_SP_FINANCE_VALUE_STORAGE)
g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_PRICE_DUMP[iOfflineCount] = g_BS_Listings[i].fCurrentPrice
IF g_BS_Listings[i].fLoggedHighValue > g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MAX_DUMP[iOfflineCount]
g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MAX_DUMP[iOfflineCount] = g_BS_Listings[i].fLoggedHighValue
ENDIF
IF g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MIN_DUMP[iOfflineCount] = 0
// Use this value.
g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MIN_DUMP[iOfflineCount] = g_BS_Listings[i].fLoggedLowValue
ELSE
// Check for low.
IF g_BS_Listings[i].fLoggedLowValue < g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MIN_DUMP[iOfflineCount]
g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MIN_DUMP[iOfflineCount] = g_BS_Listings[i].fLoggedLowValue
ENDIF
ENDIF
CDEBUG3LN(DEBUG_LCN,"Updated saved offline stock #", iOfflineCount," value/min/max: ", g_BS_Listings[i].fCurrentPrice,"/",
g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MIN_DUMP[iOfflineCount],"/",
g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MAX_DUMP[iOfflineCount])
++iOfflineCount
ELSE
SCRIPT_ASSERT("LCN_APPLY_MODIFIERS_TO_PRICES: Ran out of space to save global finance data, forward this bug to *Default Levels*.")
ENDIF
ENDIF
ENDREPEAT
ENDPROC
PROC LCN_APPLY_MODIFIERS_TO_PRICES()
#IF IS_DEBUG_BUILD
CDEBUG1LN(DEBUG_LCN, "Starting to apply offline price modifiers to stocks...")
INT iDebugTimer = GET_GAME_TIMER()
#ENDIF
STOCK_MODIFIER_CHECK()
// First of all maintain the stat based modifiers.
INT i
REPEAT BSMF_TOTAL_INDICES i
IF NOT g_BS_Modifiers[i].bOnline
IF g_BS_Modifiers[i].bReadFromProfile
//g_BS_Modifiers[i].iPrev += g_BS_Modifiers[i].iDelta
//set current this update
//buffer previous value
//grab current value from profile stat and buffer that
INT iCstat = 0
IF NOT g_BS_Modifiers[i].bProfIsFloatType
STAT_GET_INT(g_BS_Modifiers[i].ProfStatToRead, iCstat)
ELSE
FLOAT fsta = 0.0
STAT_GET_FLOAT(g_BS_Modifiers[i].ProfStatToRead, fsta)
INT fint = FLOOR(fsta)
IF g_BS_Modifiers[i].iPrev < fint
iCstat = fint
ELSE
iCstat = g_BS_Modifiers[i].iPrev
ENDIF
ENDIF
g_BS_Modifiers[i].iDelta = iCstat - g_BS_Modifiers[i].iPrev
ENDIF
ENDIF
IF i%20 = 0
WAIT(0)
STOCK_MODIFIER_CHECK()
ENDIF
ENDREPEAT
// Overwrite fUPMAppliedLastUpdate with fUniversalPriceModifier.
REPEAT BS_CO_TOTAL_LISTINGS i
IF NOT g_BS_Listings[i].bOnlineStock
IF NOT (g_BS_Listings[i].fUniversalPriceModifier = 0.0)
g_BS_Listings[i].fUPMAppliedLastUpdate = g_BS_Listings[i].fUniversalPriceModifier
ENDIF
ENDIF
IF i%40 = 0
WAIT(0)
STOCK_MODIFIER_CHECK()
ENDIF
ENDREPEAT
// Use current and last UPMs to create new price for each entry.
INT iOfflineCount = 0
REPEAT BS_CO_TOTAL_LISTINGS i
IF NOT (g_BS_Listings[i].bOnlineStock)
//g_BS_Listings[i].
//FLOAT fPriceBefore = g_BS_Listings[i].fCurrentPrice
FLOAT fPendingPriceChange = 0.0
//apply modifiers
IF(g_BS_Listings[i].fUniversalPriceModifier != 0.0)
//g_BS_Listings[i].fCurrentPrice += ((g_BS_Listings[i].fStockPriceChangeSensitivity*g_BS_Listings[i].fCurrentPrice)*g_BS_Listings[i].fUniversalPriceModifier)
//This need to be replaced with the new price calc
fPendingPriceChange += ((0.02*g_BS_Listings[i].fCurrentPrice)*g_BS_Listings[i].fUniversalPriceModifier) - g_BS_Listings[i].fCurrentPrice
CDEBUG3LN(debug_lcn,"Stock ",i," has price modifier: ",g_BS_Listings[i].fUniversalPriceModifier)
ENDIF
//apply background noise
//fCurrentPrice += (random between 1.0 and -1.0) * (fCurrentPrice + 0.01f)) * fStartingSensitivity;
fPendingPriceChange += GET_RANDOM_FLOAT_IN_RANGE(-g_BS_OfAttribData[iOfflineCount].fNoise,g_BS_OfAttribData[iOfflineCount].fNoise) *0.1 * g_BS_Listings[i].fCurrentPrice
// Now apply extra rules from the data.
// Update the inclination.
//g_BS_OfAttribData[iOfflineCount].fCurrentInclination
g_BS_OfAttribData[iOfflineCount].fCurrentInclination *= 0.995
IF fPendingPriceChange < 0.0
fPendingPriceChange *= g_BS_OfAttribData[iOfflineCount].fBullish
ELIF fPendingPriceChange > 0.0
fPendingPriceChange *= g_BS_OfAttribData[iOfflineCount].fBearish
ENDIF
//Clamp pending price change to -/+ stepCap
fPendingPriceChange = CLAMP(fPendingPriceChange,-g_BS_OfAttribData[iOfflineCount].fStepCap,g_BS_OfAttribData[iOfflineCount].fStepCap)
//finally update the price
//balance change
//PRINTLN("apply pending pre ", fPendingPriceChange)
INT lindex = ENUM_TO_INT(BS_CO_LFI)
IF i = lindex
AND (GET_MISSION_COMPLETE_STATE(SP_MISSION_LESTER_1))
AND (NOT GET_MISSION_COMPLETE_STATE(SP_MISSION_TREVOR_3))
AND fPendingPriceChange > 0.0
// Special.
g_BS_Listings[i].fCurrentPrice -= fPendingPriceChange //LFI continued crash
ELSE
IF fPendingPriceChange > 0.0
FLOAT val = GET_PRICE_RISE_SCALER_FOR_ASSET(INT_TO_ENUM(BAWSAQ_COMPANIES,i))
fPendingPriceChange *= val
//PRINTLN("apply pending mod ", fPendingPriceChange, " : ", val)
ENDIF
CDEBUG3LN(debug_lcn,"<Stock ",i,"> ",GET_STRING_FROM_TEXT_FILE(g_BS_Listings[i].sLongName),": Price ", g_BS_Listings[i].fCurrentPrice, " + ", fPendingPriceChange," min/max ",
g_BS_Listings[i].fLoggedLowValue , "/",g_BS_Listings[i].fLoggedHighValue," noise ",g_BS_OfAttribData[iOfflineCount].fNoise)
CDEBUG3LN(debug_lcn,"bull ",g_BS_OfAttribData[iOfflineCount].fBullish, " bear ",g_BS_OfAttribData[iOfflineCount].fBearish,
" stepCap ",g_BS_OfAttribData[iOfflineCount].fStepCap," incline ",g_BS_OfAttribData[iOfflineCount].fCurrentInclination)
g_BS_Listings[i].fCurrentPrice += fPendingPriceChange //regular price
ENDIF
// Check for operating under the floor or over the ceiling.
IF g_BS_Listings[i].fCurrentPrice > g_BS_OfAttribData[iOfflineCount].fCeiling
FLOAT dif = g_BS_Listings[i].fCurrentPrice - g_BS_OfAttribData[iOfflineCount].fCeiling
dif *= 0.5
g_BS_Listings[i].fCurrentPrice -= dif
ELIF g_BS_Listings[i].fCurrentPrice < g_BS_OfAttribData[iOfflineCount].fFloor
FLOAT dif = g_BS_OfAttribData[iOfflineCount].fFloor - g_BS_Listings[i].fCurrentPrice
dif *= 0.5
g_BS_Listings[i].fCurrentPrice += dif
ENDIF
//fCurrentPrice += pendingPriceChange + Inclination;
//Inclination -= ((pendingPriceChange*0.66f) + (Inclination*0.33f)) * 0.02f;
g_BS_OfAttribData[iOfflineCount].fCurrentInclination -= ((fPendingPriceChange*0.66) + (g_BS_OfAttribData[iOfflineCount].fCurrentInclination*0.33)) * 0.02
// Make sure price is not smaller than zero and throw a warning if it goes to that.
IF NOT (g_BS_Listings[i].fCurrentPrice > 0.0)
//TODO trigger rock bottom detection here
g_BS_Listings[i].fCurrentPrice = (-1.0) * g_BS_Listings[i].fCurrentPrice
CPRINTLN(debug_lcn,"WARNING! Negative (<0) current stock price detected")
g_BS_Listings[i].fCurrentPrice += 0.02
ENDIF
ENDIF
IF i%20 = 0
WAIT(0)
STOCK_MODIFIER_CHECK()
ENDIF
ENDREPEAT
LCN_UPDATE_SAVED_OFFLINE_PRICES()
// Finally set the previous value for all scripted modifiers.
i = 0
REPEAT BSMF_TOTAL_INDICES i
IF NOT g_BS_Modifiers[i].bOnline
IF g_BS_Modifiers[i].bReadFromProfile
g_BS_Modifiers[i].iPrev += g_BS_Modifiers[i].iDelta
ENDIF
ENDIF
ENDREPEAT
#IF IS_DEBUG_BUILD
CDEBUG1LN(DEBUG_LCN, "...Finished applying price modifiers to stocks after ", GET_GAME_TIMER() - iDebugTimer, "ms.")
#ENDIF
ENDPROC
FUNC BOOL CHECK_FOR_MULTIPLAYER_TOD_SKIP_AND_UPDATE_TIME(TIMEOFDAY &todUpdateTime, BOOL bUpdate = TRUE, INT iAddHours = 8)
//Check if the Multipleyr TOD has been set-up
IF IS_TIMEOFDAY_VALID(g_sMultiplayerTransitionTOD)
IF bUpdate
//Set TOD to the saved hour on the current day
TIMEOFDAY todTemp = GET_CURRENT_TIMEOFDAY()
int iHour = GET_TIMEOFDAY_HOUR(g_sMultiplayerTransitionTOD)
int iMinute = GET_TIMEOFDAY_MINUTE(g_sMultiplayerTransitionTOD)
SET_TIMEOFDAY_HOUR(todTemp,iHour)
SET_TIMEOFDAY_MINUTE(todTemp,iMinute)
SET_TIMEOFDAY_SECOND(todTemp,0)
//Add 1 day if not possible
IF IS_TIMEOFDAY_AFTER_TIMEOFDAY(GET_CURRENT_TIMEOFDAY(),todTemp)
ADD_TIME_TO_TIMEOFDAY(todTemp,0,0,0,1)
ENDIF
//Add hours to the current TOD until it is after the calculated return one
int iCount = 0 //Maximum 24h increase
WHILE IS_TIMEOFDAY_AFTER_TIMEOFDAY(todTemp,todUpdateTime) AND iCount<24
ADD_TIME_TO_TIMEOFDAY(todUpdateTime,0,0,iAddHours)
iCount += iAddHours
ENDWHILE
ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL CHECK_FOR_LOG_TIME_TRIPPED()
#IF IS_DEBUG_BUILD
TEXT_LABEL_63 txtDebugTimeOfDay
#ENDIF
//Do we need to set up an initial trip time?
IF todNextLogUpdate = INVALID_TIMEOFDAY
CDEBUG1LN(DEBUG_STOCKS, "Trip timers haven't been initialised. Setting up now...")
//We want to set our start hour to be on the next of 8, 16 or 24. Exactly on the hour.
todNextLogUpdate = GET_CURRENT_TIMEOFDAY()
INT iHour = GET_TIMEOFDAY_HOUR(todNextLogUpdate)
IF iHour = 24
iHour = 0
ENDIF
//Set the initial hour.
IF IS_HOUR_BETWEEN_THESE_HOURS(iHour, 0, 8)
SET_TIMEOFDAY_HOUR(todNextLogUpdate, 8)
ELIF IS_HOUR_BETWEEN_THESE_HOURS(iHour, 8, 16)
SET_TIMEOFDAY_HOUR(todNextLogUpdate, 16)
ELIF IS_HOUR_BETWEEN_THESE_HOURS(iHour, 16, 24)
SET_TIMEOFDAY_HOUR(todNextLogUpdate, 0)
ADD_TIME_TO_TIMEOFDAY(todNextLogUpdate, 0, 0, 0 , 1) //Roll over to midnight the next day.
ELSE
SCRIPT_ASSERT("CHECK_FOR_LOG_TIME_TRIPPED: Must have badly scripted logic. Couldn't work out starting hour.")
ENDIF
//Zero the initial minutes and seconds. It should always trip exactly on the hour.
SET_TIMEOFDAY_MINUTE(todNextLogUpdate, 0)
SET_TIMEOFDAY_SECOND(todNextLogUpdate, 0)
//Initialise the tick timer now as well. Start it off at the exact sime time as the log timer.
//They will update at different frequencies.
todNextTickUpdate = todNextLogUpdate
#IF IS_DEBUG_BUILD
txtDebugTimeOfDay = TIMEOFDAY_TO_TEXT_LABEL(todNextLogUpdate)
CDEBUG1LN(DEBUG_STOCKS, "The current hour is ", iHour, " so setting initial LOG trip time to [", txtDebugTimeOfDay, "].")
#ENDIF
RETURN FALSE
ENDIF
//Check if we've passed the next log trip time.
IF IS_NOW_AFTER_TIMEOFDAY(todNextLogUpdate)
//B* 2150106: Check if the Multiplayer TOD skip has happened
IF CHECK_FOR_MULTIPLAYER_TOD_SKIP_AND_UPDATE_TIME(todNextLogUpdate)
CPRINTLN(debug_stocks,"Multiplayer TOD skip detected, setting next LOG time to after skip:")
#IF IS_DEBUG_BUILD
PRINT_TIMEOFDAY(todNextLogUpdate,debug_stocks)
#ENDIF
RETURN FALSE
ENDIF
#IF IS_DEBUG_BUILD
txtDebugTimeOfDay = TIMEOFDAY_TO_TEXT_LABEL(todNextLogUpdate)
CDEBUG1LN(DEBUG_STOCKS, "LOG timer tripped. It is after [", txtDebugTimeOfDay, "].")
#ENDIF
ADD_TIME_TO_TIMEOFDAY(todNextLogUpdate, 0, STOCK_MARKET_LOG_UPDATE_MINS, 0)
#IF IS_DEBUG_BUILD
txtDebugTimeOfDay = TIMEOFDAY_TO_TEXT_LABEL(todNextLogUpdate)
CDEBUG1LN(DEBUG_STOCKS, "Next LOG trip time set to [", txtDebugTimeOfDay, "].")
#ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL CHECK_FOR_TICK_TIME_TRIPPED()
IF todNextTickUpdate = INVALID_TIMEOFDAY
//Waiting to be initialised in CHECK_FOR_LOG_TIME_TRIPPED.
RETURN FALSE
ENDIF
#IF IS_DEBUG_BUILD
TEXT_LABEL_63 txtDebugTimeOfDay
#ENDIF
//Check if we've passed the next tick trip time.
IF IS_NOW_AFTER_TIMEOFDAY(todNextTickUpdate)
//B* 2150106: Check if the Multiplayer TOD skip has happened
IF CHECK_FOR_MULTIPLAYER_TOD_SKIP_AND_UPDATE_TIME(todNextTickUpdate)
CPRINTLN(debug_stocks,"Multiplayer TOD skip detected, setting next TICK time to after skip:")
#IF IS_DEBUG_BUILD
PRINT_TIMEOFDAY(todNextTickUpdate, debug_stocks)
#ENDIF
RETURN FALSE
ENDIF
#IF IS_DEBUG_BUILD
txtDebugTimeOfDay = TIMEOFDAY_TO_TEXT_LABEL(todNextTickUpdate)
CDEBUG1LN(DEBUG_STOCKS, "TICK timer tripped. It is after [", txtDebugTimeOfDay, "].")
#ENDIF
ADD_TIME_TO_TIMEOFDAY(todNextTickUpdate, 0, iTickUpdateMins, 0)
#IF IS_DEBUG_BUILD
txtDebugTimeOfDay = TIMEOFDAY_TO_TEXT_LABEL(todNextTickUpdate)
CDEBUG1LN(DEBUG_STOCKS, "Next TICK trip time set to [", txtDebugTimeOfDay, "].")
#ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC LCN_INTERNAL_PERFORM_LOG_TICK(BOOL bSkipFilters = FALSE)
CDEBUG1LN(DEBUG_LCN, "Internal log tick triggered.")
// Log all the prices using LCN_INTERNAL_SNAPSHOT_LISTING_TO_LOG.
INT i = 0
REPEAT BS_CO_TOTAL_LISTINGS i
LCN_INTERNAL_SNAPSHOT_LISTING_TO_LOG(INT_TO_ENUM(BAWSAQ_COMPANIES,i),bSkipFilters)
WAIT(0)
IF !bSkipFilters
STOCK_MODIFIER_CHECK()
ENDIF
ENDREPEAT
ENDPROC
PROC STOCKS_INITIAL_PRICE_GENERATION()
CPRINTLN(DEBUG_STOCKS, "Starting first time price generation for all stocks.")
IF !g_savedGlobals.sFinanceData.bInitialPriceGenerationPerformed
CPRINTLN(DEBUG_STOCKS, "First stockmarket init detected. Generating brand new data.")
CPRINTLN(DEBUG_STOCKS, "Generating new current prices for offline stocks...")
INT i
REPEAT BS_CO_TOTAL_LISTINGS i
IF NOT g_BS_Listings[i].bOnlineStock
g_BS_Listings[i].fCurrentPrice = GET_RANDOM_FLOAT_IN_RANGE(15,290)
CDEBUG2LN(debug_stocks,"Initial price for ",i," set to ",g_BS_Listings[i].fCurrentPrice)
ENDIF
ENDREPEAT
CPRINTLN(DEBUG_STOCKS, "...Current prices created.")
CPRINTLN(DEBUG_STOCKS, "Generating new logged history for all stocks...")
i = 0
INT j = 0
FOR j = 0 TO (MAX_STOCK_PRICE_LOG_ENTRIES-1)
LCN_INTERNAL_PERFORM_LOG_TICK(TRUE)
REPEAT BS_CO_TOTAL_LISTINGS i
//Change price by +/- 15% max per tick
Float fChangeMin = 0.85
Float fChangeMax = 1.15
if g_BS_Listings[i].fCurrentPrice < 5
fchangeMin = 1.1
elif g_BS_Listings[i].fCurrentPrice< 10
fchangeMin = 0.95
elif g_BS_Listings[i].fCurrentPrice > 285
fchangeMax = 0.97
elif g_BS_Listings[i].fCurrentPrice> 270
fchangeMax = 1.05
ENDIF
g_BS_Listings[i].fCurrentPrice *= GET_RANDOM_FLOAT_IN_RANGE(fchangeMin, fchangeMax)
//Store and normalise log value
g_BS_Listings[i].fCurrentPrice = FMIN( FMAX(ABSF(g_BS_Listings[i].fCurrentPrice),3.5), 290)
CDEBUG3LN(debug_stocks,"---> ",i," logged: ",g_BS_Listings[i].fCurrentPrice)
ENDREPEAT
CDEBUG1LN(DEBUG_STOCKS, "Generated all logged history values for log entry ", j, " of ", MAX_STOCK_PRICE_LOG_ENTRIES, ".")
ENDFOR
CPRINTLN(DEBUG_STOCKS, "...Logged history created.")
//Push the new data to the saved globals to make sure it gets saved immediately.
LCN_UPDATE_SAVED_OFFLINE_PRICES()
g_savedGlobals.sFinanceData.bInitialPriceGenerationPerformed = TRUE
#IF IS_DEBUG_BUILD
ELSE
CPRINTLN(DEBUG_STOCKS, "This isn't the first stockmarket init. No need to generate fresh initial values.")
#ENDIF
ENDIF
ENDPROC
//Dictates the most an offline stock can change per update when generating fake logs.
CONST_FLOAT BAWSAQ_MIN_FAKE_PERCENTAGE_CHANGE_PER_UPDATE 1.00
CONST_FLOAT BAWSAQ_MAX_FAKE_PERCENTAGE_CHANGE_PER_UPDATE 5.00
/// PURPOSE:
/// Grabs prices from saved globals.
PROC LCN_LOAD_OFFLINE_PRICES()
CPRINTLN(DEBUG_LCN, "Loading offline prices...")
INT iOfflineCount = 0
INT i = 0
REPEAT BS_CO_TOTAL_LISTINGS i
IF iOfflineCount < MAX_SP_FINANCE_VALUE_STORAGE
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Attempting to load share price dump for stock in save dump index ", iOfflineCount, ".")
//Load saved values.
IF NOT g_BS_Listings[i].bOnlineStock
IF g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_PRICE_DUMP[iOfflineCount] > 0
g_BS_Listings[i].fCurrentPrice = g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_PRICE_DUMP[iOfflineCount]
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Current price found: ", g_BS_Listings[i].fCurrentPrice , ".")
#IF IS_DEBUG_BUILD
ELSE
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Failed to find a saved current price dump!")
#ENDIF
ENDIF
IF g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MAX_DUMP[iOfflineCount] > 0
g_BS_Listings[i].fLoggedHighValue = g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MAX_DUMP[iOfflineCount]
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Max price found: ", g_BS_Listings[i].fLoggedHighValue , ".")
#IF IS_DEBUG_BUILD
ELSE
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Failed to find a saved max price dump!")
#ENDIF
ENDIF
IF g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MIN_DUMP[iOfflineCount] > 0
g_BS_Listings[i].fLoggedLowValue = g_savedGlobals.sFinanceData.SINGLE_PLAYER_SHARE_MIN_DUMP[iOfflineCount]
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Min price found: ", g_BS_Listings[i].fLoggedLowValue , ".")
#IF IS_DEBUG_BUILD
ELSE
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Failed to find a saved min price dump!")
#ENDIF
ENDIF
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Finished loading saved values for offline stock.")
++iOfflineCount
#IF IS_DEBUG_BUILD
ELSE
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Stock was an online stat. No value dumps to load.")
#ENDIF
ENDIF
IF g_BS_Listings[i].fLoggedLowValue > 0
AND g_BS_Listings[i].fLoggedHighValue > 0
AND g_BS_Listings[i].fCurrentPrice > 0
//Generate a new logged history.
CPRINTLN(DEBUG_LCN, "<STOCK ", GET_STRING_FROM_TEXT_FILE(g_BS_Listings[i].sShortName), "> Creating a fake logged history and price change value.")
FLOAT currp = g_BS_Listings[i].fCurrentPrice
IF currp > g_BS_Listings[i].fLoggedHighValue
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Current price was above the max. Capping.")
g_BS_Listings[i].fLoggedHighValue = currp
ENDIF
IF currp < g_BS_Listings[i].fLoggedLowValue
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Current price was below the min. Capping.")
g_BS_Listings[i].fLoggedLowValue = currp
ENDIF
INT j = 0
FLOAT fStockRange = g_BS_Listings[i].fLoggedHighValue - g_BS_Listings[i].fLoggedLowValue
FLOAT fAverage = 0
FLOAT fChangeRangeThisUpdate, fChangeThisUpdate, fStockIncreaseScaling, fStockDecreaseScaling
FLOAT fLocalMin=HIGHEST_INT, fLocalMax=-HIGHEST_INT
//Work backwards through the log history generating change based on preceding log entries
//starting with the current price we have loaded. Generates a history graph that ends with
//the correct current value.
FOR j = (MAX_STOCK_PRICE_LOG_ENTRIES-1) TO 0 STEP -1
fChangeRangeThisUpdate = fStockRange*GET_RANDOM_FLOAT_IN_RANGE(BAWSAQ_MIN_FAKE_PERCENTAGE_CHANGE_PER_UPDATE, BAWSAQ_MAX_FAKE_PERCENTAGE_CHANGE_PER_UPDATE)*0.01
fStockIncreaseScaling = 1.0
fStockDecreaseScaling = 1.0
//Last log entry calculated as an offset from current price.
IF j = (MAX_STOCK_PRICE_LOG_ENTRIES-1)
//Check if this stock's value is nearing the upper limits of its stock range.
//If so scale a resistance to increasing its value based on closeness to limit.
FLOAT fUpperCloseness = (g_BS_Listings[i].fLoggedHighValue - g_BS_Listings[i].fCurrentPrice) / fStockRange
IF fUpperCloseness < 0.2
fStockIncreaseScaling = fUpperCloseness/0.2
ENDIF
CDEBUG3LN(DEBUG_LCN, "<STOCK ", i, "> fStockIncreaseScaling = ", fStockIncreaseScaling)
//Check if this stock's value is nearing the lower limits of its stock range.
//If so scale a resistance to decreasing its value based on closeness to limit.
FLOAT fLowerCloseness = (g_BS_Listings[i].fCurrentPrice - g_BS_Listings[i].fLoggedLowValue) / fStockRange
IF fLowerCloseness < 0.2
fStockDecreaseScaling = fLowerCloseness/0.2
ENDIF
CDEBUG3LN(DEBUG_LCN, "<STOCK ", i, "> fStockDecreaseScaling = ", fStockDecreaseScaling)
//Generate a random change in value for this log entry.
fChangeThisUpdate = GET_RANDOM_FLOAT_IN_RANGE(-fChangeRangeThisUpdate*fStockDecreaseScaling, fChangeRangeThisUpdate*fStockIncreaseScaling)
CDEBUG3LN(DEBUG_LCN, "<STOCK ", i, "> fChangeThisUpdate = ", fChangeThisUpdate)
//Store log entry.
g_BS_Listings[i].LoggedPrices[j] = g_BS_Listings[i].fCurrentPrice
//All other generated log entries based on preceding log entry.
ELSE
//Check if this stock's value is nearing the upper limits of its stock range.
//If so scale a resistance to increasing its value based on closeness to limit.
FLOAT fUpperCloseness = (g_BS_Listings[i].fLoggedHighValue - g_BS_Listings[i].LoggedPrices[j+1]) / fStockRange
IF fUpperCloseness < 0.2
fStockIncreaseScaling = fUpperCloseness/0.2
ENDIF
CDEBUG3LN(DEBUG_LCN, "<STOCK ", i, "> fStockIncreaseScaling = ", fStockIncreaseScaling)
//Check if this stock's value is nearing the lower limits of its stock range.
//If so scale a resistance to decreasing its value based on closeness to limit.
FLOAT fLowerCloseness = (g_BS_Listings[i].LoggedPrices[j+1] - g_BS_Listings[i].fLoggedLowValue) / fStockRange
IF fLowerCloseness < 0.2
fStockDecreaseScaling = fLowerCloseness/0.2
ENDIF
CDEBUG3LN(DEBUG_LCN, "<STOCK ", i, "> fStockDecreaseScaling = ", fStockDecreaseScaling)
//Generate a random change in value for this log entry.
fChangeThisUpdate = GET_RANDOM_FLOAT_IN_RANGE(-fChangeRangeThisUpdate*fStockDecreaseScaling, fChangeRangeThisUpdate*fStockIncreaseScaling)
CDEBUG3LN(DEBUG_LCN, "<STOCK ", i, "> fChangeThisUpdate = ", fChangeThisUpdate)
//Store log entry.
g_BS_Listings[i].LoggedPrices[j] = g_BS_Listings[i].LoggedPrices[j+1] + fChangeThisUpdate
ENDIF
fLocalMin = FMIN(fLocalMin,g_BS_Listings[i].LoggedPrices[j])
fLocalMax = FMAX(fLocalMax,g_BS_Listings[i].LoggedPrices[j])
fAverage += g_BS_Listings[i].LoggedPrices[j]
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Generated logged value ", j, " in range ", g_BS_Listings[i].fLoggedLowValue, " to ",g_BS_Listings[i].fLoggedHighValue, ": ", g_BS_Listings[i].LoggedPrices[j])
ENDFOR
//Overwrite weekly min/max
g_BS_Listings[i].fLoggedLowValue= fLocalMin
g_BS_Listings[i].fLoggedHighValue = fLocalMax
//Recalculate average, weekly change and percent
fAverage /= MAX_STOCK_PRICE_LOG_ENTRIES
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> New average change over ", MAX_STOCK_PRICE_LOG_ENTRIES, " updates calculated as ", fAverage, ".")
g_BS_Listings[i].fLoggedPriceChangeFromWeeklyAverage = g_BS_Listings[i].fCurrentPrice - fAverage
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> New last weekly average price change calculated as ", g_BS_Listings[i].fLoggedPriceChangeFromWeeklyAverage, ".")
g_BS_Listings[i].fLoggedPriceChangeInPercent = (g_BS_Listings[i].fLoggedPriceChangeFromWeeklyAverage / fAverage) * 100.0
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> New last weekly average price change percentage calculated as ", g_BS_Listings[i].fLoggedPriceChangeInPercent, ".")
//Apply filters to generated values.
CPRINTLN(DEBUG_LCN, "<STOCK ", i, "> Checking for filters to apply to generated values.")
FLOAT filt = GET_BS_PRICE_FILTER(INT_TO_ENUM(BAWSAQ_COMPANIES,i))
IF filt != 1.0
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Aplpying filter: ",filt)
fAverage = 0
FLOAT fDeltaFilt = filt-1.0
FOR j = 0 to (MAX_STOCK_PRICE_LOG_ENTRIES -1)
//Apply filter gradually, max value at the latest point
Float fIndexMod = TO_FLOAT(j)/MAX_STOCK_PRICE_LOG_ENTRIES
//Random jitter overall, movign towards target filter value
g_BS_Listings[i].LoggedPrices[j] *= (GET_RANDOM_FLOAT_IN_RANGE(0.95,1.05) + fIndexMod * fDeltaFilt)
//Overwrite current value with exact price
IF j = MAX_STOCK_PRICE_LOG_ENTRIES -1
g_BS_Listings[i].LoggedPrices[j] = g_BS_Listings[i].fCurrentPrice * filt
ENDIF
CDEBUG3LN(debug_lcn,"Current value for index ",j,": ",g_BS_Listings[i].LoggedPrices[j])
//Update max/min/average
fAverage += g_BS_Listings[i].LoggedPrices[j]
g_BS_Listings[i].fLoggedLowValue = FMIN(g_BS_Listings[i].fLoggedLowValue, g_BS_Listings[i].LoggedPrices[j])
g_BS_Listings[i].fLoggedHighValue= FMAX(g_BS_Listings[i].fLoggedHighValue, g_BS_Listings[i].LoggedPrices[j])
ENDFOR
fAverage = fAverage / MAX_STOCK_PRICE_LOG_ENTRIES
g_BS_Listings[i].fLoggedPriceChangeFromWeeklyAverage = g_BS_Listings[i].fCurrentPrice - fAverage
g_BS_Listings[i].fLoggedPriceChangeInPercent = (g_BS_Listings[i].fLoggedPriceChangeFromWeeklyAverage / fAverage) * 100.0
CDEBUG1LN(debug_lcn,"After filter, min/max/average/change % changed to ",g_BS_Listings[i].fLoggedLowValue, " / ",
g_BS_Listings[i].fLoggedHighValue, " / ", g_BS_Listings[i].fLoggedPriceChangeFromWeeklyAverage,
" / ",g_BS_Listings[i].fLoggedPriceChangeInPercent)
ENDIF
#IF IS_DEBUG_BUILD
ELSE
CDEBUG1LN(DEBUG_LCN, "<STOCK ", i, "> Missing loaded values. Couldn't generate intial stock stats.")
#ENDIF
ENDIF
ELSE
CPRINTLN(DEBUG_LCN, "More offline stocks than there are storage slots!")
SCRIPT_ASSERT("More offline stocks than there are storage slots, pass this assert to *Default Levels*.")
ENDIF
ENDREPEAT
CPRINTLN(DEBUG_LCN, "...Finished load of offline prices.")
ENDPROC
PROC UPDATE_MARKET_TRIGGERS()
CPRINTLN(DEBUG_STOCKS, "Looking for price story triggers firing...")
#IF IS_DEBUG_BUILD
INT iDebugTimer = GET_GAME_TIMER()
#ENDIF
// Price triggers.
INT i
INT m = g_iPRICE_CARET
REPEAT m i
IF g_BS_PriceTriggers[i].checkCooldown > 0
--g_BS_PriceTriggers[i].checkCooldown
ELSE
IF HAS_PRICE_STORY_TRIGGER_FIRED(i)
CPRINTLN(DEBUG_STOCKS, "A price story trigger has fired. Adding news story to the stack.")
// Try to add it to the live story list
STACKIFY_STORY(g_BS_PriceTriggers[i].s)
g_BS_PriceTriggers[i].checkCooldown = 60000
ENDIF
ENDIF
WAIT(0)
STOCK_MODIFIER_CHECK()
ENDREPEAT
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_STOCKS, "...Finished looking for price story triggers after ", GET_GAME_TIMER() - iDebugTimer, "ms.")
#ENDIF
ENDPROC
FUNC BOOL VEHICLE_DISTANCE_DRIVEN_PARSE(MODEL_NAMES mn, FLOAT distance)
IF distance < 10.0//ignore values under 10 meters
RETURN FALSE
ENDIF
#IF IS_DEBUG_BUILD
// PRINTLN("Debug(vehicle) distance trigger: ",GET_MODEL_NAME_FOR_DEBUG(mn)," : ", distance)
// SCRIPT_ASSERT("Kill trigger"
#ENDIF
SWITCH GET_MAKE_OF_VEHICLE(mn)
CASE BSICC_HVY
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_HVY,FLOOR(distance/10))
BREAK
CASE BSICC_MAI
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_MAI,FLOOR(distance/10))
BREAK
CASE BSICC_BRU
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_BRU,FLOOR(distance/10))
BREAK
CASE BSICC_VAP
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_VAP,FLOOR(distance/10))
BREAK
CASE BSICC_BFA
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_BFA,FLOOR(distance/10))
BREAK
CASE BSICC_HJK
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_HJK,FLOOR(distance/10))
BREAK
CASE BSICC_SHT
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_SHT,FLOOR(distance/10))
BREAK
CASE BSICC_UMA
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_UMA,FLOOR(distance/10))
BREAK
ENDSWITCH
SWITCH mn
CASE COACH
CASE TAXI
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_DISDRIV_FOR_LST,FLOOR(distance/10))
BREAK
CASE BMX
CASE SCORCHER
CASE TRIBIKE2
CASE FIXTER
CASE TRIBIKE
CASE CRUISER
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_SP_BIKEDIST_M,FLOOR(distance/10))
BREAK
CASE CHAR_FRANKLIN
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_SP_BIKEDIST_F,FLOOR(distance/10))
BREAK
CASE CHAR_TREVOR
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_SP_BIKEDIST_T,FLOOR(distance/10))
BREAK
ENDSWITCH
BREAK
ENDSWITCH
RETURN TRUE
ENDFUNC
VECTOR vCurrent
VECTOR vLast
VEHICLE_INDEX veh = NULL
/// PURPOSE:
/// Calls VEHICLE_DISTANCE_DRIVEN_PARSE for distances passed.
PROC DO_VEHICLE_DISTANCE_DRIVEN_CHECK()
IF NOT IS_PLAYER_PLAYING(GET_PLAYER_INDEX())
veh = NULL
EXIT
ENDIF
IF IS_PLAYER_IN_VEH_SEAT(GET_PLAYER_INDEX(), VS_DRIVER)
veh = NULL
EXIT
ENDIF
IF IS_PED_IN_ANY_VEHICLE(GET_PLAYER_PED(GET_PLAYER_INDEX()))
VEHICLE_INDEX vi = GET_VEHICLE_PED_IS_IN(GET_PLAYER_PED(GET_PLAYER_INDEX()))
IF veh != vi
vCurrent = vLast
veh = vi
ENDIF
IF vi = NULL
EXIT
ENDIF
vCurrent = GET_ENTITY_COORDS(vi,TRUE)
IF veh = NULL
vLast = vCurrent
veh = vi
EXIT
ENDIF
MODEL_NAMES mn = GET_ENTITY_MODEL(vi)
IF VEHICLE_DISTANCE_DRIVEN_PARSE(mn, GET_DISTANCE_BETWEEN_COORDS(vCurrent,vLast,FALSE))
vLast = vCurrent
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// A subset of the modifier updates that is checked on a per frame basis even during
/// price update, search for occurences of "DO_FREQUENT_CHECKS" to see
PROC DO_FREQUENT_MODIFIER_CHECKS()
PED_INDEX p = GET_PLAYER_PED(GET_PLAYER_INDEX())
IF IS_ENTITY_DEAD(p)
EXIT
ENDIF
ENTITY_INDEX ei = GET_ENTITY_FROM_PED_OR_VEHICLE(p)
IF IS_ENTITY_ON_FIRE(ei)
CDEBUG1LN(DEBUG_STOCKS, "Self on fire modifier condition found in frequent checks.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_TKFIRE)
IF (GET_ENTITY_SPEED(ei) > 5)
//Assume bailed from car or equally awesome on fire flailing
CDEBUG1LN(DEBUG_STOCKS, "Self on fire at speed (!!!) modifier condition found in frequent checks.")
BAWSAQ_INCREMENT_MODIFIER(BSMF_SM_FIBAI)
ENDIF
ENDIF
ENDPROC
PROC WAIT_WITH_MODIFIER_CHECK()
WAIT(0)
STOCK_MODIFIER_CHECK()
ENDPROC
/// PURPOSE:
/// The stock market update script
SCRIPT
CPRINTLN(DEBUG_STOCKS, "Stock controller started.")
// This script needs to cleanup only when the game moves from SP to MP
IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP)
CPRINTLN(DEBUG_STOCKS, "Stock controller cleaning up due to switch to multiplayer.")
Script_Cleanup()
ENDIF
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH (HASH ("stock_controller")) > 1
CPRINTLN(DEBUG_STOCKS, "Stock controller cleaning up as an instance of the script is already running.")
SCRIPT_ASSERT("Stock controller tried to launch when an instance was already running.")
Script_Cleanup()
ENDIF
#IF IS_DEBUG_BUILD
INT iDebugTimer = GET_GAME_TIMER()
#ENDIF
g_bStockMarketInitialisationInProgress = TRUE
CPRINTLN(DEBUG_STOCKS, "Precalulating timer frequencies based on the log timer.")
#IF IS_DEBUG_BUILD
IF TO_FLOAT(STOCK_MARKET_LOG_UPDATE_MINS) % STOCK_MARKET_TICK_UPDATES_PER_LOG != 0
SCRIPT_ASSERT("STOCK_MARKET_TICK_UPDATES_PER_LOG must divide into STOCK_MARKET_LOG_UPDATE_MINS exactly.")
ENDIF
#ENDIF
iTickUpdateMins = ROUND(TO_FLOAT(STOCK_MARKET_LOG_UPDATE_MINS)/STOCK_MARKET_TICK_UPDATES_PER_LOG)
CPRINTLN(DEBUG_STOCKS, "Simulation ticks will run every ", iTickUpdateMins, " in-game minutes.")
#IF IS_DEBUG_BUILD
IF TO_FLOAT(STOCK_MARKET_LOG_UPDATE_MINS) % STOCK_MARKET_TICK_UPDATES_PER_LOG != 0
SCRIPT_ASSERT("STOCK_MARKET_FILTER_UPDATES_PER_LOG must divide into STOCK_MARKET_LOG_UPDATE_MINS exactly.")
ENDIF
#ENDIF
CPRINTLN(DEBUG_STOCKS, "Initialising BAWSAQ stock base configuration...")
BAWSAQ_INTIALISE_LISTS()
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_STOCKS, "...Base configuration done in ", GET_GAME_TIMER()- iDebugTimer ,"ms.")
iDebugTimer = GET_GAME_TIMER()
IF GET_COMMANDLINE_PARAM_EXISTS("couponScriptTest")
CPRINTLN(DEBUG_STOCKS, "Coupon command line param is active. (-couponScriptTest)")
OBTAIN_COUPON(COUPON_HAIRCUT)
OBTAIN_COUPON(COUPON_TATOO)
OBTAIN_COUPON(COUPON_MIL_SITE)
OBTAIN_COUPON(COUPON_CAR_SITE)
OBTAIN_COUPON(COUPON_PLANE_SITE)
OBTAIN_COUPON(COUPON_MEDICAL)
OBTAIN_COUPON(COUPON_SPRUNK)
OBTAIN_COUPON(COUPON_SPRAY)
OBTAIN_COUPON(COUPON_CAR_XMAS2017)
OBTAIN_COUPON(COUPON_CAR_XMAS2018)
OBTAIN_COUPON(COUPON_HELI_XMAS2018)
OBTAIN_COUPON(COUPON_CAR2_XMAS2018)
OBTAIN_COUPON(COUPON_CASINO_PLANE_SITE)
OBTAIN_COUPON(COUPON_CASINO_BOAT_SITE)
OBTAIN_COUPON(COUPON_CASINO_CAR_SITE)
OBTAIN_COUPON(COUPON_CASINO_CAR_SITE2)
OBTAIN_COUPON(COUPON_CASINO_MIL_SITE)
OBTAIN_COUPON(COUPON_CASINO_BIKE_SITE)
#IF FEATURE_GEN9_EXCLUSIVE
OBTAIN_COUPON(COUPON_HSW_MOD1)
OBTAIN_COUPON(COUPON_HSW_MOD2)
OBTAIN_COUPON(COUPON_HSW_MOD3)
OBTAIN_COUPON(COUPON_HSW_MOD4)
OBTAIN_COUPON(COUPON_HSW_MOD5)
OBTAIN_COUPON(COUPON_HSW_MOD6)
OBTAIN_COUPON(COUPON_HSW_MOD7)
OBTAIN_COUPON(COUPON_HSW_MOD8)
OBTAIN_COUPON(COUPON_HSW_MOD9)
OBTAIN_COUPON(COUPON_HSW_MOD10)
OBTAIN_COUPON(COUPON_HSW_MOD11)
OBTAIN_COUPON(COUPON_HSW_MOD12)
OBTAIN_COUPON(COUPON_HSW_MOD13)
OBTAIN_COUPON(COUPON_HSW_MOD14)
OBTAIN_COUPON(COUPON_HSW_MOD15)
OBTAIN_COUPON(COUPON_HSW_MOD16)
OBTAIN_COUPON(COUPON_HSW_MOD17)
OBTAIN_COUPON(COUPON_HSW_MOD18)
OBTAIN_COUPON(COUPON_HSW_MOD19)
OBTAIN_COUPON(COUPON_HSW_MOD20)
OBTAIN_COUPON(COUPON_HSW_UPGRADE)
OBTAIN_COUPON(COUPON_CAR_GEN9_MIGRATION)
#ENDIF
ENDIF
#ENDIF
//Now read inital stat value for any modifiers.
CPRINTLN(DEBUG_STOCKS, "Starting offline modifier read...")
INT i = 0
REPEAT BSMF_TOTAL_INDICES i
IF NOT g_BS_Modifiers[i].bOnline
IF g_BS_Modifiers[i].bReadFromProfile
IF NOT g_BS_Modifiers[i].bProfIsFloatType
STAT_GET_INT(g_BS_Modifiers[i].ProfStatToRead, g_BS_Modifiers[i].iPrev)
ELSE
FLOAT fprev = 0
STAT_GET_FLOAT(g_BS_Modifiers[i].ProfStatToRead, fprev)
g_BS_Modifiers[i].iPrev = FLOOR(fprev)
ENDIF
CDEBUG1LN(DEBUG_LCN, "Stock inital modifier indice read for ", i ," is : ", g_BS_Modifiers[i].iPrev)
ENDIF
ENDIF
ENDREPEAT
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_STOCKS, "...Offline modifier read finished in ", GET_GAME_TIMER()- iDebugTimer ,"ms.")
iDebugTimer = GET_GAME_TIMER()
CPRINTLN(DEBUG_STOCKS, "Starting market news stories initialisation...")
#ENDIF
INIT_GIFT_COUPONS()
INITIALISE_MARKET_NEWS_STORIES()
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_STOCKS, "...News stories finished in ", GET_GAME_TIMER()- iDebugTimer ,"ms.")
iDebugTimer = GET_GAME_TIMER()
CPRINTLN(DEBUG_STOCKS, "Starting initial price generation...")
#ENDIF
STOCKS_INITIAL_PRICE_GENERATION()
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_STOCKS, "...Prices generated in ", GET_GAME_TIMER()- iDebugTimer ,"ms.")
iDebugTimer = GET_GAME_TIMER()
CPRINTLN(DEBUG_STOCKS, "Starting LCN price loading...")
#ENDIF
LCN_LOAD_OFFLINE_PRICES()
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_STOCKS, "LCN prices loaded in ", GET_GAME_TIMER()- iDebugTimer ,"ms.")
iDebugTimer = GET_GAME_TIMER()
#ENDIF
g_bStockMarketInitialisationInProgress = FALSE
CPRINTLN(DEBUG_STOCKS, "Stock market initialisation finished.")
COPY_BANK_TRANSLOGS() // Fill the snapshot buffer with the loaded state.
UPDATE_MARKET_TRIGGERS() // Prime news stories.
UPDATE_SOCIAL_CLUB_BAWSAQ_PORTFOLIO_STATS() // Update the owned totals for social club.
CPRINTLN(DEBUG_STOCKS, "Controller initialisation finished. Starting main loop.")
WHILE TRUE
// Handle command line coupon requests.
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("couponScriptTest")
CDEBUG3LN(DEBUG_STOCKS, "Coupon command line param is still active this frame. (-couponScriptTest)")
OBTAIN_COUPON(COUPON_HAIRCUT)
OBTAIN_COUPON(COUPON_TATOO)
OBTAIN_COUPON(COUPON_MIL_SITE)
OBTAIN_COUPON(COUPON_CAR_SITE)
OBTAIN_COUPON(COUPON_PLANE_SITE)
OBTAIN_COUPON(COUPON_MEDICAL)
OBTAIN_COUPON(COUPON_SPRUNK)
OBTAIN_COUPON(COUPON_SPRAY)
OBTAIN_COUPON(COUPON_CAR_XMAS2017)
OBTAIN_COUPON(COUPON_CAR_XMAS2018)
OBTAIN_COUPON(COUPON_HELI_XMAS2018)
OBTAIN_COUPON(COUPON_CAR2_XMAS2018)
OBTAIN_COUPON(COUPON_CASINO_PLANE_SITE)
OBTAIN_COUPON(COUPON_CASINO_BOAT_SITE)
OBTAIN_COUPON(COUPON_CASINO_CAR_SITE)
OBTAIN_COUPON(COUPON_CASINO_CAR_SITE2)
OBTAIN_COUPON(COUPON_CASINO_MIL_SITE)
OBTAIN_COUPON(COUPON_CASINO_BIKE_SITE)
#IF FEATURE_GEN9_EXCLUSIVE
OBTAIN_COUPON(COUPON_HSW_MOD1)
OBTAIN_COUPON(COUPON_HSW_MOD2)
OBTAIN_COUPON(COUPON_HSW_MOD3)
OBTAIN_COUPON(COUPON_HSW_MOD4)
OBTAIN_COUPON(COUPON_HSW_MOD5)
OBTAIN_COUPON(COUPON_HSW_MOD6)
OBTAIN_COUPON(COUPON_HSW_MOD7)
OBTAIN_COUPON(COUPON_HSW_MOD8)
OBTAIN_COUPON(COUPON_HSW_MOD9)
OBTAIN_COUPON(COUPON_HSW_MOD10)
OBTAIN_COUPON(COUPON_HSW_MOD11)
OBTAIN_COUPON(COUPON_HSW_MOD12)
OBTAIN_COUPON(COUPON_HSW_MOD13)
OBTAIN_COUPON(COUPON_HSW_MOD14)
OBTAIN_COUPON(COUPON_HSW_MOD15)
OBTAIN_COUPON(COUPON_HSW_MOD16)
OBTAIN_COUPON(COUPON_HSW_MOD17)
OBTAIN_COUPON(COUPON_HSW_MOD18)
OBTAIN_COUPON(COUPON_HSW_MOD19)
OBTAIN_COUPON(COUPON_HSW_MOD20)
OBTAIN_COUPON(COUPON_HSW_UPGRADE)
OBTAIN_COUPON(COUPON_CAR_GEN9_MIGRATION)
#ENDIF
ENDIF
#ENDIF
// Reset log indexes for bank account logs that have overrun their log sizes.
INT l
REPEAT MAX_BANK_ACCOUNTS l
IF NOT (g_savedGlobals.sFinanceData.PLAYER_ACCOUNT_LOGS[l].iLogIndexPoint < MAX_BANK_ACCOUNT_LOG_ENTRIES)
CDEBUG1LN(DEBUG_STOCKS, "Resetting log index point for player account ", l, ".")
g_savedGlobals.sFinanceData.PLAYER_ACCOUNT_LOGS[l].iLogIndexPoint = 0
ENDIF
ENDREPEAT
DO_VEHICLE_DISTANCE_DRIVEN_CHECK()
// Don't process the stock market while online or in Director Mode.
// Time can be manipulated in Director Mode so it's unsafe.
IF NOT NETWORK_IS_GAME_IN_PROGRESS()
AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR)
//Run this every farme.
STOCK_MODIFIER_CHECK()
//Max iterations to do before carrying on with the next update (tick->filter->log)
INT iMaxCount = STOCK_MARKET_TICK_UPDATES_PER_LOG
// Update the simulation ticks STOCK_MARKET_TICK_UPDATES_PER_LOG times per log update.
WHILE CHECK_FOR_TICK_TIME_TRIPPED() AND iMaxCount>=0
CDEBUG1LN(DEBUG_STOCKS, "Running stock market update tick.")
iMaxCount -=1
INTERMITTANT_PLAYER_CHECK()
//Informs the stock page it needs to refresh if it is currently open.
g_bStockMarketBrowserUpdateTick = TRUE
LCN_APPLY_MODIFIERS_TO_PRICES()
g_bTickerPriceChange = TRUE
STOCK_MARKET_MUSIC_MODIFIER_CHECK()
WAIT_WITH_MODIFIER_CHECK()
ENDWHILE
// Update the logs every STOCK_MARKET_LOG_UPDATE_MINS in-game minutes.
IF CHECK_FOR_LOG_TIME_TRIPPED()
LCN_INTERNAL_PERFORM_LOG_TICK()
WAIT_WITH_MODIFIER_CHECK()
//Decrement all stock filter durations after a log update.
DECREMENT_STOCK_FILTERS_DURATIONS()
WAIT_WITH_MODIFIER_CHECK()
UPDATE_MARKET_TRIGGERS()
WAIT_WITH_MODIFIER_CHECK()
ENDIF
// Check for requests to do an instant log update.
WHILE g_iForceStockLogUpdate > 0
CPRINTLN(DEBUG_STOCKS, "An instant log update has been triggered. Setting timers back ", STOCK_MARKET_LOG_UPDATE_MINS, " in-game minutes.")
#IF IS_DEBUG_BUILD
TEXT_LABEL_63 txtDebugTimeOfDay
#ENDIF
SUBTRACT_TIME_FROM_TIMEOFDAY(todNextLogUpdate, 0, STOCK_MARKET_LOG_UPDATE_MINS)
#IF IS_DEBUG_BUILD
txtDebugTimeOfDay = TIMEOFDAY_TO_TEXT_LABEL(todNextLogUpdate)
CDEBUG1LN(DEBUG_STOCKS, "Next LOG trip time set to [", txtDebugTimeOfDay, "].")
#ENDIF
SUBTRACT_TIME_FROM_TIMEOFDAY(todNextTickUpdate, 0, STOCK_MARKET_LOG_UPDATE_MINS)
#IF IS_DEBUG_BUILD
txtDebugTimeOfDay = TIMEOFDAY_TO_TEXT_LABEL(todNextTickUpdate)
CDEBUG1LN(DEBUG_STOCKS, "Next TICK trip time set to [", txtDebugTimeOfDay, "].")
#ENDIF
g_iForceStockLogUpdate -= 1
ENDWHILE
ENDIF
// Sync the BAWSAW online stock values from the servers.
BAWSAQ_PROCESS_STOCK_PRICE_SYNCH()
// Per frame market modifier checks.
DO_FREQUENT_MODIFIER_CHECKS()
WAIT(0)
ENDWHILE
ENDSCRIPT