Beispiel #1
0
def restore_fields(param, default_param, fields_to_restore):
    log(f"Restoring fields {fields_to_restore} for param {param.name}")

    for key in param.data:
        for field in fields_to_restore:
            old_value = param.data[key][field]
            value = default_param.data[key][field]
            log(f"Restore Field: {field} [{old_value} -> {value}]")
            param.data[key][field] = value
    return param
Beispiel #2
0
def main(name="Bullet",param_path="",layout_path="",save_dir=""):
    full_param_path = param_path + name +".param"
    paramb = pr.parse_param(full_param_path)

    param_data = pr.pack_param(paramb, full_param_path)

    log("Saving param")
    saved_file = dt.save_file(param_data,save_dir + name + ".param")
    log("Done saving")
    return paramb
Beispiel #3
0
def replace_zero_in_field(param, replacement_value, field):
    """ Replaces all zeros in specific field """
    log(
        f"replacing all 0 in field {field}  with {replacement_value} for param {param.name}",
        Logging_Level.INFO)

    for key in param.data:
        if (param.data[key][field] == 0):
            param.data[key][field] = replacement_value
            log(f"ID: {key}", Logging_Level.INFO)
    return param
Beispiel #4
0
def alter_params(name="Bullet"):
    full_param_path = param_path + name +".param"
    paramb = pr.parse_param(full_param_path)

    paramb = dop.replaceZero(paramb,1)

    param_data = pr.pack_param(paramb, full_param_path)

    log("Saving param")
    saved_file = dt.save_file(param_data,save_dir + name + ".param")
    log("Done saving")
    return paramb
Beispiel #5
0
def shuffle_param_ids(name="Bullet"):
    full_param_path = param_path + name +".param"
    paramb = pr.parse_param(full_param_path)

    paramb = dop.shuffle_ids(paramb)

    param_data = pr.pack_param(paramb, full_param_path)

    log("Saving param")
    saved_file = dt.save_file(param_data,save_dir + name + ".param")
    log("Done saving")
    return paramb
Beispiel #6
0
def mod_speffect_param(chance,name="SpEffectParam"):
    full_param_path = param_path + name +".param"
    paramb = pr.parse_param(full_param_path)

    paramb = dop.shuffle_ids(paramb)
    paramb = dop.add_random_self_refs(paramb,78,chance) #replacespeffectId
    #paramb = dop.restore_fields(paramb,get_param(name),0)
    #paramb = dop.limit_fields(paramb,{4:[0.1,5,1]})

    param_data = pr.pack_param(paramb, full_param_path)

    log("Saving param")
    saved_file = dt.save_file(param_data,save_dir + name + ".param")
    log("Done saving")
    return paramb
Beispiel #7
0
def add_random_self_refs(param, fields_to_change, chance=0.3):
    """ assign random ids to the specified field if the value is <0 and random > chance """
    log(f"Adding random id refs to some ids for param {param.name}")

    ids = list(param.data.keys())
    random.shuffle(ids)

    index = 0
    value_to_set = 0
    for key in param.data:
        random_chance = random.random()
        if (random_chance <= chance):
            for field in fields_to_change:
                if (param.data[key][field] > 1):
                    pass
                else:
                    value_to_set = ids[index]
                    if (value_to_set != key):
                        index += 1
                        log(
                            f"Set field {field} of ID: {key} to ID: {value_to_set}",
                            Logging_Level.INFO)
                        param.data[key][field] = ids[index]
    log(f"[{index}] references added")
    return param
Beispiel #8
0
def replaceZero(param, replacement_value):
    """ Replaces all zeros in any field """
    log(f"replacing all 0 with {replacement_value} for param {param.name}",
        Logging_Level.INFO)

    for key in param.data:
        log(f"ID: {key}", Logging_Level.INFO)
        index = 0
        for field in param.layout:
            log(f"Field: {field.name}", Logging_Level.INFO)
            log(f"Type: {field.variable_type}", Logging_Level.INFO)
            value = param.data[key][index]
            if (value == 0):
                param.data[key][index] = replacement_value
            index += 1
    return param
