whatever
This commit is contained in:
		
							
								
								
									
										176
									
								
								codegen.py
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								codegen.py
									
									
									
									
									
								
							@@ -1,176 +0,0 @@
 | 
			
		||||
import encode, decode, shared
 | 
			
		||||
import tables
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
conf={}
 | 
			
		||||
confp=os.path.expanduser('~/.config/swat.cfg') # This won't work on Windows. You'll need to tweak this to run it on Windows. Not my problem.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
defaults={'classes':[(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(0,0),(0,0),(1,3),(1,3),(1,3)],'guns':[(1,3),(1,3),(1,3),(1,3),(1,3),(0,0),(0,0),(1,3)],'armour':[(1,3),(1,3),(1,3),(1,3)],'traits':[(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3)],'specs':[(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3)],'talents':[(12,12),(1,3),(1,3),(1,3),(1,3),(1,3),(1,3)],'medals':{}}
 | 
			
		||||
def add_user(name):
 | 
			
		||||
	namehash=encode.hash_name(name) # Store the hash so that if they request a different name that happens to have the same hash, it can just be stored together.
 | 
			
		||||
	if namehash in conf: conf[namehash]['names'].add(name)
 | 
			
		||||
	else: conf[namehash]=defaults.copy()|{'names':{name}}
 | 
			
		||||
	save_conf()
 | 
			
		||||
	global active_profile
 | 
			
		||||
	active_profile=namehash
 | 
			
		||||
 | 
			
		||||
def parse_conf_line(line):
 | 
			
		||||
	a=line.split(' ')
 | 
			
		||||
	out=[]
 | 
			
		||||
	for n in a:
 | 
			
		||||
		b=n.split('/')
 | 
			
		||||
		out.append((int(b[0]),int(b[1])))
 | 
			
		||||
	return out
 | 
			
		||||
 | 
			
		||||
def load_conf():
 | 
			
		||||
	if not os.path.exists(confp): return
 | 
			
		||||
	a=open(confp).read()
 | 
			
		||||
	for n in a.split('\n\n'):
 | 
			
		||||
		lines=n.split('\n')
 | 
			
		||||
		lines=list(filter(lambda x:x,lines))
 | 
			
		||||
		if not lines: continue
 | 
			
		||||
		header=lines[0].split(' ')
 | 
			
		||||
		nhash=int(header[0]); names=set(header[1:]) # Makes deduping way easier
 | 
			
		||||
		medals={}
 | 
			
		||||
		if ':' in lines[-1]: # Since this isn't used in any other line, it's safe
 | 
			
		||||
			medals={int(n.split(':')[0]):int(n.split(':')[1]) for n in lines.pop(-1).split(' ')}
 | 
			
		||||
		stuff={k:parse_conf_line(v) for k,v in zip(tables.displays_str[:-1],lines[1:])}
 | 
			
		||||
		conf[nhash]={'names':names}|stuff|{'medals':medals}
 | 
			
		||||
	update_all_talents()
 | 
			
		||||
	global active_profile
 | 
			
		||||
	active_profile=nhash
 | 
			
		||||
 | 
			
		||||
def unparse_conf_line(line):
 | 
			
		||||
	return ' '.join([str(n[0])+'/'+str(n[1]) for n in line])
 | 
			
		||||
 | 
			
		||||
def save_conf():
 | 
			
		||||
	write=''
 | 
			
		||||
	for k,v in conf.items():
 | 
			
		||||
		write+=' '.join([str(k)]+list(v['names']))+'\n'
 | 
			
		||||
		for n in map(lambda x:unparse_conf_line(v[x]),tables.displays_str[:-1]):
 | 
			
		||||
			write+=n+'\n'
 | 
			
		||||
		write+=' '.join(f'{h}:{m}' for h,m in v['medals'].items())+'\n'
 | 
			
		||||
		write+='\n'
 | 
			
		||||
	write=write[:-2]
 | 
			
		||||
	open(confp,'w').write(write)
 | 
			
		||||
 | 
			
		||||
def update_all_talents():
 | 
			
		||||
	for profile in conf:
 | 
			
		||||
		cl=dict(enumerate(conf[profile]['classes']))
 | 
			
		||||
		t=defaults['talents'].copy()
 | 
			
		||||
		conf[profile]['talents']=t
 | 
			
		||||
		for n in range(1,7):
 | 
			
		||||
			t[n]=update_talent(n,cl)
 | 
			
		||||
 | 
			
		||||
def update_talents(clas,profile=None):
 | 
			
		||||
	if profile is None: profile=active_profile
 | 
			
		||||
	cl=dict(enumerate(conf[profile]['classes']))
 | 
			
		||||
	for talent in tables.clas[clas][1:]: # Don't care about courage
 | 
			
		||||
		conf[profile]['talents'][talent]=update_talent(talent,cl)
 | 
			
		||||
 | 
			
		||||
def update_talent(talent,classes):
 | 
			
		||||
	a=enumerate(tables.clas); b=filter(lambda x:talent in x[1],a); c=list(map(lambda x:x[0],b)); d=filter(lambda x:x[0] in c,classes.items()); rel_classes=list(map(lambda x:x[1],d))
 | 
			
		||||
	ranks,caps=[],[]
 | 
			
		||||
	for n in rel_classes: ranks.append(n[0]); caps.append(n[1])
 | 
			
		||||
	ranks,caps=sorted(ranks),sorted(caps)
 | 
			
		||||
	lon=len(ranks)//2+len(ranks)%2
 | 
			
		||||
	return (ranks[-lon],caps[-lon])
 | 
			
		||||
 | 
			
		||||
def read_code(code,name=None,save=None):
 | 
			
		||||
	if name is None: name=active_profile; save2=True
 | 
			
		||||
	else: save2=False # Don't save spoofed codes unless explicitly told
 | 
			
		||||
	if save is None: save=save2
 | 
			
		||||
	data=list(decode.decode(code,name))
 | 
			
		||||
	check,validator=data.pop(-1),data.pop(-1)
 | 
			
		||||
	talent=data.pop(5)
 | 
			
		||||
	hero=data[0:6]
 | 
			
		||||
	show=list(map(lambda x:x[0][x[1]],zip(tables.displays,hero)))
 | 
			
		||||
	rank,cap=data[6:8]
 | 
			
		||||
	cap=tables.cap[cap]
 | 
			
		||||
	if rank==12: cap=12
 | 
			
		||||
	data=data[8:]
 | 
			
		||||
	if rank<9: show[-1]='Hidden' # Don't spoil the talent
 | 
			
		||||
	print(show)
 | 
			
		||||
	print(str(rank)+'/'+str(cap))
 | 
			
		||||
	print(data) # Extract medals and save them
 | 
			
		||||
	medals=data[1:-1]
 | 
			
		||||
	if not check: print('No name given, code validation not performed')
 | 
			
		||||
	else:
 | 
			
		||||
		if check!=validator: print('code did not validate:',validator,check); return
 | 
			
		||||
		else: # Do not save medals unless validation passed
 | 
			
		||||
			if any(medals): conf[active_profile]['medals'][shared.muxhero(hero[0],hero[3],hero[4])]=shared.muxmedals(*medals)
 | 
			
		||||
			print('code validated')
 | 
			
		||||
	for thing in zip(tables.displays_str[:-1],hero):
 | 
			
		||||
		saved=conf[active_profile][thing[0]][thing[1]]
 | 
			
		||||
		saved=(max(saved[0],rank),max(saved[1],cap))
 | 
			
		||||
		conf[active_profile][thing[0]][thing[1]]=saved
 | 
			
		||||
	update_talents(hero[0])
 | 
			
		||||
	if not save: return
 | 
			
		||||
	save_conf()
 | 
			
		||||
 | 
			
		||||
def mass_add():
 | 
			
		||||
	a=input('>')
 | 
			
		||||
	while a:
 | 
			
		||||
		try: read_code(a,false)
 | 
			
		||||
		except: pass
 | 
			
		||||
		a=input('>')
 | 
			
		||||
	save_conf()
 | 
			
		||||
 | 
			
		||||
def generate(officer=None,name=None):
 | 
			
		||||
	pro=conf[active_profile]
 | 
			
		||||
	if name is None: name=active_profile
 | 
			
		||||
	if officer is None: officer=input('> ')
 | 
			
		||||
	pieces=officer.split('/')
 | 
			
		||||
	c=pieces[0].lower()
 | 
			
		||||
	if 'mav' in c:
 | 
			
		||||
		gun=c[0]
 | 
			
		||||
		pieces[0]='mav'
 | 
			
		||||
	elif 'wm' in c:
 | 
			
		||||
		gun=c[0:2]
 | 
			
		||||
		pieces[0]='wm'
 | 
			
		||||
	else: gun=''
 | 
			
		||||
	out=[]
 | 
			
		||||
	if len(pieces)==6: rank=cap=int(pieces.pop(-1))
 | 
			
		||||
	else: rank,cap=12,12
 | 
			
		||||
	try:
 | 
			
		||||
		for n in zip(pieces,tables.displays_nogun,tables.displays_nogun_str):
 | 
			
		||||
			ind=lookup_piece(n[0],n[1],n[2])
 | 
			
		||||
			rank,cap=min(rank,pro[n[2]][ind][0]),min(cap,pro[n[2]][ind][1])
 | 
			
		||||
			if 0 in [rank,cap]: print(f"{n[0]} is locked, go unlock it first.")
 | 
			
		||||
			out.append(ind)
 | 
			
		||||
		if gun: out.insert(1,lookup_piece(gun,tables.guns,'guns',True))
 | 
			
		||||
		else: out.insert(1,tables.gunmaps_wrapped[out[0]])
 | 
			
		||||
	except LookupException as ex: print(ex); return
 | 
			
		||||
	rank,cap=min(rank,pro['guns'][out[1]][0]),min(cap,pro['guns'][out[1]][1]) # Derp2, forgot to actually cap on gun
 | 
			
		||||
	if 0 in [rank,cap]: return # Already warned about locks earlier.
 | 
			
		||||
	cap=(cap-(cap<10)+(cap>10))//3 # Derp
 | 
			
		||||
	try: out[-1]=tables.clas[out[0]].index(out[-1])
 | 
			
		||||
	except ValueError: print(f"{tables.classes[out[0]]} can't get talent {tables.talent[out[-1]]}, options are {list(map(lambda x:tables.talent[x],tables.clas[out[0]]))}"); return
 | 
			
		||||
	muxed=shared.muxhero(out[0],out[3],out[4])
 | 
			
		||||
	meds=[]
 | 
			
		||||
	if muxed in pro['medals']: meds=shared.muxmedals(pro['medals'][muxed])
 | 
			
		||||
	return encode.encode(name,*out,rank,cap,0,*meds)
 | 
			
		||||
 | 
			
		||||
def lookup_piece(piece,table,name,partial=False):
 | 
			
		||||
	if len(piece)<3: p=piece.upper()
 | 
			
		||||
	else: p=piece.capitalize() # Bloody Americans
 | 
			
		||||
	if not partial:
 | 
			
		||||
		try: return table.index(p)
 | 
			
		||||
		except ValueError: raise LookupException(f"Couldn't resolve {piece} from {name}")
 | 
			
		||||
	res=list(filter(lambda x:p in x,table))
 | 
			
		||||
	if len(res)!=1: raise LookupException(f"Couldn't resolve {piece} with partial match from {name} (found {len(res)} possibilities)") # Ambiguous lookups not allowed
 | 
			
		||||
	return table.index(res[0])
 | 
			
		||||
class LookupException(Exception): pass
 | 
			
		||||
 | 
			
		||||
def ranks():
 | 
			
		||||
	for n,m in zip(tables.displays_str,tables.displays):
 | 
			
		||||
		a=zip(m,conf[active_profile][n])
 | 
			
		||||
		for o in a:
 | 
			
		||||
			print(f'{o[0]}: {o[1][0]}/{o[1][1]}',end=', ')
 | 
			
		||||
		print()
 | 
			
		||||
 | 
			
		||||
load_conf()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__=="__main__": print("Please open an interpreter and use 'import codegen', this script doesn't serve as an entrypoint on its own yet.")
 | 
			
		||||
							
								
								
									
										55
									
								
								decode.py
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								decode.py
									
									
									
									
									
								
							@@ -1,55 +0,0 @@
 | 
			
		||||
import shared
 | 
			
		||||
import tables
 | 
			
		||||
import encode
 | 
			
		||||
from functools import reduce
 | 
			
		||||
 | 
			
		||||
def decode(code,name=''): # This is going to be a huge function
 | 
			
		||||
	code=shared.delimit(code) # It didn't end up being that huge
 | 
			
		||||
	code=shared.scramble(code,True)
 | 
			
		||||
	code,validator=shared.combine(code)
 | 
			
		||||
	xp=int(code[-1]); seed=int(code[0])
 | 
			
		||||
	code=code[1:-1]
 | 
			
		||||
	data=unzip(code)
 | 
			
		||||
	xp+=data.pop(0)
 | 
			
		||||
	rank,cap,cob,lsa,rem,clas,armour,trait,spec,talent=data
 | 
			
		||||
	cob,lsa=bool(cob),bool(lsa)
 | 
			
		||||
	rank,cap,key,moh,pcc=unadjust_rank(rank,cap)
 | 
			
		||||
	if seed%2: seed-=1; clas+=10
 | 
			
		||||
	if clas==6: clas=[8,9,6][armour]; armour=3
 | 
			
		||||
	check=''
 | 
			
		||||
	oldclas=clas # Whoops this all needs to be done before globalising talent
 | 
			
		||||
	gun=tables.gunmaps[clas]
 | 
			
		||||
	clas-=(clas>8)+min(4,max(0,clas-10)) # WM and mav adjustments
 | 
			
		||||
	gtalent=tables.clas[clas][talent] # Globalise it lol
 | 
			
		||||
	# And do it *before* validation because it needs gtalent passed in now
 | 
			
		||||
	if name:
 | 
			
		||||
		check=encode.validate_data(name, oldclas,armour,trait,spec,gtalent, rank,cap,xp, key,moh,pcc,cob,lsa,rem)
 | 
			
		||||
	rank+=1 # This has to come after extracting medals
 | 
			
		||||
	return clas,gun,armour,trait,spec,talent,gtalent,rank,cap,xp,key,moh,pcc,cob,lsa,rem,seed,validator,check
 | 
			
		||||
 | 
			
		||||
############################
 | 
			
		||||
# SUPPORTING FUNCTIONS BELOW
 | 
			
		||||
############################
 | 
			
		||||
 | 
			
		||||
def unzip(code):
 | 
			
		||||
	code=int(code)
 | 
			
		||||
	out=[]
 | 
			
		||||
	weight=reduce(lambda x,y:x*y,tables.weights)
 | 
			
		||||
	for n in list(zip(tables.weights,['xp//10','rank','cap','cob','lsa','rem','clas','armour','trait','spec','talent']))[::-1]:
 | 
			
		||||
		shared.trace(code,weight,n,out)
 | 
			
		||||
		out.append(code//weight)
 | 
			
		||||
		code%=weight
 | 
			
		||||
		weight//=n[0]
 | 
			
		||||
	out[-1]*=10 # This is XP
 | 
			
		||||
	return out[::-1]
 | 
			
		||||
 | 
			
		||||
def unadjust_rank(rank,cap):
 | 
			
		||||
	key,moh,pcc=False,False,False
 | 
			
		||||
	if rank>8:
 | 
			
		||||
		pcc=bool((cap+1)%2)
 | 
			
		||||
		cap=2+(cap+1)//2
 | 
			
		||||
	if rank>11: # Actually need to check this on the way out
 | 
			
		||||
		key=rank>12
 | 
			
		||||
		moh=bool((rank-11)%2)
 | 
			
		||||
		rank=11
 | 
			
		||||
	return rank,cap,key,moh,pcc
 | 
			
		||||
							
								
								
									
										76
									
								
								encode.py
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								encode.py
									
									
									
									
									
								
							@@ -1,76 +0,0 @@
 | 
			
		||||
import shared
 | 
			
		||||
import random
 | 
			
		||||
import tables
 | 
			
		||||
 | 
			
		||||
def encode(name,clas,gun,armour,trait,spec,talent,rank=-1,cap=-1,xp=0, key=False,moh=False,pcc=False,cob=False,lsa=False,rem=False,seed=-1):
 | 
			
		||||
	if rank==-1: # actually means gun wasn't given, so shift them
 | 
			
		||||
		gun,armour,trait,spec,talent,rank=-1,gun,armour,trait,spec,talent
 | 
			
		||||
	gtalent=tables.clas[clas][talent]
 | 
			
		||||
	if clas>9: clas+=5 # Shift tech/Alice up to their positions - always
 | 
			
		||||
	# ... And do it before modifying clas below.
 | 
			
		||||
	if gun!=-1:
 | 
			
		||||
		#encode gun into class
 | 
			
		||||
		if clas==9: clas+=gun+1 # Because 9 outside is Mav, and 9 inside is GLWM
 | 
			
		||||
		if clas==8: clas+=gun-5
 | 
			
		||||
	rank-=1 # This actually DOES affect part 2 for some fucking reason
 | 
			
		||||
	cap=max(cap,(rank)//3+(rank>9)) #Sanity-check
 | 
			
		||||
	code1=encode_data(clas,armour,trait,spec,talent,rank,cap,xp, key,moh,pcc,cob,lsa,rem,seed)
 | 
			
		||||
	code2=validate_data(name,clas,armour,trait,spec,gtalent,rank,cap,xp, key,moh,pcc,cob,lsa,rem)
 | 
			
		||||
	shared.trace(code1,code2)
 | 
			
		||||
	code=shared.combine(code1,code2)
 | 
			
		||||
	shared.trace(code)
 | 
			
		||||
	return shared.delimit(shared.scramble(code),'-')
 | 
			
		||||
 | 
			
		||||
def encode_data(clas,armour,trait,spec,talent,rank,cap=-1,xp=0, key=False,moh=False,pcc=False,cob=False,lsa=False,rem=False,seed=-1):
 | 
			
		||||
	if clas==6: armour=2 # Borg is heavy borg
 | 
			
		||||
	if clas==8: clas=6; armour=0 # LR WM is light borg
 | 
			
		||||
	if clas==9: clas=6; armour=1 # GL WM is med borg
 | 
			
		||||
	seed,clas=rand(seed,clas)
 | 
			
		||||
	rank,cap=adjust_rank(rank,cap,key,moh,pcc)
 | 
			
		||||
	code1=0
 | 
			
		||||
	weight=1
 | 
			
		||||
	for n in list(zip(tables.weights,[xp//10,rank,cap,cob,lsa,rem,clas,armour,trait,spec,talent])):
 | 
			
		||||
		shared.trace(code1,weight,n[0],n[1])
 | 
			
		||||
		weight*=n[0]
 | 
			
		||||
		code1+=n[1]*weight
 | 
			
		||||
	return str(seed)+shared.fill0s(code1,9)+str(xp%10)
 | 
			
		||||
 | 
			
		||||
def validate_data(name,clas,armour,trait,spec,talent,rank,cap=0,xp=0, key=False,moh=False,pcc=False,cob=False,lsa=False,rem=False):
 | 
			
		||||
	# gtalent is now looked up outside, before class modification - because I've adjusted that table to be more useful in general.
 | 
			
		||||
	if isinstance(name,str): name=hash_name(name)
 | 
			
		||||
	fac1=[171,142,175,157,167,150,149,151,153,165]
 | 
			
		||||
	fac2=[169,170,166,173,158,177,161,180,186,159] # I don't understand these, but I hope they work.
 | 
			
		||||
	code2=name*(spec+1) +(trait+4)*(trait+6) +(rank+1)*(xp+1) +(talent+1)*43*fac1[name%10] -(clas+1)*(241+fac2[name%10]) -(rem+1)*50 +(key+1)*4 +(moh+1)*9 +(pcc+1)*19 +(cob+1)*39 +(lsa+1)*79 +(armour+1)*159
 | 
			
		||||
	code2+=100*(cap+1)*(code2%1000) # To be honest I don't understand any of this. It's just random nonsense.
 | 
			
		||||
	while code2>99999:
 | 
			
		||||
		code2=code2%100000+code2//100000
 | 
			
		||||
	return shared.fill0s(code2,5)
 | 
			
		||||
 | 
			
		||||
############################
 | 
			
		||||
# SUPPORTING FUNCTIONS BELOW
 | 
			
		||||
############################
 | 
			
		||||
 | 
			
		||||
def getval(char):
 | 
			
		||||
	vals='_9483726150rstlmeaiuonycdpjkhgxwfvqzb(-[.!' # szszss'
 | 
			
		||||
	#vals='_5698472031aeioyusptndchbrxvzjmlkwgfq-!.([' # meebs'
 | 
			
		||||
	if char in vals: return vals.index(char)+1
 | 
			
		||||
	return 43*len(char.encode('utf-8')) # Apparently multibyte chars do this
 | 
			
		||||
 | 
			
		||||
def hash_name(name):
 | 
			
		||||
	parsed=name.lower().replace(')','(').replace(']','[')
 | 
			
		||||
	checksum=0
 | 
			
		||||
	for i in range(len(parsed)):
 | 
			
		||||
		checksum+=getval(parsed[i])*((i+1)%3+1)
 | 
			
		||||
	return checksum
 | 
			
		||||
 | 
			
		||||
def adjust_rank(rank,cap=-1, key=False,moh=False,pcc=False):
 | 
			
		||||
	rank+=key*2+moh # Invalid if rank <11, but whatever
 | 
			
		||||
	if rank>8: #Can't have PCC below r10, and there are only two possible cap states after that
 | 
			
		||||
		cap=(cap==4)*2+pcc+1 # I don't know why pcc is encoded like this, I would have thought cap would behave normally if not pcc, but nope.
 | 
			
		||||
	return rank,cap
 | 
			
		||||
 | 
			
		||||
def rand(seed,clas):
 | 
			
		||||
	if seed>-1: n=seed
 | 
			
		||||
	else: n=int(random.random()*5)*2
 | 
			
		||||
	if clas>9: return n+1,clas-10
 | 
			
		||||
	return n,clas
 | 
			
		||||
							
								
								
									
										38
									
								
								shared.py
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								shared.py
									
									
									
									
									
								
							@@ -1,38 +0,0 @@
 | 
			
		||||
tracing=False
 | 
			
		||||
def trace(*args,**kwargs):
 | 
			
		||||
	if tracing: print(*args,**kwargs)
 | 
			
		||||
 | 
			
		||||
def delimit(code,spacer=''):
 | 
			
		||||
	if not spacer:
 | 
			
		||||
		if len(code)==16: return code
 | 
			
		||||
		if len(code)!=19: raise Exception('code length should be 19 for despacing, got',len(code),'from',code)
 | 
			
		||||
		return code[0:4]+code[5:9]+code[10:14]+code[15:19]
 | 
			
		||||
	if spacer:
 | 
			
		||||
		if len(code)==19: return code
 | 
			
		||||
		if len(code)!=16: raise Exception('code length should be 16 for spacing, got',len(code),'from',code)
 | 
			
		||||
		return code[0:4]+spacer+code[4:8]+spacer+code[8:12]+spacer+code[12:16]
 | 
			
		||||
 | 
			
		||||
def scramble(code,unscramble=False):
 | 
			
		||||
	n=int(code[0])
 | 
			
		||||
	if unscramble: n=15-n # Because the 1st digit is left alone this needs to be +1
 | 
			
		||||
	return code[0]+code[16-n:16]+code[1:16-n]
 | 
			
		||||
 | 
			
		||||
def combine(code,namehash=''):
 | 
			
		||||
	if namehash: return code[0:2]+namehash[4:5]+code[2:6]+namehash[3:4]+code[6:8]+namehash[1:3]+code[8:11]+namehash[0:1]
 | 
			
		||||
	charcode=code[0:2]+code[3:7]+code[8:10]+code[12:15]
 | 
			
		||||
	namehash=code[15]+code[10:12]+code[7]+code[2]
 | 
			
		||||
	return charcode,namehash
 | 
			
		||||
 | 
			
		||||
def fill0s(num,zeroes=0):
 | 
			
		||||
	if not zeroes: return str(int(num))
 | 
			
		||||
	n=str(num)
 | 
			
		||||
	if len(n)>zeroes: raise Exception(f"can't pad {n} ({len(n)}) with {zeroes} 0s")
 | 
			
		||||
	return '0'*(zeroes-len(n))+n
 | 
			
		||||
 | 
			
		||||
def muxhero(clas,trait,spec):
 | 
			
		||||
	return clas+trait*12+spec*12*16 # It's actually stored backwards like this, spec is in the most significant bits. Whatever, it doesn't need to be reversable.
 | 
			
		||||
 | 
			
		||||
def muxmedals(key,moh=-1,pcc=-1,cob=-1,lsa=-1,rem=-1):
 | 
			
		||||
	print(key,moh,pcc,cob,lsa,rem)
 | 
			
		||||
	if moh!=-1: return key+moh*2+pcc*4+cob*8+lsa*16+rem*32
 | 
			
		||||
	return bool(key&1),bool(key&2),bool(key&4),bool(key&8),bool(key&16),key//32
 | 
			
		||||
							
								
								
									
										34
									
								
								tables.py
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								tables.py
									
									
									
									
									
								
							@@ -1,34 +0,0 @@
 | 
			
		||||
#Data tables: Mostly used by the codegen itself
 | 
			
		||||
clas=[
 | 
			
		||||
[0,1,2,5], # Sniper: Crg, wire, run, tinker
 | 
			
		||||
[0,1,4,6], # Medic: Crg, wire, tough, hack
 | 
			
		||||
[0,1,2,6], # Tact: Crg, wire, run, hack
 | 
			
		||||
[0,1,3,6], # Psy: Crg, wire, spot, hack
 | 
			
		||||
[0,2,4,5], # HO: Crg, run, tough, tinker
 | 
			
		||||
[0,2,4,3], # Demo: Crg, run, tough, spot
 | 
			
		||||
[0,3,2,6], # Borg: Crg, spot, run, hack
 | 
			
		||||
[0,3,5,4], # Pyro: Crg, spot, tinker, tough
 | 
			
		||||
[0,4,5,3], # WM (LR, GL): Crg, tough, tinker, spot
 | 
			
		||||
[0,2,6,5], # Mav (AR, SR, CG, RL, F): Crg, run, hack, tinker
 | 
			
		||||
[0,1,5,6], # Tech: Crg, wire, tinker, hack
 | 
			
		||||
[0,1,3,4] # Alice: Crg, wire, spot, tough
 | 
			
		||||
]
 | 
			
		||||
weights=[1,50,15,5,2,2,4,8,3,18,9]
 | 
			
		||||
 | 
			
		||||
#Display tables: Mostly used by the rank code manager
 | 
			
		||||
classes=['Sniper','Medic','Tact','Psy','HO','Demo','Borg','Pyro','WM','Mav','Tech','Alice']
 | 
			
		||||
guns=['AR','SR','CG','RL','F','LR','GL','PF']
 | 
			
		||||
gunmaps=[1,0,0,0,2,3,2,4,5,6,0,1,2,3,4,1,7] # This is unwrapped mappings so every value matters
 | 
			
		||||
gunmaps_wrapped=[1,0,0,0,2,3,2,4,-1,-1,1,7] # Wrapped mappings return -1 for classes that have gun choices. Hopefully you'll never use it with them.
 | 
			
		||||
armour='LMHA'
 | 
			
		||||
trait=['SK', 'Gift', 'Surv', 'Goon', 'Acro', 'SL', 'Healer', 'FC', 'CR', 'RR', 'Gadg', 'Prowl', 'Gizer', 'PR', 'Engi', 'Reck']
 | 
			
		||||
spec=['Weap', 'PA', 'Cells', 'Cyber', 'Tri', 'Chem', 'Leader', 'Robo', 'Esp']
 | 
			
		||||
talent=['Crg','Wire','Run','Spot','Tough','Tinker','Hack']
 | 
			
		||||
#Convenience
 | 
			
		||||
displays=[classes,guns,armour,trait,spec,talent]
 | 
			
		||||
displays_str=['classes','guns','armour','traits','specs','talents']
 | 
			
		||||
displays_nogun=[classes,armour,trait,spec,talent]
 | 
			
		||||
displays_nogun_str=['classes','armour','traits','specs','talents']
 | 
			
		||||
rank=range(12)
 | 
			
		||||
xp=range(2500)
 | 
			
		||||
cap=[3, 6, 9, 10, 11]
 | 
			
		||||
		Reference in New Issue
	
	Block a user