// ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // 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," ",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, " 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, " Current price found: ", g_BS_Listings[i].fCurrentPrice , ".") #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_LCN, " 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, " Max price found: ", g_BS_Listings[i].fLoggedHighValue , ".") #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_LCN, " 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, " Min price found: ", g_BS_Listings[i].fLoggedLowValue , ".") #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_LCN, " Failed to find a saved min price dump!") #ENDIF ENDIF CDEBUG1LN(DEBUG_LCN, " Finished loading saved values for offline stock.") ++iOfflineCount #IF IS_DEBUG_BUILD ELSE CDEBUG1LN(DEBUG_LCN, " 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, " 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, " Current price was above the max. Capping.") g_BS_Listings[i].fLoggedHighValue = currp ENDIF IF currp < g_BS_Listings[i].fLoggedLowValue CDEBUG1LN(DEBUG_LCN, " 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, " 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, " 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, " 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, " 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, " 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, " 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, " 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, " 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, " 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, " New last weekly average price change percentage calculated as ", g_BS_Listings[i].fLoggedPriceChangeInPercent, ".") //Apply filters to generated values. CPRINTLN(DEBUG_LCN, " 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, " 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, " 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