Beispiel #9
0
def parse_type_string(input_string):
    t_string = input_string
    e_type = Data_type.String.value
    signed = False
    size = 0
    if (t_string[0:6] == "fixstr"):
        log("ERROR: fixstr not implemented yet", Logging_Level.ERROR)
        size = int(int(t_string[5:]) / 8)
        return e_type, size, False
    if (t_string[0:5] == "dummy"):
        size = int(int(t_string[5:]) / 8)
        e_type = Data_type.AoB.value
        return e_type, size, False
    elif (t_string[0] == "f"):
        size = int(int(t_string[1:]) / 8)
        if (size == 4):
            e_type = Data_type.Float.value
        elif (size == 8):
            e_type = Data_type.Double.value
        else:
            log("ERROR unknown floatingpoint size", Logging_Level.ERROR)
        return e_type, size, False
    elif t_string[0] == "b":
        return Data_type.Binary.value, 0, False
    else:
        if (t_string[0] == "s"):
            signed = True
        size = int(int(t_string[1:]) / 8)
        if (size == 1):
            e_type = Data_type.Byte.value
        if (size == 2):
            e_type = Data_type.Bytes_2.value
        if (size == 4):
            e_type = Data_type.Bytes_4.value
        if (size == 8):
            e_type = Data_type.Bytes_8.value
    return e_type, size, signed
Beispiel #10
0
def replace_zero_fields(param, dict_field_value):
    log(f"replacing all 0 in fields {dict_field_value.keys()} for param {param.name}"
        )

    for key in param.data:
        log(f"ID: {key}")
        for field in dict_field_min_max.keys():
            log(f"Field: {field}")
            value = param.data[key][field]
            if (value == 0):
                param.data[key][field] = dict_field_value[field]
    return param
Beispiel #11
0
def limit_fields(param, dict_field_min_max, ignore_inf=False):
    """ param, {min,max,default} 
        treats -1 as max"""
    log(f"Limiting fields {dict_field_min_max.keys()} for param {param.name}")

    for key in param.data:
        for field in dict_field_min_max.keys():
            value = param.data[key][field]
            if (dict_field_min_max[field][1] < value
                    or (abs(value + 1.0) < 0.01 and not ignore_inf)):
                new_value = dict_field_min_max[field][3]
                param.data[key][field] = new_value
                log(f"clamped[{value} -> {new_value}]")
            if (value < dict_field_min_max[field][0]
                    and abs(value + 1.0) > 0.01):
                new_value = dict_field_min_max[field][2]
                param.data[key][field] = new_value
                log(f"clamped[{value} -> {new_value}]")
    return param
Beispiel #12
0
def copy_param_data(param, second_param, fields_to_ignore):
    log(f"Copying fields for param {param.name}")
    log(f"Ignoring {fields_to_ignore}")

    ids2 = list(second_param.data.keys())
    id_index = 0
    for key in param.data:
        field_index = 0
        for field in param.layout:
            if (field_index in fields_to_ignore):
                pass
                #log(f"Ignoring field {field.name}", Logging_Level.DEBUG)
            else:
                old_value = param.data[key][field_index]
                value = second_param.data[ids2[id_index]][field_index]
                #log(f"Restore Field: {field.name} [{old_value} -> {value}]", Logging_Level.DEBUG)
                param.data[key][field_index] = value
            field_index += 1
        id_index += 1
    log(f"{id_index} IDs replaced")
    return param
Beispiel #13
0
def print_layout(param):
    for i, field in enumerate(param.layout):
        log(f"[{i}]: {field.name} : {field.variable_type}", Logging_Level.INFO)
Beispiel #14
0
def multiply_random(param,
                    fields_to_change,
                    chance=0.3,
                    mult_max=3,
                    adjust_bullet_angle=False):
    """ multiply specified field for random entries if the value is <0 and random > chance """
    log(
        f"Mult random for param {param.name}\nMult_max{mult_max} Field{fields_to_change}",
        Logging_Level.INFO)

    SHOOT_ANGLE = 34
    SHOOT_ANGLE_INTERVAL = 35

    index = 0
    value_to_set = 0
    for key in param.data:
        random_chance = random.random()
        if (random_chance <= chance):
            for field in fields_to_change:
                b_multiplier = random.randint(1, mult_max)
                temp_value_to_set = int(param.data[key][field] * b_multiplier)
                log(f"Set field {field} of ID: {key} to value: {value_to_set}")
                value_to_set = max(min(temp_value_to_set, 32767), -32768)
                if (value_to_set > 50):
                    log(
                        f"\n[WARNING] num_shoot > 50\n NUM:{value_to_set} (ORIGINAL: {param.data[key][field]})ID: {key}\n",
                        Logging_Level.WARN)
                    if (value_to_set != temp_value_to_set):
                        log(f"num_shoot value outside of short",
                            Logging_Level.WARN)
                    log(f"Value set to 50", Logging_Level.WARN)
                    value_to_set = int(50)
                param.data[key][field] = value_to_set
                if (adjust_bullet_angle and param.name == "BULLET_PARAM_ST"):
                    if (field == 32):
                        old_shoot_angle = param.data[key][SHOOT_ANGLE]
                        new_shoot_angle = 0
                        old_shoot_angle_interval = param.data[key][
                            SHOOT_ANGLE_INTERVAL]
                        if (b_multiplier % 2 == 1):
                            if (old_shoot_angle == 0):
                                new_shoot_angle = int(-3 * (b_multiplier - 1) /
                                                      2)
                            else:
                                new_shoot_angle = int(old_shoot_angle +
                                                      (old_shoot_angle *
                                                       (b_multiplier - 1) / 2))
                            param.data[key][SHOOT_ANGLE] = max(
                                min(new_shoot_angle, 32767), -32768)
                            if (old_shoot_angle_interval == 0):
                                param.data[key][SHOOT_ANGLE_INTERVAL] = int(3)
                            #else: param.data[key][SHOOT_ANGLE_INTERVAL] = old_shoot_angle_interval
                        else:
                            #keep one shot centered
                            if (old_shoot_angle_interval == 0):
                                param.data[key][SHOOT_ANGLE_INTERVAL] = int(3)
                        log(
                            f"Adjusted angles to {param.data[key][SHOOT_ANGLE]} : {param.data[key][SHOOT_ANGLE_INTERVAL]}",
                            Logging_Level.DEBUG)
    return param
Beispiel #15
0
def mod_param():
    log("\n\n---------- [Unpacking Param] -----------\n", Logging_Level.INFO)
    param = pr.parse_param(param_file_path,layout_path)


    if(replace_zeros!=0):
        log("[Replace Zeros] ->", Logging_Level.INFO)
        param = dop.replace_zero(param,replace_zeros)
    if(shuffle_param_ids):
        log("[Shuffle Ids] ->", Logging_Level.INFO)
        field_list_keep = []
        for field in fields_to_keep:
            field_index = pr.get_field_index(field,param.layout)
            field_list_keep.append(field_index)
        if(shuffle_safe):
            if(param.name=="BULLET_PARAM_ST"):
                param_pc_atk = pr.parse_param(param_path + "AtkParam_Pc.param",layout_path)
                param_npc_atk = pr.parse_param(param_path + "AtkParam_Npc.param",layout_path)
                pc_ids = param_pc_atk.data.keys()
                npc_ids = param_npc_atk.data.keys()
                if(len(self_ref_fields)>0):
                    log("[Add self references SAFE] ->")
                    param = dop.shuffle_bullet_ids_safe(param,field_list_keep,ids_to_keep,pc_ids,npc_ids,secondary_only,chance)
                else:
                    param = dop.shuffle_bullet_ids_safe(param,field_list_keep,ids_to_keep,pc_ids,npc_ids,secondary_only)
            else:
                log(f"Safe shuffle not implemented for {param.name}")
                return
        else:
            param = dop.shuffle_ids(param,field_list_keep,ids_to_keep,secondary_only)
    if(len(self_ref_fields)>0 and not shuffle_safe):
        log("[Add self references] ->")
        field_list_ref = []
        for field in self_ref_fields:
            index = pr.get_field_index(field,param.layout)
            field_list_ref.append(index)
        param = dop.add_random_self_refs(param,field_list_ref,chance)
    if(len(rand_bullet_mult_fields)>0):
        log("[Multiply random fields] ->")
        field_list_mult_ref = []
        for field in rand_bullet_mult_fields:
            index = pr.get_field_index(field,param.layout)
            field_list_mult_ref.append(index)
        param = dop.multiply_random(param,field_list_mult_ref,chance,mult_max,adjust_bullet_angle)
    if(make_bullets_visible>0 and param.name=="BULLET_PARAM_ST"):
        log("[Add SFX to invisible bullets] ->")
        param = dop.replace_zero_in_field(param,make_bullets_visible,1)
    if(len(restore)>0):
        log("[Restore fields] ->")
        field_list_res = []
        for field in restore:
            index = pr.get_field_index(field,param.layout)
            field_list_res.append(index)
        default_param = pr.parse_param(param_file_path,layout_path)
        param = dop.restore_fields(param,default_param,field_list_res) #TODO its probably better to deepcopy the original param
    if(len(copy_param)>0):
        log("[Copy fields] ->")
        field_list_ignore = []
        for field in copy_ignore:
            index = pr.get_field_index(field,param.layout)
            field_list_ignore.append(index)
            log("ignore: ", field)
        second_param = pr.parse_param(copy_param[0],copy_param[1])
        param = dop.copy_param_data(param,second_param,field_list_ignore)
    #paramb = dop.restore_fields(paramb,get_param(name),0)
    if(len(limit)>0):
        log("[Limiting values] ->")
        param = dop.limit_fields(param,limit_dict)

    log("\n\n---------- [Repacking Param] -----------\n")
    param_data = pr.pack_param(param, param_file_path)

    log("[Saving param]")
    saved_file = dt.save_file(param_data,save_dir + param_name + ".param")
    if(saved_file!=None):
        log("[Done saving]")
    else:
        log("Couldn't save packed param to file", Logging_Level.ERROR)
    return param
Beispiel #16
0
def shuffle_bullet_ids_safe(param,
                            fields_to_keep,
                            ids_to_keep,
                            atk_pc,
                            atk_npc,
                            secondary_only,
                            chance=0):
    log(f"Randomizing all ids for param {param.name} (Safe Mode)")
    log(f"Excluded Fields [{fields_to_keep})")
    log(f"Excluded IDs  [{ids_to_keep})")

    atk_inter = atk_pc & atk_npc
    atk_pc_only = atk_pc - atk_npc
    atk_npc_only = atk_npc - atk_pc

    ids_pc = get_param_ids_with_value_in_field(param, 0, atk_pc_only)
    ids_npc = get_param_ids_with_value_in_field(param, 0, atk_npc_only)
    ids_inter = get_param_ids_with_value_in_field(param, 0, atk_inter)

    secondary_ids = []
    if (secondary_only):
        secondary_ids = get_secondary_bullet_ids(param)
        log(f"secondary Hit IDs:{secondary_ids}", Logging_Level.DEBUG)
        log(
            f"{len(secondary_ids)} of {len(param.data.keys())} bullets have hit ids",
            Logging_Level.DEBUG)

    random.shuffle(ids_pc)
    random.shuffle(ids_npc)
    random.shuffle(ids_inter)

    log("ids:")
    log(ids_pc[0:10])
    log(ids_npc[0:10])
    log(ids_inter[0:10])

    param_data = param.data
    new_param_data = copy.deepcopy(param_data)
    index = 0
    for key in new_param_data:
        replacement_id = 0
        hit_id = 0
        if (key in ids_to_keep):
            log(f"skipping {key}")
        else:
            if (key in ids_inter):
                replacement_id = ids_inter[index % len(ids_inter)]
                hit_id = ids_inter[(index + 1) % len(ids_inter)]
            else:
                if (key in ids_pc):
                    replacement_id = ids_pc[index % len(ids_pc)]
                    hit_id = ids_pc[(index + 1) % len(ids_pc)]
                if (key in ids_npc):
                    replacement_id = ids_npc[index % len(ids_npc)]
                    hit_id = ids_npc[(index + 1) % len(ids_npc)]
            if ((not secondary_only) or (key in secondary_ids)):
                new_param_data[key] = param_data[replacement_id]
                log(f"Swapping ID: {key} with ID: {replacement_id}")
            if (random.random() <= chance):  # and new_param_data[key][26]<=0):
                log(f"Set hitId {hit_id} for id {key}")
                new_param_data[key][26] = hit_id
        index += 1

    if (len(fields_to_keep) > 0):
        for key in new_param_data:
            for field in fields_to_keep:
                log(f"restore field {field} for ID: {key}")
                new_param_data[key][field] = param_data[key][field]
    param.data = new_param_data

    log("\n\nCHECK FOR LOOPS 1\n\n")
    param = check_loops(param, 26, secondary_ids,
                        True)  #TODO maybe add this as a flag
    log("\n\nCHECK FOR LOOPS AGAIN 2\n\n")
    param = check_loops(param, 26, secondary_ids, False)

    if (10001500 in param.data.keys()):
        log("Rebalancing bullet 10001500 for Sekiro")
        #alter the bullet that is fired at Sekiro when enemies discover you
        #this makes sure the player is not nuked at sight
        param.data[10001500][
            4] = 2  #double the time until the childbullet is spawned
        random_sfxid = param.data[ids_inter[random.randint(
            0,
            len(ids_inter) - 1)]][1]
        if (random_sfxid > 0):
            param.data[10001500][1] = random_sfxid
        else:
            param.data[10001500][1] = 60

        #only allow one childbullet
        childbullet = param.data[10001500][26]
        if (childbullet > -1):
            param.data[childbullet][26] = -1
    else:
        log("No bullet with id 10001500 - probably not Sekiro Bulletparam")

    return param
Beispiel #17
0
def check_loops(param, field, secondary_ids=[], fix_loops=False):
    ids_checked = []
    current_chain = []
    current_id = 0
    discovered_loops = []
    longest_loop = []
    for id in param.data.keys():
        current_id = id
        if (current_id in ids_checked
            ):  #if one id was checked, all later in the chain were
            log(f"ID {current_id} was already checked (Skipped)",
                Logging_Level.DEBUG)
        else:
            while True:
                if (current_id not in param.data.keys()):
                    log(
                        f"[WARNING] referenced bullet {current_id} does not exist",
                        Logging_Level.WARN)
                    break
                if (param.data[current_id][field] < 0):
                    break
                if (current_id in current_chain):
                    log(
                        f"Infinite Loop [LEN {len(current_chain)}] detected for IDs:\n{current_chain}\n",
                        Logging_Level.DEBUG)
                    discovered_loops.append(
                        current_chain
                    )  #additionally save a list of all loops lists
                    if (len(current_chain) > len(longest_loop)):
                        longest_loop = current_chain
                    break
                else:
                    current_chain.append(current_id)
                    current_id = param.data[current_id][field]
            ids_checked.extend(current_chain)
            current_chain = []
            if (id not in ids_checked):
                ids_checked.append(id)
    if (len(discovered_loops) > 0):
        log(f"Number of Loops discovered: {len(discovered_loops)}")
        log(f"Longest Loop [LEN {len(longest_loop)}]: {longest_loop}")
    else:
        log("\n\n\n\n---- [No loops found] ----\n\n\n\n")
    if (fix_loops):
        for loop in discovered_loops:
            fixed_loop = False
            for n in range(len(loop) - 1, 0, -1):
                l_id = loop[n]
                if (l_id in secondary_ids or len(secondary_ids) < 1):
                    if (param.name == "BULLET_PARAM_ST"):
                        param.data[l_id][
                            field] = 0  #set to special bullet without hitid
                    else:
                        param.data[l_id][field] = -1  #set to invalid
                    fixed_loop = True
                    log(f"broke loop at id {l_id}")
                    break
            if (not fixed_loop):
                log(f"Could not break loop by replacing secondary hitids\nReplacing first hitid instead [LOOP:{loop}]"
                    )
        log(f"fixed {len(discovered_loops)} loops")
        if (param.name == "BULLET_PARAM_ST"):
            log("[modifying bullet 0]")
            #alter bullet 0
            param.data[0][
                0] = 200  #might have to change this or create special atkid, but 200 is in both pc and npc atk param and is not empty
            param.data[0][1] = 1060  # sfxid = idol blue flame
            param.data[0][4] = 1
            param.data[0][26] = -1
            param.data[0][32] = 1  #num shoot
    return param
Beispiel #18
0
def shuffle_ids(param, fields_to_keep, ids_to_keep, secondary_only):
    """ shuffle all ids for the specified param """
    log(f"Randomizing all ids for param {param.name}", Logging_Level.INFO)
    log(f"Excluded Fields [{fields_to_keep})", Logging_Level.INFO)
    log(f"Excluded IDs  [{ids_to_keep})", Logging_Level.INFO)

    ids = list(param.data.keys())
    random.shuffle(ids)
    log(ids[0:10], Logging_Level.DEBUG)

    secondary_ids = []
    if (secondary_only):
        secondary_ids = get_secondary_bullet_ids(param)
        log(f"secondary Hit IDs:{secondary_ids}")
        log(
            f"{len(secondary_ids)} of {len(param.data.keys())} bullets have hit ids",
            Logging_Level.DEBUG)

    param_data = param.data
    new_param_data = copy.deepcopy(param_data)
    index = 0
    for key in new_param_data:
        if (key in ids_to_keep
                or (secondary_only and key not in secondary_ids)):
            log(f"skipping {key}", Logging_Level.INFO)
        else:
            new_param_data[key] = param_data[ids[index]]
            log(f"Swapping ID: {key} with ID: {ids[index]}",
                Logging_Level.INFO)
        index += 1

    if (len(fields_to_keep) > 0):
        for key in new_param_data:
            for field in fields_to_keep:
                log(f"restore field {field} for ID: {key}", Logging_Level.INFO)
                new_param_data[key][field] = param_data[key][field]
    param.data = new_param_data

    log("\n\nCHECK FOR LOOPS\n\n")
    param = check_loops(param, 26, secondary_ids,
                        True)  #TODO maybe add this as a flag

    return param
Beispiel #19
0
parser.add_argument("--copy", 
                    dest="copy_param", nargs="?",
                    help="Param to copy to this one [PATH_TO_PARAM] [PATH_TO_LAYOUT_PREFIX]")
parser.add_argument("--copy_ignore", 
                    dest="copy_ignore", nargs="+",
                    help="Param fields to ignore when copying (name or index)")


parser.add_argument("-i", "--interactive",
                    action="store_true", dest="interactive", default=False,
                    help="don't load or process any param files (use with interactive console)")

if(len(sys.argv)==1):
    sys.argv.append("--help")
    log(sys.argv)
args = parser.parse_args()
d_args = vars(args)

""" read arguments """
param_name = d_args["param_name"]
param_path = d_args["param_path"]
layout_path = d_args["layout_path"]
save_dir = d_args["out_path"]
# Alternative
param_file_path = d_args["param_filename"]
layout_file_path = d_args["layout_filename"]

set_LOG_LEVEL(d_args["verbosity"])

if(bool(d_args["debug_level"])):