Initial commit

This commit is contained in:
VirtuBrick 2024-02-22 11:59:13 -05:00
commit fcf92829e8
421 changed files with 82302 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
config.py
__pycache__/
assets/
proxies.txt
*.pem
logs/*.log*
download_cache/*
*.key
*.crt
!download_cache/KEEPME

100
README.md Normal file
View File

@ -0,0 +1,100 @@
# Syntax Backend
**Last Updated: 20/2/2024**
## What you need
### Requirements
- Linux Server ( For Production environment )
- PostgreSQL Server
- Redis Server
- NGINX
- Cloudflare Account
- Domain with Cloudflare protection
- Python 3.12+
- FFmpeg
- Gunicorn
> Note: These are the bare minimum needed for Syntax Backend to run, please do not attempt to host a publicly accessible version of Syntax if you do not know what you are doing
### Optional Services
- Syntax Gameserver running on Windows Server ( Needed for rendering and games )
- Syntax Discord Bot
- Ko-Fi ( Please modify code if you are not going to use this )
- Cryptomus
- MailJet ( Email Vericiation, modification to the code is needed as email templates are not included )
- HTTP Proxies for faster asset migration ( [webshare.io](https://webshare.io/) is recommended )
- Amazon S3 Bucket ( **USE_LOCAL_STORAGE** must be enabled if you are not planning to use a S3 Bucket )
## Configuration
Copy `config.example.py` and name it as `config.py` then place it in the same directory as this readme file
1. **FLASK_SESSION_KEY** - Used for salting passwords and 2FA Secret Generation, please change to a random long string and never change it ever again!
~~2. **AuthorizationKey** - Added for debugging and bypassing ratelimits, please also change to a random long string~~ Removed from codebase
3. **SQLALCHEMY_DATABASE_URI** - URI for connecting to the postgres database, refer to [Documentation](https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/) for creating a database URI
4. **FLASK_LIMITED_STORAGE_URI** - Redis Server URI, can leave as default if your redis server is hosted locally and does not require authorization
5. **BaseDomain** - Change to your domain *(eg. roblox.com)*, please do not host on a subdomain as it is not supported!
6. **CloudflareTurnstileSiteKey** - Please setup turnstile on the domain you are hosting and then grab the turnstile site key from there
7. **CloudflareTurnstileSecretKey** - Read above
8. **DISCORD_CLIENT_ID** - Go to the Discord Developer Portal and go to the Discord Application you are going to use, then place its ClientID here
9. **DiscordBotToken** - Use your Discord Bot Token
10. **DISCORD_CLIENT_SECRET** - Discord Application Client Secret
11. **DISCORD_BOT_AUTHTOKEN** - Authorization Token for Syntax Discord Bot, use random long string
12. **DISCORD_BOT_AUTHORISED_IPS** - List of IPs which are allowed to access Discord Bot internal APIs
13. **DISCORD_ADMIN_LOGS_WEBHOOK** - Discord Webhook for logging Moderation Actions
14. **MAILJET** - You will have to modify the code and the config for this as your email template will be different
15. **KOFI_VERIFICATION_TOKEN** - Used for verifying requests from Ko-Fi to automate donations processing, please change to a random long string if you do not plan on using this. If you do you can find the verification token in your Ko-Fi API Panel.
16. **VERIFIED_EMAIL_REWARD_ASSET** - The AssetId the user is rewarded with once they verify their email, you can change this after setting up everything
17. **ASSETMIGRATOR_ROBLOSECURITY** - Used for private audio migration
18. **ASSETMIGRATOR_USE_PROXIES** - If you want to use proxies for Asset Migration ( Which you should as it speeds up everything )
19. **ASSETMIGRATOR_PROXY_LIST_LOCATION** - The path to the file which contains the proxies
20. **RSA_PRIVATE_KEY_PATH** - The path to the private key, expects a 1024 Bit RSA private key used for signing JoinScripts and everyting else **This is required!!**
21. **RSA_PRIVATE_KEY_PATH2** - Same thing for above but expects a 2048 Bit RSA private key
22. **USE_LOCAL_STORAGE** - Uses local storage for storing and reading files, bypasses S3 and uses **AWS_S3_DOWNLOAD_CACHE_DIR** as its storage directory ( SHOULD ONLY BE USED IN A DEVELOPMENT ENVIRONMENT )
23. **AWS_ACCESS_KEY** - Your AWS Access Key, please create one in your AWS IAM Manager
24. **AWS_SECRET_KEY** - The Secret Key for the access key
25. **AWS_S3_BUCKET_NAME** - The bucket name assets and images will be uploaded to
26. **AWS_S3_DOWNLOAD_CACHE_DIR** - Where files downloaded from S3 will be cached
27. **AWS_REGION_NAME** - The region of the bucket
28. **CDN_URL** - Change to where the CDN is
29. **DISCOURSE_SSO_ENABLED** - Allows authentication with Syntax for [Discourse](https://www.discourse.org/) Forums
30. **DISCOURSE_FORUM_BASEURL** - The location of the forum
31. **DISCOURSE_SECRET_KEY** - The secret key for signing
32. **ADMIN_GROUP_ID** - The GroupId where admins are in, used for showing the admin badges ingame
33. **ITEMRELEASER_DISCORD_WEBHOOK** - The Discord Webhook to use for announcing an item release
34. **ITEMRELEASER_ITEM_PING_ROLE_ID** - The Discord Role ID to ping for announcing an item release
35. **PROMETHEUS_ENABLED** - If the Prometheus endpoint is enabled
36. **PROMETHEUS_ALLOWED_IPS** - IPs which are allowed to query the Prometheus endpoint
37. **CHEATER_REPORTS_DISCORD_WEBHOOK** - The Discord webhook to use for cheater reports from RCCService
38. **ROLIMONS_API_ENABLED** - Used for Synmons
39. **ROLIMONS_API_KEY** - Used for Synmons
40. **GAMESERVER_COMM_PRIVATE_KEY_LOCATION** - The Private key location used for signing requests sent to gameservers
41. **CRYPTOMUS_PAYMENT_ENABLED** - If the cryptomus payment system is enabled
42. **CRYPTOMUS_MERCHANT_ID** - Your Cryptomus merchant ID
43. **CRYPTOMUS_API_KEY** - Your Cryptoumus API Key
44. **IPAPI_AUTH_KEY** - API Key for [IPAPI](https://ipapi.co/) used for VPN and proxy detection on signup
## KeyPair Generation
The SYNTAX Backend requires some keys for it to sign and communicate with gameservers, run the script below to generate those keys.
```
python tools/generate_new_keys.py
```
In the `tools` directory 6 new files should have been created, 2 key pairs are for joinscript signing which is needed by the Client and RCCService to authenticate and verify properly.
Another keypair is for signing requests to communicate with all gameservers, take the public key and place it in your gameserver directory.
## First Time Setup
First install all required dependencies by running `pip install -r requirements.txt` in this directory
Next run the command `flask shell` in the same directory as this README.md file, then in the shell run `db.create_all()`.
This will automatically create all the tables needed in your PostgreSQL database.
Next use type in the following command in your flask shell
```
from app.shell_commands import create_admin_user
create_admin_user()
```
This will create an admin user with all existing admin privileges
Now we can finally start the website, please make sure you have [gunicorn](https://gunicorn.org/) installed on your Linux Machine, gunicorn does not support Windows Machines. To start run the shell script `./start.sh` which will start a webserver on port `3003`. Please make sure you have NGINX configured as a reverse proxy to proxy the website and also have configured Cloudflare to serve your website on the main and all subdomains.
If you are running a Windows Machine and want to run in debug mode run `flask run --port 3006 --debug`, this will open the website on port 3006

415
app/__init__.py Normal file
View File

@ -0,0 +1,415 @@
import base64
import redis
import sys
import os
import hashlib
import traceback
import string
import random
import re
import logging
from config import Config
from logging.handlers import TimedRotatingFileHandler
from flask import Flask, jsonify, render_template, session, redirect, url_for, request, make_response, Response
from datetime import datetime, timedelta
from urllib.parse import urlparse
from app.models.user import User
from app.models.messages import Message
from app.models.user_trades import UserTrade
from app.models.friend_request import FriendRequest
from app.models.asset import Asset
from app.models.asset_version import AssetVersion
from app.models.game_session_log import GameSessionLog
from app.enums.TradeStatus import TradeStatus
from app.enums.AssetType import AssetType
from app.enums.TransactionType import TransactionType
from app.util import auth, assetversion, s3helper, signscript, transactions
from app.services.economy import IncrementTargetBalance, GetUserBalance
from app.extensions import db, limiter, scheduler, CORS, redis_controller, csrf, get_remote_address
import app.shell_commands as cmd
logging.basicConfig(
level = logging.INFO,
format = "%(asctime)s [%(levelname)s] %(message)s"
)
logger = logging.getLogger(__name__)
logname = "./logs/syntaxweb.log"
handler = TimedRotatingFileHandler(logname, when="midnight", backupCount=30)
handler.suffix = "%Y%m%d"
logging.getLogger().addHandler(handler)
TwelveClientAssets = [37801173, 46295864, 48488236, 53870848, 53870858, 60595696, 89449009, 89449094, 97188757]
def create_app(config_class=Config):
app = Flask(__name__, template_folder="pages")
app.config.from_object(config_class)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config["SECRET_KEY"] = config_class.FLASK_SESSION_KEY
app.config['CORS_HEADERS'] = 'Content-Type'
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.from_url(Config.FLASK_LIMITED_STORAGE_URI)
app.config['MAX_CONTENT_LENGTH'] = 32 * 1024 * 1024
app.config["SQUEEZE_MIN_SIZE"] = 0
#if app.debug is False:
#app.config["SERVER_NAME"] = config_class.BaseDomain
db.init_app(app)
limiter.init_app(app)
csrf.init_app(app)
clean_domain = config_class.BaseDomain.replace('.', r'\.')
CORS.init_app(app, supports_credentials=True, resources={r"/*": {"origins": [f"https://{clean_domain}", f"http://{clean_domain}", f"https://.+{clean_domain}", f"http://.+{clean_domain}"]}})
scheduler.init_app(app)
scheduler.start()
from app.pages.login.login import login
from app.pages.signup.signup import signup
from app.pages.static import static
from app.pages.settings.settings import settings
from app.pages.home.home import home
from app.pages.admin.admin import AdminRoute, GetAmountOfPendingAssets, IsUserAnAdministrator
from app.routes.asset import AssetRoute
from app.routes.authentication import AuthenticationRoute
from app.routes.jobreporthandler import JobReportHandler
from app.routes.clientinfo import ClientInfo
from app.routes.thumbnailer import Thumbnailer
from app.routes.image import ImageRoute
from app.routes.fflagssettings import FFlagRoute
from app.pages.profiles.profile import Profile
from app.routes.gamejoin import GameJoinRoute
from app.routes.marketplace import MarketPlaceRoute, EconomyV1Route
from app.routes.presence import PresenceRoute
from app.pages.messages.messages import MessageRoute
#from app.pages.clothingmigrator.migrator import ClothingMigratorRoute
from app.pages.catalog.catalog import CatalogRoute
from app.pages.avatar.avatar import AvatarRoute
from app.routes.pointsservice import PointsServiceRoute
from app.routes.datastoreservice import DataStoreRoute
from app.pages.clientpages.clientpages import ClientPages
from app.routes.luawebservice import LuaWebServiceRoute
from app.pages.develop.develop import DevelopPagesRoute
from app.routes.bootstrapper import BootstrapperRoute
from app.pages.studio.studiopages import StudioPagesRoute
from app.pages.games.games import GamePagesRoute
from app.pages.membership.membership import MembershipPages
from app.routes.rate import AssetRateRoute
from app.pages.trades.trades import TradesPageRoute
from app.routes.sets import SetsRoute
from app.pages.notapproved.notapproved import NotApprovedRoute
from app.pages.groups.groupspage import groups_page
from app.pages.giftcardredeem.redeem import GiftcardRedeemRoute
from app.pages.currencyexchange.controller import CurrencyExchangeRoute
from app.routes.kofihandler import KofiHandlerRoute
#from app.pages.invitekeys.handler import inviteKeyRoute
from app.routes.discord_internal import DiscordInternal
from app.routes.publicapi import PublicAPIRoute
from app.pages.catalog.catalog import LibraryRoute
from app.routes.discourse_sso import discourse_sso
from app.pages.transactions.transactions import TransactionsRoute
from app.routes.gametransactions import GameTransactionsRoute
from app.pages.audiomigrator.audiomigrator import AudioMigratorRoute
from app.routes.rbxapi import RBXAPIRoute
from app.routes.legacydatapersistence import LegacyDataPersistenceRoute
from app.routes.friendapi import FriendsAPIRoute
from app.routes.inventoryapi import InventoryAPI
from app.routes.usersapi import UsersAPI
from app.routes.mobile import MobileAPIRoute
from app.routes.gamesapi import GamesAPIRoute
from app.routes.accountsettingsapi import AccountSettingsAPIRoute
from app.routes.presenceapi import PresenceAPIRoute
from app.routes.avatarapi import AvatarAPIRoute
from app.routes.badgesapi import BadgesAPIRoute
from app.pages.catalog.catalog import BadgesPageRoute
from app.pages.users.users_page import users_page
from app.routes.teleportservice import TeleportServiceRoute
from app.routes.prometheus import PrometheusRoute
from app.routes.rolimons import RolimonsAPI
from app.routes.cryptomus_handler import CryptomusHandler
app.register_blueprint(login, url_prefix="/")
app.register_blueprint(signup, url_prefix="/")
app.register_blueprint(static, url_prefix="/")
app.register_blueprint(settings, url_prefix="/")
app.register_blueprint(home, url_prefix="/")
app.register_blueprint(AssetRoute, url_prefix="/")
app.register_blueprint(AuthenticationRoute, url_prefix="/")
app.register_blueprint(AdminRoute, url_prefix="/admin")
app.register_blueprint(JobReportHandler, url_prefix="/")
app.register_blueprint(ClientInfo, url_prefix="/")
app.register_blueprint(Thumbnailer, url_prefix="/internal")
app.register_blueprint(ImageRoute, url_prefix="/")
app.register_blueprint(FFlagRoute, url_prefix="/")
app.register_blueprint(Profile, url_prefix="/")
app.register_blueprint(GameJoinRoute, url_prefix="/")
app.register_blueprint(MarketPlaceRoute, url_prefix="/marketplace")
app.register_blueprint(EconomyV1Route, url_prefix="/")
app.register_blueprint(PresenceRoute, url_prefix="/presence")
app.register_blueprint(MessageRoute, url_prefix="/messages")
#app.register_blueprint(ClothingMigratorRoute, url_prefix="/")
app.register_blueprint(CatalogRoute, url_prefix="/catalog")
app.register_blueprint(AvatarRoute, url_prefix="/")
app.register_blueprint(PointsServiceRoute, url_prefix="/")
app.register_blueprint(DataStoreRoute, url_prefix="/")
app.register_blueprint(ClientPages, url_prefix="/")
app.register_blueprint(LuaWebServiceRoute, url_prefix="/")
app.register_blueprint(DevelopPagesRoute, url_prefix="/")
app.register_blueprint(BootstrapperRoute, url_prefix="/")
app.register_blueprint(StudioPagesRoute, url_prefix="/")
app.register_blueprint(GamePagesRoute, url_prefix="/")
app.register_blueprint(MembershipPages, url_prefix="/")
app.register_blueprint(AssetRateRoute, url_prefix="/")
app.register_blueprint(TradesPageRoute, url_prefix="/")
app.register_blueprint(SetsRoute, url_prefix="/")
app.register_blueprint(NotApprovedRoute, url_prefix="/")
app.register_blueprint(groups_page, url_prefix="/")
app.register_blueprint(GiftcardRedeemRoute, url_prefix="/")
app.register_blueprint(CurrencyExchangeRoute, url_prefix="/currency-exchange")
app.register_blueprint(KofiHandlerRoute, url_prefix="/")
#app.register_blueprint(inviteKeyRoute, url_prefix="/")
app.register_blueprint(DiscordInternal, url_prefix="/internal/discord_bot")
app.register_blueprint(PublicAPIRoute, url_prefix="/public-api")
app.register_blueprint(LibraryRoute, url_prefix="/library")
app.register_blueprint(discourse_sso, url_prefix="/discourse")
app.register_blueprint(TransactionsRoute, url_prefix="/transactions")
app.register_blueprint(GameTransactionsRoute, url_prefix="/")
app.register_blueprint(AudioMigratorRoute, url_prefix="/")
app.register_blueprint(RBXAPIRoute, url_prefix="/")
app.register_blueprint(LegacyDataPersistenceRoute, url_prefix="/persistence/legacy")
app.register_blueprint(FriendsAPIRoute, url_prefix="/")
app.register_blueprint(InventoryAPI, url_prefix="/")
app.register_blueprint(UsersAPI, url_prefix="/")
app.register_blueprint(MobileAPIRoute, url_prefix="/")
app.register_blueprint(GamesAPIRoute, url_prefix="/")
app.register_blueprint(AccountSettingsAPIRoute, url_prefix="/")
app.register_blueprint(PresenceAPIRoute, url_prefix="/")
app.register_blueprint(AvatarAPIRoute, url_prefix="/")
app.register_blueprint(BadgesAPIRoute, url_prefix="/")
app.register_blueprint(BadgesPageRoute, url_prefix="/badges")
app.register_blueprint(users_page, url_prefix="/")
app.register_blueprint(TeleportServiceRoute, url_prefix="/reservedservers")
app.register_blueprint(PrometheusRoute, url_prefix="/")
app.register_blueprint(RolimonsAPI, url_prefix="/api/internal_rolimons")
app.register_blueprint(CryptomusHandler, url_prefix="/cryptomus_service")
def ConvertDatetimeToDayMonthYear(date):
return date.strftime("%d/%m/%Y")
app.jinja_env.globals.update(round=round, b64decode=base64.b64decode, len=len, ConvertDatetimeToDayMonthYear=ConvertDatetimeToDayMonthYear, datetime_utcnow = datetime.utcnow)
@app.before_request
def before_request():
BrowserUserAgent = request.headers.get('User-Agent', default="Unknown")
if "Roblox" not in BrowserUserAgent:
if request.method == "GET":
CloudFlareScheme = request.headers.get('CF-Visitor')
if CloudFlareScheme is not None:
if "https" not in CloudFlareScheme:
return redirect(request.url.replace("http://", "https://", 1), code=301)
elif BrowserUserAgent == "Roblox/WinInet":
requestReferer = request.headers.get( key = "Referer", default = None )
if requestReferer is not None:
try:
if urlparse( requestReferer ).hostname[ -len( config_class.BaseDomain ): ] != config_class.BaseDomain:
logging.warn(f"Bad Referer - ref : {requestReferer} - target : {request.url}")
return "Bad Referer", 403
except:
pass
@app.after_request
def after_request( response : Response ):
if get_remote_address() in config_class.DEBUG_IPS:
logging.info(f"Debug - {response.status_code} - {request.host} - {request.path} - {request.args}")
if hasattr(response, 'direct_passthrough') and not response.direct_passthrough:
UserObj : User = auth.GetCurrentUser()
if UserObj is not None:
if UserObj.accountstatus != 1:
auth.invalidateToken(request.cookies.get(".ROBLOSECURITY"))
session["not-approved-viewer"] = UserObj.id
resp = make_response(redirect("/not-approved"))
resp.set_cookie(".ROBLOSECURITY", "", expires=0)
return resp
if request.cookies.get(key="t", default=None, type=str) is None:
NewToken = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(128))
response.set_cookie("t", NewToken, expires=datetime.utcnow() + timedelta(days=365), domain=f".{config_class.BaseDomain}")
if "not-approved-viewer" in session:
UserObj : User = auth.GetCurrentUser()
if UserObj is not None:
session.pop("not-approved-viewer")
return response
@app.context_processor
def inject_user():
if ".ROBLOSECURITY" in request.cookies:
AuthenticatedUser : User = auth.GetCurrentUser()
if AuthenticatedUser is None:
return {}
def award_daily_login_bonus():
if redis_controller.get(f"daily_login_bonus:{str(AuthenticatedUser.id)}") is not None:
return
if AuthenticatedUser.created > datetime.utcnow() - timedelta( days = 1 ):
return
if GameSessionLog.query.filter_by(user_id=AuthenticatedUser.id).filter( GameSessionLog.joined_at > datetime.utcnow() - timedelta( days = 3 ) ).first() is None:
return
redis_controller.setex(f"daily_login_bonus:{str(AuthenticatedUser.id)}", 60 * 60 * 24 ,"1")
IncrementTargetBalance(AuthenticatedUser, 10, 1)
transactions.CreateTransaction(
Reciever = AuthenticatedUser,
Sender = User.query.filter_by(id=1).first(),
CurrencyAmount = 10,
CurrencyType = 1,
TransactionType = TransactionType.BuildersClubStipend,
CustomText = "Daily Login Bonus"
)
if redis_controller.exists(f"award_daily_login_bonus_attempt:{str(AuthenticatedUser.id)}") is None:
redis_controller.setex(f"award_daily_login_bonus_attempt:{str(AuthenticatedUser.id)}", 60, "1")
award_daily_login_bonus()
unreadMessages = Message.query.filter_by(recipient_id=AuthenticatedUser.id, read=False).count()
inboundTrades = UserTrade.query.filter_by(recipient_userid=AuthenticatedUser.id, status=TradeStatus.Pending).count()
friendRequests = FriendRequest.query.filter_by(requestee_id=AuthenticatedUser.id).count()
AuthenticatedUser.lastonline = datetime.utcnow()
db.session.commit()
userRobux, userTix = GetUserBalance(AuthenticatedUser)
isAdministrator = IsUserAnAdministrator( AuthenticatedUser )
PendingAssetsCount = 0
if isAdministrator:
PendingAssetsCount = GetAmountOfPendingAssets()
return {
"currentuser": {
"id": AuthenticatedUser.id,
"username": AuthenticatedUser.username,
"robux": userRobux,
"tix": userTix,
"unread_messages": unreadMessages,
"inbound_trades": inboundTrades,
"friend_requests": friendRequests,
"is_admin": isAdministrator,
"pending_asset_count": PendingAssetsCount
},
}
return {}
@app.context_processor
def inject_website_wide_message():
if redis_controller.exists("website_wide_message"):
url_pattern = re.compile(r'(https?://\S+)')
website_message = website_wide_message=redis_controller.get("website_wide_message")
website_message = url_pattern.sub(r'<a href="\1">\1</a>', website_message)
return dict(website_wide_message=website_message)
return {}
@app.context_processor
def injecthcaptcha_sitekey():
return dict(turnstilekey=Config.CloudflareTurnstileSiteKey)
@app.route('/')
def main():
if "user" in session:
return redirect("/home")
else:
return redirect("/login")
@app.errorhandler(404)
def page_not_found(e):
BrowserUserAgent = request.headers.get('User-Agent')
if BrowserUserAgent is not None:
if "RobloxStudio" in BrowserUserAgent:
return "<h1 style='margin:0;'>404 - Page not found</h1><br><a style='margin:0;' href='/ide/welcome'>Return to homepage</a>"
#logging.error(f"404 - {request.path}")
return render_template("404.html"), 404
@app.errorhandler(403)
def page_forbidden(e):
BrowserUserAgent = request.headers.get('User-Agent')
if BrowserUserAgent is not None:
if "RobloxStudio" in BrowserUserAgent:
return "<h1 style='margin:0;'>403 - Forbidden</h1><br><a style='margin:0;' href='/ide/welcome'>Return to homepage</a>"
return render_template("403.html"), 403
@app.errorhandler(405)
def page_forbidden(e):
BrowserUserAgent = request.headers.get('User-Agent')
if BrowserUserAgent is not None:
if "RobloxStudio" in BrowserUserAgent:
return "<h1 style='margin:0;'>405 - Method Not Allowed</h1><br><a style='margin:0;' href='/ide/welcome'>Return to homepage</a>"
return render_template("405.html"), 405
@app.errorhandler(500)
def page_internal_server_error(e):
exc_type, exc_value, exc_traceback = sys.exc_info()
PageRoute = request.path
return render_template("500.html", error={
"type": exc_type,
"value": exc_value,
"traceback": str(traceback.format_exc())
}, page=PageRoute), 500
@app.errorhandler(429)
def ratelimit_handler(e):
return jsonify({"error": "You are being rate limited.", "message": "You are being rate limited.", "success": False}), 429
if config_class.ASSETMIGRATOR_USE_PROXIES:
redis_controller.delete("assetmigrator_proxies")
with open(config_class.ASSETMIGRATOR_PROXY_LIST_LOCATION, "r") as f:
LoadedProxies = 0
for line in f:
if line.strip() != "":
LoadedProxies += 1
redis_controller.sadd("assetmigrator_proxies", line.strip())
logging.info(f"Loaded {LoadedProxies} proxies")
try:
if not redis_controller.exists("coregui_ids_cooldown"):
with app.app_context():
redis_controller.setex("coregui_ids_cooldown", 60 * 60, "1")
AllCoreGui = os.listdir("./app/files/CoreGui")
redis_controller.delete("coregui_ids")
for CoreGui in AllCoreGui:
try:
redis_controller.sadd("coregui_ids", int(CoreGui))
except:
logging.error(f"Failed to load CoreGui file {CoreGui}")
AssetObj : Asset = Asset.query.filter_by(id=int(CoreGui)).first()
if AssetObj is None:
AssetObj = Asset(
name = "CoreGui",
created_at = datetime.utcnow(),
updated_at = datetime.utcnow(),
asset_type = AssetType.Lua,
creator_id = 1,
creator_type = 0,
moderation_status = 0
)
AssetObj.id = int(CoreGui)
db.session.add(AssetObj)
db.session.commit()
logging.info(f"Created CoreGui asset {CoreGui}")
CoreGuiContent = open(f"./app/files/CoreGui/{CoreGui}", "r").read()
if int(CoreGui) in TwelveClientAssets:
CoreGuiContent = signscript.signUTF8(f"%{CoreGui}%\r\n{CoreGuiContent}", addNewLine=False, twelveclient=True)
else:
CoreGuiContent = signscript.signUTF8(f"--rbxassetid%{CoreGui}%\r\n{CoreGuiContent}", addNewLine=False)
CoreGuiHash = hashlib.sha512(CoreGuiContent.encode("utf-8")).hexdigest()
AssetVersionObj : AssetVersion = assetversion.GetLatestAssetVersion( AssetObj )
if AssetVersionObj is None or AssetVersionObj.content_hash != CoreGuiHash:
s3helper.UploadBytesToS3(
CoreGuiContent.encode("utf-8"),
CoreGuiHash
)
assetversion.CreateNewAssetVersion(
AssetObj,
CoreGuiHash,
CoreGuiContent,
)
logging.info(f"Loaded {len(AllCoreGui)} CoreGui files")
except Exception as e:
logging.error(f"Failed to load CoreGui files: {e}")
logging.info("App created")
return app

70
app/enums/AssetType.py Normal file
View File

@ -0,0 +1,70 @@
from enum import Enum
class AssetType( Enum ):
Image = 1
TShirt = 2
Audio = 3
Mesh = 4
Lua = 5
HTML = 6
Text = 7
Hat = 8
Place = 9
Model = 10
Shirt = 11
Pants = 12
Decal = 13
Avatar = 16
Head = 17
Face = 18
Gear = 19
Badge = 21
GroupEmblem = 22
Animation = 24
Torso = 27
RightArm = 28
LeftArm = 29
LeftLeg = 30
RightLeg = 31
Package = 32
YoutubeVideo = 33
GamePass = 34
App = 35
Code = 37
Plugin = 38
SolidModel = 39
MeshPart = 40
HairAccessory = 41
FaceAccessory = 42
NeckAccessory = 43
ShoulderAccessory = 44
FrontAccessory = 45
BackAccessory = 46
WaistAccessory = 47
ClimbAnimation = 48
DeathAnimation = 49
FallAnimation = 50
IdleAnimation = 51
JumpAnimation = 52
RunAnimation = 53
SwimAnimation = 54
WalkAnimation = 55
PoseAnimation = 56
EarAccessory = 57
EyeAccessory = 58
EmoteAnimation = 61
Video = 62
TShirtAccessory = 64
ShirtAccessory = 65
PantsAccessory = 66
JacketAccessory = 67
SweaterAccessory = 68
ShortsAccessory = 69
LeftShoeAccessory = 70
RightShoeAccessory = 71
DressSkirtAccessory = 72
FontFamily = 73
EyebrowAccessory = 76
EyelashAccessory = 77
MoodAnimation = 78
DynamicHead = 79

10
app/enums/BanType.py Normal file
View File

@ -0,0 +1,10 @@
from enum import Enum
class BanType(Enum):
Warning = 0
Day1Ban = 1
Day3Ban = 2
Day7Ban = 3
Day14Ban = 4
Day30Ban = 5
Deleted = 6

6
app/enums/ChatStyle.py Normal file
View File

@ -0,0 +1,6 @@
from enum import Enum
class ChatStyle(Enum):
Classic = 0
Bubble = 1
ClassicAndBubble = 2

View File

@ -0,0 +1,17 @@
from enum import Enum
class CryptomusPaymentStatus(Enum):
Paid = 0
PaidOver = 1
WrongAmount = 2
Process = 3
ConfirmCheck = 4
WrongAmountWaiting = 5
Check = 6
Fail = 7
Cancel = 8
SystemFail = 9
RefundProcess = 10
RefundFail = 11
RefundPaid = 12
Locked = 13

View File

@ -0,0 +1,8 @@
from enum import Enum
class GiftcardType(Enum):
Outrageous_BuildersClub = 0
Turbo_BuildersClub = 1
RobuxCurrency = 2
TixCurrency = 3
Item = 4

View File

@ -0,0 +1,7 @@
from enum import Enum
class LimitedItemTransferMethod( Enum ):
Purchase = 0
Trade = 1
WonByLottery = 2
ForcedTransfer = 3

View File

@ -0,0 +1,7 @@
from enum import Enum
class MembershipType( Enum ):
NonBuildersClub = 0
BuildersClub = 1
TurboBuildersClub = 2
OutrageousBuildersClub = 3

View File

@ -0,0 +1,6 @@
from enum import Enum
class PlaceRigChoice( Enum ):
UserChoice = 0
ForceR6 = 1
ForceR15 = 2

17
app/enums/PlaceYear.py Normal file
View File

@ -0,0 +1,17 @@
from enum import Enum
class PlaceYear( Enum ):
Nine = 2009
Ten = 2010
Eleven = 2011
Twelve = 2012
Thirteen = 2013
Fourteen = 2014
Fifteen = 2015
Sixteen = 2016
Seventeen = 2017
Eighteen = 2018
Nineteen = 2019
Twenty = 2020
TwentyOne = 2021
TwentyTwo = 2022

8
app/enums/TradeStatus.py Normal file
View File

@ -0,0 +1,8 @@
from enum import Enum
class TradeStatus( Enum ):
Pending = 0
Accepted = 1
Declined = 2
Expired = 3
Cancelled = 4

View File

@ -0,0 +1,9 @@
from enum import Enum
class TransactionType( Enum ):
Purchase = 0
Sale = 1
GroupPayout = 2
BuildersClubStipend = 3
Commisions = 4
Trade = 5

708
app/extensions.py Normal file
View File

@ -0,0 +1,708 @@
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import or_, and_, text
from flask_limiter import Limiter, HEADERS
from flask_apscheduler import APScheduler
from flask import request
from flask_cors import CORS
import redis
import datetime
from config import Config
import logging
import time
from flask_wtf.csrf import CSRFProtect
from app.enums.AssetType import AssetType
csrf = CSRFProtect()
db = SQLAlchemy()
Config = Config()
CORS = CORS()
def get_remote_address() -> str:
cloudflare = request.headers.get("CF-Connecting-IP")
if cloudflare is not None:
return cloudflare
return request.remote_addr or "127.0.0.1"
def get_user_id() -> str:
"""
Gets the UserId for the current request
:return: UserId or -1 if not logged in
"""
if ".ROBLOSECURITY" in request.cookies:
return "user_id:-1"
from app.util.auth import GetTokenInfo
UserTokenInfo = GetTokenInfo( request.cookies.get(".ROBLOSECURITY", default = "None", type = str) )
if UserTokenInfo is None:
return "user_id:-1"
return f"user_id:{ UserTokenInfo[0] }"
limiter = Limiter(
get_remote_address,
storage_uri=Config.FLASK_LIMITED_STORAGE_URI,
strategy="fixed-window-elastic-expiry",
headers_enabled=True,
key_prefix = "address_limiter"
)
user_limiter = Limiter(
key_func = get_user_id,
storage_uri=Config.FLASK_LIMITED_STORAGE_URI,
strategy="fixed-window-elastic-expiry",
headers_enabled=True,
key_prefix = "user_limiter"
)
redis_controller = Config.REDIS_CLIENT
scheduler = APScheduler()
logging.getLogger('apscheduler').setLevel(logging.ERROR)
@scheduler.task('interval', id='item_release_pool_releaser', seconds=60, misfire_grace_time=60)
def item_release_pool_releaser():
with scheduler.app.app_context():
import time
import json
import random
import uuid
import requests
from app.models.asset import Asset
from app.pages.admin.admin import GetNextItemDropDateTime, SetAssetOffsaleJob
if redis_controller.get("item_release_pool_releaser") is not None:
return
redis_controller.set("item_release_pool_releaser", "busy", ex=120)
if redis_controller.llen("ItemReleasePool:Items") <= 0:
redis_controller.set("ItemReleasePool:LastDropTimestamp", value = str(round(time.time())))
return
if datetime.datetime.utcnow() < GetNextItemDropDateTime():
return
random.seed( time.time() )
RandomIndex = random.randint( 0, redis_controller.llen("ItemReleasePool:Items") - 1 )
SelectedAssetId = redis_controller.lindex( "ItemReleasePool:Items", RandomIndex )
if SelectedAssetId is None:
logging.warning("item_release_pool_releaser failed to selected random asset, lindex returned None")
return
redis_controller.lrem("ItemReleasePool:Items", count = 0, value = SelectedAssetId)
try:
SelectedAssetId = int(SelectedAssetId)
except Exception as e:
logging.warn(f"item_release_pool_releaser failed to cast string to integer, value: {SelectedAssetId}")
return
AssetMetadata = redis_controller.get(f"ItemReleasePool:Item_Metadata:{SelectedAssetId}")
if AssetMetadata is None:
logging.warn(f"item_release_pool_releaser failed to get asset metadata for {SelectedAssetId}")
return
try:
AssetMetadata = json.loads(AssetMetadata)
except Exception as e:
logging.warn(f"item_release_pool_releaser failed to parse json from item metadata {SelectedAssetId}, {str(e)}")
return
AssetObj : Asset = Asset.query.filter_by( id = SelectedAssetId ).first()
if AssetObj is None:
logging.warn(f"item_release_pool_releaser asset id {SelectedAssetId} does not exist")
return
AssetObj.name = AssetMetadata["Name"]
AssetObj.description = AssetMetadata["Description"]
AssetObj.price_robux = AssetMetadata["RobuxPrice"]
AssetObj.price_tix = AssetMetadata["TicketsPrice"]
AssetObj.is_limited = AssetMetadata["IsLimited"]
AssetObj.is_limited_unique = AssetMetadata["IsLimitedUnique"]
AssetObj.serial_count = AssetMetadata["SerialCount"]
AssetObj.moderation_status = 0
AssetObj.updated_at = datetime.datetime.utcnow()
AssetObj.is_for_sale = True
if AssetMetadata["OffsaleAfter"] is not None:
OffsaleAfter = datetime.timedelta( seconds = AssetMetadata["OffsaleAfter"] )
AssetOffsaleAt = datetime.datetime.utcnow() + OffsaleAfter
if redis_controller.exists(f"APSchedulerTaskJobUUID:{str(AssetObj.id)}"):
try:
scheduler.remove_job(redis_controller.get(f"APSchedulerTaskJobUUID:{str(AssetObj.id)}"))
except:
logging.warning(f"Failed to remove job {redis_controller.get(f'APSchedulerTaskJobUUID:{str(AssetObj.id)}')}")
APSchedulerTaskJobUUID = str(uuid.uuid4())
scheduler.add_job(id=APSchedulerTaskJobUUID, func=SetAssetOffsaleJob, trigger='date', run_date=AssetOffsaleAt, args=[AssetObj.id])
redis_controller.set(f"APSchedulerTaskJobUUID:{str(AssetObj.id)}", APSchedulerTaskJobUUID)
logging.info(f"Asset {str(AssetObj.id)} has been set to go offsale at {str(AssetOffsaleAt)}, job UUID: {APSchedulerTaskJobUUID}")
AssetObj.offsale_at = AssetOffsaleAt
db.session.commit()
logging.info(f"Released Item {AssetObj.id}")
redis_controller.set("ItemReleasePool:LastDropTimestamp", value = str(round(time.time())))
try:
requests.post(
Config.ITEMRELEASER_DISCORD_WEBHOOK,
json = {
"content": f"<@&{Config.ITEMRELEASER_ITEM_PING_ROLE_ID}> New Item Drop!",
"allowed_mentions": {
"replied_user": False,
"parse": [],
"roles": [
Config.ITEMRELEASER_ITEM_PING_ROLE_ID
]
},
"username": "Automatic Item Release Bot",
"avatar_url": f"{Config.BaseURL}/Thumbs/Head.ashx?x=48&y=48&userId=1",
"embeds": [{
"type": "rich",
"title": AssetObj.name,
"description": AssetObj.description,
"color": 0x00ff62,
"fields": [
{
"name": "Robux Price",
"value": f"R${AssetObj.price_robux}",
"inline": True
},
{
"name": "Tickets Price",
"value": f"T${AssetObj.price_tix}",
"inline": True
},
{
"name": "Limited Unique",
"value": str(AssetObj.is_limited_unique),
"inline": True
},
{
"name": "Serial Count",
"value": "None" if AssetObj.serial_count == 0 else str(AssetObj.serial_count),
"inline": True
},
{
"name": "Offsale in",
"value": "Never" if AssetObj.offsale_at is None else f"<t:{int(AssetObj.offsale_at.timestamp())}:R>",
"inline": True
}
],
"thumbnail": {
"url": f"{Config.BaseURL}/Thumbs/Asset.ashx?x=180&y=180&assetId={AssetObj.id}",
"height": 120,
"width": 120
},
"url": f"{Config.BaseURL}/catalog/{AssetObj.id}/--",
"footer": {
"text": f"Syntax Item Release Bot"
},
"timestamp": datetime.datetime.utcnow().isoformat()
}]
}
)
except Exception as e:
logging.warn(f"item_release_pool_releaser failed to send Discord Webhook message, {e}")
@scheduler.task('interval', id='builders_club_stipend', seconds=120, misfire_grace_time=60)
def builders_club_stipend():
with scheduler.app.app_context():
if redis_controller.get("builders_club_stipend") is not None:
return
redis_controller.set("builders_club_stipend", "busy", ex=120)
from app.models.user_membership import UserMembership
from app.models.user import User
from app.models.game_session_log import GameSessionLog
from app.enums.MembershipType import MembershipType
from app.enums.TransactionType import TransactionType
from app.services.economy import IncrementTargetBalance
from app.util.transactions import CreateTransaction
from app.util.membership import GetUserMembership, RemoveUserMembership, GiveUserMembership
from app.pages.messages.messages import CreateSystemMessage
from app.models.linked_discord import LinkedDiscord
# Get all users who membership has expired
ExpiredMemberships : list[UserMembership] = UserMembership.query.filter(
UserMembership.expiration < datetime.datetime.utcnow()
)
for MembershipObj in ExpiredMemberships:
try:
if MembershipObj.membership_type == MembershipType.BuildersClub:
# Check if their discord is still linked
LinkedDiscordObj : LinkedDiscord = LinkedDiscord.query.filter_by(user_id=MembershipObj.user_id).first()
if LinkedDiscordObj is not None:
# Give them a free month of BC
MembershipObj.membership_type = MembershipType.BuildersClub
MembershipObj.expiration = datetime.datetime.utcnow() + datetime.timedelta(days=31)
db.session.commit()
continue
elif MembershipObj.membership_type == MembershipType.TurboBuildersClub or MembershipObj.membership_type == MembershipType.OutrageousBuildersClub:
UserObj : User = User.query.filter_by(id=MembershipObj.user_id).first()
CreateSystemMessage(
subject = "Builders Club membership expired",
message = f"""Hello {UserObj.username},
This is an automated message to inform you that your Builders Club membership has expired, if you wish to renew your membership you can do so by following the instructions below
- For Turbo Builders Club members:
- You can renew your membership in the Discord Server by running the '/claim-turbo' command in the #bot-commands channel, this does require you to still be boosting our Discord Server
- For Outrageous Builders Club members:
- You can renew your membership by donating $5 to our Ko-Fi page https://ko-fi.com/syntaxeco
If you have any questions or concerns, please contact our support in our Discord Server
Sincerely,
The SYNTAX Team""",
userid = MembershipObj.user_id
)
# Remove the membership
RemoveUserMembership(MembershipObj.user_id)
LinkedDiscordObj : LinkedDiscord = LinkedDiscord.query.filter_by(user_id=MembershipObj.user_id).first()
if LinkedDiscordObj is not None:
GiveUserMembership(MembershipObj.user_id, MembershipType.BuildersClub, expiration=datetime.timedelta(days=31))
except Exception as e:
logging.info(f"Error while removing expired membership, Exception: {str(e)}")
continue
WaitingMemberships : list[UserMembership] = UserMembership.query.filter(
or_(
UserMembership.membership_type == MembershipType.TurboBuildersClub,
UserMembership.membership_type == MembershipType.OutrageousBuildersClub
)
).filter(
UserMembership.next_stipend < datetime.datetime.utcnow()
).all()
if len(WaitingMemberships) > 0:
logging.info(f"Found {len(WaitingMemberships)} users waiting for stipend")
for MembershipObj in WaitingMemberships:
UserObj : User = User.query.filter_by(id=MembershipObj.user_id).first()
if UserObj is None:
continue
if MembershipObj.membership_type == MembershipType.TurboBuildersClub:
IncrementTargetBalance(UserObj, 45, 0)
MembershipObj.next_stipend = MembershipObj.next_stipend + datetime.timedelta(hours=24)
CreateTransaction(
Reciever = UserObj,
Sender = User.query.filter_by(id=1).first(),
CurrencyAmount = 45,
CurrencyType = 0,
TransactionType = TransactionType.BuildersClubStipend,
AssetId = None,
CustomText = "Builders Club Stipend"
)
logging.info(f"Sent stipend to {UserObj.username} ({UserObj.id})")
elif MembershipObj.membership_type == MembershipType.OutrageousBuildersClub:
IncrementTargetBalance(UserObj, 80, 0)
MembershipObj.next_stipend = MembershipObj.next_stipend + datetime.timedelta(hours=24)
CreateTransaction(
Reciever = UserObj,
Sender = User.query.filter_by(id=1).first(),
CurrencyAmount = 80,
CurrencyType = 0,
TransactionType = TransactionType.BuildersClubStipend,
AssetId = None,
CustomText = "Builders Club Stipend"
)
logging.info(f"Sent stipend to {UserObj.username} ({UserObj.id})")
db.session.commit()
WaitingMemberships : list[UserMembership] = UserMembership.query.filter(
UserMembership.membership_type == MembershipType.BuildersClub
).filter(
UserMembership.next_stipend < datetime.datetime.utcnow()
).join(User).filter(
User.lastonline > datetime.datetime.utcnow() - datetime.timedelta(hours=24)
).all()
for MembershipObj in WaitingMemberships:
UserObj : User = User.query.filter_by(id=MembershipObj.user_id).first()
if UserObj is None:
continue
#if GameSessionLog.query.filter_by(user_id=UserObj.id).filter( GameSessionLog.joined_at > datetime.datetime.utcnow() - datetime.timedelta( days = 2 ) ).first() is None:
# MembershipObj.next_stipend = datetime.datetime.utcnow() + datetime.timedelta(hours=6)
# db.session.commit()
# return
IncrementTargetBalance(UserObj, 10, 0)
CreateTransaction(
Reciever = UserObj,
Sender = User.query.filter_by(id=1).first(),
CurrencyAmount = 10,
CurrencyType = 0,
TransactionType = TransactionType.BuildersClubStipend,
AssetId = None,
CustomText = "Builders Club Stipend"
)
MembershipObj.next_stipend = datetime.datetime.utcnow() + datetime.timedelta(hours=24)
logging.info(f"Sent stipend to {UserObj.username} ({UserObj.id})")
db.session.commit()
redis_controller.delete("builders_club_stipend")
@scheduler.task('interval', id='refresh_discord_token', seconds=300, misfire_grace_time=900)
def refresh_discord_token():
with scheduler.app.app_context():
if redis_controller.get("refresh_discord_token") is not None:
return
redis_controller.set("refresh_discord_token", "busy", ex=120)
from app.models.linked_discord import LinkedDiscord
from app.models.user import User
from app.models.user_membership import UserMembership
from app.enums.MembershipType import MembershipType
from app.util.membership import GetUserMembership, RemoveUserMembership
from app.pages.messages.messages import CreateSystemMessage
from app.util.discord import RefreshAccessToken, GetUserInfoFromToken, DiscordUserInfo, UnexpectedStatusCode, MissingScope
def SendUnlinkedNotification( UserId : int , Reason : str ):
UserObj : User = User.query.filter_by(id=UserId).first()
if UserObj is None:
return
CreateSystemMessage(
subject = "Discord Account unlinked",
message = f"""Hello {UserObj.username},
Your discord account was unlinked from your account because \"{Reason}\", if you currently have a Builders Club membership it will be automatically removed from your account until you link your discord account again.
If you have any questions or concerns, please contact our support in our Discord Server
Sincerely,
The SYNTAX Team""",
userid = UserObj.id
)
CurrentUserMembership : MembershipType = GetUserMembership(UserObj)
if CurrentUserMembership == MembershipType.BuildersClub:
# Remove the membership
RemoveUserMembership(UserObj)
# Get all users who has a linked discord account and has a discord_expiry that is less than the current time
WaitingDiscordLinks : list[LinkedDiscord] = LinkedDiscord.query.filter(
LinkedDiscord.discord_expiry < datetime.datetime.utcnow()
)
for LinkedDiscordObj in WaitingDiscordLinks:
try:
try:
DiscordOAuth2TokenExchangeResponseJSON = RefreshAccessToken(LinkedDiscordObj.discord_refresh_token)
except UnexpectedStatusCode as e:
db.session.delete(LinkedDiscordObj)
SendUnlinkedNotification(LinkedDiscordObj.user_id, f"UnexpectedStatusCodeException_RefreshAccessToken: {str(e)}")
continue
except MissingScope as e:
db.session.delete(LinkedDiscordObj)
SendUnlinkedNotification(LinkedDiscordObj.user_id, f"MissingScopeException_RefreshAccessToken: {str(e)}")
continue
# Get user info
try:
DiscordUserInfoObj : DiscordUserInfo = GetUserInfoFromToken(DiscordOAuth2TokenExchangeResponseJSON["access_token"])
except UnexpectedStatusCode as e:
db.session.delete(LinkedDiscordObj)
SendUnlinkedNotification(LinkedDiscordObj.user_id, f"UnexpectedStatusCodeException_RefreshUserInfo: {str(e)}")
continue
if DiscordUserInfoObj is None:
continue
LinkedDiscordObj.discord_access_token = DiscordOAuth2TokenExchangeResponseJSON["access_token"]
LinkedDiscordObj.discord_refresh_token = DiscordOAuth2TokenExchangeResponseJSON["refresh_token"]
LinkedDiscordObj.discord_expiry = datetime.datetime.utcnow() + datetime.timedelta(seconds=DiscordOAuth2TokenExchangeResponseJSON["expires_in"])
LinkedDiscordObj.discord_username = DiscordUserInfoObj.Username
LinkedDiscordObj.discord_discriminator = DiscordUserInfoObj.Discriminator
LinkedDiscordObj.discord_avatar = DiscordUserInfoObj.AvatarHash
LinkedDiscordObj.last_updated = datetime.datetime.utcnow()
db.session.commit()
except Exception as e:
logging.info(f"Error while refreshing discord token, Exception: {str(e)}")
continue
@scheduler.task('interval', id='migrate_assets', seconds=120, misfire_grace_time=60)
def migrate_assets():
with scheduler.app.app_context():
if redis_controller.get("migrate_assets_lock") is not None:
return
redis_controller.set("migrate_assets_lock", "busy", ex=120)
from app.routes.asset import migrateAsset, AddAssetToMigrationQueue, AddAudioAssetToAudioMigrationQueue
from app.routes.asset import NoPermissionException, AssetDeliveryAPIFailedException, AssetOnCooldownException, EconomyAPIFailedException, RatelimittedReachedException, AssetNotFoundException, AssetNotAllowedException
from app.models.asset import Asset
EconomyFailedCount : int = 0
while True:
if redis_controller.llen("migrate_assets_queue") == 0:
break
# Get an asset from the queue
AssetId : int = int(redis_controller.lpop("migrate_assets_queue"))
if AssetId <= 1:
continue
try:
logging.info(f"AutoAssetMigrator: Auto migrating asset {AssetId}, {redis_controller.llen('migrate_assets_queue')} assets left in queue")
migrateAsset(AssetId, throwException=True)
except RatelimittedReachedException:
logging.info("AutoAssetMigrator: Ratelimit reached while auto migrating assets, stopping")
AddAssetToMigrationQueue(AssetId, bypassQueueLimit=False)
break
except EconomyAPIFailedException:
EconomyFailedCount += 1
if EconomyFailedCount >= 4:
logging.info("AutoAssetMigrator: Economy API failed while auto migrating assets, stopping")
#AddAssetToMigrationQueue(AssetId, bypassQueueLimit=False)
break
else:
logging.info("AutoAssetMigrator: Economy API failed while auto migrating assets, retrying")
continue
except NoPermissionException:
logging.info(f"AutoAssetMigrator: No permission to migrate asset from Roblox, assetId: {AssetId}")
continue
except AssetDeliveryAPIFailedException:
logging.info(f"AutoAssetMigrator: AssetDelivery API failed while migrating asset, assetId: {AssetId}")
continue
except AssetOnCooldownException:
logging.info(f"AutoAssetMigrator: Asset is on cooldown, assetId: {AssetId}")
continue
except AssetNotAllowedException:
logging.info(f"AutoAssetMigrator: Asset is not allowed, assetId: {AssetId}")
continue
except AssetNotFoundException:
logging.info(f"AutoAssetMigrator: Asset not found, assetId: {AssetId}")
continue
except Exception as e:
logging.info(f"AutoAssetMigrator: Unknown error while migrating asset, Exception: {str(e)} ,assetId: {AssetId}")
continue
except:
logging.info(f"AutoAssetMigrator: Unknown error while migrating asset, assetId: {AssetId}")
continue
while True:
# Migrating audios have a different queue
if redis_controller.llen("migrate_audio_assets_queue") == 0:
break
AssetId : int = int(redis_controller.lpop("migrate_audio_assets_queue"))
if AssetId <= 1:
continue
try:
AssociatedPlaceId : int = int(redis_controller.get(f"audio_asset:{AssetId}:placeid"))
if AssociatedPlaceId <= 1:
continue
except:
continue
logging.info(f"AutoAssetMigrator: Auto migrating audio asset {AssetId}, {redis_controller.llen('migrate_audio_assets_queue')} assets left in queue")
try:
migrateAsset(AssetId, allowedTypes = [3], throwException=True, bypassCooldown = True, attemptSoundWithPlaceId = AssociatedPlaceId)
except RatelimittedReachedException:
logging.info("AutoAssetMigrator: Ratelimit reached while auto migrating assets, stopping")
AddAudioAssetToAudioMigrationQueue(AssetId, bypassQueueLimit=False, placeId = AssociatedPlaceId)
break
except EconomyAPIFailedException:
EconomyFailedCount += 1
if EconomyFailedCount >= 4:
logging.info("AutoAssetMigrator: Economy API failed while auto migrating assets, stopping")
#AddAssetToMigrationQueue(AssetId, bypassQueueLimit=False)
break
else:
logging.info("AutoAssetMigrator: Economy API failed while auto migrating assets, retrying")
continue
except NoPermissionException:
logging.info(f"AutoAssetMigrator: No permission to migrate asset from Roblox, assetId: {AssetId}")
continue
except AssetDeliveryAPIFailedException:
logging.info(f"AutoAssetMigrator: AssetDelivery API failed while migrating asset, assetId: {AssetId}")
continue
except AssetOnCooldownException:
logging.info(f"AutoAssetMigrator: Asset is on cooldown, assetId: {AssetId}")
continue
except AssetNotAllowedException:
logging.info(f"AutoAssetMigrator: Asset is not allowed, assetId: {AssetId}")
continue
except AssetNotFoundException:
logging.info(f"AutoAssetMigrator: Asset not found, assetId: {AssetId}")
continue
except Exception as e:
logging.info(f"AutoAssetMigrator: Unknown error while migrating asset, Exception: {str(e)} ,assetId: {AssetId}")
continue
except:
logging.info(f"AutoAssetMigrator: Unknown error while migrating asset, assetId: {AssetId}")
continue
redis_controller.delete("migrate_assets_lock")
@scheduler.task('interval', id='fix_thumbnails', seconds = 600, misfire_grace_time=60)
def fix_thumbnails():
with scheduler.app.app_context():
if redis_controller.get("fix_thumbnails") is not None:
return
redis_controller.set("fix_thumbnails", "busy", ex=60)
from app.models.gameservers import GameServer
from app.models.asset_thumbnail import AssetThumbnail
from app.models.asset_version import AssetVersion
from app.models.asset import Asset
from app.models.user import User
from app.models.user_thumbnail import UserThumbnail
from app.models.place_icon import PlaceIcon
from app.util.assetversion import GetLatestAssetVersion
from app.routes.thumbnailer import TakeThumbnail, TakeUserThumbnail
assetVersions = AssetVersion.query.filter(
~db.session.query(AssetThumbnail.asset_id).filter(
AssetThumbnail.asset_id == AssetVersion.asset_id,
).filter(
AssetThumbnail.asset_version_id == AssetVersion.version
).exists()
).join(Asset, Asset.id == AssetVersion.asset_id).filter(
and_(
Asset.moderation_status == 0,
Asset.asset_type != AssetType.Place
)
).distinct(AssetVersion.asset_id).order_by(AssetVersion.asset_id, AssetVersion.version.desc()).all()
if len(assetVersions) > 0:
AssetTypeBrokenCounter = {}
logging.info(f"Found {len(assetVersions)} broken thumbnails")
SuccessCount = 0
for assetVersion in assetVersions:
AssetObj : Asset = Asset.query.filter_by(id=assetVersion.asset_id).first()
if AssetObj is None:
continue
if AssetObj.asset_type == AssetType.Place:
continue
if AssetObj.moderation_status == 0:
LatestVersion : AssetVersion = GetLatestAssetVersion(AssetObj)
if LatestVersion is not assetVersion:
continue
Result = TakeThumbnail(assetVersion.asset_id)
if Result == "Thumbnail request sent":
SuccessCount += 1
else:
if AssetObj.asset_type.name in AssetTypeBrokenCounter:
AssetTypeBrokenCounter[AssetObj.asset_type.name] += 1
else:
AssetTypeBrokenCounter[AssetObj.asset_type.name] = 1
if SuccessCount >= 30:
logging.info(f"Stopping thumbnail fixer, reached 30 thumbnails fixed")
break
for key, value in AssetTypeBrokenCounter.items():
logging.info(f"Thumbnail fixer: {value} {key} assets failed to fix")
users = User.query.filter(User.id.notin_(db.session.query(UserThumbnail.userid))).all()
for user in users:
TakeUserThumbnail(user.id)
users = UserThumbnail.query.filter(or_(UserThumbnail.full_contenthash == None, UserThumbnail.headshot_contenthash == None)).all()
for user in users:
TakeUserThumbnail(user.userid)
Places : list[Asset] = Asset.query.filter(Asset.asset_type == AssetType.Place).filter(Asset.id.notin_(db.session.query(PlaceIcon.placeid))).all()
for PlaceObj in Places:
TakeThumbnail(PlaceObj.id, isIcon=True)
@scheduler.task('interval', id='heartbeat', seconds=15, misfire_grace_time=10)
def heartbeat():
with scheduler.app.app_context():
if redis_controller.get("heartbeat") is not None:
return # Another instance is already running
redis_controller.set("heartbeat", "busy", ex=14)
from app.models.gameservers import GameServer
from app.models.placeserver_players import PlaceServerPlayer
from app.models.placeservers import PlaceServer
from app.models.user import User
from app.services.gameserver_comm import perform_get, perform_post
from app.routes.jobreporthandler import HandleUserTimePlayed
import requests
import time
import threading
def HandlePlayerDeletion( playerObj : PlaceServerPlayer, placeId : int = None):
if placeId is not None:
try:
TotalTimePlayed = (datetime.datetime.utcnow() - playerObj.joinTime).total_seconds()
userObj : User = User.query.filter_by(id=playerObj.userid).first()
HandleUserTimePlayed(userObj, TotalTimePlayed, serverUUID = str(playerObj.serveruuid), placeId = placeId)
except Exception as e:
logging.warn(f"Failed to handle player deletion, Exception: {str(e)}")
db.session.delete(playerObj)
db.session.commit()
def RefreshServerInfo( server : GameServer ):
with scheduler.app.app_context():
server : GameServer = server
startTime = time.time()
statsRequest = None
try:
statsRequest = perform_get(
TargetGameserver = server,
Endpoint = "stats",
RequestTimeout = 6
)
except Exception as e:
# Mark the server as offline
server.isRCCOnline = False
server.thumbnailQueueSize = 0
server.RCCmemoryUsage = 0
server.heartbeatResponseTime = 0
if server.lastHeartbeat < datetime.datetime.utcnow() - datetime.timedelta(seconds=90):
# Delete all placeservers
GhostServers = PlaceServer.query.filter_by(originServerId=server.serverId).all()
for GhostServer in GhostServers:
GhostPlayers = PlaceServerPlayer.query.filter_by(serveruuid=GhostServer.serveruuid).all()
for GhostPlayer in GhostPlayers:
HandlePlayerDeletion(GhostPlayer, placeId = GhostServer.serverPlaceId)
db.session.delete(GhostServer)
db.session.commit()
return
if statsRequest is not None and statsRequest.status_code != 200:
# Mark the server as offline
server.isRCCOnline = False
server.thumbnailQueueSize = 0
server.RCCmemoryUsage = 0
server.heartbeatResponseTime = 0
if server.lastHeartbeat < datetime.datetime.utcnow() - datetime.timedelta(seconds=90):
# Delete all placeservers
GhostServers = PlaceServer.query.filter_by(originServerId=server.serverId).all()
for GhostServer in GhostServers:
GhostPlayers = PlaceServerPlayer.query.filter_by(serveruuid=GhostServer.serveruuid).all()
for GhostPlayer in GhostPlayers:
HandlePlayerDeletion(GhostPlayer, placeId = GhostServer.serverPlaceId)
db.session.delete(GhostServer)
db.session.commit()
return
if statsRequest is not None and statsRequest.status_code == 200:
endTime = time.time()
server.lastHeartbeat = datetime.datetime.utcnow()
server.heartbeatResponseTime = endTime - startTime
stats = statsRequest.json()
server.isRCCOnline = stats["RCCOnline"]
server.thumbnailQueueSize = stats["ThumbnailQueueSize"]
server.RCCmemoryUsage = stats["RCCMemoryUsage"]
db.session.commit()
if "RunningJobs" in stats:
for RunningJob in stats["RunningJobs"]:
PlaceServerObj : PlaceServer = PlaceServer.query.filter_by(serveruuid = RunningJob).first()
if PlaceServerObj is None:
logging.debug(f"CloseJob : Closing {RunningJob} because PlaceServer does not exist in database, Owner: {server.serverId} / {server.serverName}")
try:
CloseJobRequest = perform_post(
TargetGameserver = server,
Endpoint = "CloseJob",
JSONData = {
"jobid": RunningJob
}
)
except Exception as e:
continue
refresh_server_thread_list : list[threading.Thread] = []
servers : list[GameServer] = GameServer.query.all()
for server in servers:
refresh_server_thread_list.append(threading.Thread(target=RefreshServerInfo, args=(server,)))
for thread in refresh_server_thread_list:
thread.start()
for thread in refresh_server_thread_list:
thread.join()
GhostServers : list[PlaceServer] = PlaceServer.query.filter(PlaceServer.lastping < datetime.datetime.utcnow() - datetime.timedelta(seconds=60)).all()
for GhostServer in GhostServers:
GhostPlayers = PlaceServerPlayer.query.filter_by(serveruuid=GhostServer.serveruuid).all()
for GhostPlayer in GhostPlayers:
HandlePlayerDeletion(GhostPlayer, placeId = GhostServer.serverPlaceId)
db.session.delete(GhostServer)
GhostPlayers : list[PlaceServerPlayer] = PlaceServerPlayer.query.filter(PlaceServerPlayer.lastHeartbeat < datetime.datetime.utcnow() - datetime.timedelta(seconds=120)).all()
for GhostPlayer in GhostPlayers:
db.session.delete(GhostPlayer)
db.session.commit()
redis_controller.delete("heartbeat")

0
app/files/2012Studio.lua Normal file
View File

View File

@ -0,0 +1,367 @@
print("Config Load")
local placeId = {PlaceId}
local port = {NetworkPort}
local gameId = {PlaceId}
local CreatorId = {CreatorId}
local CreatorType = {CreatorType}
local TempPlaceAccessKey = "{TempPlaceAccessKey}"
local sleeptime = 1
local access = "{AuthToken}"
local JobId = "{JobId}"
local BaseURL = "http://www.syntax.eco"
local BaseDomain = "syntax.eco"
local timeout = 15
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local ScriptContext = game:GetService("ScriptContext")
print("Starting server for place "..tostring(placeId).." on port "..tostring(port).." and job id "..JobId)
------------------- UTILITY FUNCTIONS --------------------------
function waitForChild(parent, childName)
while true do
local child = parent:findFirstChild(childName)
if child then
return child
end
parent.ChildAdded:wait()
end
end
function onDied(victim, humanoid)
return
end
-----------------------------------END UTILITY FUNCTIONS -------------------------
-----------------------------------"CUSTOM" SHARED CODE----------------------------------
pcall(function() settings().Network.UseInstancePacketCache = true end)
pcall(function() settings().Network.UsePhysicsPacketCache = true end)
pcall(function() settings()["Task Scheduler"].PriorityMethod = Enum.PriorityMethod.AccumulatedError end)
settings().Network.PhysicsSend = Enum.PhysicsSendMethod.TopNErrors
settings().Network.ExperimentalPhysicsEnabled = true
settings().Network.WaitingForCharacterLogRate = 100
pcall(function() settings().Diagnostics:LegacyScriptMode() end)
-----------------------------------START GAME SHARED SCRIPT------------------------------
local RobloxPlacesList = {{
4378
}}
function isPlaceOwnedByRoblox( place_id )
for _, id in pairs( RobloxPlacesList ) do
if id == place_id then
return true
end
end
return false
end
local assetId = placeId -- might be able to remove this now
local scriptContext = game:GetService('ScriptContext')
scriptContext.ScriptsDisabled = true
game:SetPlaceID(assetId, isPlaceOwnedByRoblox(assetId))
pcall(function () if universeId ~= nil then game:SetUniverseId(universeId) end end)
pcall(function() game.JobId = JobId end)
game:GetService("ChangeHistoryService"):SetEnabled(false)
if CreatorType == 1 then
CreatorType = Enum.CreatorType.User
elseif CreatorType == 2 then
CreatorType = Enum.CreatorType.Group
else
CreatorType = Enum.CreatorType.User
end
pcall(function() game:SetCreatorID(CreatorId, CreatorType) end)
-- establish this peer as the Server
local ns = game:GetService("NetworkServer")
local badgeUrlFlagExists, badgeUrlFlagValue = pcall(function () return settings():GetFFlag("NewBadgeServiceUrlEnabled") end)
local newBadgeUrlEnabled = badgeUrlFlagExists and badgeUrlFlagValue
if BaseURL~=nil then
local apiProxyUrl = string.gsub(BaseURL, "http://www", "https://api") -- hack - passing domain (ie "sitetest1.robloxlabs.com") and appending "https://api." to it would be better
pcall(function() game:GetService("Players"):SetAbuseReportUrl(BaseURL .. "/AbuseReport/InGameChatHandler.ashx") end)
pcall(function() game:GetService("ScriptInformationProvider"):SetAssetUrl(BaseURL .. "/Asset/") end)
pcall(function() game:GetService("ContentProvider"):SetBaseUrl(BaseURL .. "/") end)
pcall(function() game:GetService("Players"):SetChatFilterUrl(BaseURL .. "/Game/ChatFilter.ashx") end)
if gameCode then
game:SetVIPServerId(tostring(gameCode))
end
game:GetService("BadgeService"):SetPlaceId(placeId)
if access~=nil then
game:GetService("BadgeService"):SetAwardBadgeUrl(BaseURL .. "/Game/Badge/AwardBadge.ashx?UserID=%d&BadgeID=%d&PlaceID=%d")
game:GetService("BadgeService"):SetHasBadgeUrl(BaseURL .. "/Game/Badge/HasBadge.ashx?UserID=%d&BadgeID=%d")
game:GetService("BadgeService"):SetIsBadgeDisabledUrl(BaseURL .. "/Game/Badge/IsBadgeDisabled.ashx?BadgeID=%d&PlaceID=%d")
game:GetService("FriendService"):SetMakeFriendUrl(BaseURL .. "/Friend/CreateFriend?firstUserId=%d&secondUserId=%d")
game:GetService("FriendService"):SetBreakFriendUrl(BaseURL .. "/Friend/BreakFriend?firstUserId=%d&secondUserId=%d")
game:GetService("FriendService"):SetGetFriendsUrl(BaseURL .. "/Friend/AreFriends?userId=%d")
game:GetService("FriendService"):SetCreateFriendRequestUrl(BaseURL .. "/Friend/CreateFriendRequest?requesterUserId=%d&requestedUserId=%d")
game:GetService("FriendService"):SetDeleteFriendRequestUrl(BaseURL .. "/Friend/DeleteFriendRequest?requesterUserId=%d&requestedUserId=%d")
end
game:GetService("BadgeService"):SetIsBadgeLegalUrl("")
game:GetService("InsertService"):SetBaseSetsUrl(BaseURL .. "/Game/Tools/InsertAsset.ashx?nsets=10&type=base")
game:GetService("InsertService"):SetUserSetsUrl(BaseURL .. "/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d")
game:GetService("InsertService"):SetCollectionUrl(BaseURL .. "/Game/Tools/InsertAsset.ashx?sid=%d")
game:GetService("InsertService"):SetAssetUrl(BaseURL .. "/Asset/?id=%d")
game:GetService("InsertService"):SetAssetVersionUrl(BaseURL .. "/Asset/?assetversionid=%d")
game:GetService("Players"):SetSaveDataUrl(BaseURL .. "/persistence/legacy/save?placeId=" .. tostring(placeId) .. "&userId=%d")
game:GetService("Players"):SetLoadDataUrl(BaseURL .. "/persistence/legacy/load?placeId=" .. tostring(placeId) .. "&userId=%d")
--pcall(function() loadfile(BaseURL .. "/Game/LoadPlaceInfo.ashx?PlaceId=" .. placeId)() end)
--pcall(function()
-- if access then
-- loadfile(BaseURL .. "/Game/PlaceSpecificScript.ashx?PlaceId=" .. placeId .. "&" .. access)()
-- end
-- end)
end
--pcall(function() game:GetService("NetworkServer"):SetIsPlayerAuthenticationRequired(true) end)
settings().Diagnostics.LuaRamLimit = 0
print("Configured Server")
local StartTime = tick()
local StoppingServer = false
local function GetPlayerByUserId( userId )
for _, player in pairs( Players:GetPlayers() ) do
if player.userId == userId then
return player
end
end
return nil
end
local function ReportServerPlayers(IgnoreThisPlayer)
--if StoppingServer then return end
local success, message = pcall(function()
local PlayerList = {{}}
for _, player in pairs(Players:GetChildren()) do
if player:IsA("Player") and player ~= IgnoreThisPlayer then
table.insert(PlayerList, {{
["UserId"] = player.userId,
["Name"] = player.Name
}})
end
end
local MessagePayload = HttpService:JSONEncode({{
["AuthToken"] = access,
["JobId"] = JobId,
["Players"] = PlayerList
}})
local ResponseData = game:HttpPost(BaseURL.."/internal/gameserver/reportplayers", MessagePayload, true, "application/json")
local ResponseJSON = HttpService:JSONDecode(ResponseData)
for _, player in pairs(ResponseJSON["bad"]) do -- This is a list of players that need to be kicked from the server
local TargetPlayer = GetPlayerByUserId(player)
if TargetPlayer ~= nil then
print("Kicking Player", tostring(player), "because was requested by backend")
TargetPlayer:Kick("There was an issue authenticating you, please contact support.")
TargetPlayer:Destroy()
end
end
end)
if not success then
print("ReportServerPlayers failed:", message)
end
end
local function ReportServerStats()
if StoppingServer then return end
local success, message = pcall(function()
local MessagePayload = HttpService:JSONEncode({{
["AuthToken"] = access,
["JobId"] = JobId,
["PlaceId"] = placeId,
["ServerAliveTime"] = (tick() - StartTime) + 1
}})
game:HttpPost(BaseURL.."/internal/gameserver/reportstats", MessagePayload, false, "application/json")
end)
if not success then
print("ReportServerStats failed:", message)
end
end
local function ReportServerShutdown()
local success, message = pcall(function()
local MessagePayload = HttpService:JSONEncode({{
["AuthToken"] = access,
["JobId"] = JobId,
["PlaceId"] = placeId,
["ServerAliveTime"] = tick() - StartTime
}})
game:HttpPost(BaseURL.."/internal/gameserver/reportshutdown", MessagePayload, false, "application/json")
end)
if not success then
print("ReportServerShutdown failed:", message)
end
end
local function AuthenticatePlayer( player )
local success, message = pcall(function()
local VerificationTicket = string.match( player.CharacterAppearance, BaseDomain.."/Asset/CharacterFetch.ashx%?userId=%d+%&t=(%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x)%&legacy=1$")
if VerificationTicket == nil then
print("Failed to get VerificationTicket for player", player.Name)
return false
end
local MessagePayload = HttpService:JSONEncode({{
["AuthToken"] = access,
["JobId"] = JobId,
["PlaceId"] = placeId,
["ServerAliveTime"] = tick() - StartTime,
["UserId"] = player.userId,
["VerificationTicket"] = VerificationTicket,
["CharacterAppearance"] = player.CharacterAppearance,
["Username"] = player.Name
}})
local ResponseData = game:HttpPost(BaseURL.."/internal/gameserver/verifyplayer", MessagePayload, true, "application/json")
local ResponseJSON = HttpService:JSONDecode(ResponseData)
return ResponseJSON["authenticated"]
end)
if not success then
print("AuthenticatePlayer failed:", message)
return false
end
return message
end
local function ShutdownServer()
StoppingServer = true
ReportServerShutdown()
ScriptContext.ScriptsDisabled = true
ns:Stop(1000)
game:Shutdown()
end
local TotalPlayersJoined = 0
game:GetService("Players").PlayerAdded:connect(function(player)
local StartTime = tick()
local CharacterURL
repeat
if string.find(player.CharacterAppearance, BaseDomain.."/Asset/CharacterFetch.ashx%?userId=%d+") then
CharacterURL = player.CharacterAppearance
end
wait(0.1)
until CharacterURL ~= nil or tick() - StartTime > 1
if CharacterURL == nil then
player:Kick("There was an issue authenticating you, please contact support.")
print("Failed to get UserId for player", player.Name, "because CharacterURL was nil")
return
end
local UserId = tonumber(string.match(CharacterURL, BaseDomain.."/Asset/CharacterFetch.ashx%?userId=(%d+)%&t=%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x%&legacy=1$"))
if UserId ~= nil then
player.userId = UserId
else
player:Kick("There was an issue authenticating you, please contact support.")
print("Failed to get UserId for player", player.Name, CharacterURL)
return
end
local IsPlayerAuthenticated = AuthenticatePlayer(player)
if IsPlayerAuthenticated then
player.DataComplexityLimit = 1024 * 1024 * 1
player.CharacterAppearance = BaseURL.."/Asset/CharacterFetch.ashx?userId="..tostring(player.userId).."&legacy=1"
ReportServerPlayers()
player:LoadData()
TotalPlayersJoined = TotalPlayersJoined + 1
local PlayerChangedConnection
PlayerChangedConnection = player.Changed:connect(function(property)
if property == "Name" then
ReportServerPlayers()
end
end)
coroutine.wrap(function()
while true do
wait(120)
if StoppingServer then break end
if player.Parent == nil then break end
pcall(function() player:SaveData() end)
end
end)()
else
player:Kick("There was an issue authenticating you, please contact support.")
print("Failed to authenticate player", player.Name)
return
end
end)
game:GetService("Players").PlayerRemoving:connect(function(player)
ReportServerPlayers(player)
pcall(function() player:SaveData() end)
local PlayerCount = #Players:GetPlayers()
if PlayerCount == 0 then
wait(10) -- Wait 10 seconds to see if anyone rejoins
PlayerCount = #Players:GetPlayers()
if PlayerCount == 0 then
ShutdownServer()
end
end
end)
local onlyCallGameLoadWhenInRccWithAccessKey = newBadgeUrlEnabled
wait()
-- load the game
print("Loading game")
local success, result = pcall(function()
game:Load(BaseURL .. "/asset/?id=" .. placeId.."&access=".. TempPlaceAccessKey)
end)
if not success then
print("Failed to Load Place File, unsupported file format")
local ErrorMessage = Instance.new("Message", workspace)
ErrorMessage.Text = "Failed to Load Place File, unsupported file format"
end
--Players:SetChatStyle(Enum.ChatStyle.ClassicAndBubble)
-- Now start the connection
ns:Start(port, sleeptime)
if timeout then
scriptContext:SetTimeout(timeout)
end
scriptContext.ScriptsDisabled = false
-- StartGame --
Game:GetService("RunService"):Run()
ReportServerStats()
coroutine.wrap(function()
while true do
wait(10)
if StoppingServer then break end
ReportServerStats()
ReportServerPlayers()
end
end)()
coroutine.wrap(function()
wait(120) -- Wait 2 minutes to check if anyone has joined
if TotalPlayersJoined == 0 then
print("Stopping server, no players joined past 2 minutes.")
ShutdownServer()
end
end)()
pcall(function() Game:GetService("ScriptContext"):AddStarterScript(37801172) end)

331
app/files/2014Join.lua Normal file
View File

@ -0,0 +1,331 @@
pcall(function() game:SetPlaceID(-1, false) end)
local startTime = tick()
local connectResolved = false
local loadResolved = false
local joinResolved = false
local playResolved = true
local playStartTime = 0
local player = nil
local BaseURL = "http://www.syntax.eco"
local PlaceId = {PlaceId}
settings()["Game Options"].CollisionSoundEnabled = true
pcall(function() settings().Rendering.EnableFRM = true end)
pcall(function() settings().Physics.Is30FpsThrottleEnabled = true end)
pcall(function() settings()["Task Scheduler"].PriorityMethod = Enum.PriorityMethod.AccumulatedError end)
pcall(function() settings().Physics.PhysicsEnvironmentalThrottle = Enum.EnviromentalPhysicsThrottle.DefaultAuto end)
-- arguments ---------------------------------------
local threadSleepTime = 15
local test = false
local closeConnection = game.Close:connect(function()
if 0 then
if not connectResolved then
local duration = tick() - startTime;
elseif (not loadResolved) or (not joinResolved) then
local duration = tick() - startTime;
if not loadResolved then
loadResolved = true
end
if not joinResolved then
joinResolved = true
end
elseif not playResolved then
local duration = tick() - playStartTime;
playResolved = true
end
end
end)
game:GetService("ChangeHistoryService"):SetEnabled(false)
game:GetService("ContentProvider"):SetThreadPool(16)
game:GetService("InsertService"):SetBaseSetsUrl(BaseURL.."/Game/Tools/InsertAsset.ashx?nsets=10&type=base")
game:GetService("InsertService"):SetUserSetsUrl(BaseURL.."/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d")
game:GetService("InsertService"):SetCollectionUrl(BaseURL.."/Game/Tools/InsertAsset.ashx?sid=%d")
game:GetService("InsertService"):SetAssetUrl(BaseURL.."/Asset/?id=%d")
game:GetService("InsertService"):SetAssetVersionUrl(BaseURL.."/Asset/?assetversionid=%d")
pcall(function() game:GetService("SocialService"):SetFriendUrl(BaseURL.."/Game/LuaWebService/HandleSocialRequest.ashx?method=IsFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetBestFriendUrl(BaseURL.."/Game/LuaWebService/HandleSocialRequest.ashx?method=IsBestFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupUrl(BaseURL.."/Game/LuaWebService/HandleSocialRequest.ashx?method=IsInGroup&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRankUrl(BaseURL.."/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRank&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRoleUrl(BaseURL.."/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRole&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("GamePassService"):SetPlayerHasPassUrl(BaseURL.."/Game/GamePass/GamePassHandler.ashx?Action=HasPass&UserID=%d&PassID=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetProductInfoUrl(BaseURL.."/marketplace/productinfo?assetId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetPlayerOwnsAssetUrl(BaseURL.."/ownership/hasasset?userId=%d&assetId=%d") end)
pcall(function() game:SetCreatorID(0, Enum.CreatorType.User) end)
-- Bubble chat. This is all-encapsulated to allow us to turn it off with a config setting
pcall(function() game:GetService("Players"):SetChatStyle(Enum.ChatStyle.Classic) end)
pcall( function() if settings().Network.MtuOverride == 0 then settings().Network.MtuOverride = 1400 end end)
local waitingForCharacter = false;
local waitingForCharacterGuid = "26c3de03-3381-4ab6-8e60-e415fa757eba";
-- globals -----------------------------------------
client = game:GetService("NetworkClient")
visit = game:GetService("Visit")
-- functions ---------------------------------------
function ifSeleniumThenSetCookie(key, value)
game:GetService("CookiesService"):SetCookieValue(key, value)
end
function setMessage(message)
game:SetMessage(message)
end
setMessage("Connecting to SYNTAX...")
function showErrorWindow(message, errorType, errorCategory)
if (not loadResolved) or (not joinResolved) then
local duration = tick() - startTime;
if not loadResolved then
loadResolved = true
end
if not joinResolved then
joinResolved = true
end
elseif not playResolved then
local duration = tick() - playStartTime;
playResolved = true
end
game:SetMessage(message)
end
function reportError(err, message)
print("***ERROR*** " .. err)
client:Disconnect()
wait(1)
showErrorWindow("Error: " .. err, message, "Other")
end
-- called when the client connection closes
function onDisconnection(peer, lostConnection)
if lostConnection then
showErrorWindow("You have lost the connection to the game", "LostConnection", "LostConnection")
else
showErrorWindow("This game has shut down", "Kick", "Kick")
end
end
function requestCharacter(replicator)
-- prepare code for when the Character appears
local connection
connection = player.Changed:connect(function (property)
if property=="Character" then
game:ClearMessage()
waitingForCharacter = false
connection:disconnect()
if 0 then
if not joinResolved then
local duration = tick() - startTime;
joinResolved = true
playStartTime = tick()
playResolved = false
end
end
end
end)
setMessage("Requesting character")
if 0 and not loadResolved then
local duration = tick() - startTime;
loadResolved = true
end
local success, err = pcall(function()
replicator:RequestCharacter()
setMessage("Waiting for character")
waitingForCharacter = true
end)
end
-- called when the client connection is established
function onConnectionAccepted(url, replicator)
connectResolved = true
--reportDuration("GameConnect", "Success", tick() - startTime, false)
local waitingForMarker = true
local success, err = pcall(function()
if not test then
visit:SetPing("", 300)
end
game:SetMessageBrickCount()
replicator.Disconnection:connect(onDisconnection)
-- Wait for a marker to return before creating the Player
local marker = replicator:SendMarker()
marker.Received:connect(function()
waitingForMarker = false
requestCharacter(replicator)
end)
end)
if not success then
reportError(err,"ConnectionAccepted")
return
end
-- TODO: report marker progress
while waitingForMarker do
workspace:ZoomToExtents()
wait(0.5)
end
end
-- called when the client connection fails
function onConnectionFailed(_, error)
showErrorWindow("Failed to connect to the Game. (ID=" .. error .. ")", "ID" .. error, "Other")
end
-- called when the client connection is rejected
function onConnectionRejected()
connectionFailed:disconnect()
showErrorWindow("This game is not available. Please try another", "WrongVersion", "WrongVersion")
end
idled = false
function onPlayerIdled(time)
if time > 20*60 then
showErrorWindow(string.format("You were disconnected for being idle %d minutes", time/60), "Idle", "Idle")
client:Disconnect()
if not idled then
idled = true
end
end
end
pcall(function() settings().Diagnostics:LegacyScriptMode() end)
coroutine.wrap(function()
game:SetRemoteBuildMode(true)
setMessage("Fetching Place Info from SYNTAX")
--print("Fetching Place Info from Server")
local joinScriptUrl = nil
local AttemptCount = 0
local success, result = nil, nil
while true do
success, result = pcall(function()
return game:HttpPost( BaseURL.."/Game/placelauncher.ashx?placeId="..tostring(PlaceId).."&rand="..tostring(math.random(1,9999999)), "{{}}", true, "application/json")
end)
--print("Placelauncher ["..tostring(AttemptCount).."]: "..tostring(result))
if success then
local JSONResponse = game:GetService("HttpService"):JSONDecode(result)
--print("Fetch Place Info Success, ["..tostring(AttemptCount).."]")
if JSONResponse["status"] == 1 then
setMessage("Waiting for Server to start... ( This may take a while ) [ "..tostring(AttemptCount).." ]")
--print("Placelauncher returned status 1")
elseif JSONResponse["status"] == 2 then -- Server Started
--print("Placelauncher returned status 2")
setMessage("Server Found! Connecting...")
joinScriptUrl = JSONResponse["joinScriptUrl"]
break
else
setMessage("RequestFailed, message: "..JSONResponse["message"])
error("RequestFailed, message: "..JSONResponse["message"])
end
if AttemptCount > 15 then
setMessage("Placelauncher request timed out, please try again later")
error("Placelauncher request timed out, please try again later")
end
--print("Waiting 3 seconds before next fetch [ "..tostring(AttemptCount).." ]")
wait(3)
AttemptCount = AttemptCount + 1
else
setMessage("Failed to get place launcher info: "..result)
error("Failed to get place launcher info: "..result)
end
end
if not joinScriptUrl then
setMessage("Failed to get join script, please try again later")
error("Failed to get join script")
end
--print("Fetch JoinScriptUrl Success")
local success, result = pcall(function()
return game:HttpGet(joinScriptUrl, true)
end)
if not success then
setMessage("Failed to get join script: "..result)
error("Failed to get join script: "..result)
end
local JSONResponse = game:GetService("HttpService"):JSONDecode(result:sub(result:find("\n", 1, true)+1))
local MachineAddress = JSONResponse["MachineAddress"]
local ServerPort = JSONResponse["ServerPort"]
local PlayerUsername = JSONResponse["UserName"]
local PlayerId = JSONResponse["UserId"]
local AccountAge = JSONResponse["AccountAge"]
local GameSessionId = JSONResponse["SessionId"]
local CharacterAppearance = JSONResponse["CharacterAppearance"]
setMessage("Welcome, "..PlayerUsername.."! Connecting to SYNTAX...")
--print("Connecting to "..MachineAddress..":"..tostring(ServerPort).." as "..PlayerUsername.." ("..tostring(PlayerId)..")")
wait(1.5)
client.ConnectionAccepted:connect(onConnectionAccepted)
client.ConnectionRejected:connect(onConnectionRejected)
connectionFailed = client.ConnectionFailed:connect(onConnectionFailed)
client.Ticket = ""
local ConnectionAttempt = 0
while true do
setMessage("Connecting to Gameserver... [ "..tostring(ConnectionAttempt).." ]")
local isConnectionSuccessful, player = pcall(function()
playerConnectSucces, player = pcall(function() return client:PlayerConnect(PlayerId, MachineAddress, ServerPort, 0, threadSleepTime) end)
if not playerConnectSucces then
--print("PlayerConnect function failed, fallback to legacy connect")
player = game:GetService("Players"):CreateLocalPlayer(0)
client:Connect(MachineAddress, ServerPort, 0, threadSleepTime)
end
return player
end)
if isConnectionSuccessful then
break
else
if ConnectionAttempt > 5 then
error("Failed to connect to server: "..player)
end
ConnectionAttempt = ConnectionAttempt + 1
wait(2)
end
end
player:SetSuperSafeChat(false)
pcall(function() player:SetUnder13(false) end)
pcall(function() player:SetMembershipType(Enum.MembershipType[JSONResponse["MembershipType"]]) end)
pcall(function() player:SetAccountAge(AccountAge) end)
pcall(function() player.Name = PlayerUsername end)
pcall(function() player.UserId = PlayerId end)
pcall(function() client:SetGameSessionID(GameSessionId) end)
pcall(function() game:SetPlaceID(PlaceId, false) end)
pcall(function() player.ChatMode = Enum.ChatMode.TextAndMenu end)
player.Idled:connect(onPlayerIdled)
player.CharacterAppearance = CharacterAppearance
game:GetService("Players"):SetChatStyle(Enum.ChatStyle[JSONResponse["ChatStyle"]])
pcall(function() game:SetScreenshotInfo("") end)
pcall(function() game:SetVideoInfo('<?xml version="1.0"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"><media:group><media:title type="plain"><![CDATA[ROBLOX Place]]></media:title><media:description type="plain"><![CDATA[ For more games visit http://www.syntax.eco]]></media:description><media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>') end)
end)()

View File

@ -0,0 +1,213 @@
local PlaceId, Port, BaseURL, AuthToken, CreatorId, CreatorType, DownloadAuthorizationToken = ...
local RunService = game:GetService("RunService")
local ContentProvider = game:GetService("ContentProvider")
local Players = game:GetService("Players")
local HttpService = game:GetService("HttpService")
local ScriptContext = game:GetService('ScriptContext')
local RobloxReplicatedStorage = game:GetService('RobloxReplicatedStorage')
HttpService.HttpEnabled = false -- Disable HttpService for security reasons
if CreatorType == 1 then
CreatorType = Enum.CreatorType.User
elseif CreatorType == 2 then
CreatorType = Enum.CreatorType.Group
else
CreatorType = Enum.CreatorType.User
end
pcall(function() game:SetCreatorID(CreatorId, CreatorType) end)
pcall(function() settings().Network.UseInstancePacketCache = true end)
pcall(function() settings().Network.UsePhysicsPacketCache = true end)
--pcall(function() settings()["Task Scheduler"].PriorityMethod = Enum.PriorityMethod.FIFO end)
pcall(function() settings()["Task Scheduler"].PriorityMethod = Enum.PriorityMethod.AccumulatedError end)
--settings().Network.PhysicsSend = 1 -- 1==RoundRobin
--settings().Network.PhysicsSend = Enum.PhysicsSendMethod.ErrorComputation2
settings().Network.PhysicsSend = Enum.PhysicsSendMethod.TopNErrors
settings().Network.ExperimentalPhysicsEnabled = true
settings().Network.WaitingForCharacterLogRate = 100
pcall(function() settings().Diagnostics:LegacyScriptMode() end)
pcall(function() ScriptContext:AddStarterScript(37801172) end)
ScriptContext.ScriptsDisabled = true
game:SetPlaceID(PlaceId, false)
game:GetService("ChangeHistoryService"):SetEnabled(false)
local NetworkServer = game:GetService("NetworkServer")
if BaseURL~=nil then
pcall(function() game:GetService("Players"):SetAbuseReportUrl(BaseURL .. "/AbuseReport/InGameChatHandler.ashx") end)
pcall(function() game:GetService("ScriptInformationProvider"):SetAssetUrl(BaseURL .. "/Asset/") end)
pcall(function() game:GetService("ContentProvider"):SetBaseUrl(BaseURL .. "/") end)
pcall(function() game:GetService("Players"):SetChatFilterUrl(BaseURL .. "/Game/ChatFilter.ashx") end)
game:GetService("BadgeService"):SetPlaceId(PlaceId)
game:GetService("BadgeService"):SetIsBadgeLegalUrl("")
game:GetService("BadgeService"):SetAwardBadgeUrl(BaseURL .. "/Game/Badge/AwardBadge.ashx?UserID=%d&BadgeID=%d&PlaceID=%d")
game:GetService("BadgeService"):SetHasBadgeUrl(BaseURL .. "/Game/Badge/HasBadge.ashx?UserID=%d&BadgeID=%d")
game:GetService("BadgeService"):SetIsBadgeDisabledUrl(BaseURL .. "/Game/Badge/IsBadgeDisabled.ashx?BadgeID=%d&PlaceID=%d")
game:GetService("InsertService"):SetBaseSetsUrl(BaseURL .. "/Game/Tools/InsertAsset.ashx?nsets=10&type=base")
game:GetService("InsertService"):SetUserSetsUrl(BaseURL .. "/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d")
game:GetService("InsertService"):SetCollectionUrl(BaseURL .. "/Game/Tools/InsertAsset.ashx?sid=%d")
game:GetService("InsertService"):SetAssetUrl(BaseURL .. "/Asset/?id=%d")
game:GetService("InsertService"):SetAssetVersionUrl(BaseURL .. "/Asset/?assetversionid=%d")
game:GetService("Players"):SetSaveDataUrl(BaseURL .. "/persistence/legacy/save?userId=%d")
game:GetService("Players"):SetLoadDataUrl(BaseURL .. "/persistence/legacy/load?userId=%d")
game:GetService("FriendService"):SetMakeFriendUrl(BaseURL .. "/Friend/CreateFriend?firstUserId=%d&secondUserId=%d")
game:GetService("FriendService"):SetBreakFriendUrl(BaseURL .. "/Friend/BreakFriend?firstUserId=%d&secondUserId=%d")
game:GetService("FriendService"):SetGetFriendsUrl(BaseURL .. "/Friend/AreFriends?userId=%d")
game:GetService("FriendService"):SetCreateFriendRequestUrl(BaseURL .. "/Friend/CreateFriendRequest?requesterUserId=%d&requestedUserId=%d")
game:GetService("FriendService"):SetDeleteFriendRequestUrl(BaseURL .. "/Friend/DeleteFriendRequest?requesterUserId=%d&requestedUserId=%d")
--pcall(function() loadfile(BaseURL .. "/Game/LoadPlaceInfo.ashx?PlaceId=" .. PlaceId)() end) idk what this is suppose to return
end
pcall(function()
game:GetService("NetworkServer"):SetIsPlayerAuthenticationRequired(true)
end)
settings().Diagnostics.LuaRamLimit = 0
local StartTime = tick()
local StoppingServer = false
local function ReportServerPlayers(IgnoreThisPlayer)
--if StoppingServer then return end
local success, message = pcall(function()
local PlayerList = {}
for _, player in pairs(Players:GetChildren()) do
if player:IsA("Player") and player ~= IgnoreThisPlayer then
table.insert(PlayerList, {
["UserId"] = player.UserId,
["Name"] = player.Name
})
end
end
local MessagePayload = HttpService:JSONEncode({
["AuthToken"] = AuthToken,
["JobId"] = game.JobId,
["Players"] = PlayerList
})
local ResponseData = game:HttpPost(BaseURL.."/internal/gameserver/reportplayers", MessagePayload, true, "application/json")
local ResponseJSON = HttpService:JSONDecode(ResponseData)
for _, player in pairs(ResponseJSON["bad"]) do -- This is a list of players that need to be kicked from the server
local TargetPlayer = Players:GetPlayerByUserId(player)
if TargetPlayer ~= nil then
TargetPlayer:Kick("There was an issue authenticating you, please contact support.")
TargetPlayer:Destroy()
end
end
end)
end
local function ReportServerStats()
if StoppingServer then return end
local success, message = pcall(function()
local MessagePayload = HttpService:JSONEncode({
["AuthToken"] = AuthToken,
["JobId"] = game.JobId,
["PlaceId"] = PlaceId,
["ServerAliveTime"] = (tick() - StartTime) + 1
})
game:HttpPost(BaseURL.."/internal/gameserver/reportstats", MessagePayload, false, "application/json")
end)
end
local function ReportServerShutdown()
local success, message = pcall(function()
local MessagePayload = HttpService:JSONEncode({
["AuthToken"] = AuthToken,
["JobId"] = game.JobId,
["PlaceId"] = PlaceId,
["ServerAliveTime"] = tick() - StartTime
})
game:HttpPost(BaseURL.."/internal/gameserver/reportshutdown", MessagePayload, false, "application/json")
end)
end
local function ShutdownServer()
StoppingServer = true
ReportServerShutdown()
ScriptContext.ScriptsDisabled = true
game:HttpPost("http://127.0.0.1:3000/CloseJob?RCCReturnAuth="..AuthToken, HttpService:JSONEncode({
["jobid"] = game.JobId
}), false, "application/json")
end
if PlaceId ~= nil and BaseURL ~= nil then
wait()
local success, message = pcall(function()
game:Load(BaseURL.."/asset/?id="..tostring(PlaceId).."&access="..DownloadAuthorizationToken)
end)
if not success then
-- Report error
local MessagePayload = HttpService:JSONEncode({
["AuthToken"] = AuthToken,
["JobId"] = game.JobId,
["PlaceId"] = PlaceId,
["Error"] = message
})
game:HttpPost(BaseURL.."/internal/gameserver/reportfailure", MessagePayload, false, "application/json")
-- Lets start the server but with an empty place and a error message
local NewMessage = Instance.new("Message", workspace)
NewMessage.Text = "There was an error loading this place file, Error Message: "..message..", PlaceId: "..tostring(PlaceId)..", JobId: "..tostring(game.JobId)
end
end
NetworkServer:Start(Port)
ScriptContext:SetTimeout(10)
ScriptContext.ScriptsDisabled = false
local TotalPlayersJoined = 0
Players.PlayerAdded:Connect(function(player)
ReportServerPlayers()
TotalPlayersJoined = TotalPlayersJoined + 1
player.DataComplexityLimit = 1024 * 1024 * 1
player:LoadData()
coroutine.wrap(function()
while true do
wait(120)
if StoppingServer then break end
if player.Parent == nil then break end
player:SaveData()
end
end)()
end)
Players.PlayerRemoving:Connect(function(player)
ReportServerPlayers(player)
player:SaveData()
local PlayerCount = #Players:GetPlayers()
if PlayerCount == 0 then
wait(10) -- Wait 10 seconds to see if anyone rejoins
PlayerCount = #Players:GetPlayers()
if PlayerCount == 0 then
ShutdownServer()
end
end
end)
game:GetService("RunService"):Run()
ReportServerStats()
coroutine.wrap(function()
while true do
wait(20)
if StoppingServer then break end
ReportServerStats()
ReportServerPlayers()
end
end)()
coroutine.wrap(function()
wait(120) -- Wait 2 minutes to check if anyone has joined
if TotalPlayersJoined == 0 then
warn("Stopping server, no players joined past 2 minutes.")
ShutdownServer()
end
end)()

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

415
app/files/Baseplate.rbxlx Normal file
View File

@ -0,0 +1,415 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Workspace" referent="RBXC7F18B7C66F748608ECF68C721F975E7">
<Properties>
<bool name="AllowThirdPartySales">false</bool>
<Ref name="CurrentCamera">RBX1512699E848543EC96B3B41C9AAF63F2</Ref>
<double name="DistributedGameTime">0</double>
<bool name="ExpSolverEnabled_Replicate">false</bool>
<float name="FallenPartsDestroyHeight">-500</float>
<bool name="FilteringEnabled">true</bool>
<CoordinateFrame name="ModelInPrimary">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<string name="Name">Workspace</string>
<bool name="PGSPhysicsSolverEnabled">false</bool>
<token name="PhysicalPropertiesMode">1</token>
<Ref name="PrimaryPart">null</Ref>
<bool name="StreamingEnabled">false</bool>
</Properties>
<Item class="Camera" referent="RBX1512699E848543EC96B3B41C9AAF63F2">
<Properties>
<CoordinateFrame name="CFrame">
<X>0</X>
<Y>18.7408524</Y>
<Z>23.4260654</Z>
<R00>1</R00>
<R01>0</R01>
<R02>-0</R02>
<R10>-0</R10>
<R11>0.707106829</R11>
<R12>0.707106829</R12>
<R20>0</R20>
<R21>-0.707106829</R21>
<R22>0.707106829</R22>
</CoordinateFrame>
<Ref name="CameraSubject">null</Ref>
<token name="CameraType">0</token>
<float name="FieldOfView">70</float>
<CoordinateFrame name="Focus">
<X>0</X>
<Y>17.3266392</Y>
<Z>22.0118523</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="HeadLocked">true</bool>
<string name="Name">Camera</string>
</Properties>
</Item>
<Item class="Terrain" referent="RBX962DC37307CB49EE949C2B4641DC8869">
<Properties>
<bool name="Anchored">true</bool>
<float name="BackParamA">-0.5</float>
<float name="BackParamB">0.5</float>
<token name="BackSurface">0</token>
<token name="BackSurfaceInput">0</token>
<float name="BottomParamA">-0.5</float>
<float name="BottomParamB">0.5</float>
<token name="BottomSurface">4</token>
<token name="BottomSurfaceInput">0</token>
<int name="BrickColor">194</int>
<CoordinateFrame name="CFrame">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="CanCollide">true</bool>
<BinaryString name="ClusterGridV3"></BinaryString>
<Color3 name="Color">4288914085</Color3>
<PhysicalProperties name="CustomPhysicalProperties">
<CustomPhysics>false</CustomPhysics>
</PhysicalProperties>
<float name="Elasticity">0.300000012</float>
<float name="Friction">0.5</float>
<float name="FrontParamA">-0.5</float>
<float name="FrontParamB">0.5</float>
<token name="FrontSurface">0</token>
<token name="FrontSurfaceInput">0</token>
<float name="LeftParamA">-0.5</float>
<float name="LeftParamB">0.5</float>
<token name="LeftSurface">0</token>
<token name="LeftSurfaceInput">0</token>
<bool name="Locked">true</bool>
<token name="Material">256</token>
<string name="Name">Terrain</string>
<float name="Reflectance">0</float>
<float name="RightParamA">-0.5</float>
<float name="RightParamB">0.5</float>
<token name="RightSurface">0</token>
<token name="RightSurfaceInput">0</token>
<Vector3 name="RotVelocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<BinaryString name="SmoothGrid">AQU=</BinaryString>
<float name="TopParamA">-0.5</float>
<float name="TopParamB">0.5</float>
<token name="TopSurface">3</token>
<token name="TopSurfaceInput">0</token>
<float name="Transparency">0</float>
<Vector3 name="Velocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<Color3 name="WaterColor">4278998108</Color3>
<float name="WaterTransparency">0.300000012</float>
<float name="WaterWaveSize">0.150000006</float>
<float name="WaterWaveSpeed">10</float>
<Vector3 name="size">
<X>2044</X>
<Y>252</Y>
<Z>2044</Z>
</Vector3>
</Properties>
</Item>
<Item class="Part" referent="RBXD9661C66155D4480B1C60243AD55DEA5">
<Properties>
<bool name="Anchored">true</bool>
<float name="BackParamA">-0.5</float>
<float name="BackParamB">0.5</float>
<token name="BackSurface">0</token>
<token name="BackSurfaceInput">0</token>
<float name="BottomParamA">-0.5</float>
<float name="BottomParamB">0.5</float>
<token name="BottomSurface">4</token>
<token name="BottomSurfaceInput">0</token>
<int name="BrickColor">199</int>
<CoordinateFrame name="CFrame">
<X>0</X>
<Y>-10</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<bool name="CanCollide">true</bool>
<Color3 name="Color">4284702562</Color3>
<PhysicalProperties name="CustomPhysicalProperties">
<CustomPhysics>false</CustomPhysics>
</PhysicalProperties>
<float name="Elasticity">0.5</float>
<float name="Friction">0.300000012</float>
<float name="FrontParamA">-0.5</float>
<float name="FrontParamB">0.5</float>
<token name="FrontSurface">0</token>
<token name="FrontSurfaceInput">0</token>
<float name="LeftParamA">-0.5</float>
<float name="LeftParamB">0.5</float>
<token name="LeftSurface">0</token>
<token name="LeftSurfaceInput">0</token>
<bool name="Locked">true</bool>
<token name="Material">256</token>
<string name="Name">BasePlate</string>
<float name="Reflectance">0</float>
<float name="RightParamA">-0.5</float>
<float name="RightParamB">0.5</float>
<token name="RightSurface">0</token>
<token name="RightSurfaceInput">0</token>
<Vector3 name="RotVelocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<float name="TopParamA">-0.5</float>
<float name="TopParamB">0.5</float>
<token name="TopSurface">3</token>
<token name="TopSurfaceInput">0</token>
<float name="Transparency">0</float>
<Vector3 name="Velocity">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
</Vector3>
<token name="formFactorRaw">0</token>
<token name="shape">1</token>
<Vector3 name="size">
<X>512</X>
<Y>20</Y>
<Z>512</Z>
</Vector3>
</Properties>
</Item>
</Item>
<Item class="NonReplicatedCSGDictionaryService" referent="RBX067CE0D023DD497B8B9EE5961977CD31">
<Properties>
<string name="Name">NonReplicatedCSGDictionaryService</string>
</Properties>
</Item>
<Item class="CSGDictionaryService" referent="RBXE0159F0B3BF24CBA8EA8E9A60AB80E0F">
<Properties>
<string name="Name">CSGDictionaryService</string>
</Properties>
</Item>
<Item class="Players" referent="RBX8A99EC5033DB43D69BEA8B98350E671D">
<Properties>
<bool name="CharacterAutoLoads">true</bool>
<int name="MaxPlayersInternal">12</int>
<string name="Name">Players</string>
<int name="PreferredPlayersInternal">7536745</int>
</Properties>
</Item>
<Item class="ReplicatedFirst" referent="RBX343D15FAE3B14EC5B01DEA5B584C79F5">
<Properties>
<string name="Name">ReplicatedFirst</string>
</Properties>
</Item>
<Item class="StarterPlayer" referent="RBXE9CF635E34094B729D64B946C7FB9F42">
<Properties>
<bool name="AutoJumpEnabled">true</bool>
<float name="CameraMaxZoomDistance">400</float>
<float name="CameraMinZoomDistance">0.5</float>
<token name="CameraMode">0</token>
<token name="DevCameraOcclusionMode">0</token>
<token name="DevComputerCameraMovementMode">0</token>
<token name="DevComputerMovementMode">0</token>
<token name="DevTouchCameraMovementMode">0</token>
<token name="DevTouchMovementMode">0</token>
<bool name="EnableMouseLockOption">true</bool>
<float name="HealthDisplayDistance">100</float>
<bool name="LoadCharacterAppearance">true</bool>
<string name="Name">StarterPlayer</string>
<float name="NameDisplayDistance">100</float>
</Properties>
<Item class="StarterPlayerScripts" referent="RBX307AE5152BDC4BA58565D2ABCE5F7DB8">
<Properties>
<string name="Name">StarterPlayerScripts</string>
</Properties>
</Item>
</Item>
<Item class="StarterPack" referent="RBX5B2912C78BAE4E7CBD812F2528B41C4A">
<Properties>
<string name="Name">StarterPack</string>
</Properties>
</Item>
<Item class="StarterGui" referent="RBXCCEE4F7509994477820DAE2433E0D50C">
<Properties>
<string name="Name">StarterGui</string>
<bool name="ResetPlayerGuiOnSpawn">true</bool>
<bool name="ShowDevelopmentGui">true</bool>
</Properties>
</Item>
<Item class="TeleportService" referent="RBX1C0D1B1D684943C9BD32C32F03B22DBC">
<Properties>
<string name="Name">Teleport Service</string>
</Properties>
</Item>
<Item class="SoundService" referent="RBX05CFF11CF7804B63A7B9A87AFF717C90">
<Properties>
<token name="AmbientReverb">0</token>
<float name="DistanceFactor">10</float>
<float name="DopplerScale">1</float>
<string name="Name">SoundService</string>
<float name="RolloffScale">1</float>
</Properties>
</Item>
<Item class="CollectionService" referent="RBX8D87D906F59B4804A229412EE38676EE">
<Properties>
<string name="Name">CollectionService</string>
</Properties>
</Item>
<Item class="PhysicsService" referent="RBX68BBBC05359049F3BD5E6B5EE18A79D1">
<Properties>
<string name="Name">PhysicsService</string>
</Properties>
</Item>
<Item class="Geometry" referent="RBX5D2ED4CB99F4425E857A8C8D60906137">
<Properties>
<string name="Name">Geometry</string>
</Properties>
</Item>
<Item class="RenderHooksService" referent="RBXAE16C6653AF3438D9CF3019235FDC39A">
<Properties>
<string name="Name">RenderHooksService</string>
</Properties>
</Item>
<Item class="InsertService" referent="RBXBAA293F59345438BA906BF0A46E84109">
<Properties>
<bool name="AllowInsertFreeModels">false</bool>
<string name="Name">InsertService</string>
</Properties>
</Item>
<Item class="SocialService" referent="RBX4A68FBCE25944173ADE26B5628ADD22E">
<Properties>
<string name="Name">SocialService</string>
</Properties>
</Item>
<Item class="GamePassService" referent="RBX903E91343393412285AC46B20AEACE07">
<Properties>
<string name="Name">GamePassService</string>
</Properties>
</Item>
<Item class="Debris" referent="RBX5566F5623A1C4C68AF0450FD10E2B277">
<Properties>
<int name="MaxItems">1000</int>
<string name="Name">Debris</string>
</Properties>
</Item>
<Item class="TimerService" referent="RBXD39BE6C8787645A592810B59B37F29DF">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="ScriptInformationProvider" referent="RBX795281AD9D034336A9A3AC60F0960A51">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="CookiesService" referent="RBXAE4ABDBBEAAE47138714681AB603AA8E">
<Properties>
<string name="Name">CookiesService</string>
</Properties>
</Item>
<Item class="ContextActionService" referent="RBX0CD406A832244F80AF59D08650F23871">
<Properties>
<string name="Name">ContextActionService</string>
</Properties>
</Item>
<Item class="ScriptService" referent="RBXBF257B38E3524ABD89D43BF8B308C06C">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="AssetService" referent="RBXC8F2AF8A58604E7CA2F15D67B0FA04E9">
<Properties>
<string name="Name">AssetService</string>
</Properties>
</Item>
<Item class="Selection" referent="RBX88557E83E45A42D49F2D6960F4BA2079">
<Properties>
<string name="Name">Selection</string>
</Properties>
</Item>
<Item class="ServerScriptService" referent="RBX8646DBC0047A4B418CFDC7A2F5194188">
<Properties>
<bool name="LoadStringEnabled">false</bool>
<string name="Name">ServerScriptService</string>
</Properties>
</Item>
<Item class="ServerStorage" referent="RBXF71D33A93A534CFB8E2C02B5044482C0">
<Properties>
<string name="Name">ServerStorage</string>
</Properties>
</Item>
<Item class="ReplicatedStorage" referent="RBX9333FC8788C3495694590852FF7AB205">
<Properties>
<string name="Name">ReplicatedStorage</string>
</Properties>
</Item>
<Item class="LuaWebService" referent="RBX4B2D942315DF48CA878ADA0362641048">
<Properties>
<string name="Name">Instance</string>
</Properties>
</Item>
<Item class="Lighting" referent="RBX169D2E7A960249C7A46E5717B943F5B8">
<Properties>
<Color3 name="Ambient">4278190080</Color3>
<float name="Brightness">1</float>
<float name="ClockTime">14</float>
<Color3 name="ColorShift_Bottom">4278190080</Color3>
<Color3 name="ColorShift_Top">4278190080</Color3>
<Color3 name="FogColor">4290822336</Color3>
<float name="FogEnd">100000</float>
<float name="FogStart">0</float>
<float name="GeographicLatitude">41.7332993</float>
<bool name="GlobalShadows">true</bool>
<string name="Name">Lighting</string>
<Color3 name="OutdoorAmbient">4286611584</Color3>
<bool name="Outlines">true</bool>
<Color3 name="ShadowColor">4289967032</Color3>
<string name="TimeOfDay">14:00:00</string>
</Properties>
</Item>
<Item class="HttpService" referent="RBX8D90633C9AD74BC59FE18FA9636536A7">
<Properties>
<bool name="HttpEnabled">false</bool>
<string name="Name">HttpService</string>
</Properties>
</Item>
</roblox>

1107
app/files/CoreGui/107893730 Normal file

File diff suppressed because it is too large Load Diff

264
app/files/CoreGui/152908679 Normal file
View File

@ -0,0 +1,264 @@
-- ContextActionTouch.lua
-- Copyright ROBLOX 2014, created by Ben Tkacheff
-- this script controls ui and firing of lua functions that are bound in ContextActionService for touch inputs
-- Essentially a user can bind a lua function to a key code, input type (mousebutton1 etc.) and this
-- Variables
local contextActionService = Game:GetService("ContextActionService")
local isTouchDevice = Game:GetService("UserInputService").TouchEnabled
local functionTable = {}
local buttonVector = {}
local buttonScreenGui = nil
local buttonFrame = nil
local ContextDownImage = "http://www.syntax.eco/asset/?id=97166756"
local ContextUpImage = "http://www.syntax.eco/asset/?id=97166444"
local oldTouches = {}
local buttonPositionTable = {
[1] = UDim2.new(0,123,0,70),
[2] = UDim2.new(0,30,0,60),
[3] = UDim2.new(0,180,0,160),
[4] = UDim2.new(0,85,0,-25),
[5] = UDim2.new(0,185,0,-25),
[6] = UDim2.new(0,185,0,260),
[7] = UDim2.new(0,216,0,65)
}
local maxButtons = #buttonPositionTable
-- Preload images
Game:GetService("ContentProvider"):Preload(ContextDownImage)
Game:GetService("ContentProvider"):Preload(ContextUpImage)
while not Game.Players do
wait()
end
while not Game.Players.LocalPlayer do
wait()
end
function createContextActionGui()
if not buttonScreenGui and isTouchDevice then
buttonScreenGui = Instance.new("ScreenGui")
buttonScreenGui.Name = "ContextActionGui"
buttonFrame = Instance.new("Frame")
buttonFrame.BackgroundTransparency = 1
buttonFrame.Size = UDim2.new(0.3,0,0.5,0)
buttonFrame.Position = UDim2.new(0.7,0,0.5,0)
buttonFrame.Name = "ContextButtonFrame"
buttonFrame.Parent = buttonScreenGui
end
end
-- functions
function setButtonSizeAndPosition(object)
local buttonSize = 55
local xOffset = 10
local yOffset = 95
-- todo: better way to determine mobile sized screens
local onSmallScreen = (game.CoreGui.RobloxGui.AbsoluteSize.X < 600)
if not onSmallScreen then
buttonSize = 85
xOffset = 40
end
object.Size = UDim2.new(0,buttonSize,0,buttonSize)
end
function contextButtonDown(button, inputObject, actionName)
if inputObject.UserInputType == Enum.UserInputType.Touch then
button.Image = ContextDownImage
contextActionService:CallFunction(actionName, Enum.UserInputState.Begin, inputObject)
end
end
function contextButtonMoved(button, inputObject, actionName)
if inputObject.UserInputType == Enum.UserInputType.Touch then
button.Image = ContextDownImage
contextActionService:CallFunction(actionName, Enum.UserInputState.Change, inputObject)
end
end
function contextButtonUp(button, inputObject, actionName)
button.Image = ContextUpImage
if inputObject.UserInputType == Enum.UserInputType.Touch and inputObject.UserInputState == Enum.UserInputState.End then
contextActionService:CallFunction(actionName, Enum.UserInputState.End, inputObject)
end
end
function isSmallScreenDevice()
return Game:GetService("GuiService"):GetScreenResolution().y <= 320
end
function createNewButton(actionName, functionInfoTable)
local contextButton = Instance.new("ImageButton")
contextButton.Name = "ContextActionButton"
contextButton.BackgroundTransparency = 1
contextButton.Size = UDim2.new(0,90,0,90)
contextButton.Active = true
if isSmallScreenDevice() then
contextButton.Size = UDim2.new(0,70,0,70)
end
contextButton.Image = ContextUpImage
contextButton.Parent = buttonFrame
local currentButtonTouch = nil
Game:GetService("UserInputService").InputEnded:connect(function ( inputObject )
oldTouches[inputObject] = nil
end)
contextButton.InputBegan:connect(function(inputObject)
if oldTouches[inputObject] then return end
if inputObject.UserInputState == Enum.UserInputState.Begin and currentButtonTouch == nil then
currentButtonTouch = inputObject
contextButtonDown(contextButton, inputObject, actionName)
end
end)
contextButton.InputChanged:connect(function(inputObject)
if oldTouches[inputObject] then return end
if currentButtonTouch ~= inputObject then return end
contextButtonMoved(contextButton, inputObject, actionName)
end)
contextButton.InputEnded:connect(function(inputObject)
if oldTouches[inputObject] then return end
if currentButtonTouch ~= inputObject then return end
currentButtonTouch = nil
oldTouches[inputObject] = true
contextButtonUp(contextButton, inputObject, actionName)
end)
local actionIcon = Instance.new("ImageLabel")
actionIcon.Name = "ActionIcon"
actionIcon.Position = UDim2.new(0.175, 0, 0.175, 0)
actionIcon.Size = UDim2.new(0.65, 0, 0.65, 0)
actionIcon.BackgroundTransparency = 1
if functionInfoTable["image"] and type(functionInfoTable["image"]) == "string" then
actionIcon.Image = functionInfoTable["image"]
end
actionIcon.Parent = contextButton
local actionTitle = Instance.new("TextLabel")
actionTitle.Name = "ActionTitle"
actionTitle.Size = UDim2.new(1,0,1,0)
actionTitle.BackgroundTransparency = 1
actionTitle.Font = Enum.Font.SourceSansBold
actionTitle.TextColor3 = Color3.new(1,1,1)
actionTitle.TextStrokeTransparency = 0
actionTitle.FontSize = Enum.FontSize.Size18
actionTitle.TextWrapped = true
actionTitle.Text = ""
if functionInfoTable["title"] and type(functionInfoTable["title"]) == "string" then
actionTitle.Text = functionInfoTable["title"]
end
actionTitle.Parent = contextButton
return contextButton
end
function createButton( actionName, functionInfoTable )
local button = createNewButton(actionName, functionInfoTable)
local position = nil
for i = 1,#buttonVector do
if buttonVector[i] == "empty" then
position = i
break
end
end
if not position then
position = #buttonVector + 1
end
if position > maxButtons then
return -- todo: let user know we have too many buttons already?
end
buttonVector[position] = button
functionTable[actionName]["button"] = button
button.Position = buttonPositionTable[position]
button.Parent = buttonFrame
if buttonScreenGui and buttonScreenGui.Parent == nil then
buttonScreenGui.Parent = Game.Players.LocalPlayer.PlayerGui
end
end
function removeAction(actionName)
if not functionTable[actionName] then return end
local actionButton = functionTable[actionName]["button"]
if actionButton then
actionButton.Parent = nil
for i = 1,#buttonVector do
if buttonVector[i] == actionButton then
buttonVector[i] = "empty"
break
end
end
actionButton:Destroy()
end
functionTable[actionName] = nil
end
function addAction(actionName,createTouchButton,functionInfoTable)
if functionTable[actionName] then
removeAction(actionName)
end
functionTable[actionName] = {functionInfoTable}
if createTouchButton and isTouchDevice then
createContextActionGui()
createButton(actionName, functionInfoTable)
end
end
-- Connections
contextActionService.BoundActionChanged:connect( function(actionName, changeName, changeTable)
if functionTable[actionName] and changeTable then
local button = functionTable[actionName]["button"]
if button then
if changeName == "image" then
button.ActionIcon.Image = changeTable[changeName]
elseif changeName == "title" then
button.ActionTitle.Text = changeTable[changeName]
elseif changeName == "description" then
-- todo: add description to menu
elseif changeName == "position" then
button.Position = changeTable[changeName]
end
end
end
end)
contextActionService.BoundActionAdded:connect( function(actionName, createTouchButton, functionInfoTable)
addAction(actionName, createTouchButton, functionInfoTable)
end)
contextActionService.BoundActionRemoved:connect( function(actionName, functionInfoTable)
removeAction(actionName)
end)
contextActionService.GetActionButtonEvent:connect( function(actionName)
if functionTable[actionName] then
contextActionService:FireActionButtonFoundSignal(actionName, functionTable[actionName]["button"])
end
end)
-- make sure any bound data before we setup connections is handled
local boundActions = contextActionService:GetAllBoundActionInfo()
for actionName, actionData in pairs(boundActions) do
addAction(actionName,actionData["createTouchButton"],actionData)
end

564
app/files/CoreGui/153556783 Normal file
View File

@ -0,0 +1,564 @@
-- This is responsible for all touch controls we show (as of this writing, only on iOS)
-- this includes character move thumbsticks, and buttons for jump, use of items, camera, etc.
-- Written by Ben Tkacheff, Copyright Roblox 2013
-- obligatory stuff to make sure we don't access nil data
while not Game do
wait()
end
while not Game:FindFirstChild("Players") do
wait()
end
while not Game.Players.LocalPlayer do
wait()
end
while not Game:FindFirstChild("CoreGui") do
wait()
end
while not Game.CoreGui:FindFirstChild("RobloxGui") do
wait()
end
local userInputService = Game:GetService("UserInputService")
local success = pcall(function() userInputService:IsLuaTouchControls() end)
if not success then
script:Destroy()
end
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- Variables
local screenResolution = Game:GetService("GuiService"):GetScreenResolution()
function isSmallScreenDevice()
return screenResolution.y <= 500
end
local localPlayer = Game.Players.LocalPlayer
local thumbstickInactiveAlpha = 0.3
local thumbstickSize = 120
if isSmallScreenDevice() then
thumbstickSize = 70
end
local touchControlsSheet = "rbxasset://textures/ui/TouchControlsSheet.png"
local ThumbstickDeadZone = 5
local ThumbstickMaxPercentGive = 0.92
local thumbstickTouches = {}
local jumpButtonSize = 90
if isSmallScreenDevice() then
jumpButtonSize = 70
end
local oldJumpTouches = {}
local currentJumpTouch = nil
local CameraRotateSensitivity = 0.007
local CameraRotateDeadZone = CameraRotateSensitivity * 16
local CameraZoomSensitivity = 0.03
local PinchZoomDelay = 0.2
local cameraTouch = nil
-- make sure all of our images are good to go
Game:GetService("ContentProvider"):Preload(touchControlsSheet)
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- Functions
function DistanceBetweenTwoPoints(point1, point2)
local dx = point2.x - point1.x
local dy = point2.y - point1.y
return math.sqrt( (dx*dx) + (dy*dy) )
end
function transformFromCenterToTopLeft(pointToTranslate, guiObject)
return UDim2.new(0,pointToTranslate.x - guiObject.AbsoluteSize.x/2,0,pointToTranslate.y - guiObject.AbsoluteSize.y/2)
end
function rotatePointAboutLocation(pointToRotate, pointToRotateAbout, radians)
local sinAnglePercent = math.sin(radians)
local cosAnglePercent = math.cos(radians)
local transformedPoint = pointToRotate
-- translate point back to origin:
transformedPoint = Vector2.new(transformedPoint.x - pointToRotateAbout.x, transformedPoint.y - pointToRotateAbout.y)
-- rotate point
local xNew = transformedPoint.x * cosAnglePercent - transformedPoint.y * sinAnglePercent
local yNew = transformedPoint.x * sinAnglePercent + transformedPoint.y * cosAnglePercent
-- translate point back:
transformedPoint = Vector2.new(xNew + pointToRotateAbout.x, yNew + pointToRotateAbout.y)
return transformedPoint
end
function dotProduct(v1,v2)
return ((v1.x*v2.x) + (v1.y*v2.y))
end
function stationaryThumbstickTouchMove(thumbstickFrame, thumbstickOuter, touchLocation)
local thumbstickOuterCenterPosition = Vector2.new(thumbstickOuter.Position.X.Offset + thumbstickOuter.AbsoluteSize.x/2, thumbstickOuter.Position.Y.Offset + thumbstickOuter.AbsoluteSize.y/2)
local centerDiff = DistanceBetweenTwoPoints(touchLocation, thumbstickOuterCenterPosition)
-- thumbstick is moving outside our region, need to cap its distance
if centerDiff > (thumbstickSize/2) then
local thumbVector = Vector2.new(touchLocation.x - thumbstickOuterCenterPosition.x,touchLocation.y - thumbstickOuterCenterPosition.y);
local normal = thumbVector.unit
if normal.x == math.nan or normal.x == math.inf then
normal = Vector2.new(0,normal.y)
end
if normal.y == math.nan or normal.y == math.inf then
normal = Vector2.new(normal.x,0)
end
local newThumbstickInnerPosition = thumbstickOuterCenterPosition + (normal * (thumbstickSize/2))
thumbstickFrame.Position = transformFromCenterToTopLeft(newThumbstickInnerPosition, thumbstickFrame)
else
thumbstickFrame.Position = transformFromCenterToTopLeft(touchLocation,thumbstickFrame)
end
return Vector2.new(thumbstickFrame.Position.X.Offset - thumbstickOuter.Position.X.Offset,thumbstickFrame.Position.Y.Offset - thumbstickOuter.Position.Y.Offset)
end
function followThumbstickTouchMove(thumbstickFrame, thumbstickOuter, touchLocation)
local thumbstickOuterCenter = Vector2.new(thumbstickOuter.Position.X.Offset + thumbstickOuter.AbsoluteSize.x/2, thumbstickOuter.Position.Y.Offset + thumbstickOuter.AbsoluteSize.y/2)
-- thumbstick is moving outside our region, need to position outer thumbstick texture carefully (to make look and feel like actual joystick controller)
if DistanceBetweenTwoPoints(touchLocation, thumbstickOuterCenter) > thumbstickSize/2 then
local thumbstickInnerCenter = Vector2.new(thumbstickFrame.Position.X.Offset + thumbstickFrame.AbsoluteSize.x/2, thumbstickFrame.Position.Y.Offset + thumbstickFrame.AbsoluteSize.y/2)
local movementVectorUnit = Vector2.new(touchLocation.x - thumbstickInnerCenter.x, touchLocation.y - thumbstickInnerCenter.y).unit
local outerToInnerVectorCurrent = Vector2.new(thumbstickInnerCenter.x - thumbstickOuterCenter.x, thumbstickInnerCenter.y - thumbstickOuterCenter.y)
local outerToInnerVectorCurrentUnit = outerToInnerVectorCurrent.unit
local movementVector = Vector2.new(touchLocation.x - thumbstickInnerCenter.x, touchLocation.y - thumbstickInnerCenter.y)
-- First, find the angle between the new thumbstick movement vector,
-- and the vector between thumbstick inner and thumbstick outer.
-- We will use this to pivot thumbstick outer around thumbstick inner, gives a nice joystick feel
local crossOuterToInnerWithMovement = (outerToInnerVectorCurrentUnit.x * movementVectorUnit.y) - (outerToInnerVectorCurrentUnit.y * movementVectorUnit.x)
local angle = math.atan2(crossOuterToInnerWithMovement, dotProduct(outerToInnerVectorCurrentUnit, movementVectorUnit))
local anglePercent = angle * math.min( (movementVector.magnitude)/(outerToInnerVectorCurrent.magnitude), 1.0);
-- If angle is significant, rotate about the inner thumbsticks current center
if math.abs(anglePercent) > 0.00001 then
local outerThumbCenter = rotatePointAboutLocation(thumbstickOuterCenter, thumbstickInnerCenter, anglePercent)
thumbstickOuter.Position = transformFromCenterToTopLeft(Vector2.new(outerThumbCenter.x,outerThumbCenter.y), thumbstickOuter)
end
-- now just translate outer thumbstick to make sure it stays nears inner thumbstick
thumbstickOuter.Position = UDim2.new(0,thumbstickOuter.Position.X.Offset+movementVector.x,0,thumbstickOuter.Position.Y.Offset+movementVector.y)
end
thumbstickFrame.Position = transformFromCenterToTopLeft(touchLocation,thumbstickFrame)
-- a bit of error checking to make sure thumbsticks stay close to eachother
thumbstickFramePosition = Vector2.new(thumbstickFrame.Position.X.Offset,thumbstickFrame.Position.Y.Offset)
thumbstickOuterPosition = Vector2.new(thumbstickOuter.Position.X.Offset,thumbstickOuter.Position.Y.Offset)
if DistanceBetweenTwoPoints(thumbstickFramePosition, thumbstickOuterPosition) > thumbstickSize/2 then
local vectorWithLength = (thumbstickOuterPosition - thumbstickFramePosition).unit * thumbstickSize/2
thumbstickOuter.Position = UDim2.new(0,thumbstickFramePosition.x + vectorWithLength.x,0,thumbstickFramePosition.y + vectorWithLength.y)
end
return Vector2.new(thumbstickFrame.Position.X.Offset - thumbstickOuter.Position.X.Offset,thumbstickFrame.Position.Y.Offset - thumbstickOuter.Position.Y.Offset)
end
function movementOutsideDeadZone(movementVector)
return ( (math.abs(movementVector.x) > ThumbstickDeadZone) or (math.abs(movementVector.y) > ThumbstickDeadZone) )
end
function constructThumbstick(defaultThumbstickPos, updateFunction, stationaryThumbstick)
local thumbstickFrame = Instance.new("Frame")
thumbstickFrame.Name = "ThumbstickFrame"
thumbstickFrame.Active = true
thumbstickFrame.Size = UDim2.new(0,thumbstickSize,0,thumbstickSize)
thumbstickFrame.Position = defaultThumbstickPos
thumbstickFrame.BackgroundTransparency = 1
local outerThumbstick = Instance.new("ImageLabel")
outerThumbstick.Name = "OuterThumbstick"
outerThumbstick.Image = touchControlsSheet
outerThumbstick.ImageRectOffset = Vector2.new(0,0)
outerThumbstick.ImageRectSize = Vector2.new(220,220)
outerThumbstick.BackgroundTransparency = 1
outerThumbstick.Size = UDim2.new(0,thumbstickSize,0,thumbstickSize)
outerThumbstick.Position = defaultThumbstickPos
outerThumbstick.Parent = Game.CoreGui.RobloxGui
local innerThumbstick = Instance.new("ImageLabel")
innerThumbstick.Name = "InnerThumbstick"
innerThumbstick.Image = touchControlsSheet
innerThumbstick.ImageRectOffset = Vector2.new(220,0)
innerThumbstick.ImageRectSize = Vector2.new(111,111)
innerThumbstick.BackgroundTransparency = 1
innerThumbstick.Size = UDim2.new(0,thumbstickSize/2,0,thumbstickSize/2)
innerThumbstick.Position = UDim2.new(0, thumbstickFrame.Size.X.Offset/2 - thumbstickSize/4, 0, thumbstickFrame.Size.Y.Offset/2 - thumbstickSize/4)
innerThumbstick.Parent = thumbstickFrame
innerThumbstick.ZIndex = 2
local thumbstickTouch = nil
local userInputServiceTouchMovedCon = nil
local userInputSeviceTouchEndedCon = nil
local startInputTracking = function(inputObject)
if thumbstickTouch then return end
if inputObject == cameraTouch then return end
if inputObject == currentJumpTouch then return end
if inputObject.UserInputType ~= Enum.UserInputType.Touch then return end
thumbstickTouch = inputObject
table.insert(thumbstickTouches,thumbstickTouch)
thumbstickFrame.Position = transformFromCenterToTopLeft(thumbstickTouch.Position,thumbstickFrame)
outerThumbstick.Position = thumbstickFrame.Position
userInputServiceTouchMovedCon = userInputService.TouchMoved:connect(function(movedInput)
if movedInput == thumbstickTouch then
local movementVector = nil
if stationaryThumbstick then
movementVector = stationaryThumbstickTouchMove(thumbstickFrame,outerThumbstick,Vector2.new(movedInput.Position.x,movedInput.Position.y))
else
movementVector = followThumbstickTouchMove(thumbstickFrame,outerThumbstick,Vector2.new(movedInput.Position.x,movedInput.Position.y))
end
if updateFunction then
updateFunction(movementVector,outerThumbstick.Size.X.Offset/2)
end
end
end)
userInputSeviceTouchEndedCon = userInputService.TouchEnded:connect(function(endedInput)
if endedInput == thumbstickTouch then
if updateFunction then
updateFunction(Vector2.new(0,0),1)
end
userInputSeviceTouchEndedCon:disconnect()
userInputServiceTouchMovedCon:disconnect()
thumbstickFrame.Position = defaultThumbstickPos
outerThumbstick.Position = defaultThumbstickPos
for i, object in pairs(thumbstickTouches) do
if object == thumbstickTouch then
table.remove(thumbstickTouches,i)
break
end
end
thumbstickTouch = nil
end
end)
end
userInputService.Changed:connect(function(prop)
if prop == "ModalEnabled" then
thumbstickFrame.Visible = not userInputService.ModalEnabled
outerThumbstick.Visible = not userInputService.ModalEnabled
end
end)
thumbstickFrame.InputBegan:connect(startInputTracking)
return thumbstickFrame
end
function setupCharacterMovement( parentFrame )
local lastMovementVector, lastMaxMovement = nil
local moveCharacterFunc = localPlayer.MoveCharacter
local moveCharacterFunction = function ( movementVector, maxMovement )
if localPlayer then
if movementOutsideDeadZone(movementVector) then
lastMovementVector = movementVector
lastMaxMovement = maxMovement
-- sometimes rounding error will not allow us to go max speed at some
-- thumbstick angles, fix this with a bit of fudging near 100% throttle
if movementVector.magnitude/maxMovement > ThumbstickMaxPercentGive then
maxMovement = movementVector.magnitude - 1
end
moveCharacterFunc(localPlayer, movementVector, maxMovement)
else
lastMovementVector = Vector2.new(0,0)
lastMaxMovement = 1
moveCharacterFunc(localPlayer, lastMovementVector, lastMaxMovement)
end
end
end
local thumbstickPos = UDim2.new(0,thumbstickSize/2,1,-thumbstickSize*1.75)
if isSmallScreenDevice() then
thumbstickPos = UDim2.new(0,(thumbstickSize/2) - 10,1,-thumbstickSize - 20)
end
local characterThumbstick = constructThumbstick(thumbstickPos, moveCharacterFunction, false)
characterThumbstick.Name = "CharacterThumbstick"
characterThumbstick.Parent = parentFrame
local refreshCharacterMovement = function()
if localPlayer and moveCharacterFunc and lastMovementVector and lastMaxMovement then
moveCharacterFunc(localPlayer, lastMovementVector, lastMaxMovement)
end
end
return refreshCharacterMovement
end
function setupJumpButton( parentFrame )
local jumpButton = Instance.new("ImageButton")
jumpButton.Name = "JumpButton"
jumpButton.BackgroundTransparency = 1
jumpButton.Image = touchControlsSheet
jumpButton.ImageRectOffset = Vector2.new(176,222)
jumpButton.ImageRectSize = Vector2.new(174,174)
jumpButton.Size = UDim2.new(0,jumpButtonSize,0,jumpButtonSize)
if isSmallScreenDevice() then
jumpButton.Position = UDim2.new(1, -(jumpButtonSize*2.25), 1, -jumpButtonSize - 20)
else
jumpButton.Position = UDim2.new(1, -(jumpButtonSize*2.75), 1, -jumpButtonSize - 120)
end
local playerJumpFunc = localPlayer.JumpCharacter
local doJumpLoop = function ()
while currentJumpTouch do
if localPlayer then
playerJumpFunc(localPlayer)
end
wait(1/60)
end
end
jumpButton.InputBegan:connect(function(inputObject)
if inputObject.UserInputType ~= Enum.UserInputType.Touch then return end
if currentJumpTouch then return end
if inputObject == cameraTouch then return end
for i, touch in pairs(oldJumpTouches) do
if touch == inputObject then
return
end
end
currentJumpTouch = inputObject
jumpButton.ImageRectOffset = Vector2.new(0,222)
jumpButton.ImageRectSize = Vector2.new(174,174)
doJumpLoop()
end)
jumpButton.InputEnded:connect(function (inputObject)
if inputObject.UserInputType ~= Enum.UserInputType.Touch then return end
jumpButton.ImageRectOffset = Vector2.new(176,222)
jumpButton.ImageRectSize = Vector2.new(174,174)
if inputObject == currentJumpTouch then
table.insert(oldJumpTouches,currentJumpTouch)
currentJumpTouch = nil
end
end)
userInputService.InputEnded:connect(function ( globalInputObject )
for i, touch in pairs(oldJumpTouches) do
if touch == globalInputObject then
table.remove(oldJumpTouches,i)
break
end
end
end)
userInputService.Changed:connect(function(prop)
if prop == "ModalEnabled" then
jumpButton.Visible = not userInputService.ModalEnabled
end
end)
jumpButton.Parent = parentFrame
end
function isTouchUsedByJumpButton( touch )
if touch == currentJumpTouch then return true end
for i, touchToCompare in pairs(oldJumpTouches) do
if touch == touchToCompare then
return true
end
end
return false
end
function isTouchUsedByThumbstick(touch)
for i, touchToCompare in pairs(thumbstickTouches) do
if touch == touchToCompare then
return true
end
end
return false
end
function setupCameraControl(parentFrame, refreshCharacterMoveFunc)
local lastPos = nil
local hasRotatedCamera = false
local rotateCameraFunc = userInputService.RotateCamera
local pinchTime = -1
local shouldPinch = false
local lastPinchScale = nil
local zoomCameraFunc = userInputService.ZoomCamera
local pinchTouches = {}
local pinchFrame = nil
local resetCameraRotateState = function()
cameraTouch = nil
hasRotatedCamera = false
lastPos = nil
end
local resetPinchState = function ()
pinchTouches = {}
lastPinchScale = nil
shouldPinch = false
pinchFrame:Destroy()
pinchFrame = nil
end
local startPinch = function(firstTouch, secondTouch)
-- track pinching in new frame
if pinchFrame then pinchFrame:Destroy() end -- make sure we didn't track in any mud
pinchFrame = Instance.new("Frame")
pinchFrame.Name = "PinchFrame"
pinchFrame.BackgroundTransparency = 1
pinchFrame.Parent = parentFrame
pinchFrame.Size = UDim2.new(1,0,1,0)
pinchFrame.InputChanged:connect(function(inputObject)
if not shouldPinch then
resetPinchState()
return
end
resetCameraRotateState()
if lastPinchScale == nil then -- first pinch move, just set up scale
if inputObject == firstTouch then
lastPinchScale = (inputObject.Position - secondTouch.Position).magnitude
firstTouch = inputObject
elseif inputObject == secondTouch then
lastPinchScale = (inputObject.Position - firstTouch.Position).magnitude
secondTouch = inputObject
end
else -- we are now actually pinching, do comparison to last pinch size
local newPinchDistance = 0
if inputObject == firstTouch then
newPinchDistance = (inputObject.Position - secondTouch.Position).magnitude
firstTouch = inputObject
elseif inputObject == secondTouch then
newPinchDistance = (inputObject.Position - firstTouch.Position).magnitude
secondTouch = inputObject
end
if newPinchDistance ~= 0 then
local pinchDiff = newPinchDistance - lastPinchScale
if pinchDiff ~= 0 then
zoomCameraFunc(userInputService, (pinchDiff * CameraZoomSensitivity))
end
lastPinchScale = newPinchDistance
end
end
end)
pinchFrame.InputEnded:connect(function(inputObject) -- pinch is over, destroy all
if inputObject == firstTouch or inputObject == secondTouch then
resetPinchState()
end
end)
end
local pinchGestureReceivedTouch = function(inputObject)
if #pinchTouches < 1 then
table.insert(pinchTouches,inputObject)
pinchTime = tick()
shouldPinch = false
elseif #pinchTouches == 1 then
shouldPinch = ( (tick() - pinchTime) <= PinchZoomDelay )
if shouldPinch then
table.insert(pinchTouches,inputObject)
startPinch(pinchTouches[1], pinchTouches[2])
else -- shouldn't ever get here, but just in case
pinchTouches = {}
end
end
end
parentFrame.InputBegan:connect(function (inputObject)
if inputObject.UserInputType ~= Enum.UserInputType.Touch then return end
if isTouchUsedByJumpButton(inputObject) then return end
local usedByThumbstick = isTouchUsedByThumbstick(inputObject)
if not usedByThumbstick then
pinchGestureReceivedTouch(inputObject)
end
if cameraTouch == nil and not usedByThumbstick then
cameraTouch = inputObject
lastPos = Vector2.new(cameraTouch.Position.x,cameraTouch.Position.y)
lastTick = tick()
end
end)
userInputService.InputChanged:connect(function (inputObject)
if inputObject.UserInputType ~= Enum.UserInputType.Touch then return end
if cameraTouch ~= inputObject then return end
local newPos = Vector2.new(cameraTouch.Position.x,cameraTouch.Position.y)
local touchDiff = (lastPos - newPos) * CameraRotateSensitivity
-- first time rotating outside deadzone, just setup for next changed event
if not hasRotatedCamera and (touchDiff.magnitude > CameraRotateDeadZone) then
hasRotatedCamera = true
lastPos = newPos
end
-- fire everytime after we have rotated out of deadzone
if hasRotatedCamera and (lastPos ~= newPos) then
rotateCameraFunc(userInputService, touchDiff)
refreshCharacterMoveFunc()
lastPos = newPos
end
end)
userInputService.InputEnded:connect(function (inputObject)
if cameraTouch == inputObject or cameraTouch == nil then
resetCameraRotateState()
end
for i, touch in pairs(pinchTouches) do
if touch == inputObject then
table.remove(pinchTouches,i)
end
end
end)
end
function setupTouchControls()
local touchControlFrame = Instance.new("Frame")
touchControlFrame.Name = "TouchControlFrame"
touchControlFrame.Size = UDim2.new(1,0,1,0)
touchControlFrame.BackgroundTransparency = 1
touchControlFrame.Parent = Game.CoreGui.RobloxGui
local refreshCharacterMoveFunc = setupCharacterMovement(touchControlFrame)
setupJumpButton(touchControlFrame)
setupCameraControl(touchControlFrame, refreshCharacterMoveFunc)
userInputService.ProcessedEvent:connect(function(inputObject, processed)
if not processed then return end
-- kill camera pan if the touch is used by some user controls
if inputObject == cameraTouch and inputObject.UserInputState == Enum.UserInputState.Begin then
cameraTouch = nil
end
end)
end
----------------------------------------------------------------------------
----------------------------------------------------------------------------
-- Start of Script
if userInputService:IsLuaTouchControls() then
setupTouchControls()
else
script:Destroy()
end

247
app/files/CoreGui/153556822 Normal file
View File

@ -0,0 +1,247 @@
--[[
This script controls the gui the player sees in regards to his or her health.
Can be turned with Game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health,false)
Copyright ROBLOX 2014. Written by Ben Tkacheff.
--]]
---------------------------------------------------------------------
-- Initialize/Variables
while not Game do
wait(1/60)
end
while not Game.Players do
wait(1/60)
end
local useCoreHealthBar = false
local success = pcall(function() useCoreHealthBar = Game.Players:GetUseCoreScriptHealthBar() end)
if not success or not useCoreHealthBar then
return
end
local currentHumanoid = nil
local HealthGui = nil
local lastHealth = 100
local HealthPercentageForOverlay = 5
local maxBarTweenTime = 0.3
local guiEnabled = false
local healthChangedConnection = nil
local humanoidDiedConnection = nil
local characterAddedConnection = nil
local greenBarImage = "http://www.syntax.eco/asset/?id=35238053"
local redBarImage = "http://www.syntax.eco/asset/?id=35238036"
local goldBarImage = "http://www.syntax.eco/asset/?id=154646431" -- for god mode
local hurtOverlayImage = "http://www.syntax.eco/asset/?id=34854607"
Game:GetService("ContentProvider"):Preload(greenBarImage)
Game:GetService("ContentProvider"):Preload(redBarImage)
Game:GetService("ContentProvider"):Preload(goldBarImage)
Game:GetService("ContentProvider"):Preload(hurtOverlayImage)
while not Game.Players.LocalPlayer do
wait(1/60)
end
---------------------------------------------------------------------
-- Functions
function CreateGui()
if HealthGui and #HealthGui:GetChildren() > 0 then
HealthGui.Parent = Game.CoreGui.RobloxGui
return
end
local hurtOverlay = Instance.new("ImageLabel")
hurtOverlay.Name = "HurtOverlay"
hurtOverlay.BackgroundTransparency = 1
hurtOverlay.Image = hurtOverlayImage
hurtOverlay.Position = UDim2.new(-10,0,-10,0)
hurtOverlay.Size = UDim2.new(20,0,20,0)
hurtOverlay.Visible = false
hurtOverlay.Parent = HealthGui
local healthFrame = Instance.new("Frame")
healthFrame.Name = "HealthFrame"
healthFrame.BackgroundColor3 = Color3.new(0,0,0)
healthFrame.BorderColor3 = Color3.new(0,0,0)
healthFrame.Position = UDim2.new(0.5,-85,1,-22)
healthFrame.Size = UDim2.new(0,170,0,18)
healthFrame.Parent = HealthGui
local healthBar = Instance.new("ImageLabel")
healthBar.Name = "HealthBar"
healthBar.BackgroundTransparency = 1
healthBar.Image = greenBarImage
healthBar.Size = UDim2.new(1,0,1,0)
healthBar.Parent = healthFrame
local healthLabel = Instance.new("TextLabel")
healthLabel.Name = "HealthLabel"
healthLabel.Text = "Health " -- gives room at end of health bar
healthLabel.Font = Enum.Font.SourceSansBold
healthLabel.FontSize = Enum.FontSize.Size14
healthLabel.TextColor3 = Color3.new(1,1,1)
healthLabel.TextStrokeTransparency = 0
healthLabel.TextXAlignment = Enum.TextXAlignment.Right
healthLabel.BackgroundTransparency = 1
healthLabel.Size = UDim2.new(1,0,1,0)
healthLabel.Parent = healthFrame
HealthGui.Parent = Game.CoreGui.RobloxGui
end
function UpdateGui(health)
if not HealthGui then return end
local healthFrame = HealthGui:FindFirstChild("HealthFrame")
if not healthFrame then return end
local healthBar = healthFrame:FindFirstChild("HealthBar")
if not healthBar then return end
-- If more than 1/4 health, bar = green. Else, bar = red.
local percentHealth = (health/currentHumanoid.MaxHealth)
if percentHealth ~= percentHealth then
percentHealth = 1
healthBar.Image = goldBarImage
elseif percentHealth > 0.25 then
healthBar.Image = greenBarImage
else
healthBar.Image = redBarImage
end
local width = (health / currentHumanoid.MaxHealth)
width = math.max(math.min(width,1),0) -- make sure width is between 0 and 1
if width ~= width then width = 1 end
local healthDelta = lastHealth - health
lastHealth = health
local percentOfTotalHealth = math.abs(healthDelta/currentHumanoid.MaxHealth)
percentOfTotalHealth = math.max(math.min(percentOfTotalHealth,1),0) -- make sure percentOfTotalHealth is between 0 and 1
if percentOfTotalHealth ~= percentOfTotalHealth then percentOfTotalHealth = 1 end
local newHealthSize = UDim2.new(width,0,1,0)
if healthBar:IsDescendantOf(Game) then
healthBar:TweenSize(newHealthSize, Enum.EasingDirection.InOut, Enum.EasingStyle.Linear, percentOfTotalHealth * maxBarTweenTime, true)
else
healthBar.Size = newHealthSize
end
local thresholdForHurtOverlay = currentHumanoid.MaxHealth * (HealthPercentageForOverlay/100)
if healthDelta >= thresholdForHurtOverlay then
AnimateHurtOverlay()
end
end
function AnimateHurtOverlay()
if not HealthGui then return end
local overlay = HealthGui:FindFirstChild("HurtOverlay")
if not overlay then return end
local newSize = UDim2.new(20, 0, 20, 0)
local newPos = UDim2.new(-10, 0, -10, 0)
if overlay:IsDescendantOf(Game) then
-- stop any tweens on overlay
overlay:TweenSizeAndPosition(newSize,newPos,Enum.EasingDirection.Out,Enum.EasingStyle.Linear,0,true,function()
-- show the gui
overlay.Size = UDim2.new(1,0,1,0)
overlay.Position = UDim2.new(0,0,0,0)
overlay.Visible = true
-- now tween the hide
if overlay:IsDescendantOf(Game) then
overlay:TweenSizeAndPosition(newSize,newPos,Enum.EasingDirection.Out,Enum.EasingStyle.Quad,10,false,function()
overlay.Visible = false
end)
else
overlay.Size = newSize
overlay.Position = newPos
end
end)
else
overlay.Size = newSize
overlay.Position = newPos
end
end
function humanoidDied()
UpdateGui(0)
end
function disconnectPlayerConnections()
if characterAddedConnection then characterAddedConnection:disconnect() end
if humanoidDiedConnection then humanoidDiedConnection:disconnect() end
if healthChangedConnection then healthChangedConnection:disconnect() end
end
function newPlayerCharacter()
disconnectPlayerConnections()
startGui()
end
function startGui()
characterAddedConnection = Game.Players.LocalPlayer.CharacterAdded:connect(newPlayerCharacter)
local character = Game.Players.LocalPlayer.Character
if not character then
return
end
currentHumanoid = character:WaitForChild("Humanoid")
if not currentHumanoid then
return
end
if not Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Health) then
return
end
healthChangedConnection = currentHumanoid.HealthChanged:connect(UpdateGui)
humanoidDiedConnection = currentHumanoid.Died:connect(humanoidDied)
UpdateGui(currentHumanoid.Health)
CreateGui()
end
---------------------------------------------------------------------
-- Start Script
HealthGui = Instance.new("Frame")
HealthGui.Name = "HealthGui"
HealthGui.BackgroundTransparency = 1
HealthGui.Size = UDim2.new(1,0,1,0)
Game.StarterGui.CoreGuiChangedSignal:connect(function(coreGuiType,enabled)
if coreGuiType == Enum.CoreGuiType.Health or coreGuiType == Enum.CoreGuiType.All then
if guiEnabled and not enabled then
if HealthGui then
HealthGui.Parent = nil
end
disconnectPlayerConnections()
elseif not guiEnabled and enabled then
startGui()
end
guiEnabled = enabled
end
end)
if Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Health) then
guiEnabled = true
startGui()
end

1038
app/files/CoreGui/157877000 Normal file

File diff suppressed because it is too large Load Diff

175
app/files/CoreGui/158948138 Normal file
View File

@ -0,0 +1,175 @@
-- Creates the generic "ROBLOX" loading screen on startup
-- Written by Ben Tkacheff, 2014
local frame
local forceRemovalTime = 5
local destroyed = false
Game:GetService("ContentProvider"):Preload("rbxasset://textures/roblox-logo.png")
-- get control functions set up immediately
function removeLoadingScreen()
if frame then frame:Destroy() end
if script then script:Destroy() end
destroyed = true
end
function startForceLoadingDoneTimer()
wait(forceRemovalTime)
removeLoadingScreen()
end
function gameIsLoaded()
if Game.ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
removeLoadingScreen()
else
startForceLoadingDoneTimer()
end
end
function makeDefaultLoadingScreen()
if not settings():GetFFlag("NewLoadingScreen") then return end
if destroyed then return end
frame = Instance.new("Frame")
frame.ZIndex = 10
frame.Active = true
frame.Size = UDim2.new(1,0,1,0)
frame.BackgroundColor3 = Color3.new(48/255,90/255,206/255)
local robloxLogo = Instance.new("ImageLabel")
robloxLogo.BackgroundTransparency = 1
robloxLogo.ZIndex = 10
robloxLogo.Image = "rbxasset://textures/roblox-logo.png"
robloxLogo.Size = UDim2.new(0,1031,0,265)
robloxLogo.Position = UDim2.new(0.5,-515,0.5,-132)
robloxLogo.Name = "RobloxLogo"
robloxLogo.Parent = frame
local poweredByText = Instance.new("TextLabel")
poweredByText.Font = Enum.Font.SourceSansBold
poweredByText.FontSize = Enum.FontSize.Size24
poweredByText.TextWrap = true
poweredByText.TextColor3 = Color3.new(1,1,1)
poweredByText.BackgroundTransparency = 1
poweredByText.ZIndex = 10
poweredByText.Text = "This Game Powered By"
poweredByText.TextXAlignment = Enum.TextXAlignment.Left
poweredByText.Size = UDim2.new(1,0,0,40)
poweredByText.Position = UDim2.new(0,0,0,-50)
poweredByText.Name = "PoweredByText"
poweredByText.Parent = robloxLogo
local exitButton = Instance.new("ImageButton")
exitButton.ZIndex = 10
exitButton.BackgroundTransparency = 1
exitButton.Image = "rbxasset://textures/ui/CloseButton.png"
exitButton.Size = UDim2.new(0,22,0,22)
exitButton.Position = UDim2.new(1,-23,0,1)
exitButton.Name = "ExitButton"
exitButton:SetVerb("Exit")
UserSettings().GameSettings.FullscreenChanged:connect(function ( isFullScreen )
if isFullScreen then
exitButton.Parent = frame
else
exitButton.Parent = nil
end
end)
if UserSettings().GameSettings:InFullScreen()then
exitButton.Parent = frame
end
-- put something visible up asap
frame.Parent = Game.CoreGui.RobloxGui
local instanceText = Instance.new("TextLabel")
instanceText.Font = Enum.Font.SourceSansBold
instanceText.FontSize = Enum.FontSize.Size18
instanceText.TextWrap = true
instanceText.TextColor3 = Color3.new(1,1,1)
instanceText.BackgroundTransparency = 1
instanceText.ZIndex = 10
instanceText.Text = ""
instanceText.Size = UDim2.new(1,0,0,40)
instanceText.Position = UDim2.new(0,0,1,-60)
instanceText.Name = "InstanceText"
instanceText.Parent = frame
local loadingText = Instance.new("TextLabel")
loadingText.Font = Enum.Font.SourceSansBold
loadingText.FontSize = Enum.FontSize.Size36
loadingText.TextWrap = true
loadingText.TextColor3 = Color3.new(1,1,1)
loadingText.BackgroundTransparency = 1
loadingText.ZIndex = 10
loadingText.Text = "Loading"
loadingText.Size = UDim2.new(1,0,0,40)
loadingText.Position = UDim2.new(0,0,1,20)
loadingText.Name = "LoadingText"
loadingText.Parent = robloxLogo
local howManyDots = 0
local lastUpdateTime = tick()
local minUpdateTime = 0.3
local aspectRatio = 1031/265
function ResolutionChanged( prop )
if prop == "AbsoluteSize" then
local size = Game.CoreGui.RobloxGui.AbsoluteSize
if size.X >= 1031 then
robloxLogo.Size = UDim2.new(0,1031,0,265)
robloxLogo.Position = UDim2.new(0.5,-515,0.5,-132)
else
local sizeReducer = -0.05
while size.X < robloxLogo.AbsoluteSize.X do
robloxLogo.Size = UDim2.new(sizeReducer,1031,0,265)
local newY = robloxLogo.AbsoluteSize.X * 265/1031
robloxLogo.Size = UDim2.new(sizeReducer,1031,0,newY)
robloxLogo.Position = UDim2.new(0.5 - (sizeReducer/2),-515,0.5,-132)
sizeReducer = sizeReducer - 0.1
end
end
end
end
ResolutionChanged("AbsoluteSize")
Game.CoreGui.RobloxGui.Changed:connect(ResolutionChanged)
Game:GetService("RunService").RenderStepped:connect(function()
instanceText.Text = Game:GetMessage()
if tick() - lastUpdateTime >= minUpdateTime then
howManyDots = howManyDots + 1
if howManyDots > 5 then
howManyDots = 0
end
loadingText.Text = "Loading"
for i = 1, howManyDots do
loadingText.Text = loadingText.Text .. "."
end
lastUpdateTime = tick()
end
end)
end
makeDefaultLoadingScreen()
Game.ReplicatedFirst.RemoveDefaultLoadingGuiSignal:connect(function()
removeLoadingScreen()
end)
if Game.ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
removeLoadingScreen()
return
end
Game.Loaded:connect(function()
gameIsLoaded()
end)
if Game:IsLoaded() then
gameIsLoaded()
end

290
app/files/CoreGui/35914081 Normal file
View File

@ -0,0 +1,290 @@
-- creates the in-game gui sub menus for property tools
-- written 9/27/2010 by Ben (jeditkacheff)
local gui = script.Parent
if gui:FindFirstChild("ControlFrame") then
gui = gui:FindFirstChild("ControlFrame")
end
local currentlySelectedButton = nil
local localAssetBase = "rbxasset://textures/ui/"
local selectedButton = Instance.new("ObjectValue")
selectedButton.RobloxLocked = true
selectedButton.Name = "SelectedButton"
selectedButton.Parent = gui.BuildTools
local closeButton = Instance.new("ImageButton")
closeButton.Name = "CloseButton"
closeButton.RobloxLocked = true
closeButton.BackgroundTransparency = 1
closeButton.Image = localAssetBase .. "CloseButton.png"
closeButton.ZIndex = 2
closeButton.Size = UDim2.new(0.2,0,0.05,0)
closeButton.AutoButtonColor = false
closeButton.Position = UDim2.new(0.75,0,0.01,0)
function setUpCloseButtonState(button)
button.MouseEnter:connect(function()
button.Image = localAssetBase .. "CloseButton_dn.png"
end)
button.MouseLeave:connect(function()
button.Image = localAssetBase .. "CloseButton.png"
end)
button.MouseButton1Click:connect(function()
button.ClosedState.Value = true
button.Image = localAssetBase .. "CloseButton.png"
end)
end
-- nice selection animation
function fadeInButton(button)
if currentlySelectedButton ~= nil then
currentlySelectedButton.Selected = false
currentlySelectedButton.ZIndex = 2
currentlySelectedButton.Frame.BackgroundTransparency = 1
end
local speed = 0.1
button.ZIndex = 3
while button.Frame.BackgroundTransparency > 0 do
button.Frame.BackgroundTransparency = button.Frame.BackgroundTransparency - speed
wait()
end
button.Selected = true
currentlySelectedButton = button
selectedButton.Value = currentlySelectedButton
end
------------------------------- create the color selection sub menu -----------------------------------
local paintMenu = Instance.new("ImageLabel")
local paintTool = gui.BuildTools.Frame.PropertyTools.PaintTool
paintMenu.Name = "PaintMenu"
paintMenu.RobloxLocked = true
paintMenu.Parent = paintTool
paintMenu.Position = UDim2.new(-2.7,0,-3,0)
paintMenu.Size = UDim2.new(2.5,0,10,0)
paintMenu.BackgroundTransparency = 1
paintMenu.ZIndex = 2
paintMenu.Image = localAssetBase .. "PaintMenu.png"
local paintColorButton = Instance.new("ImageButton")
paintColorButton.RobloxLocked = true
paintColorButton.BorderSizePixel = 0
paintColorButton.ZIndex = 2
paintColorButton.Size = UDim2.new(0.200000003, 0,0.0500000007, 0)
local selection = Instance.new("Frame")
selection.RobloxLocked = true
selection.BorderSizePixel = 0
selection.BackgroundColor3 = Color3.new(1,1,1)
selection.BackgroundTransparency = 1
selection.ZIndex = 2
selection.Size = UDim2.new(1.1,0,1.1,0)
selection.Position = UDim2.new(-0.05,0,-0.05,0)
selection.Parent = paintColorButton
local header = 0.08
local spacing = 18
local count = 1
function findNextColor()
colorName = tostring(BrickColor.new(count))
while colorName == "Medium stone grey" do
count = count + 1
colorName = tostring(BrickColor.new(count))
end
return count
end
for i = 0,15 do
for j = 1, 4 do
newButton = paintColorButton:clone()
newButton.RobloxLocked = true
newButton.BackgroundColor3 = BrickColor.new(findNextColor()).Color
newButton.Name = tostring(BrickColor.new(count))
count = count + 1
if j == 1 then newButton.Position = UDim2.new(0.08,0,i/spacing + header,0)
elseif j == 2 then newButton.Position = UDim2.new(0.29,0,i/spacing + header,0)
elseif j == 3 then newButton.Position = UDim2.new(0.5,0,i/spacing + header,0)
elseif j == 4 then newButton.Position = UDim2.new(0.71,0,i/spacing + header,0) end
newButton.Parent = paintMenu
end
end
local paintButtons = paintMenu:GetChildren()
for i = 1, #paintButtons do
paintButtons[i].MouseButton1Click:connect(function()
fadeInButton(paintButtons[i])
end)
end
local paintCloseButton = closeButton:clone()
paintCloseButton.RobloxLocked = true
paintCloseButton.Parent = paintMenu
local closedState = Instance.new("BoolValue")
closedState.RobloxLocked = true
closedState.Name = "ClosedState"
closedState.Parent = paintCloseButton
setUpCloseButtonState(paintCloseButton)
------------------------------- create the material selection sub menu -----------------------------------
local materialMenu = Instance.new("ImageLabel")
local materialTool = gui.BuildTools.Frame.PropertyTools.MaterialSelector
materialMenu.RobloxLocked = true
materialMenu.Name = "MaterialMenu"
materialMenu.Position = UDim2.new(-4,0,-3,0)
materialMenu.Size = UDim2.new(2.5,0,6.5,0)
materialMenu.BackgroundTransparency = 1
materialMenu.ZIndex = 2
materialMenu.Image = localAssetBase .. "MaterialMenu.png"
materialMenu.Parent = materialTool
local textures = {"Plastic","Wood","Slate","CorrodedMetal","Ice","Grass","Foil","DiamondPlate","Concrete"}
local materialButtons = {}
local materialButton = Instance.new("ImageButton")
materialButton.RobloxLocked = true
materialButton.BackgroundTransparency = 1
materialButton.Size = UDim2.new(0.400000003, 0,0.16, 0)
materialButton.ZIndex = 2
selection.Parent = materialButton
local current = 1
function getTextureAndName(button)
if current > #textures then
button:remove()
return false
end
button.Image = localAssetBase .. textures[current] .. ".png"
button.Name = textures[current]
current = current + 1
return true
end
local ySpacing = 0.10
local xSpacing = 0.07
for i = 1,5 do
for j = 1,2 do
local button = materialButton:clone()
button.RobloxLocked = true
button.Position = UDim2.new((j -1)/2.2 + xSpacing,0,ySpacing + (i - 1)/5.5,0)
if getTextureAndName(button) then button.Parent = materialMenu else button:remove() end
table.insert(materialButtons,button)
end
end
for i = 1, #materialButtons do
materialButtons[i].MouseButton1Click:connect(function()
fadeInButton(materialButtons[i])
end)
end
local materialCloseButton = closeButton:clone()
materialCloseButton.RobloxLocked = true
materialCloseButton.Size = UDim2.new(0.2,0,0.08,0)
materialCloseButton.Parent = materialMenu
local closedState = Instance.new("BoolValue")
closedState.RobloxLocked = true
closedState.Name = "ClosedState"
closedState.Parent = materialCloseButton
setUpCloseButtonState(materialCloseButton)
------------------------------- create the surface selection sub menu -----------------------------------
local surfaceMenu = Instance.new("ImageLabel")
local surfaceTool = gui.BuildTools.Frame.PropertyTools.InputSelector
surfaceMenu.RobloxLocked = true
surfaceMenu.Name = "SurfaceMenu"
surfaceMenu.Position = UDim2.new(-2.6,0,-4,0)
surfaceMenu.Size = UDim2.new(2.5,0,5.5,0)
surfaceMenu.BackgroundTransparency = 1
surfaceMenu.ZIndex = 2
surfaceMenu.Image = localAssetBase .. "SurfaceMenu.png"
surfaceMenu.Parent = surfaceTool
textures = {"Smooth", "Studs", "Inlets", "Universal", "Glue", "Weld", "Hinge", "Motor"}
current = 1
local surfaceButtons = {}
local surfaceButton = Instance.new("ImageButton")
surfaceButton.RobloxLocked = true
surfaceButton.BackgroundTransparency = 1
surfaceButton.Size = UDim2.new(0.400000003, 0,0.19, 0)
surfaceButton.ZIndex = 2
selection.Parent = surfaceButton
local ySpacing = 0.14
local xSpacing = 0.07
for i = 1,4 do
for j = 1,2 do
local button = surfaceButton:clone()
button.RobloxLocked = true
button.Position = UDim2.new((j -1)/2.2 + xSpacing,0,ySpacing + (i - 1)/4.6,0)
getTextureAndName(button)
button.Parent = surfaceMenu
table.insert(surfaceButtons,button)
end
end
for i = 1, #surfaceButtons do
surfaceButtons[i].MouseButton1Click:connect(function()
fadeInButton(surfaceButtons[i])
end)
end
local surfaceMenuCloseButton = closeButton:clone()
surfaceMenuCloseButton.RobloxLocked = true
surfaceMenuCloseButton.Size = UDim2.new(0.2,0,0.09,0)
surfaceMenuCloseButton.Parent = surfaceMenu
local closedState = Instance.new("BoolValue")
closedState.RobloxLocked = true
closedState.Name = "ClosedState"
closedState.Parent = surfaceMenuCloseButton
setUpCloseButtonState(surfaceMenuCloseButton)
if game.CoreGui.Version >= 2 then
local function setupTweenTransition(button, menu, outXScale, inXScale)
button.Changed:connect(
function(property)
if property ~= "Selected" then
return
end
if button.Selected then
menu:TweenPosition(UDim2.new(inXScale, menu.Position.X.Offset, menu.Position.Y.Scale, menu.Position.Y.Offset),
Enum.EasingDirection.Out, Enum.EasingStyle.Quart, 1, true)
else
menu:TweenPosition(UDim2.new(outXScale, menu.Position.X.Offset, menu.Position.Y.Scale, menu.Position.Y.Offset),
Enum.EasingDirection.In, Enum.EasingStyle.Quart, 0.5, true)
end
end)
end
setupTweenTransition(paintTool, paintMenu, -2.7, 2.6)
setupTweenTransition(surfaceTool, surfaceMenu, -2.6, 2.6)
setupTweenTransition(materialTool, materialMenu, -4, 1.4)
end

View File

@ -0,0 +1,70 @@
-- this script is responsible for keeping the gui proportions under control
local screen = script.Parent
local BottomLeftControl
local BottomRightControl
local TopLeftControl
local BuildTools
local controlFrame = script.Parent:FindFirstChild("ControlFrame")
local loadoutPadding = 43
local currentLoadout
BottomLeftControl = controlFrame:FindFirstChild("BottomLeftControl")
BottomRightControl = controlFrame:FindFirstChild("BottomRightControl")
TopLeftControl = controlFrame:FindFirstChild("TopLeftControl")
currentLoadout = script.Parent:FindFirstChild("CurrentLoadout")
BuildTools = controlFrame:FindFirstChild("BuildTools")
function makeYRelative()
BottomLeftControl.SizeConstraint = 2
BottomRightControl.SizeConstraint = 2
if TopLeftControl then TopLeftControl.SizeConstraint = 2 end
if currentLoadout then currentLoadout.SizeConstraint = 2 end
if BuildTools then BuildTools.Frame.SizeConstraint = 2 end
BottomLeftControl.Position = UDim2.new(0,0,1,-BottomLeftControl.AbsoluteSize.Y)
BottomRightControl.Position = UDim2.new(1,-BottomRightControl.AbsoluteSize.X,1,-BottomRightControl.AbsoluteSize.Y)
end
function makeXRelative()
BottomLeftControl.SizeConstraint = 1
BottomRightControl.SizeConstraint = 1
if TopLeftControl then TopLeftControl.SizeConstraint = 1 end
if currentLoadout then currentLoadout.SizeConstraint = 1 end
if BuildTools then BuildTools.Frame.SizeConstraint = 1 end
BottomLeftControl.Position = UDim2.new(0,0,1,-BottomLeftControl.AbsoluteSize.Y)
BottomRightControl.Position = UDim2.new(1,-BottomRightControl.AbsoluteSize.X,1,-BottomRightControl.AbsoluteSize.Y)
end
local function resize()
if screen.AbsoluteSize.x > screen.AbsoluteSize.y then
makeYRelative()
else
makeXRelative()
end
if currentLoadout then
currentLoadout.Position =
UDim2.new(0,screen.AbsoluteSize.X/2 -currentLoadout.AbsoluteSize.X/2,currentLoadout.Position.Y.Scale,-currentLoadout.AbsoluteSize.Y - loadoutPadding)
end
end
screen.Changed:connect(function(property)
if property == "AbsoluteSize" then
wait()
resize()
end
end)
wait()
resize()

View File

@ -0,0 +1,35 @@
-- this script is responsible for moving the material menu in and out when selected/deselected
local button = script.Parent
local activated = false
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForChild(script.Parent,"PaintMenu")
local menu = script.Parent:FindFirstChild("PaintMenu")
local moving = false
local speed = 0.35
button.Changed:connect(function(property)
if property ~= "Selected" then return end
if moving then return end
moving = true activated = button.Selected
if activated then
while menu.Position.X.Scale < 2.6 do
menu.Position = UDim2.new(menu.Position.X.Scale + speed,menu.Position.X.Offset,menu.Position.Y.Scale,menu.Position.Y.Offset)
wait()
end
else
while menu.Position.X.Scale > -2.7 do
menu.Position = UDim2.new(menu.Position.X.Scale - speed,menu.Position.X.Offset,menu.Position.Y.Scale,menu.Position.Y.Offset)
wait()
end
end
moving = false
end)

View File

@ -0,0 +1,36 @@
-- this script is responsible for moving the surface menu in and out when selected/deselected
local button = script.Parent
local activated = false
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForChild(script.Parent,"SurfaceMenu")
local menu = script.Parent:FindFirstChild("SurfaceMenu")
local speed = 0.35
local moving = false
button.Changed:connect(function(property)
if property ~= "Selected" then return end
if moving then return end
moving = true
activated = button.Selected
if activated then
while menu.Position.X.Scale < 2.6 do
menu.Position = UDim2.new(menu.Position.X.Scale + speed,menu.Position.X.Offset,menu.Position.Y.Scale,menu.Position.Y.Offset)
wait()
end
else
while menu.Position.X.Scale > -2.6 do
menu.Position = UDim2.new(menu.Position.X.Scale - speed,menu.Position.X.Offset,menu.Position.Y.Scale,menu.Position.Y.Offset)
wait()
end
end
moving = false end)

View File

@ -0,0 +1,36 @@
-- this script is responsible for moving the material menu in and out when selected/deselected
local button = script.Parent
local activated = false
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForChild(script.Parent,"MaterialMenu")
local menu = script.Parent:FindFirstChild("MaterialMenu")
local moving = false
local speed = 0.35
button.Changed:connect(function(property)
if property ~= "Selected" then return end
if moving then return end
moving = true
activated = button.Selected
if activated then
while menu.Position.X.Scale < 1.4 do
menu.Position = UDim2.new(menu.Position.X.Scale + speed,menu.Position.X.Offset,menu.Position.Y.Scale,menu.Position.Y.Offset)
wait()
end
else
while menu.Position.X.Scale > -4 do
menu.Position = UDim2.new(menu.Position.X.Scale - speed,menu.Position.X.Offset,menu.Position.Y.Scale,menu.Position.Y.Offset)
wait()
end
end
moving = false end)

707
app/files/CoreGui/36051740 Normal file
View File

@ -0,0 +1,707 @@
--[[if game.Players.LocalPlayer.Name == "Player" then
return
end]]
-- Script Globals
local buildDeleteID = 36738185
local buildStamperID = 87198196
local buildGroupDraggerID = 36334760
local buildConfigID = 87240571
local buildRotateID = 0
local buildTools = {}
local player = nil
local backpack = nil
-- Functions
local function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
function getLatestPlayer()
waitForProperty(game.Players,"LocalPlayer")
player = game.Players.LocalPlayer
waitForChild(player,"Backpack")
backpack = player.Backpack
end
function backpackHasTool(tool)
local backpackChildren = backpack:GetChildren()
for i = 1, #backpackChildren do
if backpackChildren[i] == tool then
return true
end
end
return false
end
function getToolAssetID(assetID,toolName)
local newTool = game:GetService("InsertService"):LoadAsset(assetID)
newTool = newTool:FindFirstChild(toolName)
return newTool
end
function giveAssetId(assetID,toolName)
local theTool = getToolAssetID(assetID,toolName)
if theTool and not backpackHasTool(theTool) then
theTool.Parent = backpack
table.insert(buildTools,theTool)
end
end
function givePlayerBuildTools()
getLatestPlayer()
giveAssetId(buildStamperID,"StamperTool")
giveAssetId(buildDeleteID,"BuildDelete")
giveAssetId(buildGroupDraggerID,"BuildGroupDragger")
giveAssetId(buildRotateID,"BuildRotate")
giveAssetId(buildConfigID,"BuildConfiguration")
end
function takePlayerBuildTools()
for k,v in ipairs(buildTools) do
v.Parent = nil
end
buildTools = {}
end
print("start script")
-- Start Script
if game.CoreGui.RobloxGui.ControlFrame.BottomLeftControl:FindFirstChild("ToolButton") then -- we are still using old build tools (TODO: remove this when new tools are good enough)
print("old tools")
local localAssetBase = "rbxasset://textures/ui/"
local control = script.Parent:FindFirstChild("ControlFrame")
local bottomLeftControls
local buildTools
if control then
bottomLeftControls = control.BottomLeftControl
buildTools = control.BuildTools
else
bottomLeftControls = script.Parent.BottomLeftControl
buildTools = script.Parent.BuildTools
end
buildToolsVisible = false
-- used right now to push build tools down a bit (should change in client)
buildTools.Frame.Position = UDim2.new(-0.15,0,0.3,0)
bottomLeftControls.ToolButton.Image = localAssetBase .. "ToolButton.png"
local prevObject = nil
local tryCount = 0
local location = 0
local name
local buttons = {}
local value
local player
local backpack
local resetCon
local equippedTool
local selectedButton
-- the build tools
local buildResize
local buildClone
local buildInsert
local buildDragger
local buildColor
local buildGroupDragger
local buildSurface
local buildMaterial
local buildConfiguration
local buildDelete
-- the build tools asset ids
local buildResizeID = 36738142
local buildCloneID = 36017373
local buildInsertID = 36431591
local buildDraggerID = 36068233
local buildColorID = 35205409
local buildGroupDraggerID = 36334760
local buildSurfaceID = 35226945
local buildMaterialID = 35223828
local buildConfigurationID = 36270159
local buildDeleteID = 36738185
function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
function setPlayerAndBackpack()
waitForProperty(game.Players,"LocalPlayer")
player = game.Players.LocalPlayer
backpack = player.Backpack
end
setPlayerAndBackpack()
function playerReset()
loadTools()
local prevObject = nil
local equippedTool = nil
setPlayerAndBackpack()
resetCon:disconnect()
resetCon = game.Players.LocalPlayer.CharacterAdded:connect(playerReset)
end
resetCon = game.Players.LocalPlayer.CharacterAdded:connect(playerReset)
function giveSelectedValue(tool)
if tool:FindFirstChild("SelectedButton") == nil then
local selected = Instance.new("ObjectValue")
selected.Name = "SelectedButton"
selected.RobloxLocked = true
if tool.Name == "BuildConfiguration" then
selected.Value = buildTools.Frame.MiscTools.PropertyTool
elseif tool.Name == "BuildInsert" then
selected.Value = buildTools.Frame
end
selected.Parent = tool
end
end
function loadTools()
-- load in all tools to decrease issues with loading, also don't have to keep reloading assets
buildResize = game:GetService("InsertService"):LoadAsset(buildResizeID)
buildResize = buildResize:FindFirstChild("BuildResize")
giveSelectedValue(buildResize)
buildResize.Parent = backpack
buildClone = game:GetService("InsertService"):LoadAsset(buildCloneID)
buildClone = buildClone:FindFirstChild("BuildClone")
giveSelectedValue(buildClone)
buildClone.Parent = backpack
buildInsert = game:GetService("InsertService"):LoadAsset(buildInsertID)
buildInsert = buildInsert:FindFirstChild("BuildInsert")
giveSelectedValue(buildInsert)
buildInsert.Parent = backpack
buildDragger = game:GetService("InsertService"):LoadAsset(buildDraggerID)
buildDragger = buildDragger:FindFirstChild("BuildDragger")
giveSelectedValue(buildDragger)
buildDragger.Parent = backpack
buildColor = game:GetService("InsertService"):LoadAsset(buildColorID)
buildColor = buildColor:FindFirstChild("BuildColorTester")
giveSelectedValue(buildColor)
buildColor.Parent = backpack
buildGroupDragger = game:GetService("InsertService"):LoadAsset(buildGroupDraggerID)
buildGroupDragger = buildGroupDragger:FindFirstChild("BuildGroupDragger")
giveSelectedValue(buildGroupDragger)
buildGroupDragger.Parent = backpack
buildSurface = game:GetService("InsertService"):LoadAsset(buildSurfaceID)
buildSurface = buildSurface:FindFirstChild("BuildSurfaceTest")
giveSelectedValue(buildSurface)
buildSurface.Parent = backpack
buildMaterial = game:GetService("InsertService"):LoadAsset(buildMaterialID)
buildMaterial = buildMaterial:FindFirstChild("BuildMaterialTest")
giveSelectedValue(buildMaterial)
buildMaterial.Parent = backpack
buildConfiguration = game:GetService("InsertService"):LoadAsset(buildConfigurationID)
buildConfiguration = buildConfiguration:FindFirstChild("BuildConfiguration")
giveSelectedValue(buildConfiguration)
buildConfiguration.Parent = backpack
buildDelete = game:GetService("InsertService"):LoadAsset(buildDeleteID)
buildDelete = buildDelete:FindFirstChild("BuildDelete")
giveSelectedValue(buildDelete)
buildDelete.Parent = backpack
end
loadTools()
waitForChild(buildTools,"SelectedButton")
buildTools.SelectedButton.Changed:connect(function(property)
if value == buildTools.SelectedButton.Value then return end
value = buildTools.SelectedButton.Value
selectedButton = buildTools.SelectedButton.Value
if equippedTool then
equippedTool.SelectedButton.Value = selectedButton
end
end)
local frames = buildTools.Frame:GetChildren()
for i = 1, #frames do
if frames[i]:IsA("Frame") and frames[i].Name ~= "Divs" then
local buttonSubSet = frames[i]:GetChildren()
for j = 1, #buttonSubSet do
table.insert(buttons,buttonSubSet[j])
end
end
end
function unEquipAnyItems()
playerItems = player.Character:GetChildren()
for i = 1, #playerItems do
if playerItems[i]:isA("Tool") or playerItems[i]:isA("HopperBin") then
playerItems[i].Parent = backpack
return
end
end
end
unEquipAnyItems()
--------------------- Build Bar Tool Tip Code -----------------------------
function setUpText(toolTip)
local name = toolTip.Parent.Name
if name == "CloneObject" then toolTip.Text = "Copy Part"
elseif name == "DeleteObject" then toolTip.Text = "Delete Part"
elseif name == "InsertObject" then toolTip.Text = "Insert Part"
elseif name == "PropertyTool" then toolTip.Text = "Edit Part"
elseif name == "GroupMove" then toolTip.Text = "Move Models and Parts"
elseif name == "PartMove" then toolTip.Text = "Move Parts"
elseif name == "ScaleObject" then toolTip.Text = "Resize a part"
elseif name == "InputSelector" then toolTip.Text = "Change Surface"
elseif name == "MaterialSelector" then toolTip.Text = "Change Material"
elseif name == "PaintTool" then toolTip.Text = "Change Color" end
end
local fadeSpeed = 0.1
function buildToolsTips()
local frame = Instance.new("TextLabel")
frame.Name = "ToolTip"
frame.Text = "Hi! I'm a ToolTip!"
frame.ZIndex = 10
frame.Size = UDim2.new(2,0,1,0)
frame.Position = UDim2.new(1,0,0,0)
frame.BackgroundColor3 = Color3.new(1,1,153/255)
frame.BackgroundTransparency = 1
frame.TextTransparency = 1
frame.TextWrap = true
for i = 1, #buttons do
local tip = frame:Clone()
tip.RobloxLocked = true
tip.Parent = buttons[i]
setUpText(tip)
local inside = Instance.new("BoolValue")
inside.Value = false
inside.RobloxLocked = true
tip.Parent.MouseEnter:connect(function()
inside.Value = true
wait(1.2)
if inside.Value then
while inside.Value and tip.BackgroundTransparency > 0 do
tip.BackgroundTransparency = tip.BackgroundTransparency - fadeSpeed
tip.TextTransparency = tip.TextTransparency - fadeSpeed
wait()
end
end
end)
tip.Parent.MouseLeave:connect(function()
inside.Value = false
tip.BackgroundTransparency = 1
tip.TextTransparency = 1
end)
tip.Parent.MouseButton1Click:connect(function()
inside.Value = false
tip.BackgroundTransparency = 1
tip.TextTransparency = 1
end)
end
end
--------------------- End Build Bar Tool Tip Code --------------------------
----------------------------- Reset Button Code ----------------------------
function reset(subset)
local buttons = subset:GetChildren()
if subset.Name == "AddDeleteTools" then
for i = 1, #buttons do
buttons[i].Selected = false
if buttons[i].Name == "CloneObject" then buttons[i].Image = localAssetBase .. "CloneButton.png"
elseif buttons[i].Name == "DeleteObject" then buttons[i].Image = localAssetBase .. "DeleteButton.png"
elseif buttons[i].Name == "InsertObject" then buttons[i].Image = localAssetBase .. "InsertButton.png" end
end
elseif subset.Name == "MiscTools" then
for i = 1, #buttons do
buttons[i].Selected = false
if buttons[i].Name == "PropertyTool" then buttons[i].Image = localAssetBase .. "PropertyButton.png" end
end
elseif subset.Name == "PhysicalTools" then
for i = 1, #buttons do
buttons[i].Selected = false
if buttons[i].Name == "GroupMove" then buttons[i].Image = localAssetBase .. "GroupMoveButton.png"
elseif buttons[i].Name == "PartMove" then buttons[i].Image = localAssetBase .."PartMoveButton.png"
elseif buttons[i].Name == "ScaleObject" then buttons[i].Image = localAssetBase .. "ScaleButton.png" end
end
elseif subset.Name == "PropertyTools" then
for i = 1, #buttons do
buttons[i].Selected = false
if buttons[i].Name == "InputSelector" then buttons[i].Image = localAssetBase .. "SurfaceButton.png"
elseif buttons[i].Name == "MaterialSelector" then buttons[i].Image = localAssetBase .. "MaterialButton.png"
elseif buttons[i].Name == "PaintTool" then buttons[i].Image = localAssetBase .. "PaintButton.png" end
end
end
end
function resetAllButtons()
local categories = buildTools.Frame:GetChildren()
for i = 1, #categories do
reset(categories[i])
end
end
----------------------------- End Reset Button Code -------------------------
resetAllButtons()
-- sets button to active image
function setButtonStateActive(Object, Name)
if Name == "BuildInsert" then Object.Image = localAssetBase .. "InsertButton_dn.png" Object.Selected = true
elseif Name == "BuildDelete" then Object.Image = localAssetBase .. "DeleteButton_dn.png" Object.Selected = true
elseif Name == "BuildClone" then Object.Image = localAssetBase .. "CloneButton_dn.png" Object.Selected = true
elseif Name == "BuildConfiguration" then Object.Image = localAssetBase .. "PropertyButton_dn.png" Object.Selected = true
elseif Name == "BuildDragger" then Object.Image = localAssetBase .. "PartMoveButton_dn.png" Object.Selected = true
elseif Name == "BuildGroupDragger" then Object.Image = localAssetBase .. "GroupMoveButton_dn.png" Object.Selected = true
elseif Name == "BuildResize" then Object.Image = localAssetBase .. "ScaleButton_dn.png" Object.Selected = true
elseif Name == "BuildSurfaceTest" then Object.Image = localAssetBase .. "SurfaceButton_dn.png" Object.Selected = true
elseif Name == "BuildMaterialTest" then Object.Image = localAssetBase .. "MaterialButton_dn.png" Object.Selected = true
elseif Name == "BuildColorTester" then Object.Image = localAssetBase .. "PaintButton_dn.png" Object.Selected = true
end
end
function removeTool(tool, Object)
playerItems = player.Characer:GetChildren()
for i = 1, #playerItems do
if playerItems[i].Name == tool and playerItems[i]:isA("Tool") then
playerItems[i].Parent = backpack
playerItems[i]:remove()
return
end
end
backpackStuff = backpack:GetChildren()
for i = 1, #backpackStuff do
if backpackStuff[i].Name == tool then
backpackStuff[i].Parent = nil
backpackStuff[i]:remove()
return
end
end
end
function getTool(tool)
playerItems = player.Character:GetChildren()
for i = 1, #playerItems do
if playerItems[i].Name == tool then
if playerItems[i]:isA("Tool") then return playerItems[i], true end
end
end
backpackStuff = backpack:GetChildren()
for i = 1, #backpackStuff do
if backpackStuff[i].Name == tool then
return backpackStuff[i], false
end
end
end
function toolDeselection(Name,Object,id)
local hasTool, equipped = getTool(Name)
if equipped then
resetAllButtons()
unEquipAnyItems()
hasTool.Parent = nil
hasTool:remove()
if equippedTool then
equippedTool.Parent = nil
equippedTool:remove()
equippedTool = nil
end
end
end
-- Used to find allocated tool that we got at beginning of script
function getToolLocal(Name)
if Name == "BuildInsert" then return buildInsert
elseif Name == "BuildDelete" then return buildDelete
elseif Name == "BuildClone" then return buildClone
elseif Name == "BuildConfiguration" then return buildConfiguration
elseif Name == "BuildDragger" then return buildDragger
elseif Name == "BuildGroupDragger" then return buildGroupDragger
elseif Name == "BuildResize" then return buildResize
elseif Name == "BuildSurfaceTest" then return buildSurface
elseif Name == "BuildMaterialTest" then return buildMaterial
elseif Name == "BuildColorTester" then return buildColor
end
end
function assureTool(tool, id, Name)
if tool == nil or type(tool) ~= "userdata" or tool:FindFirstChild("Handle") == nil then
tool = game:GetService("InsertService"):LoadAsset(id)
local instances = tool:GetChildren()
if #instances == 0 then
tool:Remove()
return nil
end
tool = tool:FindFirstChild(Name)
tool.Parent = backpack
end
end
-- general function to get tool when button is clicked
function toolSelection(Name,Object,id)
local tool = nil
local hasTool, equipped = getTool(Name)
if equipped then
if hasTool:FindFirstChild("SelectedButton") == false then
giveSelectedValue(hasTool)
end
resetAllButtons()
unEquipAnyItems()
hasTool.Parent = nil
if equippedTool ~= nil then
equippedTool.Parent = backpack
end
elseif hasTool then
-- failsafe to make sure we load in tool, no matter what
assureTool(hasTool,id, Name)
if hasTool == nil then return nil end
unEquipAnyItems()
Object.Selected = true
hasTool.Parent = player.Character
equippedTool = hasTool
hasTool.Unequipped:connect(function() resetAllButtons() end)
setButtonStateActive(Object, Name)
else
-- first try to find tool we already loaded in
tool = getToolLocal(Name)
-- failsafe to make sure we load in tool, no matter what
assureTool(tool,id, Name)
if tool == nil then return nil end
if tool then
if tool:FindFirstChild("SelectedButton") == nil then
local selected = Instance.new("ObjectValue")
selected.Name = "SelectedButton"
selected.RobloxLocked = true
if Name == "BuildConfiguration" then
selected.Value = buildTools.Frame.MiscTools.PropertyTool
elseif Name == "BuildInsert" then
selected.Value = buildTools.Frame
end
selected.Parent = tool
end
unEquipAnyItems()
if equippedTool ~= nil then
if prevObject then resetAllButtons() end
equippedTool.Parent = backpack
end
equippedTool = tool
equippedTool.Parent = player.Character
Object.Selected = true
equippedTool.Unequipped:connect(function() resetAllButtons() end)
setButtonStateActive(Object, Name)
end
end
prevObject = Object
end
-- used to animate the tool bar open/close
local scrollSpeed = 0.01
function openCloseTools()
buildToolsVisible = not buildToolsVisible
if buildToolsVisible then
bottomLeftControls.ToolButton.Image = localAssetBase .. "ToolButton_dn.png"
buildTools.Frame.CloseButton.Image = localAssetBase .. "CloseButton.png"
buildTools.Frame.Size = UDim2.new(0.15,0,0.57,0)
buildTools.Frame.Position = UDim2.new(-0.1, 0,buildTools.Frame.Position.Y.Scale,0)
while buildTools.Frame.Position.X.Scale < -0.01 and buildToolsVisible do
buildTools.Frame.Position = UDim2.new(buildTools.Frame.Position.X.Scale + scrollSpeed, 0,buildTools.Frame.Position.Y.Scale,0)
wait()
end
buildTools.Frame.Position = UDim2.new(0, 0,buildTools.Frame.Position.Y.Scale,0)
else
bottomLeftControls.ToolButton.Image = localAssetBase .. "ToolButton.png"
while buildTools.Frame.AbsolutePosition.X + buildTools.Frame.AbsoluteSize.X > 0 and not buildToolsVisible do
buildTools.Frame.Position = UDim2.new(buildTools.Frame.Position.X.Scale - scrollSpeed, 0,buildTools.Frame.Position.Y.Scale,0)
wait()
end
buildTools.Frame.Size = UDim2.new(0,buildTools.Frame.AbsoluteSize.X,buildTools.Frame.Size.Y.Scale,buildTools.Frame.Size.Y.Offset)
buildTools.Frame.Position = UDim2.new(0,-buildTools.Frame.AbsoluteSize.X,buildTools.Frame.Position.Y.Scale,buildTools.Frame.Position.Y.Offset)
end
end
-- setup tool button listeners
bottomLeftControls.ToolButton.MouseButton1Click:connect(openCloseTools)
bottomLeftControls.ToolButton.MouseEnter:connect(function() if not buildToolsVisible then bottomLeftControls.ToolButton.Image = localAssetBase .. "ToolButton_dn.png" end end)
bottomLeftControls.ToolButton.MouseLeave:connect(function() if not buildToolsVisible then bottomLeftControls.ToolButton.Image = localAssetBase .. "ToolButton.png" end end)
-- close button on build tools
buildTools.Frame.CloseButton.MouseButton1Click:connect(openCloseTools)
buildTools.Frame.CloseButton.MouseEnter:connect(function() buildTools.Frame.CloseButton.Image = localAssetBase .. "CloseButton_dn.png" end)
buildTools.Frame.CloseButton.MouseLeave:connect(function() buildTools.Frame.CloseButton.Image = localAssetBase .. "CloseButton.png" end)
buildToolsTips()
-- Add/Delete Tools
buildTools.Frame.AddDeleteTools.DeleteObject.MouseButton1Click:connect(function()
toolSelection("BuildDelete", buildTools.Frame.AddDeleteTools.DeleteObject,buildDeleteID) end)
buildTools.Frame.AddDeleteTools.CloneObject.MouseButton1Click:connect(function()
toolSelection("BuildClone",buildTools.Frame.AddDeleteTools.CloneObject,buildCloneID) end)
buildTools.Frame.AddDeleteTools.InsertObject.MouseButton1Click:connect(function()
toolSelection("BuildInsert",buildTools.Frame.AddDeleteTools.InsertObject,buildInsertID)
if(buildTools.Frame:FindFirstChild("InsertToolboxMain")) then
buildTools.Frame.InsertToolboxMain.InsertMainDialog.InsertTab.CloseButton.ClosedState.Changed:connect(function(value)
if value == true then
toolSelection("BuildInsert",buildTools.Frame.AddDeleteTools.InsertObject,buildInsertID)
if(buildTools.Frame:FindFirstChild("InsertToolboxMain")) then
buildTools.Frame.InsertToolboxMain.InsertMainDialog.InsertTab.CloseButton.ClosedState.Value = false
end
end
end)
end
end)
-- Physical Tools
buildTools.Frame.PhysicalTools.ScaleObject.MouseButton1Click:connect(function()
toolSelection("BuildResize",buildTools.Frame.PhysicalTools.ScaleObject, buildResizeID) end)
--[[buildTools.Frame.PhysicalTools.PartMove.MouseButton1Click:connect(function()
toolSelection("BuildDragger",buildTools.Frame.PhysicalTools.PartMove,buildDraggerID) end)]]
buildTools.Frame.PhysicalTools.GroupMove.MouseButton1Click:connect(function()
toolSelection("BuildGroupDragger",buildTools.Frame.PhysicalTools.GroupMove,buildGroupDraggerID) end)
-- Property Tools
buildTools.Frame.PropertyTools.MaterialSelector.MouseButton1Click:connect(function()
toolSelection("BuildMaterialTest",buildTools.Frame.PropertyTools.MaterialSelector,buildMaterialID) end)
buildTools.Frame.PropertyTools.MaterialSelector.MaterialMenu.CloseButton.ClosedState.Changed:connect(function(value)
if value == true then
toolSelection("BuildMaterialTest",buildTools.Frame.PropertyTools.MaterialSelector,buildMaterialID)
buildTools.Frame.PropertyTools.MaterialSelector.MaterialMenu.CloseButton.ClosedState.Value = false
end
end)
buildTools.Frame.PropertyTools.PaintTool.MouseButton1Click:connect(function()
toolSelection("BuildColorTester",buildTools.Frame.PropertyTools.PaintTool, buildColorID) end)
buildTools.Frame.PropertyTools.PaintTool.PaintMenu.CloseButton.ClosedState.Changed:connect(function(value)
if value == true then
toolSelection("BuildColorTester",buildTools.Frame.PropertyTools.PaintTool,buildColorID)
buildTools.Frame.PropertyTools.PaintTool.PaintMenu.CloseButton.ClosedState.Value = false
end
end)
buildTools.Frame.PropertyTools.InputSelector.MouseButton1Click:connect(function()
toolSelection("BuildSurfaceTest",buildTools.Frame.PropertyTools.InputSelector, buildSurfaceID) end)
buildTools.Frame.PropertyTools.InputSelector.SurfaceMenu.CloseButton.ClosedState.Changed:connect(function(value)
if value == true then
toolSelection("BuildSurfaceTest",buildTools.Frame.PropertyTools.InputSelector,buildSurfaceID)
buildTools.Frame.PropertyTools.InputSelector.SurfaceMenu.CloseButton.ClosedState.Value = false
end
end)
-- Misc Tools
buildTools.Frame.MiscTools.PropertyTool.MouseButton1Click:connect(function()
toolSelection("BuildConfiguration",buildTools.Frame.MiscTools.PropertyTool, buildConfigurationID) end)
else -- we are using new build tools
getLatestPlayer()
givePlayerBuildTools()
-- If player dies, we make sure to give them build tools again
player.CharacterAdded:connect(function()
takePlayerBuildTools()
givePlayerBuildTools()
end)
end

109
app/files/CoreGui/36868950 Normal file
View File

@ -0,0 +1,109 @@
local controlFrame = script.Parent:FindFirstChild("ControlFrame")
if not controlFrame then return end
local topLeftControl = controlFrame:FindFirstChild("TopLeftControl")
local bottomLeftControl = controlFrame:FindFirstChild("BottomLeftControl")
local bottomRightControl = controlFrame:FindFirstChild("BottomRightControl")
local frameTip = Instance.new("TextLabel")
frameTip.Name = "ToolTip"
frameTip.Text = ""
frameTip.Font = Enum.Font.ArialBold
frameTip.FontSize = Enum.FontSize.Size12
frameTip.TextColor3 = Color3.new(1,1,1)
frameTip.BorderSizePixel = 0
frameTip.ZIndex = 10
frameTip.Size = UDim2.new(2,0,1,0)
frameTip.Position = UDim2.new(1,0,0,0)
frameTip.BackgroundColor3 = Color3.new(0,0,0)
frameTip.BackgroundTransparency = 1
frameTip.TextTransparency = 1
frameTip.TextWrap = true
local inside = Instance.new("BoolValue")
inside.Name = "inside"
inside.Value = false
inside.Parent = frameTip
function setUpListeners(frameToListen)
local fadeSpeed = 0.1
frameToListen.Parent.MouseEnter:connect(function()
if frameToListen:FindFirstChild("inside") then
frameToListen.inside.Value = true
wait(1.2)
if frameToListen.inside.Value then
while frameToListen.inside.Value and frameToListen.BackgroundTransparency > 0 do
frameToListen.BackgroundTransparency = frameToListen.BackgroundTransparency - fadeSpeed
frameToListen.TextTransparency = frameToListen.TextTransparency - fadeSpeed
wait()
end
end
end
end)
function killTip(killFrame)
killFrame.inside.Value = false
killFrame.BackgroundTransparency = 1
killFrame.TextTransparency = 1
end
frameToListen.Parent.MouseLeave:connect(function() killTip(frameToListen) end)
frameToListen.Parent.MouseButton1Click:connect(function() killTip(frameToListen) end)
end
function createSettingsButtonTip(parent)
if parent == nil then
parent = bottomLeftControl:FindFirstChild("SettingsButton")
end
local toolTip = frameTip:clone()
toolTip.RobloxLocked = true
toolTip.Text = "Settings/Leave Game"
toolTip.Position = UDim2.new(0,0,0,-18)
toolTip.Size = UDim2.new(0,120,0,20)
toolTip.Parent = parent
setUpListeners(toolTip)
end
wait(5) -- make sure we are loaded in, won't need tool tips for first 5 seconds anyway
---------------- set up Bottom Left Tool Tips -------------------------
local bottomLeftChildren = bottomLeftControl:GetChildren()
local hasSettingsTip = false
for i = 1, #bottomLeftChildren do
if bottomLeftChildren[i].Name == "Exit" then
local exitTip = frameTip:clone()
exitTip.RobloxLocked = true
exitTip.Text = "Leave Place"
exitTip.Position = UDim2.new(0,0,-1,0)
exitTip.Size = UDim2.new(1,0,1,0)
exitTip.Parent = bottomLeftChildren[i]
setUpListeners(exitTip)
elseif bottomLeftChildren[i].Name == "SettingsButton" then
hasSettingsTip = true
createSettingsButtonTip(bottomLeftChildren[i])
end
end
---------------- set up Bottom Right Tool Tips -------------------------
local bottomRightChildren = bottomRightControl:GetChildren()
for i = 1, #bottomRightChildren do
if bottomRightChildren[i].Name:find("Camera") ~= nil then
local cameraTip = frameTip:clone()
cameraTip.RobloxLocked = true
cameraTip.Text = "Camera View"
if bottomRightChildren[i].Name:find("Zoom") then
cameraTip.Position = UDim2.new(-1,0,-1.5)
else
cameraTip.Position = UDim2.new(0,0,-1.5,0)
end
cameraTip.Size = UDim2.new(2,0,1.25,0)
cameraTip.Parent = bottomRightChildren[i]
setUpListeners(cameraTip)
end
end

115
app/files/CoreGui/37801172 Normal file
View File

@ -0,0 +1,115 @@
-- Creates all neccessary scripts for the gui on initial load, everything except build tools
-- Created by Ben T. 10/29/10
-- Please note that these are loaded in a specific order to diminish errors/perceived load time by user
local scriptContext = game:GetService("ScriptContext")
local touchEnabled = false
pcall(function() touchEnabled = game:GetService("UserInputService").TouchEnabled end)
-- library registration
scriptContext:AddCoreScript(60595695, scriptContext,"/Libraries/LibraryRegistration/LibraryRegistration")
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
-- Responsible for tracking logging items
local scriptContext = game:GetService("ScriptContext")
scriptContext:AddCoreScript(59002209, scriptContext, "CoreScripts/Sections")
waitForChild(game:GetService("CoreGui"),"RobloxGui")
local screenGui = game:GetService("CoreGui"):FindFirstChild("RobloxGui")
if not touchEnabled then
-- ToolTipper (creates tool tips for gui)
scriptContext:AddCoreScript(36868950,screenGui,"CoreScripts/ToolTip")
-- SettingsScript
scriptContext:AddCoreScript(46295863,screenGui,"CoreScripts/Settings")
else
scriptContext:AddCoreScript(153556783,screenGui,"CoreScripts/TouchControls")
end
-- MainBotChatScript
scriptContext:AddCoreScript(39250920,screenGui,"CoreScripts/MainBotChatScript")
-- Developer Console Script
scriptContext:AddCoreScript(157877000,screenGui,"CoreScripts/DeveloperConsole")
-- Popup Script
scriptContext:AddCoreScript(48488451,screenGui,"CoreScripts/PopupScript")
-- Friend Notification Script (probably can use this script to expand out to other notifications)
scriptContext:AddCoreScript(48488398,screenGui,"CoreScripts/NotificationScript")
-- Chat script
scriptContext:AddCoreScript(97188756, screenGui, "CoreScripts/ChatScript")
-- Purchase Prompt Script
scriptContext:AddCoreScript(107893730, screenGui, "CoreScripts/PurchasePromptScript")
-- Health Script
scriptContext:AddCoreScript(153556822, screenGui, "CoreScripts/HealthScript")
if not touchEnabled then
-- New Player List
scriptContext:AddCoreScript(48488235,screenGui,"CoreScripts/PlayerListScript")
elseif screenGui.AbsoluteSize.Y > 600 then
-- New Player List
scriptContext:AddCoreScript(48488235,screenGui,"CoreScripts/PlayerListScript")
else
delay(5, function()
if screenGui.AbsoluteSize.Y >= 600 then
-- New Player List
scriptContext:AddCoreScript(48488235,screenGui,"CoreScripts/PlayerListScript")
end
end)
end
if game.CoreGui.Version >= 3 then
-- Backpack Builder, creates most of the backpack gui
scriptContext:AddCoreScript(53878047,screenGui,"CoreScripts/BackpackScripts/BackpackBuilder")
waitForChild(screenGui,"CurrentLoadout")
waitForChild(screenGui,"Backpack")
local Backpack = screenGui.Backpack
-- Manager handles all big backpack state changes, other scripts subscribe to this and do things accordingly
if game.CoreGui.Version >= 7 then
scriptContext:AddCoreScript(89449093,Backpack,"CoreScripts/BackpackScripts/BackpackManager")
end
-- Backpack Gear (handles all backpack gear tab stuff)
game:GetService("ScriptContext"):AddCoreScript(89449008,Backpack,"CoreScripts/BackpackScripts/BackpackGear")
-- Loadout Script, used for gear hotkeys
scriptContext:AddCoreScript(53878057,screenGui.CurrentLoadout,"CoreScripts/BackpackScripts/LoadoutScript")
if game.CoreGui.Version >= 8 then
-- Wardrobe script handles all character dressing operations
scriptContext:AddCoreScript(-1,Backpack,"CoreScripts/BackpackScripts/BackpackWardrobe")
end
end
local IsPersonalServer = not not game.Workspace:FindFirstChild("PSVariable")
if IsPersonalServer then
game:GetService("ScriptContext"):AddCoreScript(64164692,game.Players.LocalPlayer,"BuildToolManager")
end
game.Workspace.ChildAdded:connect(function(nchild)
if nchild.Name=='PSVariable' and nchild:IsA('BoolValue') then
IsPersonalServer = true
game:GetService("ScriptContext"):AddCoreScript(64164692,game.Players.LocalPlayer,"BuildToolManager")
end
end)
if touchEnabled then -- touch devices don't use same control frame
-- only used for touch device button generation
scriptContext:AddCoreScript(152908679,screenGui,"CoreScripts/ContextActionTouch")
waitForChild(screenGui, 'ControlFrame')
waitForChild(screenGui.ControlFrame, 'BottomLeftControl')
screenGui.ControlFrame.BottomLeftControl.Visible = false
waitForChild(screenGui.ControlFrame, 'TopLeftControl')
screenGui.ControlFrame.TopLeftControl.Visible = false
end

View File

@ -0,0 +1,74 @@
-- Creates all neccessary scripts for the gui on initial load, everything except build tools
-- Created by Ben T. 10/29/10
-- Please note that these are loaded in a specific order to diminish errors/perceived load time by user
local scriptContext = game:GetService("ScriptContext")
local touchEnabled = false
pcall(function() touchEnabled = game:GetService("UserInputService").TouchEnabled end)
-- library registration
scriptContext:AddCoreScript(60595696, scriptContext,"/Libraries/LibraryRegistration/LibraryRegistration")
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
-- Responsible for tracking logging items
local scriptContext = game:GetService("ScriptContext")
scriptContext:AddCoreScript(59002209, scriptContext, "CoreScripts/Sections")
waitForChild(game:GetService("CoreGui"),"RobloxGui")
local screenGui = game:GetService("CoreGui"):FindFirstChild("RobloxGui")
if not touchEnabled then
-- ToolTipper (creates tool tips for gui)
scriptContext:AddCoreScript(36868950,screenGui,"CoreScripts/ToolTip")
-- SettingsScript
scriptContext:AddCoreScript(46295864,screenGui,"CoreScripts/Settings")
end
-- MainBotChatScript
scriptContext:AddCoreScript(39250920,screenGui,"CoreScripts/MainBotChatScript")
-- New Player List
scriptContext:AddCoreScript(48488236,screenGui,"CoreScripts/PlayerListScript")
-- Popup Script
scriptContext:AddCoreScript(48488451,screenGui,"CoreScripts/PopupScript")
-- Friend Notification Script (probably can use this script to expand out to other notifications)
scriptContext:AddCoreScript(48488398,screenGui,"CoreScripts/NotificationScript")
-- Chat script
scriptContext:AddCoreScript(97188757, screenGui, "CoreScripts/ChatScript")
if game.CoreGui.Version >= 3 then
-- Backpack Builder, creates most of the backpack gui
scriptContext:AddCoreScript(53878048,screenGui,"CoreScripts/BackpackScripts/BackpackBuilder")
waitForChild(screenGui,"CurrentLoadout")
waitForChild(screenGui,"Backpack")
local Backpack = screenGui.Backpack
-- Manager handles all big backpack state changes, other scripts subscribe to this and do things accordingly
if game.CoreGui.Version >= 7 then
scriptContext:AddCoreScript(89449094,Backpack,"CoreScripts/BackpackScripts/BackpackManager")
end
-- Backpack Gear (handles all backpack gear tab stuff)
game:GetService("ScriptContext"):AddCoreScript(89449009,Backpack,"CoreScripts/BackpackScripts/BackpackGear")
-- Loadout Script, used for gear hotkeys
scriptContext:AddCoreScript(53878058,screenGui.CurrentLoadout,"CoreScripts/BackpackScripts/LoadoutScript")
if game.CoreGui.Version >= 8 then
-- Wardrobe script handles all character dressing operations
scriptContext:AddCoreScript(-1,Backpack,"CoreScripts/BackpackScripts/BackpackWardrobe")
end
end
if touchEnabled then -- touch devices don't use same control frame
waitForChild(screenGui, 'ControlFrame')
screenGui.ControlFrame.Visible = false
end

560
app/files/CoreGui/39250920 Normal file
View File

@ -0,0 +1,560 @@
function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local mainFrame
local choices = {}
local lastChoice
local choiceMap = {}
local currentConversationDialog
local currentConversationPartner
local currentAbortDialogScript
local tooFarAwayMessage = "You are too far away to chat!"
local tooFarAwaySize = 300
local characterWanderedOffMessage = "Chat ended because you walked away"
local characterWanderedOffSize = 350
local conversationTimedOut = "Chat ended because you didn't reply"
local conversationTimedOutSize = 350
local player
local screenGui
local chatNotificationGui
local messageDialog
local timeoutScript
local reenableDialogScript
local dialogMap = {}
local dialogConnections = {}
local gui = nil
waitForChild(game,"CoreGui")
waitForChild(game.CoreGui,"RobloxGui")
if game.CoreGui.RobloxGui:FindFirstChild("ControlFrame") then
gui = game.CoreGui.RobloxGui.ControlFrame
else
gui = game.CoreGui.RobloxGui
end
function currentTone()
if currentConversationDialog then
return currentConversationDialog.Tone
else
return Enum.DialogTone.Neutral
end
end
function createChatNotificationGui()
chatNotificationGui = Instance.new("BillboardGui")
chatNotificationGui.Name = "ChatNotificationGui"
chatNotificationGui.ExtentsOffset = Vector3.new(0,1,0)
chatNotificationGui.Size = UDim2.new(4, 0, 5.42857122, 0)
chatNotificationGui.SizeOffset = Vector2.new(0,0)
chatNotificationGui.StudsOffset = Vector3.new(0.4, 4.3, 0)
chatNotificationGui.Enabled = true
chatNotificationGui.RobloxLocked = true
chatNotificationGui.Active = true
local image = Instance.new("ImageLabel")
image.Name = "Image"
image.Active = false
image.BackgroundTransparency = 1
image.Position = UDim2.new(0,0,0,0)
image.Size = UDim2.new(1.0,0,1.0,0)
image.Image = ""
image.RobloxLocked = true
image.Parent = chatNotificationGui
local button = Instance.new("ImageButton")
button.Name = "Button"
button.AutoButtonColor = false
button.Position = UDim2.new(0.0879999995, 0, 0.0529999994, 0)
button.Size = UDim2.new(0.829999983, 0, 0.460000008, 0)
button.Image = ""
button.BackgroundTransparency = 1
button.RobloxLocked = true
button.Parent = image
end
function getChatColor(tone)
if tone == Enum.DialogTone.Neutral then
return Enum.ChatColor.Blue
elseif tone == Enum.DialogTone.Friendly then
return Enum.ChatColor.Green
elseif tone == Enum.DialogTone.Enemy then
return Enum.ChatColor.Red
end
end
function styleChoices(tone)
for i, obj in pairs(choices) do
resetColor(obj, tone)
end
resetColor(lastChoice, tone)
end
function styleMainFrame(tone)
if tone == Enum.DialogTone.Neutral then
mainFrame.Style = Enum.FrameStyle.ChatBlue
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botBlue_tailRight.png"
elseif tone == Enum.DialogTone.Friendly then
mainFrame.Style = Enum.FrameStyle.ChatGreen
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botGreen_tailRight.png"
elseif tone == Enum.DialogTone.Enemy then
mainFrame.Style = Enum.FrameStyle.ChatRed
mainFrame.Tail.Image = "rbxasset://textures/chatBubble_botRed_tailRight.png"
end
styleChoices(tone)
end
function setChatNotificationTone(gui, purpose, tone)
if tone == Enum.DialogTone.Neutral then
gui.Image.Image = "rbxasset://textures/chatBubble_botBlue_notify_bkg.png"
elseif tone == Enum.DialogTone.Friendly then
gui.Image.Image = "rbxasset://textures/chatBubble_botGreen_notify_bkg.png"
elseif tone == Enum.DialogTone.Enemy then
gui.Image.Image = "rbxasset://textures/chatBubble_botRed_notify_bkg.png"
end
if purpose == Enum.DialogPurpose.Quest then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_bang.png"
elseif purpose == Enum.DialogPurpose.Help then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_question.png"
elseif purpose == Enum.DialogPurpose.Shop then
gui.Image.Button.Image = "rbxasset://textures/chatBubble_bot_notify_money.png"
end
end
function createMessageDialog()
messageDialog = Instance.new("Frame");
messageDialog.Name = "DialogScriptMessage"
messageDialog.Style = Enum.FrameStyle.RobloxRound
messageDialog.Visible = false
local text = Instance.new("TextLabel")
text.Name = "Text"
text.Position = UDim2.new(0,0,0,-1)
text.Size = UDim2.new(1,0,1,0)
text.FontSize = Enum.FontSize.Size14
text.BackgroundTransparency = 1
text.TextColor3 = Color3.new(1,1,1)
text.RobloxLocked = true
text.Parent = messageDialog
end
function showMessage(msg, size)
messageDialog.Text.Text = msg
messageDialog.Size = UDim2.new(0,size,0,40)
messageDialog.Position = UDim2.new(0.5, -size/2, 0.5, -40)
messageDialog.Visible = true
wait(2)
messageDialog.Visible = false
end
function variableDelay(str)
local length = math.min(string.len(str), 100)
wait(0.75 + ((length/75) * 1.5))
end
function resetColor(frame, tone)
if tone == Enum.DialogTone.Neutral then
frame.BackgroundColor3 = Color3.new(0/255, 0/255, 179/255)
frame.Number.TextColor3 = Color3.new(45/255, 142/255, 245/255)
elseif tone == Enum.DialogTone.Friendly then
frame.BackgroundColor3 = Color3.new(0/255, 77/255, 0/255)
frame.Number.TextColor3 = Color3.new(0/255, 190/255, 0/255)
elseif tone == Enum.DialogTone.Enemy then
frame.BackgroundColor3 = Color3.new(140/255, 0/255, 0/255)
frame.Number.TextColor3 = Color3.new(255/255,88/255, 79/255)
end
end
function highlightColor(frame, tone)
if tone == Enum.DialogTone.Neutral then
frame.BackgroundColor3 = Color3.new(2/255, 108/255, 255/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
elseif tone == Enum.DialogTone.Friendly then
frame.BackgroundColor3 = Color3.new(0/255, 128/255, 0/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
elseif tone == Enum.DialogTone.Enemy then
frame.BackgroundColor3 = Color3.new(204/255, 0/255, 0/255)
frame.Number.TextColor3 = Color3.new(1, 1, 1)
end
end
function wanderDialog()
print("Wander")
mainFrame.Visible = false
endDialog()
showMessage(characterWanderedOffMessage, characterWanderedOffSize)
end
function timeoutDialog()
print("Timeout")
mainFrame.Visible = false
endDialog()
showMessage(conversationTimedOut, conversationTimedOutSize)
end
function normalEndDialog()
print("Done")
endDialog()
end
function endDialog()
if currentAbortDialogScript then
currentAbortDialogScript:Remove()
currentAbortDialogScript = nil
end
local dialog = currentConversationDialog
currentConversationDialog = nil
if dialog and dialog.InUse then
local reenableScript = reenableDialogScript:Clone()
reenableScript.archivable = false
reenableScript.Disabled = false
reenableScript.Parent = dialog
end
for dialog, gui in pairs(dialogMap) do
if dialog and gui then
gui.Enabled = not dialog.InUse
end
end
currentConversationPartner = nil
end
function sanitizeMessage(msg)
if string.len(msg) == 0 then
return "..."
else
return msg
end
end
function selectChoice(choice)
renewKillswitch(currentConversationDialog)
--First hide the Gui
mainFrame.Visible = false
if choice == lastChoice then
game.Chat:Chat(game.Players.LocalPlayer.Character, "Goodbye!", getChatColor(currentTone()))
normalEndDialog()
else
local dialogChoice = choiceMap[choice]
game.Chat:Chat(game.Players.LocalPlayer.Character, sanitizeMessage(dialogChoice.UserDialog), getChatColor(currentTone()))
wait(1)
currentConversationDialog:SignalDialogChoiceSelected(player, dialogChoice)
game.Chat:Chat(currentConversationPartner, sanitizeMessage(dialogChoice.ResponseDialog), getChatColor(currentTone()))
variableDelay(dialogChoice.ResponseDialog)
presentDialogChoices(currentConversationPartner, dialogChoice:GetChildren())
end
end
function newChoice(numberText)
local frame = Instance.new("TextButton")
frame.BackgroundColor3 = Color3.new(0/255, 0/255, 179/255)
frame.AutoButtonColor = false
frame.BorderSizePixel = 0
frame.Text = ""
frame.MouseEnter:connect(function() highlightColor(frame, currentTone()) end)
frame.MouseLeave:connect(function() resetColor(frame, currentTone()) end)
frame.MouseButton1Click:connect(function() selectChoice(frame) end)
frame.RobloxLocked = true
local number = Instance.new("TextLabel")
number.Name = "Number"
number.TextColor3 = Color3.new(127/255, 212/255, 255/255)
number.Text = numberText
number.FontSize = Enum.FontSize.Size14
number.BackgroundTransparency = 1
number.Position = UDim2.new(0,4,0,2)
number.Size = UDim2.new(0,20,0,24)
number.TextXAlignment = Enum.TextXAlignment.Left
number.TextYAlignment = Enum.TextYAlignment.Top
number.RobloxLocked = true
number.Parent = frame
local prompt = Instance.new("TextLabel")
prompt.Name = "UserPrompt"
prompt.BackgroundTransparency = 1
prompt.TextColor3 = Color3.new(1,1,1)
prompt.FontSize = Enum.FontSize.Size14
prompt.Position = UDim2.new(0,28, 0, 2)
prompt.Size = UDim2.new(1,-32, 1, -4)
prompt.TextXAlignment = Enum.TextXAlignment.Left
prompt.TextYAlignment = Enum.TextYAlignment.Top
prompt.TextWrap = true
prompt.RobloxLocked = true
prompt.Parent = frame
return frame
end
function initialize(parent)
choices[1] = newChoice("1)")
choices[2] = newChoice("2)")
choices[3] = newChoice("3)")
choices[4] = newChoice("4)")
lastChoice = newChoice("5)")
lastChoice.UserPrompt.Text = "Goodbye!"
lastChoice.Size = UDim2.new(1,0,0,28)
mainFrame = Instance.new("Frame")
mainFrame.Name = "UserDialogArea"
mainFrame.Size = UDim2.new(0, 350, 0, 200)
mainFrame.Style = Enum.FrameStyle.ChatBlue
mainFrame.Visible = false
imageLabel = Instance.new("ImageLabel")
imageLabel.Name = "Tail"
imageLabel.Size = UDim2.new(0,62,0,53)
imageLabel.Position = UDim2.new(1,8,0.25)
imageLabel.Image = "rbxasset://textures/chatBubble_botBlue_tailRight.png"
imageLabel.BackgroundTransparency = 1
imageLabel.RobloxLocked = true
imageLabel.Parent = mainFrame
for n, obj in pairs(choices) do
obj.RobloxLocked = true
obj.Parent = mainFrame
end
lastChoice.RobloxLocked = true
lastChoice.Parent = mainFrame
mainFrame.RobloxLocked = true
mainFrame.Parent = parent
end
function presentDialogChoices(talkingPart, dialogChoices)
if not currentConversationDialog then
return
end
currentConversationPartner = talkingPart
sortedDialogChoices = {}
for n, obj in pairs(dialogChoices) do
if obj:IsA("DialogChoice") then
table.insert(sortedDialogChoices, obj)
end
end
table.sort(sortedDialogChoices, function(a,b) return a.Name < b.Name end)
if #sortedDialogChoices == 0 then
normalEndDialog()
return
end
local pos = 1
local yPosition = 0
choiceMap = {}
for n, obj in pairs(choices) do
obj.Visible = false
end
for n, obj in pairs(sortedDialogChoices) do
if pos <= #choices then
--3 lines is the maximum, set it to that temporarily
choices[pos].Size = UDim2.new(1, 0, 0, 24*3)
choices[pos].UserPrompt.Text = obj.UserDialog
local height = math.ceil(choices[pos].UserPrompt.TextBounds.Y/24)*24
choices[pos].Position = UDim2.new(0, 0, 0, yPosition)
choices[pos].Size = UDim2.new(1, 0, 0, height)
choices[pos].Visible = true
choiceMap[choices[pos]] = obj
yPosition = yPosition + height
pos = pos + 1
end
end
lastChoice.Position = UDim2.new(0,0,0,yPosition)
lastChoice.Number.Text = pos .. ")"
mainFrame.Size = UDim2.new(0, 350, 0, yPosition+24+32)
mainFrame.Position = UDim2.new(0,20,0.0, -mainFrame.Size.Y.Offset-20)
styleMainFrame(currentTone())
mainFrame.Visible = true
end
function doDialog(dialog)
while not Instance.Lock(dialog, player) do
wait()
end
if dialog.InUse then
Instance.Unlock(dialog)
return
else
dialog.InUse = true
Instance.Unlock(dialog)
end
currentConversationDialog = dialog
game.Chat:Chat(dialog.Parent, dialog.InitialPrompt, getChatColor(dialog.Tone))
variableDelay(dialog.InitialPrompt)
presentDialogChoices(dialog.Parent, dialog:GetChildren())
end
function renewKillswitch(dialog)
if currentAbortDialogScript then
currentAbortDialogScript:Remove()
currentAbortDialogScript = nil
end
currentAbortDialogScript = timeoutScript:Clone()
currentAbortDialogScript.archivable = false
currentAbortDialogScript.Disabled = false
currentAbortDialogScript.Parent = dialog
end
function checkForLeaveArea()
while currentConversationDialog do
if currentConversationDialog.Parent and (player:DistanceFromCharacter(currentConversationDialog.Parent.Position) >= currentConversationDialog.ConversationDistance) then
wanderDialog()
end
wait(1)
end
end
function startDialog(dialog)
if dialog.Parent and dialog.Parent:IsA("BasePart") then
if player:DistanceFromCharacter(dialog.Parent.Position) >= dialog.ConversationDistance then
showMessage(tooFarAwayMessage, tooFarAwaySize)
return
end
for dialog, gui in pairs(dialogMap) do
if dialog and gui then
gui.Enabled = false
end
end
renewKillswitch(dialog)
delay(1, checkForLeaveArea)
doDialog(dialog)
end
end
function removeDialog(dialog)
if dialogMap[dialog] then
dialogMap[dialog]:Remove()
dialogMap[dialog] = nil
end
if dialogConnections[dialog] then
dialogConnections[dialog]:disconnect()
dialogConnections[dialog] = nil
end
end
function addDialog(dialog)
if dialog.Parent then
if dialog.Parent:IsA("BasePart") then
local chatGui = chatNotificationGui:clone()
chatGui.Enabled = not dialog.InUse
chatGui.Adornee = dialog.Parent
chatGui.RobloxLocked = true
chatGui.Parent = game.CoreGui
chatGui.Image.Button.MouseButton1Click:connect(function() startDialog(dialog) end)
setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone)
dialogMap[dialog] = chatGui
dialogConnections[dialog] = dialog.Changed:connect(function(prop)
if prop == "Parent" and dialog.Parent then
--This handles the reparenting case, seperate from removal case
removeDialog(dialog)
addDialog(dialog)
elseif prop == "InUse" then
chatGui.Enabled = not currentConversationDialog and not dialog.InUse
if dialog == currentConversationDialog then
timeoutDialog()
end
elseif prop == "Tone" or prop == "Purpose" then
setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone)
end
end)
else -- still need to listen to parent changes even if current parent is not a BasePart
dialogConnections[dialog] = dialog.Changed:connect(function(prop)
if prop == "Parent" and dialog.Parent then
--This handles the reparenting case, seperate from removal case
removeDialog(dialog)
addDialog(dialog)
end
end)
end
end
end
function fetchScripts()
local model = game:GetService("InsertService"):LoadAsset(39226062)
if type(model) == "string" then -- load failed, lets try again
wait(0.1)
model = game:GetService("InsertService"):LoadAsset(39226062)
end
if type(model) == "string" then -- not going to work, lets bail
return
end
waitForChild(model,"TimeoutScript")
timeoutScript = model.TimeoutScript
waitForChild(model,"ReenableDialogScript")
reenableDialogScript = model.ReenableDialogScript
end
function onLoad()
waitForProperty(game.Players, "LocalPlayer")
player = game.Players.LocalPlayer
waitForProperty(player, "Character")
--print("Fetching Scripts")
fetchScripts()
--print("Creating Guis")
createChatNotificationGui()
--print("Creating MessageDialog")
createMessageDialog()
messageDialog.RobloxLocked = true
messageDialog.Parent = gui
--print("Waiting for BottomLeftControl")
waitForChild(gui, "BottomLeftControl")
--print("Initializing Frame")
local frame = Instance.new("Frame")
frame.Name = "DialogFrame"
frame.Position = UDim2.new(0,0,0,0)
frame.Size = UDim2.new(0,0,0,0)
frame.BackgroundTransparency = 1
frame.RobloxLocked = true
frame.Parent = gui.BottomLeftControl
initialize(frame)
--print("Adding Dialogs")
game.CollectionService.ItemAdded:connect(function(obj) if obj:IsA("Dialog") then addDialog(obj) end end)
game.CollectionService.ItemRemoved:connect(function(obj) if obj:IsA("Dialog") then removeDialog(obj) end end)
for i, obj in pairs(game.CollectionService:GetCollection("Dialog")) do
if obj:IsA("Dialog") then
addDialog(obj)
end
end
end
onLoad()

3844
app/files/CoreGui/45284430 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
local t = {}
t.Foo =
function()
print("foo")
end
t.Bar =
function()
print("bar")
end
t.Help =
function(funcNameOrFunc)
--input argument can be a string or a function. Should return a description (of arguments and expected side effects)
if funcNameOrFunc == "Foo" or funcNameOrFunc == t.Foo then
return "Function Foo. Arguments: None. Side effect: prints foo"
elseif funcNameOrFunc == "Bar" or funcNameOrFunc == t.Bar then
return "Function Bar. Arguments: None. Side effect: prints bar"
end
end
return t

2153
app/files/CoreGui/46295863 Normal file

File diff suppressed because it is too large Load Diff

2098
app/files/CoreGui/46295864 Normal file

File diff suppressed because it is too large Load Diff

3074
app/files/CoreGui/48488235 Normal file

File diff suppressed because it is too large Load Diff

2425
app/files/CoreGui/48488236 Normal file

File diff suppressed because it is too large Load Diff

306
app/files/CoreGui/48488398 Normal file
View File

@ -0,0 +1,306 @@
function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForProperty(game.Players,"LocalPlayer")
waitForChild(script.Parent,"Popup")
waitForChild(script.Parent.Popup,"AcceptButton")
script.Parent.Popup.AcceptButton.Modal = true
local localPlayer = game.Players.LocalPlayer
local teleportUI = nil
local acceptedTeleport = Instance.new("IntValue")
local friendRequestBlacklist = {}
local teleportEnabled = true
local makePopupInvisible = function()
if script.Parent.Popup then script.Parent.Popup.Visible = false end
end
function makeFriend(fromPlayer,toPlayer)
local popup = script.Parent:FindFirstChild("Popup")
if popup == nil then return end -- there is no popup!
if popup.Visible then return end -- currently popping something, abort!
if friendRequestBlacklist[fromPlayer] then return end -- previously cancelled friend request, we don't want it!
popup.PopupText.Text = "Accept Friend Request from " .. tostring(fromPlayer.Name) .. "?"
popup.PopupImage.Image = "http://www.syntax.eco/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=352&y=352"
showTwoButtons()
popup.Visible = true
popup.AcceptButton.Text = "Accept"
popup.DeclineButton.Text = "Decline"
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
local yesCon, noCon
yesCon = popup.AcceptButton.MouseButton1Click:connect(function()
popup.Visible = false
toPlayer:RequestFriendship(fromPlayer)
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
noCon = popup.DeclineButton.MouseButton1Click:connect(function()
popup.Visible = false
toPlayer:RevokeFriendship(fromPlayer)
friendRequestBlacklist[fromPlayer] = true
print("pop up blacklist")
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
game.Players.FriendRequestEvent:connect(function(fromPlayer,toPlayer,event)
-- if this doesn't involve me, then do nothing
if fromPlayer ~= localPlayer and toPlayer ~= localPlayer then return end
if fromPlayer == localPlayer then
if event == Enum.FriendRequestEvent.Accept then
game:GetService("GuiService"):SendNotification("You are Friends",
"With " .. toPlayer.Name .. "!",
"http://www.syntax.eco/thumbs/avatar.ashx?userId="..tostring(toPlayer.userId).."&x=48&y=48",
5,
function()
end)
end
elseif toPlayer == localPlayer then
if event == Enum.FriendRequestEvent.Issue then
if friendRequestBlacklist[fromPlayer] then return end -- previously cancelled friend request, we don't want it!
game:GetService("GuiService"):SendNotification("Friend Request",
"From " .. fromPlayer.Name,
"http://www.syntax.eco/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=48&y=48",
8,
function()
makeFriend(fromPlayer,toPlayer)
end)
elseif event == Enum.FriendRequestEvent.Accept then
game:GetService("GuiService"):SendNotification("You are Friends",
"With " .. fromPlayer.Name .. "!",
"http://www.syntax.eco/thumbs/avatar.ashx?userId="..tostring(fromPlayer.userId).."&x=48&y=48",
5,
function()
end)
end
end
end)
function showOneButton()
local popup = script.Parent:FindFirstChild("Popup")
if popup then
popup.OKButton.Visible = true
popup.DeclineButton.Visible = false
popup.AcceptButton.Visible = false
end
end
function showTwoButtons()
local popup = script.Parent:FindFirstChild("Popup")
if popup then
popup.OKButton.Visible = false
popup.DeclineButton.Visible = true
popup.AcceptButton.Visible = true
end
end
function onTeleport(teleportState, placeId, spawnName)
if game:GetService("TeleportService").CustomizedTeleportUI == false then
if teleportState == Enum.TeleportState.Started then
showTeleportUI("Teleport started...", 0)
elseif teleportState == Enum.TeleportState.WaitingForServer then
showTeleportUI("Requesting server...", 0)
elseif teleportState == Enum.TeleportState.InProgress then
showTeleportUI("Teleporting...", 0)
elseif teleportState == Enum.TeleportState.Failed then
showTeleportUI("Teleport failed. Insufficient privileges or target place does not exist.", 3)
end
end
end
function showTeleportUI(message, timer)
if teleportUI ~= nil then
teleportUI:Remove()
end
waitForChild(localPlayer, "PlayerGui")
teleportUI = Instance.new("Message", localPlayer.PlayerGui)
teleportUI.Text = message
if timer > 0 then
wait(timer)
teleportUI:Remove()
end
end
if teleportEnabled then
localPlayer.OnTeleport:connect(onTeleport)
game:GetService("TeleportService").ErrorCallback = function(message)
local popup = script.Parent:FindFirstChild("Popup")
showOneButton()
popup.PopupText.Text = message
local clickCon
clickCon = popup.OKButton.MouseButton1Click:connect(function()
game:GetService("TeleportService"):TeleportCancel()
if clickCon then clickCon:disconnect() end
game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showOneButton()
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
game:GetService("TeleportService").ConfirmationCallback = function(message, placeId, spawnName)
local popup = script.Parent:FindFirstChild("Popup")
popup.PopupText.Text = message
popup.PopupImage.Image = ""
local yesCon, noCon
local function killCons()
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end
yesCon = popup.AcceptButton.MouseButton1Click:connect(function()
killCons()
local success, err = pcall(function() game:GetService("TeleportService"):TeleportImpl(placeId,spawnName) end)
if not success then
showOneButton()
popup.PopupText.Text = err
local clickCon
clickCon = popup.OKButton.MouseButton1Click:connect(function()
if clickCon then clickCon:disconnect() end
game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showOneButton()
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end
end)
noCon = popup.DeclineButton.MouseButton1Click:connect(function()
killCons()
local success = pcall(function() game:GetService("TeleportService"):TeleportCancel() end)
end)
local centerDialogSuccess = pcall(function() game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
--ShowFunction
function()
showTwoButtons()
popup.AcceptButton.Text = "Leave"
popup.DeclineButton.Text = "Stay"
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
--HideFunction
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end)
if centerDialogSuccess == false then
script.Parent:FindFirstChild("Popup").Visible = true
popup.AcceptButton.Text = "Leave"
popup.DeclineButton.Text = "Stay"
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end
return true
end
end
game:GetService("MarketplaceService").ClientLuaDialogRequested:connect(function(message, accept, decline)
local popup = script.Parent:FindFirstChild("Popup")
popup.PopupText.Text = message
popup.PopupImage.Image = ""
local yesCon, noCon
local function killCons()
if yesCon then yesCon:disconnect() end
if noCon then noCon:disconnect() end
game.GuiService:RemoveCenterDialog(script.Parent:FindFirstChild("Popup"))
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end
yesCon = popup.AcceptButton.MouseButton1Click:connect(function()
killCons()
game:GetService("MarketplaceService"):SignalServerLuaDialogClosed(true);
end)
noCon = popup.DeclineButton.MouseButton1Click:connect(function()
killCons()
game:GetService("MarketplaceService"):SignalServerLuaDialogClosed(false);
end)
local centerDialogSuccess = pcall(function() game.GuiService:AddCenterDialog(script.Parent:FindFirstChild("Popup"), Enum.CenterDialogType.QuitDialog,
function()
showTwoButtons()
popup.AcceptButton.Text = accept
popup.DeclineButton.Text = decline
script.Parent:FindFirstChild("Popup").Visible = true
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end,
function()
popup:TweenSize(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true,makePopupInvisible())
end)
end)
if centerDialogSuccess == false then
script.Parent:FindFirstChild("Popup").Visible = true
popup.AcceptButton.Text = accept
popup.DeclineButton.Text = decline
popup:TweenSize(UDim2.new(0,330,0,350),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,1,true)
end
return true
end)
Game:GetService("PointsService").PointsAwarded:connect( function(userId, pointsAwarded, userBalanceInGame, userTotalBalance)
if userId == Game.Players.LocalPlayer.userId then
game:GetService("GuiService"):SendNotification("Points Awarded!",
"You received " ..tostring(pointsAwarded) .. " points!",
"http://www.syntax.eco/asset?id=155363793",
5,
function()
end)
end
end)

View File

@ -0,0 +1,72 @@
--build our gui
local popupFrame = Instance.new("Frame")
popupFrame.Position = UDim2.new(0.5,-165,0.5,-175)
popupFrame.Size = UDim2.new(0,330,0,350)
popupFrame.Style = Enum.FrameStyle.RobloxRound
popupFrame.ZIndex = 4
popupFrame.Name = "Popup"
popupFrame.Visible = false
popupFrame.Parent = script.Parent
local darken = popupFrame:clone()
darken.Size = UDim2.new(1,16,1,16)
darken.Position = UDim2.new(0,-8,0,-8)
darken.Name = "Darken"
darken.ZIndex = 1
darken.Parent = popupFrame
local acceptButton = Instance.new("TextButton")
acceptButton.Position = UDim2.new(0,20,0,270)
acceptButton.Size = UDim2.new(0,100,0,50)
acceptButton.Font = Enum.Font.ArialBold
acceptButton.FontSize = Enum.FontSize.Size24
acceptButton.Style = Enum.ButtonStyle.RobloxButton
acceptButton.TextColor3 = Color3.new(248/255,248/255,248/255)
acceptButton.Text = "Yes"
acceptButton.ZIndex = 5
acceptButton.Name = "AcceptButton"
acceptButton.Parent = popupFrame
local declineButton = acceptButton:clone()
declineButton.Position = UDim2.new(1,-120,0,270)
declineButton.Text = "No"
declineButton.Name = "DeclineButton"
declineButton.Parent = popupFrame
local okButton = acceptButton:clone()
okButton.Name = "OKButton"
okButton.Text = "OK"
okButton.Position = UDim2.new(0.5,-50,0,270)
okButton.Visible = false
okButton.Parent = popupFrame
local popupImage = Instance.new("ImageLabel")
popupImage.BackgroundTransparency = 1
popupImage.Position = UDim2.new(0.5,-140,0,0)
popupImage.Size = UDim2.new(0,280,0,280)
popupImage.ZIndex = 3
popupImage.Name = "PopupImage"
popupImage.Parent = popupFrame
local backing = Instance.new("ImageLabel")
backing.BackgroundTransparency = 1
backing.Size = UDim2.new(1,0,1,0)
backing.Image = "http://www.syntax.eco/asset/?id=47574181"
backing.Name = "Backing"
backing.ZIndex = 2
backing.Parent = popupImage
local popupText = Instance.new("TextLabel")
popupText.Name = "PopupText"
popupText.Size = UDim2.new(1,0,0.8,0)
popupText.Font = Enum.Font.ArialBold
popupText.FontSize = Enum.FontSize.Size36
popupText.BackgroundTransparency = 1
popupText.Text = "Hello I'm a popup"
popupText.TextColor3 = Color3.new(248/255,248/255,248/255)
popupText.TextWrap = true
popupText.ZIndex = 5
popupText.Parent = popupFrame
script:remove()

874
app/files/CoreGui/53878047 Normal file
View File

@ -0,0 +1,874 @@
-- This script creates almost all gui elements found in the backpack (warning: there are a lot!)
-- TODO: automate this process
if game.CoreGui.Version < 3 then return end -- peace out if we aren't using the right client
local gui = script.Parent
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
local function IsTouchDevice()
local touchEnabled = false
pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end)
return touchEnabled
end
local function IsPhone()
if gui.AbsoluteSize.Y <= 320 then
return true
end
return false
end
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
-- First up is the current loadout
local CurrentLoadout = Instance.new("Frame")
CurrentLoadout.Name = "CurrentLoadout"
CurrentLoadout.Position = UDim2.new(0.5, -300, 1, -85)
CurrentLoadout.Size = UDim2.new(0, 600, 0, 54)
CurrentLoadout.BackgroundTransparency = 1
CurrentLoadout.RobloxLocked = true
CurrentLoadout.Parent = gui
local CLBackground = Instance.new('ImageLabel')
CLBackground.Name = 'Background';
CLBackground.Size = UDim2.new(1.2, 0, 1.2, 0);
CLBackground.Image = "http://www.syntax.eco/asset/?id=96536002"
CLBackground.BackgroundTransparency = 1.0;
CLBackground.Position = UDim2.new(-0.1, 0, -0.1, 0);
CLBackground.ZIndex = 0.0;
CLBackground.Parent = CurrentLoadout
CLBackground.Visible = false
local BackgroundUp = Instance.new('ImageLabel')
BackgroundUp.Size = UDim2.new(1, 0, 0.025, 1)
BackgroundUp.Position = UDim2.new(0, 0, 0, 0)
BackgroundUp.Image = 'http://www.syntax.eco/asset/?id=97662207'
BackgroundUp.BackgroundTransparency = 1.0
BackgroundUp.Parent = CLBackground
local Debounce = Instance.new("BoolValue")
Debounce.Name = "Debounce"
Debounce.RobloxLocked = true
Debounce.Parent = CurrentLoadout
local BackpackButton = Instance.new("ImageButton")
BackpackButton.RobloxLocked = true
BackpackButton.Visible = false
BackpackButton.Name = "BackpackButton"
BackpackButton.BackgroundTransparency = 1
BackpackButton.Image = "http://www.syntax.eco/asset/?id=97617958"
BackpackButton.Position = UDim2.new(0.5, -60, 1, -108)
BackpackButton.Size = UDim2.new(0, 120, 0, 18)
waitForChild(gui,"ControlFrame")
BackpackButton.Parent = gui.ControlFrame
local NumSlots = 9
if IsPhone() then
NumSlots = 3
CurrentLoadout.Size = UDim2.new(0,180,0,54)
CurrentLoadout.Position = UDim2.new(0.5,-90,1,-85)
end
for i = 0, NumSlots do
local slotFrame = Instance.new("Frame")
slotFrame.RobloxLocked = true
slotFrame.BackgroundColor3 = Color3.new(0,0,0)
slotFrame.BackgroundTransparency = 1
slotFrame.BorderColor3 = Color3.new(1, 1, 1)
slotFrame.Name = "Slot" .. tostring(i)
slotFrame.ZIndex = 4.0
if i == 0 then
slotFrame.Position = UDim2.new(0.9, 0, 0, 0)
else
slotFrame.Position = UDim2.new((i - 1) * 0.1, (i-1)* 6,0,0)
end
slotFrame.Size = UDim2.new(0, 54, 1, 0)
slotFrame.Parent = CurrentLoadout
if gui.AbsoluteSize.Y <= 320 then
slotFrame.Position = UDim2.new(0, (i-1)* 60, 0, -50)
print('Well got here', slotFrame, slotFrame.Position.X.Scale, slotFrame.Position.X.Offset)
end
if gui.AbsoluteSize.Y <= 320 and i == 0 then
slotFrame:Destroy()
end
end
local TempSlot = Instance.new("ImageButton")
TempSlot.Name = "TempSlot"
TempSlot.Active = true
TempSlot.Size = UDim2.new(1,0,1,0)
TempSlot.BackgroundTransparency = 1.0
TempSlot.Style = 'Custom'
TempSlot.Visible = false
TempSlot.RobloxLocked = true
TempSlot.Parent = CurrentLoadout
TempSlot.ZIndex = 3.0
local slotBackground = Instance.new('ImageLabel')
slotBackground.Name = 'Background'
slotBackground.BackgroundTransparency = 1.0
slotBackground.Image = 'http://www.syntax.eco/asset/?id=97613075'
slotBackground.Size = UDim2.new(1, 0, 1, 0)
slotBackground.Parent = TempSlot
local HighLight = Instance.new('ImageLabel')
HighLight.Name = 'Highlight'
HighLight.BackgroundTransparency = 1.0
HighLight.Image = 'http://www.syntax.eco/asset/?id=97643886'
HighLight.Size = UDim2.new(1, 0, 1, 0)
--HighLight.Parent = TempSlot
HighLight.Visible = false
-- TempSlot Children
local GearReference = Instance.new("ObjectValue")
GearReference.Name = "GearReference"
GearReference.RobloxLocked = true
GearReference.Parent = TempSlot
local ToolTipLabel = Instance.new("TextLabel")
ToolTipLabel.Name = "ToolTipLabel"
ToolTipLabel.RobloxLocked = true
ToolTipLabel.Text = ""
ToolTipLabel.BackgroundTransparency = 0.5
ToolTipLabel.BorderSizePixel = 0
ToolTipLabel.Visible = false
ToolTipLabel.TextColor3 = Color3.new(1,1,1)
ToolTipLabel.BackgroundColor3 = Color3.new(0,0,0)
ToolTipLabel.TextStrokeTransparency = 0
ToolTipLabel.Font = Enum.Font.ArialBold
ToolTipLabel.FontSize = Enum.FontSize.Size14
--ToolTipLabel.TextWrap = true
ToolTipLabel.Size = UDim2.new(1,60,0,20)
ToolTipLabel.Position = UDim2.new(0,-30,0,-30)
ToolTipLabel.Parent = TempSlot
local Kill = Instance.new("BoolValue")
Kill.Name = "Kill"
Kill.RobloxLocked = true
Kill.Parent = TempSlot
local GearImage = Instance.new("ImageLabel")
GearImage.Name = "GearImage"
GearImage.BackgroundTransparency = 1
GearImage.Position = UDim2.new(0, 0, 0, 0)
GearImage.Size = UDim2.new(1, 0, 1, 0)
GearImage.ZIndex = 5.0
GearImage.RobloxLocked = true
GearImage.Parent = TempSlot
local SlotNumber = Instance.new("TextLabel")
SlotNumber.Name = "SlotNumber"
SlotNumber.BackgroundTransparency = 1
SlotNumber.BorderSizePixel = 0
SlotNumber.Font = Enum.Font.ArialBold
SlotNumber.FontSize = Enum.FontSize.Size18
SlotNumber.Position = UDim2.new(0, 0, 0, 0)
SlotNumber.Size = UDim2.new(0,10,0,15)
SlotNumber.TextColor3 = Color3.new(1,1,1)
SlotNumber.TextTransparency = 0
SlotNumber.TextXAlignment = Enum.TextXAlignment.Left
SlotNumber.TextYAlignment = Enum.TextYAlignment.Bottom
SlotNumber.RobloxLocked = true
SlotNumber.Parent = TempSlot
SlotNumber.ZIndex = 5
if IsTouchDevice() then
SlotNumber.Visible = false
end
local SlotNumberDownShadow = SlotNumber:Clone()
SlotNumberDownShadow.Name = "SlotNumberDownShadow"
SlotNumberDownShadow.TextColor3 = Color3.new(0,0,0)
SlotNumberDownShadow.Position = UDim2.new(0, 1, 0, -1)
SlotNumberDownShadow.Parent = TempSlot
SlotNumberDownShadow.ZIndex = 2
local SlotNumberUpShadow = SlotNumberDownShadow:Clone()
SlotNumberUpShadow.Name = "SlotNumberUpShadow"
SlotNumberUpShadow.Position = UDim2.new(0, -1, 0, -1)
SlotNumberUpShadow.Parent = TempSlot
local GearText = Instance.new("TextLabel")
GearText.RobloxLocked = true
GearText.Name = "GearText"
GearText.BackgroundTransparency = 1
GearText.Font = Enum.Font.Arial
GearText.FontSize = Enum.FontSize.Size14
GearText.Position = UDim2.new(0,-8,0,-8)
GearText.Size = UDim2.new(1,16,1,16)
GearText.Text = ""
GearText.TextColor3 = Color3.new(1,1,1)
GearText.TextWrap = true
GearText.Parent = TempSlot
GearText.ZIndex = 5.0
--- Great, now lets make the inventory!
local Backpack = Instance.new("Frame")
Backpack.RobloxLocked = true
Backpack.Visible = false
Backpack.Name = "Backpack"
Backpack.Position = UDim2.new(0.5, 0, 0.5, 0)
Backpack.BackgroundColor3 = Color3.new(32/255, 32/255, 32/255)
Backpack.BackgroundTransparency = 0.0
Backpack.BorderSizePixel = 0
Backpack.Parent = gui
Backpack.Active = true
-- Backpack Children
local SwapSlot = Instance.new("BoolValue")
SwapSlot.RobloxLocked = true
SwapSlot.Name = "SwapSlot"
SwapSlot.Parent = Backpack
-- SwapSlot Children
local Slot = Instance.new("IntValue")
Slot.RobloxLocked = true
Slot.Name = "Slot"
Slot.Parent = SwapSlot
local GearButton = Instance.new("ObjectValue")
GearButton.RobloxLocked = true
GearButton.Name = "GearButton"
GearButton.Parent = SwapSlot
local Tabs = Instance.new("Frame")
Tabs.Name = "Tabs"
Tabs.Visible = false
Tabs.Active = false
Tabs.RobloxLocked = true
Tabs.BackgroundColor3 = Color3.new(0,0,0)
Tabs.BackgroundTransparency = 0.08
Tabs.BorderSizePixel = 0
Tabs.Position = UDim2.new(0,0,-0.1,-4)
Tabs.Size = UDim2.new(1,0,0.1,4)
Tabs.Parent = Backpack
-- Tabs Children
local tabLine = Instance.new("Frame")
tabLine.RobloxLocked = true
tabLine.Name = "TabLine"
tabLine.BackgroundColor3 = Color3.new(53/255, 53/255, 53/255)
tabLine.BorderSizePixel = 0
tabLine.Position = UDim2.new(0,5,1,-4)
tabLine.Size = UDim2.new(1,-10,0,4)
tabLine.ZIndex = 2
tabLine.Parent = Tabs
local InventoryButton = Instance.new("TextButton")
InventoryButton.RobloxLocked = true
InventoryButton.Name = "InventoryButton"
InventoryButton.Size = UDim2.new(0,60,0,30)
InventoryButton.Position = UDim2.new(0,7,1,-31)
InventoryButton.BackgroundColor3 = Color3.new(1,1,1)
InventoryButton.BorderColor3 = Color3.new(1,1,1)
InventoryButton.Font = Enum.Font.ArialBold
InventoryButton.FontSize = Enum.FontSize.Size18
InventoryButton.Text = "Gear"
InventoryButton.AutoButtonColor = false
InventoryButton.TextColor3 = Color3.new(0,0,0)
InventoryButton.Selected = true
InventoryButton.Active = true
InventoryButton.ZIndex = 3
InventoryButton.Parent = Tabs
if game.CoreGui.Version >= 8 then
local WardrobeButton = Instance.new("TextButton")
WardrobeButton.RobloxLocked = true
WardrobeButton.Name = "WardrobeButton"
WardrobeButton.Size = UDim2.new(0,90,0,30)
WardrobeButton.Position = UDim2.new(0,77,1,-31)
WardrobeButton.BackgroundColor3 = Color3.new(0,0,0)
WardrobeButton.BorderColor3 = Color3.new(1,1,1)
WardrobeButton.Font = Enum.Font.ArialBold
WardrobeButton.FontSize = Enum.FontSize.Size18
WardrobeButton.Text = "Wardrobe"
WardrobeButton.AutoButtonColor = false
WardrobeButton.TextColor3 = Color3.new(1,1,1)
WardrobeButton.Selected = false
WardrobeButton.Active = true
WardrobeButton.Parent = Tabs
end
local closeButton = Instance.new("TextButton")
closeButton.RobloxLocked = true
closeButton.Name = "CloseButton"
closeButton.Font = Enum.Font.ArialBold
closeButton.FontSize = Enum.FontSize.Size24
closeButton.Position = UDim2.new(1,-33,0,4)
closeButton.Size = UDim2.new(0,30,0,30)
closeButton.Style = Enum.ButtonStyle.RobloxButton
closeButton.Text = ""
closeButton.TextColor3 = Color3.new(1,1,1)
closeButton.Parent = Tabs
closeButton.Modal = true
--closeButton child
local XImage = Instance.new("ImageLabel")
XImage.RobloxLocked = true
XImage.Name = "XImage"
game:GetService("ContentProvider"):Preload("http://www.syntax.eco/asset/?id=75547445")
XImage.Image = "http://www.syntax.eco/asset/?id=75547445" --TODO: move to rbxasset
XImage.BackgroundTransparency = 1
XImage.Position = UDim2.new(-.25,-1,-.25,-1)
XImage.Size = UDim2.new(1.5,2,1.5,2)
XImage.ZIndex = 2
XImage.Parent = closeButton
-- Generic Search gui used across backpack
local SearchFrame = Instance.new("Frame")
SearchFrame.RobloxLocked = true
SearchFrame.Name = "SearchFrame"
SearchFrame.BackgroundTransparency = 1
SearchFrame.Position = UDim2.new(1,-220,0,2)
SearchFrame.Size = UDim2.new(0,220,0,24)
SearchFrame.Parent = Backpack
-- SearchFrame Children
local SearchButton = Instance.new("ImageButton")
SearchButton.RobloxLocked = true
SearchButton.Name = "SearchButton"
SearchButton.Size = UDim2.new(0,25,0,25)
SearchButton.BackgroundTransparency = 1
SearchButton.Image = "rbxasset://textures/ui/SearchIcon.png"
SearchButton.Parent = SearchFrame
local SearchBoxFrame = Instance.new("TextButton")
SearchBoxFrame.RobloxLocked = true
SearchBoxFrame.Position = UDim2.new(0,25,0,0)
SearchBoxFrame.Size = UDim2.new(1,-28,0,26)
SearchBoxFrame.Name = "SearchBoxFrame"
SearchBoxFrame.Text = ""
SearchBoxFrame.Style = Enum.ButtonStyle.RobloxButton
SearchBoxFrame.Parent = SearchFrame
-- SearchBoxFrame Children
local SearchBox = Instance.new("TextBox")
SearchBox.RobloxLocked = true
SearchBox.Name = "SearchBox"
SearchBox.BackgroundTransparency = 1
SearchBox.Font = Enum.Font.ArialBold
SearchBox.FontSize = Enum.FontSize.Size12
SearchBox.Position = UDim2.new(0,-5,0,-5)
SearchBox.Size = UDim2.new(1,10,1,10)
SearchBox.TextColor3 = Color3.new(1,1,1)
SearchBox.TextXAlignment = Enum.TextXAlignment.Left
SearchBox.ZIndex = 2
SearchBox.TextWrap = true
SearchBox.Text = "Search..."
SearchBox.Parent = SearchBoxFrame
local ResetButton = Instance.new("TextButton")
ResetButton.RobloxLocked = true
ResetButton.Visible = false
ResetButton.Name = "ResetButton"
ResetButton.Position = UDim2.new(1,-26,0,3)
ResetButton.Size = UDim2.new(0,20,0,20)
ResetButton.Style = Enum.ButtonStyle.RobloxButtonDefault
ResetButton.Text = "X"
ResetButton.TextColor3 = Color3.new(1,1,1)
ResetButton.Font = Enum.Font.ArialBold
ResetButton.FontSize = Enum.FontSize.Size18
ResetButton.ZIndex = 3
ResetButton.Parent = SearchFrame
------------------------------- GEAR -------------------------------------------------------
local Gear = Instance.new("Frame")
Gear.Name = "Gear"
Gear.RobloxLocked = true
Gear.BackgroundTransparency = 1
Gear.Size = UDim2.new(1,0,1,0)
Gear.ClipsDescendants = true
Gear.Parent = Backpack
-- Gear Children
local AssetsList = Instance.new("Frame")
AssetsList.RobloxLocked = true
AssetsList.Name = "AssetsList"
AssetsList.BackgroundTransparency = 1
AssetsList.Size = UDim2.new(0.2,0,1,0)
AssetsList.Style = Enum.FrameStyle.RobloxSquare
AssetsList.Visible = false
AssetsList.Parent = Gear
local GearGrid = Instance.new("Frame")
GearGrid.RobloxLocked = true
GearGrid.Name = "GearGrid"
GearGrid.Size = UDim2.new(0.95, 0, 1, 0)
GearGrid.BackgroundTransparency = 1
GearGrid.Parent = Gear
local GearButton = Instance.new("ImageButton")
GearButton.RobloxLocked = true
GearButton.Visible = false
GearButton.Name = "GearButton"
GearButton.Size = UDim2.new(0, 54, 0, 54)
GearButton.Style = 'Custom'
GearButton.Parent = GearGrid
GearButton.BackgroundTransparency = 1.0
local slotBackground = Instance.new('ImageLabel')
slotBackground.Name = 'Background'
slotBackground.BackgroundTransparency = 1.0
slotBackground.Image = 'http://www.syntax.eco/asset/?id=97613075'
slotBackground.Size = UDim2.new(1, 0, 1, 0)
slotBackground.Parent = GearButton
-- GearButton Children
local GearReference = Instance.new("ObjectValue")
GearReference.RobloxLocked = true
GearReference.Name = "GearReference"
GearReference.Parent = GearButton
local GreyOutButton = Instance.new("Frame")
GreyOutButton.RobloxLocked = true
GreyOutButton.Name = "GreyOutButton"
GreyOutButton.BackgroundTransparency = 0.5
GreyOutButton.Size = UDim2.new(1,0,1,0)
GreyOutButton.Active = true
GreyOutButton.Visible = false
GreyOutButton.ZIndex = 3
GreyOutButton.Parent = GearButton
local GearText = Instance.new("TextLabel")
GearText.RobloxLocked = true
GearText.Name = "GearText"
GearText.BackgroundTransparency = 1
GearText.Font = Enum.Font.Arial
GearText.FontSize = Enum.FontSize.Size14
GearText.Position = UDim2.new(0,-8,0,-8)
GearText.Size = UDim2.new(1,16,1,16)
GearText.Text = ""
GearText.ZIndex = 2
GearText.TextColor3 = Color3.new(1,1,1)
GearText.TextWrap = true
GearText.Parent = GearButton
local GearGridScrollingArea = Instance.new("Frame")
GearGridScrollingArea.RobloxLocked = true
GearGridScrollingArea.Name = "GearGridScrollingArea"
GearGridScrollingArea.Position = UDim2.new(1, -19, 0, 35)
GearGridScrollingArea.Size = UDim2.new(0, 17, 1, -45)
GearGridScrollingArea.BackgroundTransparency = 1
GearGridScrollingArea.Parent = Gear
local GearLoadouts = Instance.new("Frame")
GearLoadouts.RobloxLocked = true
GearLoadouts.Name = "GearLoadouts"
GearLoadouts.BackgroundTransparency = 1
GearLoadouts.Position = UDim2.new(0.7,23,0.5,1)
GearLoadouts.Size = UDim2.new(0.3,-23,0.5,-1)
GearLoadouts.Parent = Gear
GearLoadouts.Visible = false
-- GearLoadouts Children
local GearLoadoutsHeader = Instance.new("Frame")
GearLoadoutsHeader.RobloxLocked = true
GearLoadoutsHeader.Name = "GearLoadoutsHeader"
GearLoadoutsHeader.BackgroundColor3 = Color3.new(0,0,0)
GearLoadoutsHeader.BackgroundTransparency = 0.2
GearLoadoutsHeader.BorderColor3 = Color3.new(1,0,0)
GearLoadoutsHeader.Size = UDim2.new(1,2,0.15,-1)
GearLoadoutsHeader.Parent = GearLoadouts
-- GearLoadoutsHeader Children
local LoadoutsHeaderText = Instance.new("TextLabel")
LoadoutsHeaderText.RobloxLocked = true
LoadoutsHeaderText.Name = "LoadoutsHeaderText"
LoadoutsHeaderText.BackgroundTransparency = 1
LoadoutsHeaderText.Font = Enum.Font.ArialBold
LoadoutsHeaderText.FontSize = Enum.FontSize.Size18
LoadoutsHeaderText.Size = UDim2.new(1,0,1,0)
LoadoutsHeaderText.Text = "Loadouts"
LoadoutsHeaderText.TextColor3 = Color3.new(1,1,1)
LoadoutsHeaderText.Parent = GearLoadoutsHeader
local GearLoadoutsScrollingArea = GearGridScrollingArea:clone()
GearLoadoutsScrollingArea.RobloxLocked = true
GearLoadoutsScrollingArea.Name = "GearLoadoutsScrollingArea"
GearLoadoutsScrollingArea.Position = UDim2.new(1,-15,0.15,2)
GearLoadoutsScrollingArea.Size = UDim2.new(0,17,0.85,-2)
GearLoadoutsScrollingArea.Parent = GearLoadouts
local LoadoutsList = Instance.new("Frame")
LoadoutsList.RobloxLocked = true
LoadoutsList.Name = "LoadoutsList"
LoadoutsList.Position = UDim2.new(0,0,0.15,2)
LoadoutsList.Size = UDim2.new(1,-17,0.85,-2)
LoadoutsList.Style = Enum.FrameStyle.RobloxSquare
LoadoutsList.Parent = GearLoadouts
local GearPreview = Instance.new("Frame")
GearPreview.RobloxLocked = true
GearPreview.Name = "GearPreview"
GearPreview.Position = UDim2.new(0.7,23,0,0)
GearPreview.Size = UDim2.new(0.3,-28,0.5,-1)
GearPreview.BackgroundTransparency = 1
GearPreview.ZIndex = 7
GearPreview.Parent = Gear
-- GearPreview Children
local GearStats = Instance.new("Frame")
GearStats.RobloxLocked = true
GearStats.Name = "GearStats"
GearStats.BackgroundTransparency = 1
GearStats.Position = UDim2.new(0,0,0.75,0)
GearStats.Size = UDim2.new(1,0,0.25,0)
GearStats.ZIndex = 8
GearStats.Parent = GearPreview
-- GearStats Children
local GearName = Instance.new("TextLabel")
GearName.RobloxLocked = true
GearName.Name = "GearName"
GearName.BackgroundTransparency = 1
GearName.Font = Enum.Font.ArialBold
GearName.FontSize = Enum.FontSize.Size18
GearName.Position = UDim2.new(0,-3,0,0)
GearName.Size = UDim2.new(1,6,1,5)
GearName.Text = ""
GearName.TextColor3 = Color3.new(1,1,1)
GearName.TextWrap = true
GearName.ZIndex = 9
GearName.Parent = GearStats
local GearImage = Instance.new("ImageLabel")
GearImage.RobloxLocked = true
GearImage.Name = "GearImage"
GearImage.Image = ""
GearImage.BackgroundTransparency = 1
GearImage.Position = UDim2.new(0.125,0,0,0)
GearImage.Size = UDim2.new(0.75,0,0.75,0)
GearImage.ZIndex = 8
GearImage.Parent = GearPreview
--GearImage Children
local GearIcons = Instance.new("Frame")
GearIcons.BackgroundColor3 = Color3.new(0,0,0)
GearIcons.BackgroundTransparency = 0.5
GearIcons.BorderSizePixel = 0
GearIcons.RobloxLocked = true
GearIcons.Name = "GearIcons"
GearIcons.Position = UDim2.new(0.4,2,0.85,-2)
GearIcons.Size = UDim2.new(0.6,0,0.15,0)
GearIcons.Visible = false
GearIcons.ZIndex = 9
GearIcons.Parent = GearImage
-- GearIcons Children
local GenreImage = Instance.new("ImageLabel")
GenreImage.RobloxLocked = true
GenreImage.Name = "GenreImage"
GenreImage.BackgroundColor3 = Color3.new(102/255,153/255,1)
GenreImage.BackgroundTransparency = 0.5
GenreImage.BorderSizePixel = 0
GenreImage.Size = UDim2.new(0.25,0,1,0)
GenreImage.Parent = GearIcons
local AttributeOneImage = GenreImage:clone()
AttributeOneImage.RobloxLocked = true
AttributeOneImage.Name = "AttributeOneImage"
AttributeOneImage.BackgroundColor3 = Color3.new(1,51/255,0)
AttributeOneImage.Position = UDim2.new(0.25,0,0,0)
AttributeOneImage.Parent = GearIcons
local AttributeTwoImage = GenreImage:clone()
AttributeTwoImage.RobloxLocked = true
AttributeTwoImage.Name = "AttributeTwoImage"
AttributeTwoImage.BackgroundColor3 = Color3.new(153/255,1,153/255)
AttributeTwoImage.Position = UDim2.new(0.5,0,0,0)
AttributeTwoImage.Parent = GearIcons
local AttributeThreeImage = GenreImage:clone()
AttributeThreeImage.RobloxLocked = true
AttributeThreeImage.Name = "AttributeThreeImage"
AttributeThreeImage.BackgroundColor3 = Color3.new(0,0.5,0.5)
AttributeThreeImage.Position = UDim2.new(0.75,0,0,0)
AttributeThreeImage.Parent = GearIcons
------------------------------- WARDROBE -------------------------------------------------------
if game.CoreGui.Version < 8 then
-- no need for this to stick around, we aren't ready for wardrobe
script:remove()
return
end
local function makeCharFrame(frameName, parent)
local frame = Instance.new("Frame")
frame.RobloxLocked = true
frame.Size = UDim2.new(1,0,1,-70)
frame.Position = UDim2.new(0,0,0,20)
frame.Name = frameName
frame.BackgroundTransparency = 1
frame.Parent = parent
frame.Visible = false
return frame
end
local function makeZone( zoneName, image, size, position, parent )
local zone = Instance.new("ImageLabel")
zone.RobloxLocked = true
zone.Name = zoneName
zone.Image = image
zone.Size = size
zone.BackgroundTransparency = 1
zone.Position = position
zone.Parent = parent
return zone
end
local function makeStyledButton( buttonName, size, position, parent, buttonStyle )
local button = Instance.new("ImageButton")
button.RobloxLocked = true
button.Name = buttonName
button.Size = size
button.Position = position
if buttonStyle then
button.Style = buttonStyle
else
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderColor3 = Color3.new(1,1,1)
end
button.Parent = parent
return button
end
local function makeTextLabel( TextLabelName,text,position,parent )
local label = Instance.new("TextLabel")
label.RobloxLocked = true
label.BackgroundTransparency = 1
label.Size = UDim2.new(0,32,0,14)
label.Name = TextLabelName
label.Font = Enum.Font.Arial
label.TextColor3 = Color3.new(1,1,1)
label.FontSize = Enum.FontSize.Size14
label.Text = text
label.Position = position
label.Parent = parent
end
local Wardrobe = Instance.new("Frame")
Wardrobe.Name = "Wardrobe"
Wardrobe.RobloxLocked = true
Wardrobe.BackgroundTransparency = 1
Wardrobe.Visible = false
Wardrobe.Size = UDim2.new(1,0,1,0)
Wardrobe.Parent = Backpack
local AssetList = Instance.new("Frame")
AssetList.RobloxLocked = true
AssetList.Name = "AssetList"
AssetList.Position = UDim2.new(0,4,0,5)
AssetList.Size = UDim2.new(0,85,1,-5)
AssetList.BackgroundTransparency = 1
AssetList.Visible = true
AssetList.Parent = Wardrobe
local PreviewAssetFrame = Instance.new("Frame")
PreviewAssetFrame.RobloxLocked = true
PreviewAssetFrame.Name = "PreviewAssetFrame"
PreviewAssetFrame.BackgroundTransparency = 1
PreviewAssetFrame.Position = UDim2.new(1,-240,0,30)
PreviewAssetFrame.Size = UDim2.new(0,250,0,250)
PreviewAssetFrame.Parent = Wardrobe
local PreviewAssetBacking = Instance.new("TextButton")
PreviewAssetBacking.RobloxLocked = true
PreviewAssetBacking.Name = "PreviewAssetBacking"
PreviewAssetBacking.Active = false
PreviewAssetBacking.Text = ""
PreviewAssetBacking.AutoButtonColor = false
PreviewAssetBacking.Size = UDim2.new(1,0,1,0)
PreviewAssetBacking.Style = Enum.ButtonStyle.RobloxButton
PreviewAssetBacking.Visible = false
PreviewAssetBacking.ZIndex = 9
PreviewAssetBacking.Parent = PreviewAssetFrame
local PreviewAssetImage = Instance.new("ImageLabel")
PreviewAssetImage.RobloxLocked = true
PreviewAssetImage.Name = "PreviewAssetImage"
PreviewAssetImage.BackgroundTransparency = 0.8
PreviewAssetImage.Position = UDim2.new(0.5,-100,0,0)
PreviewAssetImage.Size = UDim2.new(0,200,0,200)
PreviewAssetImage.BorderSizePixel = 0
PreviewAssetImage.ZIndex = 10
PreviewAssetImage.Parent = PreviewAssetBacking
local AssetNameLabel = Instance.new("TextLabel")
AssetNameLabel.Name = "AssetNameLabel"
AssetNameLabel.RobloxLocked = true
AssetNameLabel.BackgroundTransparency = 1
AssetNameLabel.Position = UDim2.new(0,0,1,-20)
AssetNameLabel.Size = UDim2.new(0.5,0,0,24)
AssetNameLabel.ZIndex = 10
AssetNameLabel.Font = Enum.Font.Arial
AssetNameLabel.Text = ""
AssetNameLabel.TextColor3 = Color3.new(1,1,1)
AssetNameLabel.TextScaled = true
AssetNameLabel.Parent = PreviewAssetBacking
local AssetTypeLabel = AssetNameLabel:clone()
AssetTypeLabel.RobloxLocked = true
AssetTypeLabel.Name = "AssetTypeLabel"
AssetTypeLabel.TextScaled = false
AssetTypeLabel.FontSize = Enum.FontSize.Size18
AssetTypeLabel.Position = UDim2.new(0.5,3,1,-20)
AssetTypeLabel.Parent = PreviewAssetBacking
local PreviewButton = Instance.new("TextButton")
PreviewButton.RobloxLocked = true
PreviewButton.Name = "PreviewButton"
PreviewButton.Text = "Rotate"
PreviewButton.BackgroundColor3 = Color3.new(0,0,0)
PreviewButton.BackgroundTransparency = 0.5
PreviewButton.BorderColor3 = Color3.new(1,1,1)
PreviewButton.Position = UDim2.new(1.2,-62,1,-50)
PreviewButton.Size = UDim2.new(0,125,0,50)
PreviewButton.Font = Enum.Font.ArialBold
PreviewButton.FontSize = Enum.FontSize.Size24
PreviewButton.TextColor3 = Color3.new(1,1,1)
PreviewButton.TextWrapped = true
PreviewButton.TextStrokeTransparency = 0
PreviewButton.Parent = Wardrobe
local CharacterPane = Instance.new("Frame")
CharacterPane.RobloxLocked = true
CharacterPane.Name = "CharacterPane"
CharacterPane.Position = UDim2.new(1,-220,0,32)
CharacterPane.Size = UDim2.new(0,220,1,-40)
CharacterPane.BackgroundTransparency = 1
CharacterPane.Visible = true
CharacterPane.Parent = Wardrobe
--CharacterPane Children
local FaceFrame = makeCharFrame("FacesFrame", CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.syntax.eco/asset/?id=75460621")
makeZone("FaceZone","http://www.syntax.eco/asset/?id=75460621",UDim2.new(0,157,0,137),UDim2.new(0.5,-78,0.5,-68),FaceFrame)
makeStyledButton("Face",UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-135),FaceFrame)
local HeadFrame = makeCharFrame("HeadsFrame", CharacterPane)
makeZone("FaceZone","http://www.syntax.eco/asset/?id=75460621",UDim2.new(0,157,0,137),UDim2.new(0.5,-78,0.5,-68),HeadFrame)
makeStyledButton("Head",UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-135),HeadFrame)
local HatsFrame = makeCharFrame("HatsFrame", CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.syntax.eco/asset/?id=75457888")
local HatsZone = makeZone("HatsZone","http://www.syntax.eco/asset/?id=75457888",UDim2.new(0,186,0,184),UDim2.new(0.5,-93,0.5,-100), HatsFrame)
makeStyledButton("Hat1Button",UDim2.new(0,64,0,64),UDim2.new(0,-1,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton)
makeStyledButton("Hat2Button",UDim2.new(0,64,0,64),UDim2.new(0,63,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton)
makeStyledButton("Hat3Button",UDim2.new(0,64,0,64),UDim2.new(0,127,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton)
local PantsFrame = makeCharFrame("PantsFrame", CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.syntax.eco/asset/?id=75457920")
makeZone("PantsZone","http://www.syntax.eco/asset/?id=75457920",UDim2.new(0,121,0,99),UDim2.new(0.5,-60,0.5,-100),PantsFrame)
local pantFrame = Instance.new("Frame")
pantFrame.RobloxLocked = true
pantFrame.Size = UDim2.new(0,25,0,56)
pantFrame.Position = UDim2.new(0.5,-26,0.5,0)
pantFrame.BackgroundColor3 = Color3.new(0,0,0)
pantFrame.BorderColor3 = Color3.new(1,1,1)
pantFrame.Name = "PantFrame"
pantFrame.Parent = PantsFrame
local otherPantFrame = pantFrame:clone()
otherPantFrame.Position = UDim2.new(0.5,3,0.5,0)
otherPantFrame.RobloxLocked = true
otherPantFrame.Parent = PantsFrame
local CurrentPants = Instance.new("ImageButton")
CurrentPants.RobloxLocked = true
CurrentPants.BackgroundTransparency = 1
CurrentPants.ZIndex = 2
CurrentPants.Name = "CurrentPants"
CurrentPants.Position = UDim2.new(0.5,-31,0.5,-4)
CurrentPants.Size = UDim2.new(0,54,0,59)
CurrentPants.Parent = PantsFrame
local MeshFrame = makeCharFrame("PackagesFrame", CharacterPane)
local torsoButton = makeStyledButton("TorsoMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("TorsoLabel","Torso",UDim2.new(0.5,-16,0,-25),torsoButton)
local leftLegButton = makeStyledButton("LeftLegMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,0,0.5,-25),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("LeftLegLabel","Left Leg",UDim2.new(0.5,-16,0,-25),leftLegButton)
local rightLegButton = makeStyledButton("RightLegMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-64,0.5,-25),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("RightLegLabel","Right Leg",UDim2.new(0.5,-16,0,-25),rightLegButton)
local rightArmButton = makeStyledButton("RightArmMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-96,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("RightArmLabel","Right Arm",UDim2.new(0.5,-16,0,-25),rightArmButton)
local leftArmButton = makeStyledButton("LeftArmMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,32,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("LeftArmLabel","Left Arm",UDim2.new(0.5,-16,0,-25),leftArmButton)
local TShirtFrame = makeCharFrame("T-ShirtsFrame",CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.syntax.eco/asset/?id=75460642")
makeZone("TShirtZone","http://www.syntax.eco/asset/?id=75460642",UDim2.new(0,121,0,154),UDim2.new(0.5,-60,0.5,-100),TShirtFrame)
makeStyledButton("TShirtButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-64),TShirtFrame)
local ShirtFrame = makeCharFrame("ShirtsFrame", CharacterPane)
makeZone("ShirtZone","http://www.syntax.eco/asset/?id=75460642",UDim2.new(0,121,0,154),UDim2.new(0.5,-60,0.5,-100),ShirtFrame)
makeStyledButton("ShirtButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-64),ShirtFrame)
local ColorFrame = makeCharFrame("ColorFrame", CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.syntax.eco/asset/?id=76049888")
local ColorZone = makeZone("ColorZone","http://www.syntax.eco/asset/?id=76049888", UDim2.new(0,120,0,150),UDim2.new(0.5,-60,0.5,-100),ColorFrame)
makeStyledButton("Head",UDim2.new(0.26,0,0.19,0),UDim2.new(0.37,0,0.02,0),ColorZone).AutoButtonColor = false
makeStyledButton("LeftArm",UDim2.new(0.19,0,0.36,0),UDim2.new(0.78,0,0.26,0),ColorZone).AutoButtonColor = false
makeStyledButton("RightArm",UDim2.new(0.19,0,0.36,0),UDim2.new(0.025,0,0.26,0),ColorZone).AutoButtonColor = false
makeStyledButton("Torso",UDim2.new(0.43,0,0.36,0),UDim2.new(0.28,0,0.26,0),ColorZone).AutoButtonColor = false
makeStyledButton("RightLeg",UDim2.new(0.19,0,0.31,0),UDim2.new(0.275,0,0.67,0),ColorZone).AutoButtonColor = false
makeStyledButton("LeftLeg",UDim2.new(0.19,0,0.31,0),UDim2.new(0.525,0,0.67,0),ColorZone).AutoButtonColor = false
-- Character Panel label (shows what category we are currently browsing)
local CategoryLabel = Instance.new("TextLabel")
CategoryLabel.RobloxLocked = true
CategoryLabel.Name = "CategoryLabel"
CategoryLabel.BackgroundTransparency = 1
CategoryLabel.Font = Enum.Font.ArialBold
CategoryLabel.FontSize = Enum.FontSize.Size18
CategoryLabel.Position = UDim2.new(0,0,0,-7)
CategoryLabel.Size = UDim2.new(1,0,0,20)
CategoryLabel.TextXAlignment = Enum.TextXAlignment.Center
CategoryLabel.Text = "All"
CategoryLabel.TextColor3 = Color3.new(1,1,1)
CategoryLabel.Parent = CharacterPane
--Save Button
local SaveButton = Instance.new("TextButton")
SaveButton.RobloxLocked = true
SaveButton.Name = "SaveButton"
SaveButton.Size = UDim2.new(0.6,0,0,50)
SaveButton.Position = UDim2.new(0.2,0,1,-50)
SaveButton.Style = Enum.ButtonStyle.RobloxButton
SaveButton.Selected = false
SaveButton.Font = Enum.Font.ArialBold
SaveButton.FontSize = Enum.FontSize.Size18
SaveButton.Text = "Save"
SaveButton.TextColor3 = Color3.new(1,1,1)
SaveButton.Parent = CharacterPane
-- no need for this to stick around
script:Destroy()

790
app/files/CoreGui/53878048 Normal file
View File

@ -0,0 +1,790 @@
-- This script creates almost all gui elements found in the backpack (warning: there are a lot!)
-- TODO: automate this process
if game.CoreGui.Version < 3 then return end -- peace out if we aren't using the right client
local gui = script.Parent
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
-- First up is the current loadout
local CurrentLoadout = Instance.new("Frame")
CurrentLoadout.Name = "CurrentLoadout"
CurrentLoadout.Position = UDim2.new(0.5, -240, 1, -85)
CurrentLoadout.Size = UDim2.new(0, 480, 0, 48)
CurrentLoadout.BackgroundTransparency = 1
CurrentLoadout.RobloxLocked = true
CurrentLoadout.Parent = gui
local Debounce = Instance.new("BoolValue")
Debounce.Name = "Debounce"
Debounce.RobloxLocked = true
Debounce.Parent = CurrentLoadout
local BackpackButton = Instance.new("ImageButton")
BackpackButton.RobloxLocked = true
BackpackButton.Visible = false
BackpackButton.Name = "BackpackButton"
BackpackButton.BackgroundTransparency = 1
BackpackButton.Image = "rbxasset://textures/ui/backpackButton.png"
BackpackButton.Position = UDim2.new(0.5, -195, 1, -30)
BackpackButton.Size = UDim2.new(0,107,0,26)
waitForChild(gui,"ControlFrame")
BackpackButton.Parent = gui.ControlFrame
for i = 0, 9 do
local slotFrame = Instance.new("Frame")
slotFrame.RobloxLocked = true
slotFrame.BackgroundColor3 = Color3.new(0,0,0)
slotFrame.BackgroundTransparency = 1
slotFrame.BorderColor3 = Color3.new(1,1,1)
slotFrame.Name = "Slot" .. tostring(i)
if i == 0 then
slotFrame.Position = UDim2.new(0.9,0,0,0)
else
slotFrame.Position = UDim2.new((i - 1) * 0.1,0,0,0)
end
slotFrame.Size = UDim2.new(0.1,0,1,0)
slotFrame.Parent = CurrentLoadout
end
local TempSlot = Instance.new("ImageButton")
TempSlot.Name = "TempSlot"
TempSlot.Active = true
TempSlot.Size = UDim2.new(1,0,1,0)
TempSlot.Style = Enum.ButtonStyle.RobloxButton
TempSlot.Visible = false
TempSlot.RobloxLocked = true
TempSlot.Parent = CurrentLoadout
-- TempSlot Children
local GearReference = Instance.new("ObjectValue")
GearReference.Name = "GearReference"
GearReference.RobloxLocked = true
GearReference.Parent = TempSlot
local ToolTipLabel = Instance.new("TextLabel")
ToolTipLabel.Name = "ToolTipLabel"
ToolTipLabel.RobloxLocked = true
ToolTipLabel.Text = ""
ToolTipLabel.BackgroundTransparency = 0.5
ToolTipLabel.BorderSizePixel = 0
ToolTipLabel.Visible = false
ToolTipLabel.TextColor3 = Color3.new(1,1,1)
ToolTipLabel.BackgroundColor3 = Color3.new(0,0,0)
ToolTipLabel.TextStrokeTransparency = 0
ToolTipLabel.Font = Enum.Font.ArialBold
ToolTipLabel.FontSize = Enum.FontSize.Size14
--ToolTipLabel.TextWrap = true
ToolTipLabel.Size = UDim2.new(1,60,0,20)
ToolTipLabel.Position = UDim2.new(0,-30,0,-30)
ToolTipLabel.Parent = TempSlot
local Kill = Instance.new("BoolValue")
Kill.Name = "Kill"
Kill.RobloxLocked = true
Kill.Parent = TempSlot
local GearImage = Instance.new("ImageLabel")
GearImage.Name = "GearImage"
GearImage.BackgroundTransparency = 1
GearImage.Position = UDim2.new(0,-7,0,-7)
GearImage.Size = UDim2.new(1,14,1,14)
GearImage.ZIndex = 2
GearImage.RobloxLocked = true
GearImage.Parent = TempSlot
local SlotNumber = Instance.new("TextLabel")
SlotNumber.Name = "SlotNumber"
SlotNumber.BackgroundTransparency = 1
SlotNumber.BorderSizePixel = 0
SlotNumber.Font = Enum.Font.ArialBold
SlotNumber.FontSize = Enum.FontSize.Size18
SlotNumber.Position = UDim2.new(0,-7,0,-7)
SlotNumber.Size = UDim2.new(0,10,0,15)
SlotNumber.TextColor3 = Color3.new(1,1,1)
SlotNumber.TextTransparency = 0
SlotNumber.TextXAlignment = Enum.TextXAlignment.Left
SlotNumber.TextYAlignment = Enum.TextYAlignment.Bottom
SlotNumber.ZIndex = 4
SlotNumber.RobloxLocked = true
SlotNumber.Parent = TempSlot
local SlotNumberDownShadow = SlotNumber:clone()
SlotNumberDownShadow.Name = "SlotNumberDownShadow"
SlotNumberDownShadow.TextColor3 = Color3.new(0,0,0)
SlotNumberDownShadow.ZIndex = 3
SlotNumberDownShadow.Position = UDim2.new(0,-6,0,-6)
SlotNumberDownShadow.Parent = TempSlot
local SlotNumberUpShadow = SlotNumberDownShadow:clone()
SlotNumberUpShadow.Name = "SlotNumberUpShadow"
SlotNumberUpShadow.Position = UDim2.new(0,-8,0,-8)
SlotNumberUpShadow.Parent = TempSlot
local GearText = Instance.new("TextLabel")
GearText.RobloxLocked = true
GearText.Name = "GearText"
GearText.BackgroundTransparency = 1
GearText.Font = Enum.Font.Arial
GearText.FontSize = Enum.FontSize.Size14
GearText.Position = UDim2.new(0,-8,0,-8)
GearText.ZIndex = 2
GearText.Size = UDim2.new(1,16,1,16)
GearText.Text = ""
GearText.TextColor3 = Color3.new(1,1,1)
GearText.TextWrap = true
GearText.Parent = TempSlot
--- Great, now lets make the inventory!
local Backpack = Instance.new("Frame")
Backpack.RobloxLocked = true
Backpack.Visible = false
Backpack.Name = "Backpack"
Backpack.Position = UDim2.new(0.5,0,0.5,0)
Backpack.BackgroundColor3 = Color3.new(0,0,0)
Backpack.BackgroundTransparency = 0.08
Backpack.BorderSizePixel = 0
Backpack.Parent = gui
Backpack.Active = true
-- Backpack Children
local SwapSlot = Instance.new("BoolValue")
SwapSlot.RobloxLocked = true
SwapSlot.Name = "SwapSlot"
SwapSlot.Parent = Backpack
-- SwapSlot Children
local Slot = Instance.new("IntValue")
Slot.RobloxLocked = true
Slot.Name = "Slot"
Slot.Parent = SwapSlot
local GearButton = Instance.new("ObjectValue")
GearButton.RobloxLocked = true
GearButton.Name = "GearButton"
GearButton.Parent = SwapSlot
local Tabs = Instance.new("Frame")
Tabs.Name = "Tabs"
Tabs.Visible = true
Tabs.RobloxLocked = true
Tabs.BackgroundColor3 = Color3.new(0,0,0)
Tabs.BackgroundTransparency = 0.08
Tabs.BorderSizePixel = 0
Tabs.Position = UDim2.new(0,0,-0.1,-4)
Tabs.Size = UDim2.new(1,0,0.1,4)
Tabs.Parent = Backpack
-- Tabs Children
local tabLine = Instance.new("Frame")
tabLine.RobloxLocked = true
tabLine.Name = "TabLine"
tabLine.BackgroundColor3 = Color3.new(53/255, 53/255, 53/255)
tabLine.BorderSizePixel = 0
tabLine.Position = UDim2.new(0,5,1,-4)
tabLine.Size = UDim2.new(1,-10,0,4)
tabLine.ZIndex = 2
tabLine.Parent = Tabs
local InventoryButton = Instance.new("TextButton")
InventoryButton.RobloxLocked = true
InventoryButton.Name = "InventoryButton"
InventoryButton.Size = UDim2.new(0,60,0,30)
InventoryButton.Position = UDim2.new(0,7,1,-31)
InventoryButton.BackgroundColor3 = Color3.new(1,1,1)
InventoryButton.BorderColor3 = Color3.new(1,1,1)
InventoryButton.Font = Enum.Font.ArialBold
InventoryButton.FontSize = Enum.FontSize.Size18
InventoryButton.Text = "Gear"
InventoryButton.AutoButtonColor = false
InventoryButton.TextColor3 = Color3.new(0,0,0)
InventoryButton.Selected = true
InventoryButton.Active = true
InventoryButton.ZIndex = 3
InventoryButton.Parent = Tabs
if game.CoreGui.Version >= 8 then
local WardrobeButton = Instance.new("TextButton")
WardrobeButton.RobloxLocked = true
WardrobeButton.Name = "WardrobeButton"
WardrobeButton.Size = UDim2.new(0,90,0,30)
WardrobeButton.Position = UDim2.new(0,77,1,-31)
WardrobeButton.BackgroundColor3 = Color3.new(0,0,0)
WardrobeButton.BorderColor3 = Color3.new(1,1,1)
WardrobeButton.Font = Enum.Font.ArialBold
WardrobeButton.FontSize = Enum.FontSize.Size18
WardrobeButton.Text = "Wardrobe"
WardrobeButton.AutoButtonColor = false
WardrobeButton.TextColor3 = Color3.new(1,1,1)
WardrobeButton.Selected = false
WardrobeButton.Active = true
WardrobeButton.Parent = Tabs
end
local closeButton = Instance.new("TextButton")
closeButton.RobloxLocked = true
closeButton.Name = "CloseButton"
closeButton.Font = Enum.Font.ArialBold
closeButton.FontSize = Enum.FontSize.Size24
closeButton.Position = UDim2.new(1,-33,0,4)
closeButton.Size = UDim2.new(0,30,0,30)
closeButton.Style = Enum.ButtonStyle.RobloxButton
closeButton.Text = ""
closeButton.TextColor3 = Color3.new(1,1,1)
closeButton.Parent = Tabs
closeButton.Modal = true
--closeButton child
local XImage = Instance.new("ImageLabel")
XImage.RobloxLocked = true
XImage.Name = "XImage"
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=75547445")
XImage.Image = "http://www.roblox.com/asset/?id=75547445" --TODO: move to rbxasset
XImage.BackgroundTransparency = 1
XImage.Position = UDim2.new(-.25,-1,-.25,-1)
XImage.Size = UDim2.new(1.5,2,1.5,2)
XImage.ZIndex = 2
XImage.Parent = closeButton
-- Generic Search gui used across backpack
local SearchFrame = Instance.new("Frame")
SearchFrame.RobloxLocked = true
SearchFrame.Name = "SearchFrame"
SearchFrame.BackgroundTransparency = 1
SearchFrame.Position = UDim2.new(1,-220,0,2)
SearchFrame.Size = UDim2.new(0,220,0,24)
SearchFrame.Parent = Backpack
-- SearchFrame Children
local SearchButton = Instance.new("ImageButton")
SearchButton.RobloxLocked = true
SearchButton.Name = "SearchButton"
SearchButton.Size = UDim2.new(0,25,0,25)
SearchButton.BackgroundTransparency = 1
SearchButton.Image = "rbxasset://textures/ui/SearchIcon.png"
SearchButton.Parent = SearchFrame
local SearchBoxFrame = Instance.new("TextButton")
SearchBoxFrame.RobloxLocked = true
SearchBoxFrame.Position = UDim2.new(0,25,0,0)
SearchBoxFrame.Size = UDim2.new(1,-28,0,26)
SearchBoxFrame.Name = "SearchBoxFrame"
SearchBoxFrame.Text = ""
SearchBoxFrame.Style = Enum.ButtonStyle.RobloxButton
SearchBoxFrame.Parent = SearchFrame
-- SearchBoxFrame Children
local SearchBox = Instance.new("TextBox")
SearchBox.RobloxLocked = true
SearchBox.Name = "SearchBox"
SearchBox.BackgroundTransparency = 1
SearchBox.Font = Enum.Font.ArialBold
SearchBox.FontSize = Enum.FontSize.Size12
SearchBox.Position = UDim2.new(0,-5,0,-5)
SearchBox.Size = UDim2.new(1,10,1,10)
SearchBox.TextColor3 = Color3.new(1,1,1)
SearchBox.TextXAlignment = Enum.TextXAlignment.Left
SearchBox.ZIndex = 2
SearchBox.TextWrap = true
SearchBox.Text = "Search..."
SearchBox.Parent = SearchBoxFrame
local ResetButton = Instance.new("TextButton")
ResetButton.RobloxLocked = true
ResetButton.Visible = false
ResetButton.Name = "ResetButton"
ResetButton.Position = UDim2.new(1,-26,0,3)
ResetButton.Size = UDim2.new(0,20,0,20)
ResetButton.Style = Enum.ButtonStyle.RobloxButtonDefault
ResetButton.Text = "X"
ResetButton.TextColor3 = Color3.new(1,1,1)
ResetButton.Font = Enum.Font.ArialBold
ResetButton.FontSize = Enum.FontSize.Size18
ResetButton.ZIndex = 3
ResetButton.Parent = SearchFrame
------------------------------- GEAR -------------------------------------------------------
local Gear = Instance.new("Frame")
Gear.Name = "Gear"
Gear.RobloxLocked = true
Gear.BackgroundTransparency = 1
Gear.Size = UDim2.new(1,0,1,0)
Gear.Parent = Backpack
-- Gear Children
local AssetsList = Instance.new("Frame")
AssetsList.RobloxLocked = true
AssetsList.Name = "AssetsList"
AssetsList.BackgroundTransparency = 1
AssetsList.Size = UDim2.new(0.2,0,1,0)
AssetsList.Style = Enum.FrameStyle.RobloxSquare
AssetsList.Visible = false
AssetsList.Parent = Gear
local GearGrid = Instance.new("Frame")
GearGrid.RobloxLocked = true
GearGrid.Name = "GearGrid"
GearGrid.Size = UDim2.new(0.69,0,1,0)
GearGrid.BackgroundTransparency = 1
GearGrid.Parent = Gear
local GearButton = Instance.new("ImageButton")
GearButton.RobloxLocked = true
GearButton.Visible = false
GearButton.Name = "GearButton"
GearButton.Size = UDim2.new(0,64,0,64)
GearButton.Style = Enum.ButtonStyle.RobloxButton
GearButton.Parent = GearGrid
-- GearButton Children
local GearReference = Instance.new("ObjectValue")
GearReference.RobloxLocked = true
GearReference.Name = "GearReference"
GearReference.Parent = GearButton
local GreyOutButton = Instance.new("Frame")
GreyOutButton.RobloxLocked = true
GreyOutButton.Name = "GreyOutButton"
GreyOutButton.BackgroundTransparency = 0.5
GreyOutButton.Size = UDim2.new(1,0,1,0)
GreyOutButton.Active = true
GreyOutButton.Visible = false
GreyOutButton.ZIndex = 3
GreyOutButton.Parent = GearButton
local GearText = Instance.new("TextLabel")
GearText.RobloxLocked = true
GearText.Name = "GearText"
GearText.BackgroundTransparency = 1
GearText.Font = Enum.Font.Arial
GearText.FontSize = Enum.FontSize.Size14
GearText.Position = UDim2.new(0,-8,0,-8)
GearText.Size = UDim2.new(1,16,1,16)
GearText.Text = ""
GearText.ZIndex = 2
GearText.TextColor3 = Color3.new(1,1,1)
GearText.TextWrap = true
GearText.Parent = GearButton
local GearGridScrollingArea = Instance.new("Frame")
GearGridScrollingArea.RobloxLocked = true
GearGridScrollingArea.Name = "GearGridScrollingArea"
GearGridScrollingArea.Position = UDim2.new(0.7,0,0,35)
GearGridScrollingArea.Size = UDim2.new(0,17,1,-45)
GearGridScrollingArea.BackgroundTransparency = 1
GearGridScrollingArea.Parent = Gear
local GearLoadouts = Instance.new("Frame")
GearLoadouts.RobloxLocked = true
GearLoadouts.Name = "GearLoadouts"
GearLoadouts.BackgroundTransparency = 1
GearLoadouts.Position = UDim2.new(0.7,23,0.5,1)
GearLoadouts.Size = UDim2.new(0.3,-23,0.5,-1)
GearLoadouts.Parent = Gear
GearLoadouts.Visible = false
-- GearLoadouts Children
local GearLoadoutsHeader = Instance.new("Frame")
GearLoadoutsHeader.RobloxLocked = true
GearLoadoutsHeader.Name = "GearLoadoutsHeader"
GearLoadoutsHeader.BackgroundColor3 = Color3.new(0,0,0)
GearLoadoutsHeader.BackgroundTransparency = 0.2
GearLoadoutsHeader.BorderColor3 = Color3.new(1,0,0)
GearLoadoutsHeader.Size = UDim2.new(1,2,0.15,-1)
GearLoadoutsHeader.Parent = GearLoadouts
-- GearLoadoutsHeader Children
local LoadoutsHeaderText = Instance.new("TextLabel")
LoadoutsHeaderText.RobloxLocked = true
LoadoutsHeaderText.Name = "LoadoutsHeaderText"
LoadoutsHeaderText.BackgroundTransparency = 1
LoadoutsHeaderText.Font = Enum.Font.ArialBold
LoadoutsHeaderText.FontSize = Enum.FontSize.Size18
LoadoutsHeaderText.Size = UDim2.new(1,0,1,0)
LoadoutsHeaderText.Text = "Loadouts"
LoadoutsHeaderText.TextColor3 = Color3.new(1,1,1)
LoadoutsHeaderText.Parent = GearLoadoutsHeader
local GearLoadoutsScrollingArea = GearGridScrollingArea:clone()
GearLoadoutsScrollingArea.RobloxLocked = true
GearLoadoutsScrollingArea.Name = "GearLoadoutsScrollingArea"
GearLoadoutsScrollingArea.Position = UDim2.new(1,-15,0.15,2)
GearLoadoutsScrollingArea.Size = UDim2.new(0,17,0.85,-2)
GearLoadoutsScrollingArea.Parent = GearLoadouts
local LoadoutsList = Instance.new("Frame")
LoadoutsList.RobloxLocked = true
LoadoutsList.Name = "LoadoutsList"
LoadoutsList.Position = UDim2.new(0,0,0.15,2)
LoadoutsList.Size = UDim2.new(1,-17,0.85,-2)
LoadoutsList.Style = Enum.FrameStyle.RobloxSquare
LoadoutsList.Parent = GearLoadouts
local GearPreview = Instance.new("Frame")
GearPreview.RobloxLocked = true
GearPreview.Name = "GearPreview"
GearPreview.Position = UDim2.new(0.7,23,0,0)
GearPreview.Size = UDim2.new(0.3,-28,0.5,-1)
GearPreview.BackgroundTransparency = 1
GearPreview.ZIndex = 7
GearPreview.Parent = Gear
-- GearPreview Children
local GearStats = Instance.new("Frame")
GearStats.RobloxLocked = true
GearStats.Name = "GearStats"
GearStats.BackgroundTransparency = 1
GearStats.Position = UDim2.new(0,0,0.75,0)
GearStats.Size = UDim2.new(1,0,0.25,0)
GearStats.ZIndex = 8
GearStats.Parent = GearPreview
-- GearStats Children
local GearName = Instance.new("TextLabel")
GearName.RobloxLocked = true
GearName.Name = "GearName"
GearName.BackgroundTransparency = 1
GearName.Font = Enum.Font.ArialBold
GearName.FontSize = Enum.FontSize.Size18
GearName.Position = UDim2.new(0,-3,0,0)
GearName.Size = UDim2.new(1,6,1,5)
GearName.Text = ""
GearName.TextColor3 = Color3.new(1,1,1)
GearName.TextWrap = true
GearName.ZIndex = 9
GearName.Parent = GearStats
local GearImage = Instance.new("ImageLabel")
GearImage.RobloxLocked = true
GearImage.Name = "GearImage"
GearImage.Image = ""
GearImage.BackgroundTransparency = 1
GearImage.Position = UDim2.new(0.125,0,0,0)
GearImage.Size = UDim2.new(0.75,0,0.75,0)
GearImage.ZIndex = 8
GearImage.Parent = GearPreview
--GearImage Children
local GearIcons = Instance.new("Frame")
GearIcons.BackgroundColor3 = Color3.new(0,0,0)
GearIcons.BackgroundTransparency = 0.5
GearIcons.BorderSizePixel = 0
GearIcons.RobloxLocked = true
GearIcons.Name = "GearIcons"
GearIcons.Position = UDim2.new(0.4,2,0.85,-2)
GearIcons.Size = UDim2.new(0.6,0,0.15,0)
GearIcons.Visible = false
GearIcons.ZIndex = 9
GearIcons.Parent = GearImage
-- GearIcons Children
local GenreImage = Instance.new("ImageLabel")
GenreImage.RobloxLocked = true
GenreImage.Name = "GenreImage"
GenreImage.BackgroundColor3 = Color3.new(102/255,153/255,1)
GenreImage.BackgroundTransparency = 0.5
GenreImage.BorderSizePixel = 0
GenreImage.Size = UDim2.new(0.25,0,1,0)
GenreImage.Parent = GearIcons
local AttributeOneImage = GenreImage:clone()
AttributeOneImage.RobloxLocked = true
AttributeOneImage.Name = "AttributeOneImage"
AttributeOneImage.BackgroundColor3 = Color3.new(1,51/255,0)
AttributeOneImage.Position = UDim2.new(0.25,0,0,0)
AttributeOneImage.Parent = GearIcons
local AttributeTwoImage = GenreImage:clone()
AttributeTwoImage.RobloxLocked = true
AttributeTwoImage.Name = "AttributeTwoImage"
AttributeTwoImage.BackgroundColor3 = Color3.new(153/255,1,153/255)
AttributeTwoImage.Position = UDim2.new(0.5,0,0,0)
AttributeTwoImage.Parent = GearIcons
local AttributeThreeImage = GenreImage:clone()
AttributeThreeImage.RobloxLocked = true
AttributeThreeImage.Name = "AttributeThreeImage"
AttributeThreeImage.BackgroundColor3 = Color3.new(0,0.5,0.5)
AttributeThreeImage.Position = UDim2.new(0.75,0,0,0)
AttributeThreeImage.Parent = GearIcons
------------------------------- WARDROBE -------------------------------------------------------
if game.CoreGui.Version < 8 then
-- no need for this to stick around, we aren't ready for wardrobe
script:remove()
return
end
local function makeCharFrame(frameName, parent)
local frame = Instance.new("Frame")
frame.RobloxLocked = true
frame.Size = UDim2.new(1,0,1,-70)
frame.Position = UDim2.new(0,0,0,20)
frame.Name = frameName
frame.BackgroundTransparency = 1
frame.Parent = parent
frame.Visible = false
return frame
end
local function makeZone( zoneName, image, size, position, parent )
local zone = Instance.new("ImageLabel")
zone.RobloxLocked = true
zone.Name = zoneName
zone.Image = image
zone.Size = size
zone.BackgroundTransparency = 1
zone.Position = position
zone.Parent = parent
return zone
end
local function makeStyledButton( buttonName, size, position, parent, buttonStyle )
local button = Instance.new("ImageButton")
button.RobloxLocked = true
button.Name = buttonName
button.Size = size
button.Position = position
if buttonStyle then
button.Style = buttonStyle
else
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderColor3 = Color3.new(1,1,1)
end
button.Parent = parent
return button
end
local function makeTextLabel( TextLabelName,text,position,parent )
local label = Instance.new("TextLabel")
label.RobloxLocked = true
label.BackgroundTransparency = 1
label.Size = UDim2.new(0,32,0,14)
label.Name = TextLabelName
label.Font = Enum.Font.Arial
label.TextColor3 = Color3.new(1,1,1)
label.FontSize = Enum.FontSize.Size14
label.Text = text
label.Position = position
label.Parent = parent
end
local Wardrobe = Instance.new("Frame")
Wardrobe.Name = "Wardrobe"
Wardrobe.RobloxLocked = true
Wardrobe.BackgroundTransparency = 1
Wardrobe.Visible = false
Wardrobe.Size = UDim2.new(1,0,1,0)
Wardrobe.Parent = Backpack
local AssetList = Instance.new("Frame")
AssetList.RobloxLocked = true
AssetList.Name = "AssetList"
AssetList.Position = UDim2.new(0,4,0,5)
AssetList.Size = UDim2.new(0,85,1,-5)
AssetList.BackgroundTransparency = 1
AssetList.Visible = true
AssetList.Parent = Wardrobe
local PreviewAssetFrame = Instance.new("Frame")
PreviewAssetFrame.RobloxLocked = true
PreviewAssetFrame.Name = "PreviewAssetFrame"
PreviewAssetFrame.BackgroundTransparency = 1
PreviewAssetFrame.Position = UDim2.new(1,-240,0,30)
PreviewAssetFrame.Size = UDim2.new(0,250,0,250)
PreviewAssetFrame.Parent = Wardrobe
local PreviewAssetBacking = Instance.new("TextButton")
PreviewAssetBacking.RobloxLocked = true
PreviewAssetBacking.Name = "PreviewAssetBacking"
PreviewAssetBacking.Active = false
PreviewAssetBacking.Text = ""
PreviewAssetBacking.AutoButtonColor = false
PreviewAssetBacking.Size = UDim2.new(1,0,1,0)
PreviewAssetBacking.Style = Enum.ButtonStyle.RobloxButton
PreviewAssetBacking.Visible = false
PreviewAssetBacking.ZIndex = 9
PreviewAssetBacking.Parent = PreviewAssetFrame
local PreviewAssetImage = Instance.new("ImageLabel")
PreviewAssetImage.RobloxLocked = true
PreviewAssetImage.Name = "PreviewAssetImage"
PreviewAssetImage.BackgroundTransparency = 0.8
PreviewAssetImage.Position = UDim2.new(0.5,-100,0,0)
PreviewAssetImage.Size = UDim2.new(0,200,0,200)
PreviewAssetImage.BorderSizePixel = 0
PreviewAssetImage.ZIndex = 10
PreviewAssetImage.Parent = PreviewAssetBacking
local AssetNameLabel = Instance.new("TextLabel")
AssetNameLabel.Name = "AssetNameLabel"
AssetNameLabel.RobloxLocked = true
AssetNameLabel.BackgroundTransparency = 1
AssetNameLabel.Position = UDim2.new(0,0,1,-20)
AssetNameLabel.Size = UDim2.new(0.5,0,0,24)
AssetNameLabel.ZIndex = 10
AssetNameLabel.Font = Enum.Font.Arial
AssetNameLabel.Text = ""
AssetNameLabel.TextColor3 = Color3.new(1,1,1)
AssetNameLabel.TextScaled = true
AssetNameLabel.Parent = PreviewAssetBacking
local AssetTypeLabel = AssetNameLabel:clone()
AssetTypeLabel.RobloxLocked = true
AssetTypeLabel.Name = "AssetTypeLabel"
AssetTypeLabel.TextScaled = false
AssetTypeLabel.FontSize = Enum.FontSize.Size18
AssetTypeLabel.Position = UDim2.new(0.5,3,1,-20)
AssetTypeLabel.Parent = PreviewAssetBacking
local PreviewButton = Instance.new("TextButton")
PreviewButton.RobloxLocked = true
PreviewButton.Name = "PreviewButton"
PreviewButton.Text = "Rotate"
PreviewButton.BackgroundColor3 = Color3.new(0,0,0)
PreviewButton.BackgroundTransparency = 0.5
PreviewButton.BorderColor3 = Color3.new(1,1,1)
PreviewButton.Position = UDim2.new(1.2,-62,1,-50)
PreviewButton.Size = UDim2.new(0,125,0,50)
PreviewButton.Font = Enum.Font.ArialBold
PreviewButton.FontSize = Enum.FontSize.Size24
PreviewButton.TextColor3 = Color3.new(1,1,1)
PreviewButton.TextWrapped = true
PreviewButton.TextStrokeTransparency = 0
PreviewButton.Parent = Wardrobe
local CharacterPane = Instance.new("Frame")
CharacterPane.RobloxLocked = true
CharacterPane.Name = "CharacterPane"
CharacterPane.Position = UDim2.new(1,-220,0,32)
CharacterPane.Size = UDim2.new(0,220,1,-40)
CharacterPane.BackgroundTransparency = 1
CharacterPane.Visible = true
CharacterPane.Parent = Wardrobe
--CharacterPane Children
local FaceFrame = makeCharFrame("FacesFrame", CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=75460621")
makeZone("FaceZone","http://www.roblox.com/asset/?id=75460621",UDim2.new(0,157,0,137),UDim2.new(0.5,-78,0.5,-68),FaceFrame)
makeStyledButton("Face",UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-135),FaceFrame)
local HeadFrame = makeCharFrame("HeadsFrame", CharacterPane)
makeZone("FaceZone","http://www.roblox.com/asset/?id=75460621",UDim2.new(0,157,0,137),UDim2.new(0.5,-78,0.5,-68),HeadFrame)
makeStyledButton("Head",UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-135),HeadFrame)
local HatsFrame = makeCharFrame("HatsFrame", CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=75457888")
local HatsZone = makeZone("HatsZone","http://www.roblox.com/asset/?id=75457888",UDim2.new(0,186,0,184),UDim2.new(0.5,-93,0.5,-100), HatsFrame)
makeStyledButton("Hat1Button",UDim2.new(0,64,0,64),UDim2.new(0,-1,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton)
makeStyledButton("Hat2Button",UDim2.new(0,64,0,64),UDim2.new(0,63,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton)
makeStyledButton("Hat3Button",UDim2.new(0,64,0,64),UDim2.new(0,127,0,-1),HatsZone,Enum.ButtonStyle.RobloxButton)
local PantsFrame = makeCharFrame("PantsFrame", CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=75457920")
makeZone("PantsZone","http://www.roblox.com/asset/?id=75457920",UDim2.new(0,121,0,99),UDim2.new(0.5,-60,0.5,-100),PantsFrame)
local pantFrame = Instance.new("Frame")
pantFrame.RobloxLocked = true
pantFrame.Size = UDim2.new(0,25,0,56)
pantFrame.Position = UDim2.new(0.5,-26,0.5,0)
pantFrame.BackgroundColor3 = Color3.new(0,0,0)
pantFrame.BorderColor3 = Color3.new(1,1,1)
pantFrame.Name = "PantFrame"
pantFrame.Parent = PantsFrame
local otherPantFrame = pantFrame:clone()
otherPantFrame.Position = UDim2.new(0.5,3,0.5,0)
otherPantFrame.RobloxLocked = true
otherPantFrame.Parent = PantsFrame
local CurrentPants = Instance.new("ImageButton")
CurrentPants.RobloxLocked = true
CurrentPants.BackgroundTransparency = 1
CurrentPants.ZIndex = 2
CurrentPants.Name = "CurrentPants"
CurrentPants.Position = UDim2.new(0.5,-31,0.5,-4)
CurrentPants.Size = UDim2.new(0,54,0,59)
CurrentPants.Parent = PantsFrame
local MeshFrame = makeCharFrame("PackagesFrame", CharacterPane)
local torsoButton = makeStyledButton("TorsoMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("TorsoLabel","Torso",UDim2.new(0.5,-16,0,-25),torsoButton)
local leftLegButton = makeStyledButton("LeftLegMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,0,0.5,-25),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("LeftLegLabel","Left Leg",UDim2.new(0.5,-16,0,-25),leftLegButton)
local rightLegButton = makeStyledButton("RightLegMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-64,0.5,-25),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("RightLegLabel","Right Leg",UDim2.new(0.5,-16,0,-25),rightLegButton)
local rightArmButton = makeStyledButton("RightArmMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-96,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("RightArmLabel","Right Arm",UDim2.new(0.5,-16,0,-25),rightArmButton)
local leftArmButton = makeStyledButton("LeftArmMeshButton", UDim2.new(0,64,0,64),UDim2.new(0.5,32,0.5,-110),MeshFrame,Enum.ButtonStyle.RobloxButton)
makeTextLabel("LeftArmLabel","Left Arm",UDim2.new(0.5,-16,0,-25),leftArmButton)
local TShirtFrame = makeCharFrame("T-ShirtsFrame",CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=75460642")
makeZone("TShirtZone","http://www.roblox.com/asset/?id=75460642",UDim2.new(0,121,0,154),UDim2.new(0.5,-60,0.5,-100),TShirtFrame)
makeStyledButton("TShirtButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-64),TShirtFrame)
local ShirtFrame = makeCharFrame("ShirtsFrame", CharacterPane)
makeZone("ShirtZone","http://www.roblox.com/asset/?id=75460642",UDim2.new(0,121,0,154),UDim2.new(0.5,-60,0.5,-100),ShirtFrame)
makeStyledButton("ShirtButton", UDim2.new(0,64,0,64),UDim2.new(0.5,-32,0.5,-64),ShirtFrame)
local ColorFrame = makeCharFrame("ColorFrame", CharacterPane)
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=76049888")
local ColorZone = makeZone("ColorZone","http://www.roblox.com/asset/?id=76049888", UDim2.new(0,120,0,150),UDim2.new(0.5,-60,0.5,-100),ColorFrame)
makeStyledButton("Head",UDim2.new(0.26,0,0.19,0),UDim2.new(0.37,0,0.02,0),ColorZone).AutoButtonColor = false
makeStyledButton("LeftArm",UDim2.new(0.19,0,0.36,0),UDim2.new(0.78,0,0.26,0),ColorZone).AutoButtonColor = false
makeStyledButton("RightArm",UDim2.new(0.19,0,0.36,0),UDim2.new(0.025,0,0.26,0),ColorZone).AutoButtonColor = false
makeStyledButton("Torso",UDim2.new(0.43,0,0.36,0),UDim2.new(0.28,0,0.26,0),ColorZone).AutoButtonColor = false
makeStyledButton("RightLeg",UDim2.new(0.19,0,0.31,0),UDim2.new(0.275,0,0.67,0),ColorZone).AutoButtonColor = false
makeStyledButton("LeftLeg",UDim2.new(0.19,0,0.31,0),UDim2.new(0.525,0,0.67,0),ColorZone).AutoButtonColor = false
-- Character Panel label (shows what category we are currently browsing)
local CategoryLabel = Instance.new("TextLabel")
CategoryLabel.RobloxLocked = true
CategoryLabel.Name = "CategoryLabel"
CategoryLabel.BackgroundTransparency = 1
CategoryLabel.Font = Enum.Font.ArialBold
CategoryLabel.FontSize = Enum.FontSize.Size18
CategoryLabel.Position = UDim2.new(0,0,0,-7)
CategoryLabel.Size = UDim2.new(1,0,0,20)
CategoryLabel.TextXAlignment = Enum.TextXAlignment.Center
CategoryLabel.Text = "All"
CategoryLabel.TextColor3 = Color3.new(1,1,1)
CategoryLabel.Parent = CharacterPane
--Save Button
local SaveButton = Instance.new("TextButton")
SaveButton.RobloxLocked = true
SaveButton.Name = "SaveButton"
SaveButton.Size = UDim2.new(0.6,0,0,50)
SaveButton.Position = UDim2.new(0.2,0,1,-50)
SaveButton.Style = Enum.ButtonStyle.RobloxButton
SaveButton.Selected = false
SaveButton.Font = Enum.Font.ArialBold
SaveButton.FontSize = Enum.FontSize.Size18
SaveButton.Text = "Save"
SaveButton.TextColor3 = Color3.new(1,1,1)
SaveButton.Parent = CharacterPane
-- no need for this to stick around
script:remove()

968
app/files/CoreGui/53878053 Normal file
View File

@ -0,0 +1,968 @@
if game.CoreGui.Version < 3 then return end -- peace out if we aren't using the right client
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
local RbxGui,msg = LoadLibrary("RbxGui")
if not RbxGui then print("could not find RbxGui!") return end
--- Begin Locals
waitForChild(game,"Players")
-- don't do anything if we are in an empty game
if #game.Players:GetChildren() < 1 then
game.Players.ChildAdded:wait()
end
local tilde = "~"
local backquote = "`"
game:GetService("GuiService"):AddKey(tilde) -- register our keys
game:GetService("GuiService"):AddKey(backquote)
local player = game.Players.LocalPlayer
local backpack = script.Parent
local screen = script.Parent.Parent
local closeButton = backpack.Tabs.CloseButton
local openCloseDebounce = false
local backpackItems = {}
local buttons = {}
local debounce = false
local guiTweenSpeed = 1
local backpackOldStateVisible = false
local browsingMenu = false
local mouseEnterCons = {}
local mouseClickCons = {}
local characterChildAddedCon = nil
local characterChildRemovedCon = nil
local backpackAddCon = nil
local humanoidDiedCon = nil
local backpackButtonClickCon = nil
local guiServiceKeyPressCon = nil
waitForChild(player,"Backpack")
local playerBackpack = player.Backpack
waitForChild(backpack,"Gear")
waitForChild(backpack.Gear,"GearPreview")
local gearPreview = backpack.Gear.GearPreview
waitForChild(backpack.Gear,"GearGridScrollingArea")
local scroller = backpack.Gear.GearGridScrollingArea
waitForChild(backpack.Parent,"CurrentLoadout")
local currentLoadout = backpack.Parent.CurrentLoadout
waitForChild(backpack.Parent,"ControlFrame")
waitForChild(backpack.Parent.ControlFrame,"BackpackButton")
local backpackButton = backpack.Parent.ControlFrame.BackpackButton
waitForChild(backpack.Gear,"GearGrid")
waitForChild(backpack.Gear.GearGrid,"GearButton")
local gearButton = backpack.Gear.GearGrid.GearButton
local grid = backpack.Gear.GearGrid
waitForChild(backpack.Gear.GearGrid,"SearchFrame")
waitForChild(backpack.Gear.GearGrid.SearchFrame,"SearchBoxFrame")
waitForChild(backpack.Gear.GearGrid.SearchFrame.SearchBoxFrame,"SearchBox")
local searchBox = backpack.Gear.GearGrid.SearchFrame.SearchBoxFrame.SearchBox
waitForChild(backpack.Gear.GearGrid.SearchFrame,"SearchButton")
local searchButton = backpack.Gear.GearGrid.SearchFrame.SearchButton
waitForChild(backpack.Gear.GearGrid,"ResetFrame")
local resetFrame = backpack.Gear.GearGrid.ResetFrame
waitForChild(backpack.Gear.GearGrid.ResetFrame,"ResetButtonBorder")
local resetButton = backpack.Gear.GearGrid.ResetFrame.ResetButtonBorder
waitForChild(script.Parent,"SwapSlot")
local swapSlot = script.Parent.SwapSlot
-- creating scroll bar early as to make sure items get placed correctly
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil, "grid", Vector2.new(4, 4))
scrollFrame.Position = UDim2.new(0,0,0,30)
scrollFrame.Size = UDim2.new(1,0,1,-30)
scrollFrame.Parent = backpack.Gear.GearGrid
local scrollBar = Instance.new("Frame")
scrollBar.Name = "ScrollBar"
scrollBar.BackgroundTransparency = 0.9
scrollBar.BackgroundColor3 = Color3.new(1,1,1)
scrollBar.BorderSizePixel = 0
scrollBar.Size = UDim2.new(0, 17, 1, -36)
scrollBar.Position = UDim2.new(0,0,0,18)
scrollBar.Parent = scroller
scrollDown.Position = UDim2.new(0,0,1,-17)
scrollUp.Parent = scroller
scrollDown.Parent = scroller
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
local LoadoutButton = Instance.new("TextButton")
LoadoutButton.RobloxLocked = true
LoadoutButton.Name = "LoadoutButton"
LoadoutButton.Font = Enum.Font.ArialBold
LoadoutButton.FontSize = Enum.FontSize.Size14
LoadoutButton.Position = UDim2.new(0,0,0,0)
LoadoutButton.Size = UDim2.new(1,0,0,32)
LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
LoadoutButton.Text = "Loadout #1"
LoadoutButton.TextColor3 = Color3.new(1,1,1)
LoadoutButton.Parent = scrollFrameLoadout
local LoadoutButtonTwo = LoadoutButton:clone()
LoadoutButtonTwo.Text = "Loadout #2"
LoadoutButtonTwo.Parent = scrollFrameLoadout
local LoadoutButtonThree = LoadoutButton:clone()
LoadoutButtonThree.Text = "Loadout #3"
LoadoutButtonThree.Parent = scrollFrameLoadout
local LoadoutButtonFour = LoadoutButton:clone()
LoadoutButtonFour.Text = "Loadout #4"
LoadoutButtonFour.Parent = scrollFrameLoadout
local scrollBarLoadout = Instance.new("Frame")
scrollBarLoadout.Name = "ScrollBarLoadout"
scrollBarLoadout.BackgroundTransparency = 0.9
scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
scrollBarLoadout.BorderSizePixel = 0
scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
scrollBarLoadout.Position = UDim2.new(0,0,0,18)
scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
-- Begin Functions
function removeFromMap(map,object)
for i = 1, #map do
if map[i] == object then
table.remove(map,i)
break
end
end
end
function robloxLock(instance)
instance.RobloxLocked = true
children = instance:GetChildren()
if children then
for i, child in ipairs(children) do
robloxLock(child)
end
end
end
function resize()
local size = 0
if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
size = gearPreview.AbsoluteSize.X * 0.75
else
size = gearPreview.AbsoluteSize.Y * 0.75
end
gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
resizeGrid()
end
function addToGrid(child)
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
return
end
end
if child:FindFirstChild("RobloxBuildTool") then return end
for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
if v == child then return end
end
table.insert(backpackItems,child)
local changeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if buttons[child] then
if buttons[child].Image == "" then
buttons[child].GearText.Text = child.Name
end
end
end
end)
local ancestryCon = nil
ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
local thisObject = nil
for k,v in pairs(backpackItems) do
if v == child then
thisObject = v
break
end
end
waitForProperty(player,"Character")
waitForChild(player,"Backpack")
if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
if ancestryCon then ancestryCon:disconnect() end
if changeCon then changeCon:disconnect() end
for k,v in pairs(backpackItems) do
if v == thisObject then
if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
buttons[v].Parent = nil
buttons[v] = nil
break
end
end
removeFromMap(backpackItems,thisObject)
resizeGrid()
else
resizeGrid()
end
updateGridActive()
end)
resizeGrid()
end
function buttonClick(button)
if button:FindFirstChild("UnequipContextMenu") and not button.Active then
button.UnequipContextMenu.Visible = true
browsingMenu = true
end
end
function previewGear(button)
if not browsingMenu then
gearPreview.GearImage.Image = button.Image
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
end
end
function findEmptySlot()
local smallestNum = nil
local loadout = currentLoadout:GetChildren()
for i = 1, #loadout do
if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
local frameNum = tonumber(string.sub(loadout[i].Name,5))
if frameNum == 0 then frameNum = 10 end
if not smallestNum or (smallestNum > frameNum) then
smallestNum = frameNum
end
end
end
if smallestNum == 10 then smallestNum = 0 end
return smallestNum
end
function checkForSwap(button,x,y)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
swapGearSlot(slot,button)
return true
end
end
end
end
return false
end
function resizeGrid()
for k,v in pairs(backpackItems) do
if not v:FindFirstChild("RobloxBuildTool") then
if not buttons[v] then
local buttonClone = gearButton:clone()
buttonClone.Parent = grid.ScrollingFrame
buttonClone.Visible = true
buttonClone.Image = v.TextureId
if buttonClone.Image == "" then
buttonClone.GearText.Text = v.Name
end
buttonClone.GearReference.Value = v
buttonClone.Draggable = true
buttons[v] = buttonClone
local unequipMenu = getGearContextMenu()
unequipMenu.Visible = false
unequipMenu.Parent = buttonClone
local beginPos = nil
buttonClone.DragBegin:connect(function(value)
buttonClone.ZIndex = 9
beginPos = value
end)
buttonClone.DragStopped:connect(function(x,y)
buttonClone.ZIndex = 1
if beginPos ~= buttonClone.Position then
if not checkForSwap(buttonClone,x,y) then
buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
buttonClone.Draggable = false
delay(0.5,function()
buttonClone.Draggable = true
end)
else
buttonClone.Position = beginPos
end
end
end)
local clickTime = tick()
mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
local newClickTime = tick()
if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
local slot = findEmptySlot()
if slot then
buttonClone.ZIndex = 1
swapGearSlot(slot,buttonClone)
end
else
buttonClick(buttonClone)
end
clickTime = newClickTime
end)
end
end
end
recalculateScroll()
end
function showPartialGrid(subset)
resetFrame.Visible = true
for k,v in pairs(buttons) do
v.Parent = nil
end
for k,v in pairs(subset) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function showEntireGrid()
resetFrame.Visible = false
for k,v in pairs(buttons) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function inLoadout(gear)
local children = currentLoadout:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
local button = children[i]:GetChildren()
if #button > 0 then
if button[1].GearReference.Value and button[1].GearReference.Value == gear then
return true
end
end
end
end
return false
end
function updateGridActive()
for k,v in pairs(backpackItems) do
if buttons[v] then
local gear = nil
local gearRef = buttons[v]:FindFirstChild("GearReference")
if gearRef then gear = gearRef.Value end
if not gear then
buttons[v].Active = false
elseif inLoadout(gear) then
buttons[v].Active = false
else
buttons[v].Active = true
end
end
end
end
function centerGear(loadoutChildren)
local gearButtons = {}
local lastSlotAdd = nil
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
if loadoutChildren[i].Name == "Slot0" then
lastSlotAdd = loadoutChildren[i]
else
table.insert(gearButtons, loadoutChildren[i])
end
end
end
if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
for i = 1, #gearButtons do
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
function spreadOutGear(loadoutChildren)
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
if slot == 0 then slot = 10 end
loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
end
function openCloseBackpack(close)
if openCloseDebounce then return end
openCloseDebounce = true
local visible = not backpack.Visible
if visible and not close then
updateGridActive()
local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
backpack.Visible = true
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 0.5
end
end
spreadOutGear(loadoutChildren)
end,
function()
backpack.Visible = false
end)
end)
backpackButton.Selected = true
backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.6, 0),UDim2.new(0.225, 0, 0.2, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
delay(guiTweenSpeed/2 + 0.01,
function()
local children = backpack:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
children[i].Visible = true
end
end
resizeGrid()
resize()
openCloseDebounce = false
end)
else
backpackButton.Selected = false
local children = backpack:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
children[i].Visible = false
end
end
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 1
end
end
centerGear(loadoutChildren)
backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
delay(guiTweenSpeed/2 + 0.01,
function()
backpack.Visible = visible
resizeGrid()
resize()
pcall(function() game.GuiService:RemoveCenterDialog(backpack) end)
openCloseDebounce = false
end)
end
end
function loadoutCheck(child, selectState)
if not child:IsA("ImageButton") then return end
for k,v in pairs(backpackItems) do
if buttons[v] then
if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
if buttons[v].GearReference.Value == child.GearReference.Value then
buttons[v].Active = selectState
break
end
end
end
end
end
function clearPreview()
gearPreview.GearImage.Image = ""
gearPreview.GearStats.GearName.Text = ""
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
stuff[i].Parent = playerBackpack
end
end
end
function equipGear(physGear)
removeAllEquippedGear(physGear)
physGear.Parent = player.Character
updateGridActive()
end
function unequipGear(physGear)
physGear.Parent = playerBackpack
updateGridActive()
end
function highlight(button)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
end
function clearHighlight(button)
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundColor3 = Color3.new(0,0,0)
end
function swapGearSlot(slot,gearButton)
if not swapSlot.Value then -- signal loadout to swap a gear out
swapSlot.Slot.Value = slot
swapSlot.GearButton.Value = gearButton
swapSlot.Value = true
updateGridActive()
end
end
local UnequipGearMenuClick = function(element, menu)
if type(element.Action) ~= "number" then return end
local num = element.Action
if num == 1 then -- remove from loadout
unequipGear(menu.Parent.GearReference.Value)
local inventoryButton = menu.Parent
local gearToUnequip = inventoryButton.GearReference.Value
local loadoutChildren = currentLoadout:GetChildren()
local slot = -1
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local button = loadoutChildren[i]:GetChildren()
if button[1] and button[1].GearReference.Value == gearToUnequip then
slot = button[1].SlotNumber.Text
break
end
end
end
swapGearSlot(slot,nil)
end
end
-- these next two functions are used to stop any use of backpack while the player is dead (can cause issues)
function activateBackpack()
backpack.Visible = backpackOldStateVisible
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 1
end
end
backpackButtonClickCon = backpackButton.MouseButton1Click:connect(function() openCloseBackpack() end)
guiServiceKeyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key)
if key == tilde or key == backquote then
openCloseBackpack()
end
end)
end
function deactivateBackpack()
if backpackButtonClickCon then backpackButtonClickCon:disconnect() end
if guiServiceKeyPressCon then guiServiceKeyPressCon:disconnect() end
backpackOldStateVisible = backpack.Visible
backpack.Visible = false
openCloseBackpack(true)
end
function setupCharacterConnections()
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
-- make sure we get all the children
local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
if characterChildAddedCon then characterChildAddedCon:disconnect() end
characterChildAddedCon =
game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
addToGrid(child)
updateGridActive()
end)
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
characterChildRemovedCon =
game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child)
updateGridActive()
end)
if humanoidDiedCon then humanoidDiedCon:disconnect() end
local localPlayer = game.Players.LocalPlayer
waitForProperty(localPlayer,"Character")
waitForChild(localPlayer.Character,"Humanoid")
humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(function() deactivateBackpack() end)
activateBackpack()
wait()
centerGear(currentLoadout:GetChildren())
end
function removeCharacterConnections()
if characterChildAddedCon then characterChildAddedCon:disconnect() end
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
if backpackAddCon then backpackAddCon:disconnect() end
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function splitByWhiteSpace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 2 then
table.insert(terms,token)
end
end
return terms
end
function filterGear(searchTerm)
string.lower(searchTerm)
searchTerm = trim(searchTerm)
if string.len(searchTerm) < 2 then return nil end
local terms = splitByWhiteSpace(searchTerm)
local filteredGear = {}
for k,v in pairs(backpackItems) do
if buttons[v] then
local gearString = string.lower(buttons[v].GearReference.Value.Name)
gearString = trim(gearString)
for i = 1, #terms do
if string.match(gearString,terms[i]) then
table.insert(filteredGear,buttons[v])
break
end
end
end
end
return filteredGear
end
function showSearchGear()
local searchText = searchBox.Text
searchBox.Text = "Search..."
local filteredButtons = filterGear(searchText)
if filteredButtons and #filteredButtons > 0 then
showPartialGrid(filteredButtons)
else
showEntireGrid()
end
end
function nukeBackpack()
while #buttons > 0 do
table.remove(buttons)
end
buttons = {}
while #backpackItems > 0 do
table.remove(backpackItems)
end
backpackItems = {}
local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
for i = 1, #scrollingFrameChildren do
scrollingFrameChildren[i]:remove()
end
end
function getGearContextMenu()
local gearContextMenu = Instance.new("Frame")
gearContextMenu.Active = true
gearContextMenu.Name = "UnequipContextMenu"
gearContextMenu.Size = UDim2.new(0,115,0,70)
gearContextMenu.Position = UDim2.new(0,-16,0,-16)
gearContextMenu.BackgroundTransparency = 1
gearContextMenu.Visible = false
local gearContextMenuButton = Instance.new("TextButton")
gearContextMenuButton.Name = "UnequipContextMenuButton"
gearContextMenuButton.Text = ""
gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
gearContextMenuButton.ZIndex = 8
gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
gearContextMenuButton.Visible = true
gearContextMenuButton.Parent = gearContextMenu
local elementHeight = 12
local contextMenuElements = {}
local contextMenuElementsName = {"Remove Hotkey"}
for i = 1, #contextMenuElementsName do
local element = {}
element.Type = "Button"
element.Text = contextMenuElementsName[i]
element.Action = i
element.DoIt = UnequipGearMenuClick
table.insert(contextMenuElements,element)
end
for i, contextElement in ipairs(contextMenuElements) do
local element = contextElement
if element.Type == "Button" then
local button = Instance.new("TextButton")
button.Name = "UnequipContextButton" .. i
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderSizePixel = 0
button.TextXAlignment = Enum.TextXAlignment.Left
button.Text = " " .. contextElement.Text
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.Size = UDim2.new(1, 8, 0, elementHeight)
button.Position = UDim2.new(0,0,0,elementHeight * i)
button.TextColor3 = Color3.new(1,1,1)
button.ZIndex = 9
button.Parent = gearContextMenuButton
button.MouseButton1Click:connect(function()
if button.Active and not gearContextMenu.Parent.Active then
local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
browsingMenu = false
gearContextMenu.Visible = false
clearHighlight(button)
clearPreview()
end
end)
button.MouseEnter:connect(function()
if button.Active and gearContextMenu.Parent.Active then
highlight(button)
end
end)
button.MouseLeave:connect(function()
if button.Active and gearContextMenu.Parent.Active then
clearHighlight(button)
end
end)
contextElement.Button = button
contextElement.Element = button
elseif element.Type == "Label" then
local frame = Instance.new("Frame")
frame.Name = "ContextLabel" .. i
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 8, 0, elementHeight)
local label = Instance.new("TextLabel")
label.Name = "Text1"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Left
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.0, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label1 = label
if element.GetText2 then
label = Instance.new("TextLabel")
label.Name = "Text2"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Right
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.5, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label2 = label
end
frame.Parent = gearContextMenuButton
element.Label = frame
element.Element = frame
end
end
gearContextMenu.ZIndex = 4
gearContextMenu.MouseLeave:connect(function()
browsingMenu = false
gearContextMenu.Visible = false
clearPreview()
end)
robloxLock(gearContextMenu)
return gearContextMenu
end
local backpackChildren = player.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
------------------------- Start Lifelong Connections -----------------------
screen.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
if debounce then return end
debounce = true
wait()
resize()
resizeGrid()
debounce = false
end
end)
currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
currentLoadout.DescendantAdded:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
centerGear(currentLoadout:GetChildren())
end
end)
currentLoadout.DescendantRemoving:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
wait()
centerGear(currentLoadout:GetChildren())
end
end)
grid.MouseEnter:connect(function() clearPreview() end)
grid.MouseLeave:connect(function() clearPreview() end)
player.CharacterRemoving:connect(function()
removeCharacterConnections()
nukeBackpack()
end)
player.CharacterAdded:connect(function() setupCharacterConnections() end)
player.ChildAdded:connect(function(child)
if child:IsA("Backpack") then
playerBackpack = child
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
end)
swapSlot.Changed:connect(function()
if not swapSlot.Value then
updateGridActive()
end
end)
searchBox.FocusLost:connect(function(enterPressed)
if enterPressed then
showSearchGear()
end
end)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
loadoutChildren[i].ChildRemoved:connect(function()
updateGridActive()
end)
loadoutChildren[i].ChildAdded:connect(function()
updateGridActive()
end)
end
end
pcall(function() closeButton.Modal = true end)
closeButton.MouseButton1Click:connect(function() openCloseBackpack() end)
searchButton.MouseButton1Click:connect(function() showSearchGear() end)
resetButton.MouseButton1Click:connect(function() showEntireGrid() end)
------------------------- End Lifelong Connections -----------------------
resize()
resizeGrid()
-- make sure any items in the loadout are accounted for in inventory
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
loadoutCheck(loadoutChildren[i], false)
end
if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
-- make sure that inventory is listening to gear reparenting
if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then
setupCharacterConnections()
end
if not backpackAddCon then
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
-- flip it on if we are good
if game.CoreGui.Version >= 3 then
backpackButton.Visible = true
end
recalculateScrollLoadout()

1098
app/files/CoreGui/53878057 Normal file

File diff suppressed because it is too large Load Diff

883
app/files/CoreGui/53878058 Normal file
View File

@ -0,0 +1,883 @@
if game.CoreGui.Version < 3 then return end -- peace out if we aren't using the right client
-- A couple of necessary functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
local currentLoadout = script.Parent
local StaticTabName = "gear"
local robloxGui = game:GetService("CoreGui"):FindFirstChild("RobloxGui")
assert(robloxGui)
waitForChild(robloxGui,"CurrentLoadout")
waitForChild(robloxGui.CurrentLoadout,"TempSlot")
waitForChild(robloxGui.CurrentLoadout.TempSlot,"SlotNumber")
--- Begin Locals
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
waitForChild(game, "LocalBackpack")
game.LocalBackpack:SetOldSchoolBackpack(false)
waitForChild(currentLoadout.Parent,"Backpack")
local guiBackpack = currentLoadout.Parent.Backpack
local backpackManager = waitForChild(guiBackpack,"CoreScripts/BackpackScripts/BackpackManager")
local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent")
local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent")
local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent")
local resizeEvent = waitForChild(backpackManager,"ResizeEvent")
local inGearTab = true
local maxNumLoadoutItems = 10
local characterChildAddedCon = nil
local backpackChildCon = nil
local debounce = false
local enlargeFactor = 1.18
local buttonSizeEnlarge = UDim2.new(1 * enlargeFactor,0,1 * enlargeFactor,0)
local buttonSizeNormal = UDim2.new(1,0,1,0)
local enlargeOverride = true
local guiTweenSpeed = 0.5
local inventory = {}
for i = 0, 9 do
game:GetService("GuiService"):AddKey(tostring(i)) -- register our keys
end
local gearSlots = {}
for i = 1, maxNumLoadoutItems do
gearSlots[i] = "empty"
end
--- End Locals
-- Begin Functions
local function kill(prop,con,gear)
if con then con:disconnect() end
if prop == true and gear then
reorganizeLoadout(gear,false)
end
end
function characterInWorkspace()
if game.Players["LocalPlayer"] then
if game.Players.LocalPlayer["Character"] then
if game.Players.LocalPlayer.Character ~= nil then
if game.Players.LocalPlayer.Character.Parent ~= nil then
return true
end
end
end
end
return false
end
function removeGear(gear)
local emptySlot = nil
for i = 1, #gearSlots do
if gearSlots[i] == gear and gear.Parent ~= nil then
emptySlot = i
break
end
end
if emptySlot then
if gearSlots[emptySlot].GearReference.Value then
if gearSlots[emptySlot].GearReference.Value.Parent == game.Players.LocalPlayer.Character then -- if we currently have this equipped, unequip it
gearSlots[emptySlot].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack
end
if gearSlots[emptySlot].GearReference.Value:IsA("HopperBin") and gearSlots[emptySlot].GearReference.Value.Active then -- this is an active hopperbin
gearSlots[emptySlot].GearReference.Value:Disable()
gearSlots[emptySlot].GearReference.Value.Active = false
end
end
gearSlots[emptySlot] = "empty"
local centerizeX = gear.Size.X.Scale/2
local centerizeY = gear.Size.Y.Scale/2
gear:TweenSizeAndPosition(UDim2.new(0,0,0,0),
UDim2.new(gear.Position.X.Scale + centerizeX,gear.Position.X.Offset,gear.Position.Y.Scale + centerizeY,gear.Position.Y.Offset),
Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/4,true)
delay(guiTweenSpeed/2,
function()
gear:remove()
end)
end
end
function insertGear(gear, addToSlot)
local pos = nil
if not addToSlot then
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then
pos = i
break
end
end
if pos == 1 and gearSlots[1] ~= "empty" then gear:remove() return end -- we are currently full, can't add in
else
pos = addToSlot
-- push all gear down one slot
local start = 1
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then
start = i
break
end
end
for i = start, pos + 1, -1 do
gearSlots[i] = gearSlots[i - 1]
if i == 10 then
gearSlots[i].SlotNumber.Text = "0"
gearSlots[i].SlotNumberDownShadow.Text = "0"
gearSlots[i].SlotNumberUpShadow.Text = "0"
else
gearSlots[i].SlotNumber.Text = i
gearSlots[i].SlotNumberDownShadow.Text = i
gearSlots[i].SlotNumberUpShadow.Text = i
end
end
end
gearSlots[pos] = gear
if pos ~= maxNumLoadoutItems then
if(type(tostring(pos)) == "string") then
local posString = tostring(pos)
gear.SlotNumber.Text = posString
gear.SlotNumberDownShadow.Text = posString
gear.SlotNumberUpShadow.Text = posString
end
else -- tenth gear doesn't follow mathematical pattern :(
gear.SlotNumber.Text = "0"
gear.SlotNumberDownShadow.Text = "0"
gear.SlotNumberUpShadow.Text = "0"
end
gear.Visible = true
local con = nil
con = gear.Kill.Changed:connect(function(prop) kill(prop,con,gear) end)
end
function reorganizeLoadout(gear, inserting, equipped, addToSlot)
if inserting then -- add in gear
insertGear(gear, addToSlot)
else
removeGear(gear)
end
if gear ~= "empty" then gear.ZIndex = 1 end
end
function checkToolAncestry(child,parent)
if child:FindFirstChild("RobloxBuildTool") then return end -- don't show roblox build tools
if child:IsA("Tool") or child:IsA("HopperBin") then
for i = 1, #gearSlots do
if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then
if parent == nil then
gearSlots[i].Kill.Value = true
return false
elseif child.Parent == player.Character then
gearSlots[i].Selected = true
return true
elseif child.Parent == player.Backpack then
if child:IsA("Tool") or child:IsA("HopperBin") then gearSlots[i].Selected = false end
return true
else
gearSlots[i].Kill.Value = true
return false
end
return true
end
end
end
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
if stuff[i]:IsA("Tool") then stuff[i].Parent = player.Backpack end
if stuff[i]:IsA("HopperBin") then
stuff[i]:Disable()
end
end
end
end
function hopperBinSwitcher(numKey, physGear)
if not physGear then return end
physGear:ToggleSelect()
if gearSlots[numKey] == "empty" then return end
if not physGear.Active then
gearSlots[numKey].Selected = false
normalizeButton(gearSlots[numKey])
else
gearSlots[numKey].Selected = true
enlargeButton(gearSlots[numKey])
end
end
function toolSwitcher(numKey)
if not gearSlots[numKey] then return end
local physGear = gearSlots[numKey].GearReference.Value
if physGear == nil then return end
removeAllEquippedGear(physGear) -- we don't remove this gear, as then we get a double switcheroo
local key = numKey
if numKey == 0 then key = 10 end
for i = 1, #gearSlots do
if gearSlots[i] and gearSlots[i] ~= "empty" and i ~= key then
normalizeButton(gearSlots[i])
gearSlots[i].Selected = false
if gearSlots[i].GearReference and gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value:IsA("HopperBin") and gearSlots[i].GearReference.Value.Active then
gearSlots[i].GearReference.Value:ToggleSelect()
end
end
end
if physGear:IsA("HopperBin") then
hopperBinSwitcher(numKey,physGear)
else
if physGear.Parent == player.Character then
physGear.Parent = player.Backpack
if gearSlots[numKey] ~= "empty" then
gearSlots[numKey].Selected = false
normalizeButton(gearSlots[numKey])
end
else
--player.Character.Humanoid:EquipTool(physGear)
physGear.Parent = player.Character
gearSlots[numKey].Selected = true
enlargeButton(gearSlots[numKey])
end
end
end
function activateGear(num)
local numKey = nil
if num == "0" then
numKey = 10 -- why do lua indexes have to start at 1? :(
else
numKey = tonumber(num)
end
if(numKey == nil) then return end
if gearSlots[numKey] ~= "empty" then
toolSwitcher(numKey)
end
end
enlargeButton = function(button)
if button.Size.Y.Scale > 1 then return end
if not button.Parent then return end
if not button.Selected then return end
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then break end
if gearSlots[i] ~= button then
normalizeButton(gearSlots[i])
end
end
if not enlargeOverride then
return
end
if button:IsA("ImageButton") or button:IsA("TextButton") then
button.ZIndex = 2
local centerizeX = -(buttonSizeEnlarge.X.Scale - button.Size.X.Scale)/2
local centerizeY = -(buttonSizeEnlarge.Y.Scale - button.Size.Y.Scale)/2
button:TweenSizeAndPosition(buttonSizeEnlarge,
UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset),
Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/5,enlargeOverride)
end
end
normalizeAllButtons = function()
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then break end
if gearSlots[i] ~= button then
normalizeButton(gearSlots[i],0.1)
end
end
end
normalizeButton = function(button, speed)
if not button then return end
if button.Size.Y.Scale <= 1 then return end
if button.Selected then return end
if not button.Parent then return end
local moveSpeed = speed
if moveSpeed == nil or type(moveSpeed) ~= "number" then moveSpeed = guiTweenSpeed/5 end
if button:IsA("ImageButton") or button:IsA("TextButton") then
button.ZIndex = 1
local inverseEnlarge = 1/enlargeFactor
local centerizeX = -(buttonSizeNormal.X.Scale - button.Size.X.Scale)/2
local centerizeY = -(buttonSizeNormal.Y.Scale - button.Size.Y.Scale)/2
button:TweenSizeAndPosition(buttonSizeNormal,
UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset),
Enum.EasingDirection.Out, Enum.EasingStyle.Quad,moveSpeed,enlargeOverride)
end
end
local waitForDebounce = function()
while debounce do
wait()
end
end
function pointInRectangle(point,rectTopLeft,rectSize)
if point.x > rectTopLeft.x and point.x < (rectTopLeft.x + rectSize.x) then
if point.y > rectTopLeft.y and point.y < (rectTopLeft.y + rectSize.y) then
return true
end
end
return false
end
function swapGear(gearClone,toFrame)
local toFrameChildren = toFrame:GetChildren()
if #toFrameChildren == 1 then
if toFrameChildren[1]:FindFirstChild("SlotNumber") then
local toSlot = tonumber(toFrameChildren[1].SlotNumber.Text)
local gearCloneSlot = tonumber(gearClone.SlotNumber.Text)
if toSlot == 0 then toSlot = 10 end
if gearCloneSlot == 0 then gearCloneSlot = 10 end
gearSlots[toSlot] = gearClone
gearSlots[gearCloneSlot] = toFrameChildren[1]
toFrameChildren[1].SlotNumber.Text = gearClone.SlotNumber.Text
toFrameChildren[1].SlotNumberDownShadow.Text = gearClone.SlotNumber.Text
toFrameChildren[1].SlotNumberUpShadow.Text = gearClone.SlotNumber.Text
local subString = string.sub(toFrame.Name,5)
gearClone.SlotNumber.Text = subString
gearClone.SlotNumberDownShadow.Text = subString
gearClone.SlotNumberUpShadow.Text = subString
gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0)
toFrameChildren[1].Position = UDim2.new(toFrameChildren[1].Position.X.Scale,0,toFrameChildren[1].Position.Y.Scale,0)
toFrameChildren[1].Parent = gearClone.Parent
gearClone.Parent = toFrame
end
else
local slotNum = tonumber(gearClone.SlotNumber.Text)
if slotNum == 0 then slotNum = 10 end
gearSlots[slotNum] = "empty" -- reset this gear slot
local subString = string.sub(toFrame.Name,5)
gearClone.SlotNumber.Text = subString
gearClone.SlotNumberDownShadow.Text = subString
gearClone.SlotNumberUpShadow.Text = subString
local toSlotNum = tonumber(gearClone.SlotNumber.Text)
if toSlotNum == 0 then toSlotNum = 10 end
gearSlots[toSlotNum] = gearClone
gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0)
gearClone.Parent = toFrame
end
end
function resolveDrag(gearClone,x,y)
local mousePoint = Vector2.new(x,y)
local frame = gearClone.Parent
local frames = frame.Parent:GetChildren()
for i = 1, #frames do
if frames[i]:IsA("Frame") then
if pointInRectangle(mousePoint, frames[i].AbsolutePosition,frames[i].AbsoluteSize) then
swapGear(gearClone,frames[i])
return true
end
end
end
if x < frame.AbsolutePosition.x or x > ( frame.AbsolutePosition.x + frame.AbsoluteSize.x ) then
reorganizeLoadout(gearClone,false)
return false
elseif y < frame.AbsolutePosition.y or y > ( frame.AbsolutePosition.y + frame.AbsoluteSize.y ) then
reorganizeLoadout(gearClone,false)
return false
else
if dragBeginPos then gearClone.Position = dragBeginPos end
return -1
end
end
function unequipAllItems(dontEquipThis)
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then break end
if gearSlots[i].GearReference.Value and gearSlots[i].GearReference.Value ~= dontEquipThis then
if gearSlots[i].GearReference.Value:IsA("HopperBin") then
gearSlots[i].GearReference.Value:Disable()
elseif gearSlots[i].GearReference.Value:IsA("Tool") then
gearSlots[i].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack
end
gearSlots[i].Selected = false
end
end
end
function showToolTip(button, tip)
if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then
button.ToolTipLabel.Text = tostring(tip)
local xSize = button.ToolTipLabel.TextBounds.X + 6
button.ToolTipLabel.Size = UDim2.new(0,xSize,0,20)
button.ToolTipLabel.Position = UDim2.new(0.5,-xSize/2,0,-30)
button.ToolTipLabel.Visible = true
end
end
function hideToolTip(button, tip)
if button and button:FindFirstChild("ToolTipLabel") and button.ToolTipLabel:IsA("TextLabel") then
button.ToolTipLabel.Visible = false
end
end
local addingPlayerChild = function(child, equipped, addToSlot, inventoryGearButton)
waitForDebounce()
debounce = true
if child:FindFirstChild("RobloxBuildTool") then debounce = false return end -- don't show roblox build tools
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
debounce = false
return -- we don't care about anything besides tools (sigh...)
end
end
if not addToSlot then
for i = 1, #gearSlots do
if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then -- we already have gear, do nothing
debounce = false
return
end
end
end
local gearClone = currentLoadout.TempSlot:clone()
gearClone.Name = child.Name
gearClone.GearImage.Image = child.TextureId
if gearClone.GearImage.Image == "" then
gearClone.GearText.Text = child.Name
end
gearClone.GearReference.Value = child
gearClone.MouseEnter:connect(function()
if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then
showToolTip(gearClone, gearClone.GearReference.Value.ToolTip)
end
end)
gearClone.MouseLeave:connect(function()
if gearClone.GearReference and gearClone.GearReference.Value["ToolTip"] and gearClone.GearReference.Value.ToolTip ~= "" then
hideToolTip(gearClone, gearClone.GearReference.Value.ToolTip)
end
end)
gearClone.RobloxLocked = true
local slotToMod = -1
if not addToSlot then
for i = 1, #gearSlots do
if gearSlots[i] == "empty" then
slotToMod = i
break
end
end
else
slotToMod = addToSlot
end
if slotToMod == - 1 then -- No available slot to add in!
debounce = false
return
end
local slotNum = slotToMod % 10
local parent = currentLoadout:FindFirstChild("Slot"..tostring(slotNum))
gearClone.Parent = parent
if inventoryGearButton then
local absolutePositionFinal = inventoryGearButton.AbsolutePosition
local currentAbsolutePosition = gearClone.AbsolutePosition
local diff = absolutePositionFinal - currentAbsolutePosition
gearClone.Position = UDim2.new(gearClone.Position.X.Scale,diff.x,gearClone.Position.Y.Scale,diff.y)
gearClone.ZIndex = 4
end
if addToSlot then
reorganizeLoadout(gearClone, true, equipped, addToSlot)
else
reorganizeLoadout(gearClone, true)
end
if gearClone.Parent == nil then debounce = false return end -- couldn't fit in (hopper is full!)
if equipped then
gearClone.Selected = true
unequipAllItems(child)
delay(guiTweenSpeed + 0.01,function() -- if our gear is equipped, we will want to enlarge it when done moving
if gearClone:FindFirstChild("GearReference") and ( (gearClone.GearReference.Value:IsA("Tool") and gearClone.GearReference.Value.Parent == player.Character) or
(gearClone.GearReference.Value:IsA("HopperBin") and gearClone.GearReference.Value.Active == true) ) then
enlargeButton(gearClone)
end
end)
end
local dragBeginPos = nil
local clickCon, buttonDeleteCon, mouseEnterCon, mouseLeaveCon, dragStop, dragBegin = nil
clickCon = gearClone.MouseButton1Click:connect(function()
if characterInWorkspace() then
if not gearClone.Draggable then
activateGear(gearClone.SlotNumber.Text)
end
end
end)
mouseEnterCon = gearClone.MouseEnter:connect(function()
if guiBackpack.Visible then
gearClone.Draggable = true
end
end)
dragBegin = gearClone.DragBegin:connect(function(pos)
dragBeginPos = pos
gearClone.ZIndex = 7
local children = gearClone:GetChildren()
for i = 1, #children do
if children[i]:IsA("TextLabel") then
if string.find(children[i].Name,"Shadow") then
children[i].ZIndex = 8
else
children[i].ZIndex = 9
end
elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then
children[i].ZIndex = 7
end
end
end)
dragStop = gearClone.DragStopped:connect(function(x,y)
if gearClone.Selected then
gearClone.ZIndex = 2
else
gearClone.ZIndex = 1
end
local children = gearClone:GetChildren()
for i = 1, #children do
if children[i]:IsA("TextLabel") then
if string.find(children[i].Name,"Shadow") then
children[i].ZIndex = 3
else
children[i].ZIndex = 4
end
elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then
children[i].ZIndex = 2
end
end
resolveDrag(gearClone,x,y)
end)
mouseLeaveCon = gearClone.MouseLeave:connect(function()
gearClone.Draggable = false
end)
buttonDeleteCon = gearClone.AncestryChanged:connect(function()
if gearClone.Parent and gearClone.Parent.Parent == currentLoadout then return end
if clickCon then clickCon:disconnect() end
if buttonDeleteCon then buttonDeleteCon:disconnect() end
if mouseEnterCon then mouseEnterCon:disconnect() end
if mouseLeaveCon then mouseLeaveCon:disconnect() end
if dragStop then dragStop:disconnect() end
if dragBegin then dragBegin:disconnect() end
end) -- this probably isn't necessary since objects are being deleted (probably), but this might still leak just in case
local childCon = nil
local childChangeCon = nil
childCon = child.AncestryChanged:connect(function(newChild,parent)
if not checkToolAncestry(newChild,parent) then
if childCon then childCon:disconnect() end
if childChangeCon then childChangeCon:disconnect() end
removeFromInventory(child)
elseif parent == game.Players.LocalPlayer.Backpack then
normalizeButton(gearClone)
end
end)
childChangeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if gearClone and gearClone.GearImage.Image == "" then
gearClone.GearText.Text = child.Name
end
elseif prop == "Active" then
if child and child:IsA("HopperBin") then
if not child.Active then
gearClone.Selected = false
normalizeButton(gearClone)
end
end
elseif prop == "TextureId" then
gearClone.GearImage.Image = child.TextureId
end
end)
debounce = false
end
function addToInventory(child)
if not child:IsA("Tool") or not child:IsA("HopperBin") then return end
local slot = nil
for i = 1, #inventory do
if inventory[i] and inventory[i] == child then return end
if not inventory[i] then slot = i end
end
if slot then
inventory[slot] = child
elseif #inventory < 1 then
inventory[1] = child
else
inventory[#inventory + 1] = child
end
end
function removeFromInventory(child)
for i = 1, #inventory do
if inventory[i] == child then
table.remove(inventory,i)
inventory[i] = nil
end
end
end
local spreadOutGear = function()
loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
loadoutChildren[i].BackgroundTransparency = 0.5
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
if slot == 0 then slot = 10 end
loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
end
local centerGear = function()
loadoutChildren = currentLoadout:GetChildren()
local gearButtons = {}
local lastSlotAdd = nlii
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
if #loadoutChildren[i]:GetChildren() > 0 then
if loadoutChildren[i].Name == "Slot0" then
lastSlotAdd = loadoutChildren[i]
else
table.insert(gearButtons, loadoutChildren[i])
end
end
loadoutChildren[i].BackgroundTransparency = 1
end
end
if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
for i = 1, #gearButtons do
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
function editLoadout()
if inGearTab then
spreadOutGear()
end
end
function readonlyLoadout()
if not inGearTab then
centerGear()
end
end
function setupBackpackListener()
if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end
backpackChildCon = player.Backpack.ChildAdded:connect(function(child)
addingPlayerChild(child)
addToInventory(child)
end)
end
function playerCharacterChildAdded(child)
addingPlayerChild(child,true)
addToInventory(child)
end
function activateLoadout()
currentLoadout.Visible = true
end
function deactivateLoadout()
currentLoadout.Visible = false
end
function tabHandler(inFocus)
inGearTab = inFocus
if inFocus then
editLoadout()
else
readonlyLoadout()
end
end
-- End Functions
-- Begin Script
wait() -- let stuff initialize incase this is first heartbeat...
waitForChild(player,"Backpack")
waitForProperty(player,"Character")
-- not sure why this had no delay but the player.CharacterAdded one had one... this type of error would be easier to avoid with function reusage
delay(1,function()
local backpackChildren = player.Backpack:GetChildren()
local size = math.min(10,#backpackChildren)
for i = 1, size do
addingPlayerChild(backpackChildren[i],false)
end
setupBackpackListener()
end)
waitForProperty(player,"Character")
for i,v in ipairs(player.Character:GetChildren()) do
playerCharacterChildAdded(v)
end
characterChildAddedCon = player.Character.ChildAdded:connect(function(child) playerCharacterChildAdded(child) end)
waitForChild(player.Character,"Humanoid")
humanoidDiedCon = player.Character.Humanoid.Died:connect(function()
if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end
deactivateLoadout()
if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end
end)
player.CharacterRemoving:connect(function()
for i = 1, #gearSlots do
if gearSlots[i] ~= "empty" then
gearSlots[i].Parent = nil
gearSlots[i] = "empty"
end
end
end)
player.CharacterAdded:connect(function()
waitForProperty(game.Players,"LocalPlayer")
player = game.Players.LocalPlayer -- make sure we are still looking at the correct character
waitForChild(player,"Backpack")
delay(1,function()
local backpackChildren = player.Backpack:GetChildren()
local size = math.min(10,#backpackChildren)
for i = 1, size do
addingPlayerChild(backpackChildren[i],false)
end
setupBackpackListener()
end)
activateLoadout()
if characterChildAddedCon then
characterChildAddedCon:disconnect()
characterChildAddedCon = nil
end
characterChildAddedCon =
player.Character.ChildAdded:connect(function(child)
addingPlayerChild(child,true)
end)
waitForChild(player.Character,"Humanoid")
humanoidDiedCon =
player.Character.Humanoid.Died:connect(function()
deactivateLoadout()
if humanoidDiedCon then humanoidDiedCon:disconnect() humanoidDiedCon = nil end
if backpackChildCon then backpackChildCon:disconnect() backpackChildCon = nil end
end)
end)
waitForChild(guiBackpack,"SwapSlot")
guiBackpack.SwapSlot.Changed:connect(function()
if guiBackpack.SwapSlot.Value then
local swapSlot = guiBackpack.SwapSlot
local pos = swapSlot.Slot.Value
if pos == 0 then pos = 10 end
if gearSlots[pos] then
reorganizeLoadout(gearSlots[pos],false)
end
if swapSlot.GearButton.Value then
addingPlayerChild(swapSlot.GearButton.Value.GearReference.Value,false,pos)
end
guiBackpack.SwapSlot.Value = false
end
end)
game:GetService("GuiService").KeyPressed:connect(function(key)
if characterInWorkspace() then
activateGear(key)
end
end)
backpackOpenEvent.Event:connect(editLoadout)
backpackCloseEvent.Event:connect(centerGear)
tabClickedEvent.Event:connect(function ( tabName )
tabHandler(tabName == StaticTabName)
end)

View File

@ -0,0 +1 @@

204
app/files/CoreGui/59431535 Normal file
View File

@ -0,0 +1,204 @@
-- This script is responsible for loading in all build tools for build mode
-- Script Globals
local buildTools = {}
local currentTools = {}
local DeleteToolID = 73089190
local PartSelectionID = 73089166
local CloneToolID = 73089204
local RecentPartToolID = 73089229
local RotateToolID = 73089214
local ConfigToolID = 73089239
local WiringToolID = 73089259
local classicToolID = 58921588
local player = nil
local backpack = nil
-- Basic Functions
local function waitForProperty(instance, name)
while not instance[name] do
instance.Changed:wait()
end
end
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
end
waitForProperty(game.Players,"LocalPlayer")
waitForProperty(game.Players.LocalPlayer,"userId")
-- we aren't in a true build mode session, don't give build tools and delete this script
if game.Players.LocalPlayer.userId < 1 then
script:Destroy()
return -- this is probably not necessesary, doing it just in case
end
-- Functions
function getLatestPlayer()
waitForProperty(game.Players,"LocalPlayer")
player = game.Players.LocalPlayer
waitForChild(player,"Backpack")
backpack = player.Backpack
end
function waitForCharacterLoad()
local startTick = tick()
local playerLoaded = false
local success = pcall(function() playerLoaded = player.AppearanceDidLoad end) --TODO: remove pcall once this in client on prod
if not success then return false end
while not playerLoaded do
player.Changed:wait()
playerLoaded = player.AppearanceDidLoad
end
return true
end
function showBuildToolsTutorial()
local tutorialKey = "BuildToolsTutorial"
if UserSettings().GameSettings:GetTutorialState(tutorialKey) == true then return end --already have shown tutorial
local RbxGui = LoadLibrary("RbxGui")
local frame, showTutorial, dismissTutorial, gotoPage = RbxGui.CreateTutorial("Build", tutorialKey, false)
local firstPage = RbxGui.CreateImageTutorialPage(" ", "http://www.syntax.eco/asset/?id=59162193", 359, 296, function() dismissTutorial() end, true)
RbxGui.AddTutorialPage(frame, firstPage)
frame.Parent = game:GetService("CoreGui"):FindFirstChild("RobloxGui")
game:GetService("GuiService"):AddCenterDialog(frame, Enum.CenterDialogType.UnsolicitedDialog,
--showFunction
function()
frame.Visible = true
showTutorial()
end,
--hideFunction
function()
frame.Visible = false
end
)
wait(1)
showTutorial()
end
function clearLoadout()
currentTools = {}
local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
if backpackChildren[i]:IsA("Tool") or backpackChildren[i]:IsA("HopperBin") then
table.insert(currentTools,backpackChildren[i])
end
end
if game.Players.LocalPlayer["Character"] then
local characterChildren = game.Players.LocalPlayer.Character:GetChildren()
for i = 1, #characterChildren do
if characterChildren[i]:IsA("Tool") or characterChildren[i]:IsA("HopperBin") then
table.insert(currentTools,characterChildren[i])
end
end
end
for i = 1, #currentTools do
currentTools[i].Parent = nil
end
end
function giveToolsBack()
for i = 1, #currentTools do
currentTools[i].Parent = game.Players.LocalPlayer.Backpack
end
end
function backpackHasTool(tool)
local backpackChildren = backpack:GetChildren()
for i = 1, #backpackChildren do
if backpackChildren[i] == tool then
return true
end
end
return false
end
function getToolAssetID(assetID)
local newTool = game:GetService("InsertService"):LoadAsset(assetID)
local toolChildren = newTool:GetChildren()
for i = 1, #toolChildren do
if toolChildren[i]:IsA("Tool") then
return toolChildren[i]
end
end
return nil
end
-- remove legacy identifiers
-- todo: determine if we still need this
function removeBuildToolTag(tool)
if tool:FindFirstChild("RobloxBuildTool") then
tool.RobloxBuildTool:Destroy()
end
end
function giveAssetId(assetID,toolName)
local theTool = getToolAssetID(assetID,toolName)
if theTool and not backpackHasTool(theTool) then
removeBuildToolTag(theTool)
theTool.Parent = backpack
table.insert(buildTools,theTool)
end
end
function loadBuildTools()
giveAssetId(PartSelectionID)
giveAssetId(DeleteToolID)
giveAssetId(CloneToolID)
giveAssetId(RotateToolID)
giveAssetId(RecentPartToolID)
giveAssetId(WiringToolID)
giveAssetId(ConfigToolID)
-- deprecated tools
giveAssetId(classicToolID)
end
function givePlayerBuildTools()
getLatestPlayer()
clearLoadout()
loadBuildTools()
giveToolsBack()
end
function takePlayerBuildTools()
for k,v in ipairs(buildTools) do
v.Parent = nil
end
buildTools = {}
end
-- Script start
getLatestPlayer()
waitForCharacterLoad()
givePlayerBuildTools()
-- If player dies, we make sure to give them build tools again
player.CharacterAdded:connect(function()
takePlayerBuildTools()
givePlayerBuildTools()
end)
showBuildToolsTutorial()

1115
app/files/CoreGui/60595411 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
-- Library Registration Script
-- This script is used to register RbxLua libraries on game servers, so game scripts have
-- access to all of the libraries (otherwise only local scripts do)
local deepakTestingPlace = 3569749
local sc = game:GetService("ScriptContext")
local tries = 0
while not sc and tries < 3 do
tries = tries + 1
sc = game:GetService("ScriptContext")
wait(0.2)
end
if sc then
sc:RegisterLibrary("Libraries/RbxGui", "45284430")
sc:RegisterLibrary("Libraries/RbxGear", "45374389")
if game.PlaceId == deepakTestingPlace then
sc:RegisterLibrary("Libraries/RbxStatus", "52177566")
end
sc:RegisterLibrary("Libraries/RbxUtility", "60595411")
sc:RegisterLibrary("Libraries/RbxStamper", "73157242")
sc:LibraryRegistrationComplete()
else
print("failed to find script context, libraries did not load")
end

View File

@ -0,0 +1,26 @@
-- Library Registration Script
-- This script is used to register RbxLua libraries on game servers, so game scripts have
-- access to all of the libraries (otherwise only local scripts do)
local deepakTestingPlace = 3569749
local sc = game:GetService("ScriptContext")
local tries = 0
while not sc and tries < 3 do
tries = tries + 1
sc = game:GetService("ScriptContext")
wait(0.2)
end
if sc then
sc:RegisterLibrary("Libraries/RbxGui", "45284430")
sc:RegisterLibrary("Libraries/RbxGear", "45374389")
if game.PlaceId == deepakTestingPlace then
sc:RegisterLibrary("Libraries/RbxStatus", "52177566")
end
sc:RegisterLibrary("Libraries/RbxUtility", "60595411")
sc:RegisterLibrary("Libraries/RbxStamper", "73157242")
sc:LibraryRegistrationComplete()
else
print("failed to find script context, libraries did not load")
end

146
app/files/CoreGui/64164692 Normal file
View File

@ -0,0 +1,146 @@
-- Responsible for giving out tools in personal servers
-- first, lets see if buildTools have already been created
-- create the object in lighting (TODO: move to some sort of "container" object when we have one)
local toolsArray = game.Lighting:FindFirstChild("BuildToolsModel")
local ownerArray = game.Lighting:FindFirstChild("OwnerToolsModel")
local hasBuildTools = false
function getIds(idTable, assetTable)
for i = 1, #idTable do
local model = game:GetService("InsertService"):LoadAsset(idTable[i])
if model then
local children = model:GetChildren()
for i = 1, #children do
if children[i]:IsA("Tool") then
table.insert(assetTable,children[i])
end
end
end
end
end
function storeInLighting(modelName, assetTable)
local model = Instance.new("Model")
model.Archivable = false
model.Name = modelName
for i = 1, #assetTable do
assetTable[i].Parent = model
end
if not game.Lighting:FindFirstChild(modelName) then -- no one beat us to it, we get to insert
model.Parent = game.Lighting
end
end
if not toolsArray then -- no one has made build tools yet, we get to!
local buildToolIds = {}
local ownerToolIds = {}
table.insert(buildToolIds,73089166) -- PartSelectionTool
table.insert(buildToolIds,73089190) -- DeleteTool
table.insert(buildToolIds,73089204) -- CloneTool
table.insert(buildToolIds,73089214) -- RotateTool
table.insert(buildToolIds,73089239) -- ConfigTool
table.insert(buildToolIds,73089259) -- WiringTool
table.insert(buildToolIds,58921588) -- ClassicTool
table.insert(ownerToolIds, 65347268)
-- next, create array of our tools
local buildTools = {}
local ownerTools = {}
getIds(buildToolIds, buildTools)
getIds(ownerToolIds, ownerTools)
storeInLighting("BuildToolsModel",buildTools)
storeInLighting("OwnerToolsModel",ownerTools)
toolsArray = game.Lighting:FindFirstChild("BuildToolsModel")
ownerArray = game.Lighting:FindFirstChild("OwnerToolsModel")
end
local localBuildTools = {}
function giveBuildTools()
if not hasBuildTools then
hasBuildTools = true
local theTools = toolsArray:GetChildren()
for i = 1, #theTools do
local toolClone = theTools[i]:clone()
if toolClone then
toolClone.Parent = game.Players.LocalPlayer.Backpack
table.insert(localBuildTools,toolClone)
end
end
end
end
function giveOwnerTools()
local theOwnerTools = ownerArray:GetChildren()
for i = 1, #theOwnerTools do
local ownerToolClone = theOwnerTools[i]:clone()
if ownerToolClone then
ownerToolClone.Parent = game.Players.LocalPlayer.Backpack
table.insert(localBuildTools,ownerToolClone)
end
end
end
function removeBuildTools()
if hasBuildTools then
hasBuildTools = false
for i = 1, #localBuildTools do
localBuildTools[i].Parent = nil
end
localBuildTools = {}
end
end
if game.Players.LocalPlayer.HasBuildTools then
giveBuildTools()
end
if game.Players.LocalPlayer.PersonalServerRank >= 255 then
giveOwnerTools()
end
local debounce = false
game.Players.LocalPlayer.Changed:connect(function(prop)
if prop == "HasBuildTools" then
while debounce do
wait(0.5)
end
debounce = true
if game.Players.LocalPlayer.HasBuildTools then
giveBuildTools()
else
removeBuildTools()
end
if game.Players.LocalPlayer.PersonalServerRank >= 255 then
giveOwnerTools()
end
debounce = false
elseif prop == "PersonalServerRank" then
if game.Players.LocalPlayer.PersonalServerRank >= 255 then
giveOwnerTools()
elseif game.Players.LocalPlayer.PersonalServerRank <= 0 then
game.Players.LocalPlayer:Remove() -- you're banned, goodbye!
end
end
end)
game.Players.LocalPlayer.CharacterAdded:connect(function()
hasBuildTools = false
if game.Players.LocalPlayer.HasBuildTools then
giveBuildTools()
end
if game.Players.LocalPlayer.PersonalServerRank >= 255 then
giveOwnerTools()
end
end)

2207
app/files/CoreGui/73157242 Normal file

File diff suppressed because it is too large Load Diff

876
app/files/CoreGui/89449008 Normal file
View File

@ -0,0 +1,876 @@
-- A couple of necessary functions
local function waitForChild(instance, name)
assert(instance)
assert(name)
while not instance:FindFirstChild(name) do
print('Waiting for ...', instance, name)
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
assert(instance)
assert(property)
while not instance[property] do
instance.Changed:wait()
end
end
local function IsTouchDevice()
local touchEnabled = false
pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end)
return touchEnabled
end
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
local RbxGui, msg = LoadLibrary("RbxGui")
if not RbxGui then print("could not find RbxGui!") return end
--- Begin Locals
local StaticTabName = "gear"
local backpack = script.Parent
local screen = script.Parent.Parent
local backpackItems = {}
local buttons = {}
local debounce = false
local browsingMenu = false
local mouseEnterCons = {}
local mouseClickCons = {}
local characterChildAddedCon = nil
local characterChildRemovedCon = nil
local backpackAddCon = nil
local playerBackpack = waitForChild(player,"Backpack")
waitForChild(backpack,"Tabs")
waitForChild(backpack,"Gear")
local gearPreview = waitForChild(backpack.Gear,"GearPreview")
local scroller = waitForChild(backpack.Gear,"GearGridScrollingArea")
local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout")
local grid = waitForChild(backpack.Gear,"GearGrid")
local gearButton = waitForChild(grid,"GearButton")
local swapSlot = waitForChild(script.Parent,"SwapSlot")
local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager")
local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent")
local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent")
local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent")
local resizeEvent = waitForChild(backpackManager,"ResizeEvent")
local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent")
local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady")
-- creating scroll bar early as to make sure items get placed correctly
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil, "grid", Vector2.new(6, 6))
scrollFrame.Position = UDim2.new(0,0,0,30)
scrollFrame.Size = UDim2.new(1,0,1,-30)
scrollFrame.Parent = backpack.Gear.GearGrid
local scrollBar = Instance.new("Frame")
scrollBar.Name = "ScrollBar"
scrollBar.BackgroundTransparency = 0.9
scrollBar.BackgroundColor3 = Color3.new(1,1,1)
scrollBar.BorderSizePixel = 0
scrollBar.Size = UDim2.new(0, 17, 1, -36)
scrollBar.Position = UDim2.new(0,0,0,18)
scrollBar.Parent = scroller
scrollDown.Position = UDim2.new(0,0,1,-17)
scrollUp.Parent = scroller
scrollDown.Parent = scroller
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
local LoadoutButton = Instance.new("TextButton")
LoadoutButton.RobloxLocked = true
LoadoutButton.Name = "LoadoutButton"
LoadoutButton.Font = Enum.Font.ArialBold
LoadoutButton.FontSize = Enum.FontSize.Size14
LoadoutButton.Position = UDim2.new(0,0,0,0)
LoadoutButton.Size = UDim2.new(1,0,0,32)
LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
LoadoutButton.Text = "Loadout #1"
LoadoutButton.TextColor3 = Color3.new(1,1,1)
LoadoutButton.Parent = scrollFrameLoadout
local LoadoutButtonTwo = LoadoutButton:clone()
LoadoutButtonTwo.Text = "Loadout #2"
LoadoutButtonTwo.Parent = scrollFrameLoadout
local LoadoutButtonThree = LoadoutButton:clone()
LoadoutButtonThree.Text = "Loadout #3"
LoadoutButtonThree.Parent = scrollFrameLoadout
local LoadoutButtonFour = LoadoutButton:clone()
LoadoutButtonFour.Text = "Loadout #4"
LoadoutButtonFour.Parent = scrollFrameLoadout
local scrollBarLoadout = Instance.new("Frame")
scrollBarLoadout.Name = "ScrollBarLoadout"
scrollBarLoadout.BackgroundTransparency = 0.9
scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
scrollBarLoadout.BorderSizePixel = 0
scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
scrollBarLoadout.Position = UDim2.new(0,0,0,18)
scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
-- Begin Functions
function removeFromMap(map,object)
for i = 1, #map do
if map[i] == object then
table.remove(map,i)
break
end
end
end
function robloxLock(instance)
instance.RobloxLocked = true
children = instance:GetChildren()
if children then
for i, child in ipairs(children) do
robloxLock(child)
end
end
end
function resize()
local size = 0
if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
size = gearPreview.AbsoluteSize.X * 0.75
else
size = gearPreview.AbsoluteSize.Y * 0.75
end
waitForChild(gearPreview,"GearImage")
gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
resizeGrid()
end
function addToGrid(child)
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
return
end
end
if child:FindFirstChild("RobloxBuildTool") then return end
for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
if v == child then return end
end
table.insert(backpackItems,child)
local changeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if buttons[child] then
if buttons[child].Image == "" then
buttons[child].GearText.Text = child.Name
end
end
end
end)
local ancestryCon = nil
ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
local thisObject = nil
for k,v in pairs(backpackItems) do
if v == child then
thisObject = v
break
end
end
waitForProperty(player,"Character")
waitForChild(player,"Backpack")
if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
if ancestryCon then ancestryCon:disconnect() end
if changeCon then changeCon:disconnect() end
for k,v in pairs(backpackItems) do
if v == thisObject then
if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
buttons[v].Parent = nil
buttons[v] = nil
break
end
end
removeFromMap(backpackItems,thisObject)
resizeGrid()
else
resizeGrid()
end
updateGridActive()
end)
resizeGrid()
end
function buttonClick(button)
if button:FindFirstChild("UnequipContextMenu") and not button.Active then
button.UnequipContextMenu.Visible = true
browsingMenu = true
end
end
function previewGear(button)
if not browsingMenu then
gearPreview.Visible = false
gearPreview.GearImage.Image = button.Image
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
end
end
function findEmptySlot()
local smallestNum = nil
local loadout = currentLoadout:GetChildren()
for i = 1, #loadout do
if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
local frameNum = tonumber(string.sub(loadout[i].Name,5))
if frameNum == 0 then frameNum = 10 end
if not smallestNum or (smallestNum > frameNum) then
smallestNum = frameNum
end
end
end
if smallestNum == 10 then smallestNum = 0 end
return smallestNum
end
function checkForSwap(button,x,y)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
swapGearSlot(slot,button)
return true
end
end
end
end
return false
end
function resizeGrid()
for k,v in pairs(backpackItems) do
if not v:FindFirstChild("RobloxBuildTool") then
if not buttons[v] then
local buttonClone = gearButton:clone()
buttonClone.Parent = grid.ScrollingFrame
buttonClone.Visible = true
buttonClone.Image = v.TextureId
if buttonClone.Image == "" then
buttonClone.GearText.Text = v.Name
end
buttonClone.GearReference.Value = v
buttonClone.Draggable = true
buttons[v] = buttonClone
if not IsTouchDevice() then
local unequipMenu = getGearContextMenu()
unequipMenu.Visible = false
unequipMenu.Parent = buttonClone
end
local beginPos = nil
buttonClone.DragBegin:connect(function(value)
waitForChild(buttonClone, 'Background')
buttonClone['Background'].ZIndex = 10
buttonClone.ZIndex = 10
beginPos = value
end)
buttonClone.DragStopped:connect(function(x,y)
waitForChild(buttonClone, 'Background')
buttonClone['Background'].ZIndex = 1.0
buttonClone.ZIndex = 2
if beginPos ~= buttonClone.Position then
if not checkForSwap(buttonClone,x,y) then
buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
buttonClone.Draggable = false
delay(0.5,function()
buttonClone.Draggable = true
end)
else
buttonClone.Position = beginPos
end
end
end)
local clickTime = tick()
mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
local newClickTime = tick()
if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
local slot = findEmptySlot()
if slot then
buttonClone.ZIndex = 1
swapGearSlot(slot,buttonClone)
end
else
buttonClick(buttonClone)
end
clickTime = newClickTime
end)
end
end
end
recalculateScroll()
end
function showPartialGrid(subset)
for k,v in pairs(buttons) do
v.Parent = nil
end
if subset then
for k,v in pairs(subset) do
v.Parent = grid.ScrollingFrame
end
end
recalculateScroll()
end
function showEntireGrid()
for k,v in pairs(buttons) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function inLoadout(gear)
local children = currentLoadout:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
local button = children[i]:GetChildren()
if #button > 0 then
if button[1].GearReference.Value and button[1].GearReference.Value == gear then
return true
end
end
end
end
return false
end
function updateGridActive()
for k,v in pairs(backpackItems) do
if buttons[v] then
local gear = nil
local gearRef = buttons[v]:FindFirstChild("GearReference")
if gearRef then gear = gearRef.Value end
if not gear then
buttons[v].Active = false
elseif inLoadout(gear) then
buttons[v].Active = false
else
buttons[v].Active = true
end
end
end
end
function centerGear(loadoutChildren)
local gearButtons = {}
local lastSlotAdd = nil
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
if loadoutChildren[i].Name == "Slot0" then
lastSlotAdd = loadoutChildren[i]
else
table.insert(gearButtons, loadoutChildren[i])
end
end
end
if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
for i = 1, #gearButtons do
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
function tabClickHandler(tabName)
if tabName == StaticTabName then
backpackOpenHandler(tabName)
else
backpackCloseHandler(tabName)
end
end
function backpackOpenHandler(currentTab)
if currentTab and currentTab ~= StaticTabName then
backpack.Gear.Visible = false
return
end
backpack.Gear.Visible = true
updateGridActive()
resizeGrid()
resize()
tellBackpackReadyFunc:Invoke()
end
function backpackCloseHandler(currentTab)
if currentTab and currentTab ~= StaticTabName then
backpack.Gear.Visible = false
return
end
backpack.Gear.Visible = false
resizeGrid()
resize()
tellBackpackReadyFunc:Invoke()
end
function loadoutCheck(child, selectState)
if not child:IsA("ImageButton") then return end
for k,v in pairs(backpackItems) do
if buttons[v] then
if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
if buttons[v].GearReference.Value == child.GearReference.Value then
buttons[v].Active = selectState
break
end
end
end
end
end
function clearPreview()
gearPreview.GearImage.Image = ""
gearPreview.GearStats.GearName.Text = ""
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
stuff[i].Parent = playerBackpack
end
end
end
function equipGear(physGear)
removeAllEquippedGear(physGear)
physGear.Parent = player.Character
updateGridActive()
end
function unequipGear(physGear)
physGear.Parent = playerBackpack
updateGridActive()
end
function highlight(button)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
end
function clearHighlight(button)
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundColor3 = Color3.new(0,0,0)
end
function swapGearSlot(slot,gearButton)
if not swapSlot.Value then -- signal loadout to swap a gear out
swapSlot.Slot.Value = slot
swapSlot.GearButton.Value = gearButton
swapSlot.Value = true
updateGridActive()
end
end
local UnequipGearMenuClick = function(element, menu)
if type(element.Action) ~= "number" then return end
local num = element.Action
if num == 1 then -- remove from loadout
unequipGear(menu.Parent.GearReference.Value)
local inventoryButton = menu.Parent
local gearToUnequip = inventoryButton.GearReference.Value
local loadoutChildren = currentLoadout:GetChildren()
local slot = -1
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local button = loadoutChildren[i]:GetChildren()
if button[1] and button[1].GearReference.Value == gearToUnequip then
slot = button[1].SlotNumber.Text
break
end
end
end
swapGearSlot(slot,nil)
end
end
function setupCharacterConnections()
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
-- make sure we get all the children
local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
if characterChildAddedCon then characterChildAddedCon:disconnect() end
characterChildAddedCon =
game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
addToGrid(child)
updateGridActive()
end)
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
characterChildRemovedCon =
game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child)
updateGridActive()
end)
wait()
centerGear(currentLoadout:GetChildren())
end
function removeCharacterConnections()
if characterChildAddedCon then characterChildAddedCon:disconnect() end
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
if backpackAddCon then backpackAddCon:disconnect() end
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function filterGear(terms)
local filteredGear = {}
for k,v in pairs(backpackItems) do
if buttons[v] then
local gearString = string.lower(buttons[v].GearReference.Value.Name)
gearString = trim(gearString)
for i = 1, #terms do
if string.match(gearString,terms[i]) then
table.insert(filteredGear,buttons[v])
break
end
end
end
end
return filteredGear
end
function splitByWhitespace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 0 then
table.insert(terms,token)
end
end
return terms
end
function showSearchGear(searchTerms)
if not backpack.Gear.Visible then return end -- currently not active tab
local searchTermTable = splitByWhitespace(searchTerms)
if searchTermTable and (#searchTermTable > 0) then
currSearchTerms = searchTermTable
else
currSearchTerms = nil
end
if searchTermTable == nil then
showEntireGrid()
return
end
local filteredButtons = filterGear(currSearchTerms)
showPartialGrid(filteredButtons)
end
function nukeBackpack()
while #buttons > 0 do
table.remove(buttons)
end
buttons = {}
while #backpackItems > 0 do
table.remove(backpackItems)
end
backpackItems = {}
local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
for i = 1, #scrollingFrameChildren do
scrollingFrameChildren[i]:remove()
end
end
function getGearContextMenu()
local gearContextMenu = Instance.new("Frame")
gearContextMenu.Active = true
gearContextMenu.Name = "UnequipContextMenu"
gearContextMenu.Size = UDim2.new(0,115,0,70)
gearContextMenu.Position = UDim2.new(0,-16,0,-16)
gearContextMenu.BackgroundTransparency = 1
gearContextMenu.Visible = false
local gearContextMenuButton = Instance.new("TextButton")
gearContextMenuButton.Name = "UnequipContextMenuButton"
gearContextMenuButton.Text = ""
gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
gearContextMenuButton.ZIndex = 8
gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
gearContextMenuButton.Visible = true
gearContextMenuButton.Parent = gearContextMenu
local elementHeight = 12
local contextMenuElements = {}
local contextMenuElementsName = {"Remove Hotkey"}
for i = 1, #contextMenuElementsName do
local element = {}
element.Type = "Button"
element.Text = contextMenuElementsName[i]
element.Action = i
element.DoIt = UnequipGearMenuClick
table.insert(contextMenuElements,element)
end
for i, contextElement in ipairs(contextMenuElements) do
local element = contextElement
if element.Type == "Button" then
local button = Instance.new("TextButton")
button.Name = "UnequipContextButton" .. i
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderSizePixel = 0
button.TextXAlignment = Enum.TextXAlignment.Left
button.Text = " " .. contextElement.Text
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.Size = UDim2.new(1, 8, 0, elementHeight)
button.Position = UDim2.new(0,0,0,elementHeight * i)
button.TextColor3 = Color3.new(1,1,1)
button.ZIndex = 9
button.Parent = gearContextMenuButton
if not IsTouchDevice() then
button.MouseButton1Click:connect(function()
if button.Active and not gearContextMenu.Parent.Active then
local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
browsingMenu = false
gearContextMenu.Visible = false
clearHighlight(button)
clearPreview()
end
end)
button.MouseEnter:connect(function()
if button.Active and gearContextMenu.Parent.Active then
highlight(button)
end
end)
button.MouseLeave:connect(function()
if button.Active and gearContextMenu.Parent.Active then
clearHighlight(button)
end
end)
end
contextElement.Button = button
contextElement.Element = button
elseif element.Type == "Label" then
local frame = Instance.new("Frame")
frame.Name = "ContextLabel" .. i
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 8, 0, elementHeight)
local label = Instance.new("TextLabel")
label.Name = "Text1"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Left
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.0, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label1 = label
if element.GetText2 then
label = Instance.new("TextLabel")
label.Name = "Text2"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Right
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.5, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label2 = label
end
frame.Parent = gearContextMenuButton
element.Label = frame
element.Element = frame
end
end
gearContextMenu.ZIndex = 4
gearContextMenu.MouseLeave:connect(function()
browsingMenu = false
gearContextMenu.Visible = false
clearPreview()
end)
robloxLock(gearContextMenu)
return gearContextMenu
end
function coreGuiChanged(coreGuiType,enabled)
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then
if not enabled then
backpack.Gear.Visible = false
end
end
end
local backpackChildren = player.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
------------------------- Start Lifelong Connections -----------------------
resizeEvent.Event:connect(function(absSize)
if debounce then return end
debounce = true
wait()
resize()
resizeGrid()
debounce = false
end)
currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
currentLoadout.DescendantAdded:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
centerGear(currentLoadout:GetChildren())
end
end)
currentLoadout.DescendantRemoving:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
wait()
centerGear(currentLoadout:GetChildren())
end
end)
grid.MouseEnter:connect(function() clearPreview() end)
grid.MouseLeave:connect(function() clearPreview() end)
player.CharacterRemoving:connect(function()
removeCharacterConnections()
nukeBackpack()
end)
player.CharacterAdded:connect(function() setupCharacterConnections() end)
player.ChildAdded:connect(function(child)
if child:IsA("Backpack") then
playerBackpack = child
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
end)
swapSlot.Changed:connect(function()
if not swapSlot.Value then
updateGridActive()
end
end)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
loadoutChildren[i].ChildRemoved:connect(function()
updateGridActive()
end)
loadoutChildren[i].ChildAdded:connect(function()
updateGridActive()
end)
end
end
------------------------- End Lifelong Connections -----------------------
pcall(function()
coreGuiChanged(Enum.CoreGuiType.Backpack, Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Backpack))
Game.StarterGui.CoreGuiChangedSignal:connect(coreGuiChanged)
end)
resize()
resizeGrid()
-- make sure any items in the loadout are accounted for in inventory
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
loadoutCheck(loadoutChildren[i], false)
end
if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
-- make sure that inventory is listening to gear reparenting
if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then
setupCharacterConnections()
end
if not backpackAddCon then
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
backpackOpenEvent.Event:connect(backpackOpenHandler)
backpackCloseEvent.Event:connect(backpackCloseHandler)
tabClickedEvent.Event:connect(tabClickHandler)
searchRequestedEvent.Event:connect(showSearchGear)
recalculateScrollLoadout()

842
app/files/CoreGui/89449009 Normal file
View File

@ -0,0 +1,842 @@
-- A couple of necessary functions
local function waitForChild(instance, name)
assert(instance)
assert(name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
assert(instance)
assert(property)
while not instance[property] do
instance.Changed:wait()
end
end
waitForChild(game,"Players")
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
local RbxGui, msg = LoadLibrary("RbxGui")
if not RbxGui then print("could not find RbxGui!") return end
--- Begin Locals
local StaticTabName = "gear"
local backpack = script.Parent
local screen = script.Parent.Parent
local backpackItems = {}
local buttons = {}
local debounce = false
local browsingMenu = false
local mouseEnterCons = {}
local mouseClickCons = {}
local characterChildAddedCon = nil
local characterChildRemovedCon = nil
local backpackAddCon = nil
local playerBackpack = waitForChild(player,"Backpack")
waitForChild(backpack,"Tabs")
waitForChild(backpack,"Gear")
local gearPreview = waitForChild(backpack.Gear,"GearPreview")
local scroller = waitForChild(backpack.Gear,"GearGridScrollingArea")
local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout")
local grid = waitForChild(backpack.Gear,"GearGrid")
local gearButton = waitForChild(grid,"GearButton")
local swapSlot = waitForChild(script.Parent,"SwapSlot")
local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager")
local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent")
local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent")
local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent")
local resizeEvent = waitForChild(backpackManager,"ResizeEvent")
local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent")
local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady")
-- creating scroll bar early as to make sure items get placed correctly
local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil,"grid")
scrollFrame.Position = UDim2.new(0,0,0,30)
scrollFrame.Size = UDim2.new(1,0,1,-30)
scrollFrame.Parent = backpack.Gear.GearGrid
local scrollBar = Instance.new("Frame")
scrollBar.Name = "ScrollBar"
scrollBar.BackgroundTransparency = 0.9
scrollBar.BackgroundColor3 = Color3.new(1,1,1)
scrollBar.BorderSizePixel = 0
scrollBar.Size = UDim2.new(0, 17, 1, -36)
scrollBar.Position = UDim2.new(0,0,0,18)
scrollBar.Parent = scroller
scrollDown.Position = UDim2.new(0,0,1,-17)
scrollUp.Parent = scroller
scrollDown.Parent = scroller
local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
local LoadoutButton = Instance.new("TextButton")
LoadoutButton.RobloxLocked = true
LoadoutButton.Name = "LoadoutButton"
LoadoutButton.Font = Enum.Font.ArialBold
LoadoutButton.FontSize = Enum.FontSize.Size14
LoadoutButton.Position = UDim2.new(0,0,0,0)
LoadoutButton.Size = UDim2.new(1,0,0,32)
LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
LoadoutButton.Text = "Loadout #1"
LoadoutButton.TextColor3 = Color3.new(1,1,1)
LoadoutButton.Parent = scrollFrameLoadout
local LoadoutButtonTwo = LoadoutButton:clone()
LoadoutButtonTwo.Text = "Loadout #2"
LoadoutButtonTwo.Parent = scrollFrameLoadout
local LoadoutButtonThree = LoadoutButton:clone()
LoadoutButtonThree.Text = "Loadout #3"
LoadoutButtonThree.Parent = scrollFrameLoadout
local LoadoutButtonFour = LoadoutButton:clone()
LoadoutButtonFour.Text = "Loadout #4"
LoadoutButtonFour.Parent = scrollFrameLoadout
local scrollBarLoadout = Instance.new("Frame")
scrollBarLoadout.Name = "ScrollBarLoadout"
scrollBarLoadout.BackgroundTransparency = 0.9
scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
scrollBarLoadout.BorderSizePixel = 0
scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
scrollBarLoadout.Position = UDim2.new(0,0,0,18)
scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
-- Begin Functions
function removeFromMap(map,object)
for i = 1, #map do
if map[i] == object then
table.remove(map,i)
break
end
end
end
function robloxLock(instance)
instance.RobloxLocked = true
children = instance:GetChildren()
if children then
for i, child in ipairs(children) do
robloxLock(child)
end
end
end
function resize()
local size = 0
if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
size = gearPreview.AbsoluteSize.X * 0.75
else
size = gearPreview.AbsoluteSize.Y * 0.75
end
waitForChild(gearPreview,"GearImage")
gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
resizeGrid()
end
function addToGrid(child)
if not child:IsA("Tool") then
if not child:IsA("HopperBin") then
return
end
end
if child:FindFirstChild("RobloxBuildTool") then return end
for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
if v == child then return end
end
table.insert(backpackItems,child)
local changeCon = child.Changed:connect(function(prop)
if prop == "Name" then
if buttons[child] then
if buttons[child].Image == "" then
buttons[child].GearText.Text = child.Name
end
end
end
end)
local ancestryCon = nil
ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
local thisObject = nil
for k,v in pairs(backpackItems) do
if v == child then
thisObject = v
break
end
end
waitForProperty(player,"Character")
waitForChild(player,"Backpack")
if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
if ancestryCon then ancestryCon:disconnect() end
if changeCon then changeCon:disconnect() end
for k,v in pairs(backpackItems) do
if v == thisObject then
if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
buttons[v].Parent = nil
buttons[v] = nil
break
end
end
removeFromMap(backpackItems,thisObject)
resizeGrid()
else
resizeGrid()
end
updateGridActive()
end)
resizeGrid()
end
function buttonClick(button)
if button:FindFirstChild("UnequipContextMenu") and not button.Active then
button.UnequipContextMenu.Visible = true
browsingMenu = true
end
end
function previewGear(button)
if not browsingMenu then
gearPreview.GearImage.Image = button.Image
gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
end
end
function findEmptySlot()
local smallestNum = nil
local loadout = currentLoadout:GetChildren()
for i = 1, #loadout do
if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
local frameNum = tonumber(string.sub(loadout[i].Name,5))
if frameNum == 0 then frameNum = 10 end
if not smallestNum or (smallestNum > frameNum) then
smallestNum = frameNum
end
end
end
if smallestNum == 10 then smallestNum = 0 end
return smallestNum
end
function checkForSwap(button,x,y)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
swapGearSlot(slot,button)
return true
end
end
end
end
return false
end
function resizeGrid()
for k,v in pairs(backpackItems) do
if not v:FindFirstChild("RobloxBuildTool") then
if not buttons[v] then
local buttonClone = gearButton:clone()
buttonClone.Parent = grid.ScrollingFrame
buttonClone.Visible = true
buttonClone.Image = v.TextureId
if buttonClone.Image == "" then
buttonClone.GearText.Text = v.Name
end
buttonClone.GearReference.Value = v
buttonClone.Draggable = true
buttons[v] = buttonClone
local unequipMenu = getGearContextMenu()
unequipMenu.Visible = false
unequipMenu.Parent = buttonClone
local beginPos = nil
buttonClone.DragBegin:connect(function(value)
buttonClone.ZIndex = 9
beginPos = value
end)
buttonClone.DragStopped:connect(function(x,y)
buttonClone.ZIndex = 1
if beginPos ~= buttonClone.Position then
if not checkForSwap(buttonClone,x,y) then
buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
buttonClone.Draggable = false
delay(0.5,function()
buttonClone.Draggable = true
end)
else
buttonClone.Position = beginPos
end
end
end)
local clickTime = tick()
mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
local newClickTime = tick()
if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
local slot = findEmptySlot()
if slot then
buttonClone.ZIndex = 1
swapGearSlot(slot,buttonClone)
end
else
buttonClick(buttonClone)
end
clickTime = newClickTime
end)
end
end
end
recalculateScroll()
end
function showPartialGrid(subset)
for k,v in pairs(buttons) do
v.Parent = nil
end
if subset then
for k,v in pairs(subset) do
v.Parent = grid.ScrollingFrame
end
end
recalculateScroll()
end
function showEntireGrid()
for k,v in pairs(buttons) do
v.Parent = grid.ScrollingFrame
end
recalculateScroll()
end
function inLoadout(gear)
local children = currentLoadout:GetChildren()
for i = 1, #children do
if children[i]:IsA("Frame") then
local button = children[i]:GetChildren()
if #button > 0 then
if button[1].GearReference.Value and button[1].GearReference.Value == gear then
return true
end
end
end
end
return false
end
function updateGridActive()
for k,v in pairs(backpackItems) do
if buttons[v] then
local gear = nil
local gearRef = buttons[v]:FindFirstChild("GearReference")
if gearRef then gear = gearRef.Value end
if not gear then
buttons[v].Active = false
elseif inLoadout(gear) then
buttons[v].Active = false
else
buttons[v].Active = true
end
end
end
end
function centerGear(loadoutChildren)
local gearButtons = {}
local lastSlotAdd = nil
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
if loadoutChildren[i].Name == "Slot0" then
lastSlotAdd = loadoutChildren[i]
else
table.insert(gearButtons, loadoutChildren[i])
end
end
end
if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
for i = 1, #gearButtons do
gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
end
end
function tabClickHandler(tabName)
if tabName == StaticTabName then
backpackOpenHandler(tabName)
else
backpackCloseHandler(tabName)
end
end
function backpackOpenHandler(currentTab)
if currentTab and currentTab ~= StaticTabName then
backpack.Gear.Visible = false
return
end
backpack.Gear.Visible = true
updateGridActive()
resizeGrid()
resize()
tellBackpackReadyFunc:Invoke()
end
function backpackCloseHandler(currentTab)
if currentTab and currentTab ~= StaticTabName then
backpack.Gear.Visible = false
return
end
backpack.Gear.Visible = false
resizeGrid()
resize()
tellBackpackReadyFunc:Invoke()
end
function loadoutCheck(child, selectState)
if not child:IsA("ImageButton") then return end
for k,v in pairs(backpackItems) do
if buttons[v] then
if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
if buttons[v].GearReference.Value == child.GearReference.Value then
buttons[v].Active = selectState
break
end
end
end
end
end
function clearPreview()
gearPreview.GearImage.Image = ""
gearPreview.GearStats.GearName.Text = ""
end
function removeAllEquippedGear(physGear)
local stuff = player.Character:GetChildren()
for i = 1, #stuff do
if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
stuff[i].Parent = playerBackpack
end
end
end
function equipGear(physGear)
removeAllEquippedGear(physGear)
physGear.Parent = player.Character
updateGridActive()
end
function unequipGear(physGear)
physGear.Parent = playerBackpack
updateGridActive()
end
function highlight(button)
button.TextColor3 = Color3.new(0,0,0)
button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
end
function clearHighlight(button)
button.TextColor3 = Color3.new(1,1,1)
button.BackgroundColor3 = Color3.new(0,0,0)
end
function swapGearSlot(slot,gearButton)
if not swapSlot.Value then -- signal loadout to swap a gear out
swapSlot.Slot.Value = slot
swapSlot.GearButton.Value = gearButton
swapSlot.Value = true
updateGridActive()
end
end
local UnequipGearMenuClick = function(element, menu)
if type(element.Action) ~= "number" then return end
local num = element.Action
if num == 1 then -- remove from loadout
unequipGear(menu.Parent.GearReference.Value)
local inventoryButton = menu.Parent
local gearToUnequip = inventoryButton.GearReference.Value
local loadoutChildren = currentLoadout:GetChildren()
local slot = -1
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") then
local button = loadoutChildren[i]:GetChildren()
if button[1] and button[1].GearReference.Value == gearToUnequip then
slot = button[1].SlotNumber.Text
break
end
end
end
swapGearSlot(slot,nil)
end
end
function setupCharacterConnections()
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
-- make sure we get all the children
local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
if characterChildAddedCon then characterChildAddedCon:disconnect() end
characterChildAddedCon =
game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
addToGrid(child)
updateGridActive()
end)
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
characterChildRemovedCon =
game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child)
updateGridActive()
end)
wait()
centerGear(currentLoadout:GetChildren())
end
function removeCharacterConnections()
if characterChildAddedCon then characterChildAddedCon:disconnect() end
if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
if backpackAddCon then backpackAddCon:disconnect() end
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function filterGear(terms)
local filteredGear = {}
for k,v in pairs(backpackItems) do
if buttons[v] then
local gearString = string.lower(buttons[v].GearReference.Value.Name)
gearString = trim(gearString)
for i = 1, #terms do
if string.match(gearString,terms[i]) then
table.insert(filteredGear,buttons[v])
break
end
end
end
end
return filteredGear
end
function splitByWhitespace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 0 then
table.insert(terms,token)
end
end
return terms
end
function showSearchGear(searchTerms)
if not backpack.Gear.Visible then return end -- currently not active tab
local searchTermTable = splitByWhitespace(searchTerms)
if searchTermTable and (#searchTermTable > 0) then
currSearchTerms = searchTermTable
else
currSearchTerms = nil
end
if searchTermTable == nil then
showEntireGrid()
return
end
local filteredButtons = filterGear(currSearchTerms)
showPartialGrid(filteredButtons)
end
function nukeBackpack()
while #buttons > 0 do
table.remove(buttons)
end
buttons = {}
while #backpackItems > 0 do
table.remove(backpackItems)
end
backpackItems = {}
local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
for i = 1, #scrollingFrameChildren do
scrollingFrameChildren[i]:remove()
end
end
function getGearContextMenu()
local gearContextMenu = Instance.new("Frame")
gearContextMenu.Active = true
gearContextMenu.Name = "UnequipContextMenu"
gearContextMenu.Size = UDim2.new(0,115,0,70)
gearContextMenu.Position = UDim2.new(0,-16,0,-16)
gearContextMenu.BackgroundTransparency = 1
gearContextMenu.Visible = false
local gearContextMenuButton = Instance.new("TextButton")
gearContextMenuButton.Name = "UnequipContextMenuButton"
gearContextMenuButton.Text = ""
gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
gearContextMenuButton.ZIndex = 8
gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
gearContextMenuButton.Visible = true
gearContextMenuButton.Parent = gearContextMenu
local elementHeight = 12
local contextMenuElements = {}
local contextMenuElementsName = {"Remove Hotkey"}
for i = 1, #contextMenuElementsName do
local element = {}
element.Type = "Button"
element.Text = contextMenuElementsName[i]
element.Action = i
element.DoIt = UnequipGearMenuClick
table.insert(contextMenuElements,element)
end
for i, contextElement in ipairs(contextMenuElements) do
local element = contextElement
if element.Type == "Button" then
local button = Instance.new("TextButton")
button.Name = "UnequipContextButton" .. i
button.BackgroundColor3 = Color3.new(0,0,0)
button.BorderSizePixel = 0
button.TextXAlignment = Enum.TextXAlignment.Left
button.Text = " " .. contextElement.Text
button.Font = Enum.Font.Arial
button.FontSize = Enum.FontSize.Size14
button.Size = UDim2.new(1, 8, 0, elementHeight)
button.Position = UDim2.new(0,0,0,elementHeight * i)
button.TextColor3 = Color3.new(1,1,1)
button.ZIndex = 9
button.Parent = gearContextMenuButton
button.MouseButton1Click:connect(function()
if button.Active and not gearContextMenu.Parent.Active then
local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
browsingMenu = false
gearContextMenu.Visible = false
clearHighlight(button)
clearPreview()
end
end)
button.MouseEnter:connect(function()
if button.Active and gearContextMenu.Parent.Active then
highlight(button)
end
end)
button.MouseLeave:connect(function()
if button.Active and gearContextMenu.Parent.Active then
clearHighlight(button)
end
end)
contextElement.Button = button
contextElement.Element = button
elseif element.Type == "Label" then
local frame = Instance.new("Frame")
frame.Name = "ContextLabel" .. i
frame.BackgroundTransparency = 1
frame.Size = UDim2.new(1, 8, 0, elementHeight)
local label = Instance.new("TextLabel")
label.Name = "Text1"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Left
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.0, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label1 = label
if element.GetText2 then
label = Instance.new("TextLabel")
label.Name = "Text2"
label.BackgroundTransparency = 1
label.BackgroundColor3 = Color3.new(1,1,1)
label.BorderSizePixel = 0
label.TextXAlignment = Enum.TextXAlignment.Right
label.Font = Enum.Font.Arial
label.FontSize = Enum.FontSize.Size14
label.Position = UDim2.new(0.5, 0, 0, 0)
label.Size = UDim2.new(0.5, 0, 1, 0)
label.TextColor3 = Color3.new(1,1,1)
label.ZIndex = 9
label.Parent = frame
element.Label2 = label
end
frame.Parent = gearContextMenuButton
element.Label = frame
element.Element = frame
end
end
gearContextMenu.ZIndex = 4
gearContextMenu.MouseLeave:connect(function()
browsingMenu = false
gearContextMenu.Visible = false
clearPreview()
end)
robloxLock(gearContextMenu)
return gearContextMenu
end
local backpackChildren = player.Backpack:GetChildren()
for i = 1, #backpackChildren do
addToGrid(backpackChildren[i])
end
------------------------- Start Lifelong Connections -----------------------
resizeEvent.Event:connect(function(absSize)
if debounce then return end
debounce = true
wait()
resize()
resizeGrid()
debounce = false
end)
currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
currentLoadout.DescendantAdded:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
centerGear(currentLoadout:GetChildren())
end
end)
currentLoadout.DescendantRemoving:connect(function(descendant)
if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
wait()
centerGear(currentLoadout:GetChildren())
end
end)
grid.MouseEnter:connect(function() clearPreview() end)
grid.MouseLeave:connect(function() clearPreview() end)
player.CharacterRemoving:connect(function()
removeCharacterConnections()
nukeBackpack()
end)
player.CharacterAdded:connect(function() setupCharacterConnections() end)
player.ChildAdded:connect(function(child)
if child:IsA("Backpack") then
playerBackpack = child
if backpackAddCon then backpackAddCon:disconnect() end
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
end)
swapSlot.Changed:connect(function()
if not swapSlot.Value then
updateGridActive()
end
end)
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
loadoutChildren[i].ChildRemoved:connect(function()
updateGridActive()
end)
loadoutChildren[i].ChildAdded:connect(function()
updateGridActive()
end)
end
end
------------------------- End Lifelong Connections -----------------------
resize()
resizeGrid()
-- make sure any items in the loadout are accounted for in inventory
local loadoutChildren = currentLoadout:GetChildren()
for i = 1, #loadoutChildren do
loadoutCheck(loadoutChildren[i], false)
end
if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
-- make sure that inventory is listening to gear reparenting
if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then
setupCharacterConnections()
end
if not backpackAddCon then
backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
end
backpackOpenEvent.Event:connect(backpackOpenHandler)
backpackCloseEvent.Event:connect(backpackCloseHandler)
tabClickedEvent.Event:connect(tabClickHandler)
searchRequestedEvent.Event:connect(showSearchGear)
recalculateScrollLoadout()

443
app/files/CoreGui/89449093 Normal file
View File

@ -0,0 +1,443 @@
-- This script manages context switches in the backpack (Gear to Wardrobe, etc.) and player state changes. Also manages global functions across different tabs (currently only search)
if game.CoreGui.Version < 7 then return end -- peace out if we aren't using the right client
-- basic functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
-- don't do anything if we are in an empty game
waitForChild(game,"Players")
if #game.Players:GetChildren() < 1 then
game.Players.ChildAdded:wait()
end
-- make sure everything is loaded in before we do anything
-- get our local player
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
------------------------ Locals ------------------------------
local backpack = script.Parent
waitForChild(backpack,"Gear")
local screen = script.Parent.Parent
assert(screen:IsA("ScreenGui"))
waitForChild(backpack, "Tabs")
waitForChild(backpack.Tabs, "CloseButton")
local closeButton = backpack.Tabs.CloseButton
waitForChild(backpack.Tabs, "InventoryButton")
local inventoryButton = backpack.Tabs.InventoryButton
if game.CoreGui.Version >= 8 then
waitForChild(backpack.Tabs, "WardrobeButton")
local wardrobeButton = backpack.Tabs.WardrobeButton
end
waitForChild(backpack.Parent,"ControlFrame")
local backpackButton = waitForChild(backpack.Parent.ControlFrame,"BackpackButton")
local currentTab = "gear"
local searchFrame = waitForChild(backpack,"SearchFrame")
waitForChild(backpack.SearchFrame,"SearchBoxFrame")
local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame,"SearchBox")
local searchButton = waitForChild(backpack.SearchFrame,"SearchButton")
local resetButton = waitForChild(backpack.SearchFrame,"ResetButton")
local robloxGui = waitForChild(Game.CoreGui, 'RobloxGui')
local currentLoadout = waitForChild(robloxGui, 'CurrentLoadout')
local loadoutBackground = waitForChild(currentLoadout, 'Background')
local canToggle = true
local readyForNextEvent = true
local backpackIsOpen = false
local active = true
local disabledByDeveloper = false
local humanoidDiedCon = nil
local backpackButtonPos
local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack
local searchDefaultText = "Search..."
local tilde = "~"
local backquote = "`"
local backpackSize = UDim2.new(0, 600, 0, 400)
if robloxGui.AbsoluteSize.Y <= 320 then
backpackSize = UDim2.new(0, 200, 0, 140)
end
------------------------ End Locals ---------------------------
---------------------------------------- Public Event Setup ----------------------------------------
function createPublicEvent(eventName)
assert(eventName, "eventName is nil")
assert(tostring(eventName),"eventName is not a string")
local newEvent = Instance.new("BindableEvent")
newEvent.Name = tostring(eventName)
newEvent.Parent = script
return newEvent
end
function createPublicFunction(funcName, invokeFunc)
assert(funcName, "funcName is nil")
assert(tostring(funcName), "funcName is not a string")
assert(invokeFunc, "invokeFunc is nil")
assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'")
local newFunction = Instance.new("BindableFunction")
newFunction.Name = tostring(funcName)
newFunction.OnInvoke = invokeFunc
newFunction.Parent = script
return newFunction
end
-- Events
local resizeEvent = createPublicEvent("ResizeEvent")
local backpackOpenEvent = createPublicEvent("BackpackOpenEvent")
local backpackCloseEvent = createPublicEvent("BackpackCloseEvent")
local tabClickedEvent = createPublicEvent("TabClickedEvent")
local searchRequestedEvent = createPublicEvent("SearchRequestedEvent")
---------------------------------------- End Public Event Setup ----------------------------------------
--------------------------- Internal Functions ----------------------------------------
function deactivateBackpack()
backpack.Visible = false
active = false
end
function activateBackpack()
initHumanoidDiedConnections()
active = true
backpack.Visible = backpackIsOpen
if backpackIsOpen then
toggleBackpack()
end
end
function initHumanoidDiedConnections()
if humanoidDiedCon then
humanoidDiedCon:disconnect()
end
waitForProperty(game.Players.LocalPlayer,"Character")
waitForChild(game.Players.LocalPlayer.Character,"Humanoid")
humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack)
end
local hideBackpack = function()
backpackIsOpen = false
readyForNextEvent = false
backpackButton.Selected = false
resetSearch()
backpackCloseEvent:Fire(currentTab)
backpack.Tabs.Visible = false
searchFrame.Visible = false
backpack:TweenSizeAndPosition(UDim2.new(0, backpackSize.X.Offset,0, 0), UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -85), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true,
function()
game.GuiService:RemoveCenterDialog(backpack)
backpack.Visible = false
backpackButton.Selected = false
end)
delay(guiTweenSpeed,function()
game.GuiService:RemoveCenterDialog(backpack)
backpack.Visible = false
backpackButton.Selected = false
readyForNextEvent = true
canToggle = true
end)
end
function showBackpack()
game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
backpack.Visible = true
backpackButton.Selected = true
end,
function()
backpack.Visible = false
backpackButton.Selected = false
end)
backpack.Visible = true
backpackButton.Selected = true
backpack:TweenSizeAndPosition(backpackSize, UDim2.new(0.5, -backpackSize.X.Offset/2, 1, -backpackSize.Y.Offset - 88), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true)
delay(guiTweenSpeed,function()
backpack.Tabs.Visible = false
searchFrame.Visible = true
backpackOpenEvent:Fire(currentTab)
canToggle = true
readyForNextEvent = true
backpackButton.Image = 'http://www.syntax.eco/asset/?id=97644093'
backpackButton.Position = UDim2.new(0.5, -60, 1, -backpackSize.Y.Offset - 103)
end)
end
function toggleBackpack()
if not game.Players.LocalPlayer then return end
if not game.Players.LocalPlayer["Character"] then return end
if not canToggle then return end
if not readyForNextEvent then return end
readyForNextEvent = false
canToggle = false
backpackIsOpen = not backpackIsOpen
if backpackIsOpen then
loadoutBackground.Image = 'http://www.syntax.eco/asset/?id=97623721'
loadoutBackground.Position = UDim2.new(-0.03, 0, -0.17, 0)
loadoutBackground.Size = UDim2.new(1.05, 0, 1.25, 0)
loadoutBackground.ZIndex = 2.0
loadoutBackground.Visible = true
showBackpack()
else
backpackButton.Position = UDim2.new(0.5, -60, 1, -44)
loadoutBackground.Visible = false
backpackButton.Selected = false
backpackButton.Image = "http://www.syntax.eco/asset/?id=97617958"
loadoutBackground.Image = 'http://www.syntax.eco/asset/?id=96536002'
loadoutBackground.Position = UDim2.new(-0.1, 0, -0.1, 0)
loadoutBackground.Size = UDim2.new(1.2, 0, 1.2, 0)
hideBackpack()
local clChildren = currentLoadout:GetChildren()
for i = 1, #clChildren do
if clChildren[i] and clChildren[i]:IsA('Frame') then
local frame = clChildren[i]
if #frame:GetChildren() > 0 then
backpackButton.Position = UDim2.new(0.5, -60, 1, -108)
backpackButton.Visible = true
loadoutBackground.Visible = true
if frame:GetChildren()[1]:IsA('ImageButton') then
local imgButton = frame:GetChildren()[1]
imgButton.Active = true
imgButton.Draggable = false
end
end
end
end
end
end
function closeBackpack()
if backpackIsOpen then
toggleBackpack()
end
end
function setSelected(tab)
assert(tab)
assert(tab:IsA("TextButton"))
tab.BackgroundColor3 = Color3.new(1,1,1)
tab.TextColor3 = Color3.new(0,0,0)
tab.Selected = true
tab.ZIndex = 3
end
function setUnselected(tab)
assert(tab)
assert(tab:IsA("TextButton"))
tab.BackgroundColor3 = Color3.new(0,0,0)
tab.TextColor3 = Color3.new(1,1,1)
tab.Selected = false
tab.ZIndex = 1
end
function updateTabGui(selectedTab)
assert(selectedTab)
if selectedTab == "gear" then
setSelected(inventoryButton)
setUnselected(wardrobeButton)
elseif selectedTab == "wardrobe" then
setSelected(wardrobeButton)
setUnselected(inventoryButton)
end
end
function mouseLeaveTab(button)
assert(button)
assert(button:IsA("TextButton"))
if button.Selected then return end
button.BackgroundColor3 = Color3.new(0,0,0)
end
function mouseOverTab(button)
assert(button)
assert(button:IsA("TextButton"))
if button.Selected then return end
button.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
end
function newTabClicked(tabName)
assert(tabName)
tabName = string.lower(tabName)
currentTab = tabName
updateTabGui(tabName)
tabClickedEvent:Fire(tabName)
resetSearch()
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function splitByWhitespace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 0 then
table.insert(terms,token)
end
end
return terms
end
function resetSearchBoxGui()
resetButton.Visible = false
searchBox.Text = searchDefaultText
end
function doSearch()
local searchText = searchBox.Text
if searchText == "" then
resetSearch()
return
end
searchText = trim(searchText)
resetButton.Visible = true
termTable = splitByWhitespace(searchText)
searchRequestedEvent:Fire(searchText) -- todo: replace this with termtable when table passing is possible
end
function resetSearch()
resetSearchBoxGui()
searchRequestedEvent:Fire()
end
local backpackReady = function()
readyForNextEvent = true
end
function coreGuiChanged(coreGuiType,enabled)
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then
active = enabled
disabledByDeveloper = not enabled
if disabledByDeveloper then
pcall(function()
game:GetService("GuiService"):RemoveKey(tilde)
game:GetService("GuiService"):RemoveKey(backquote)
end)
else
game:GetService("GuiService"):AddKey(tilde)
game:GetService("GuiService"):AddKey(backquote)
end
resetSearch()
searchFrame.Visible = enabled and backpackIsOpen
currentLoadout.Visible = enabled
backpack.Visible = enabled
backpackButton.Visible = enabled
end
end
--------------------------- End Internal Functions -------------------------------------
------------------------------ Public Functions Setup -------------------------------------
createPublicFunction("CloseBackpack", hideBackpack)
createPublicFunction("BackpackReady", backpackReady)
------------------------------ End Public Functions Setup ---------------------------------
------------------------ Connections/Script Main -------------------------------------------
pcall(function()
coreGuiChanged(Enum.CoreGuiType.Backpack, Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Backpack))
Game.StarterGui.CoreGuiChangedSignal:connect(coreGuiChanged)
end)
inventoryButton.MouseButton1Click:connect(function() newTabClicked("gear") end)
inventoryButton.MouseEnter:connect(function() mouseOverTab(inventoryButton) end)
inventoryButton.MouseLeave:connect(function() mouseLeaveTab(inventoryButton) end)
if game.CoreGui.Version >= 8 then
wardrobeButton.MouseButton1Click:connect(function() newTabClicked("wardrobe") end)
wardrobeButton.MouseEnter:connect(function() mouseOverTab(wardrobeButton) end)
wardrobeButton.MouseLeave:connect(function() mouseLeaveTab(wardrobeButton) end)
end
closeButton.MouseButton1Click:connect(closeBackpack)
screen.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
resizeEvent:Fire(screen.AbsoluteSize)
end
end)
-- GuiService key setup
game:GetService("GuiService"):AddKey(tilde)
game:GetService("GuiService"):AddKey(backquote)
game:GetService("GuiService").KeyPressed:connect(function(key)
if not active or disabledByDeveloper then return end
if key == tilde or key == backquote then
toggleBackpack()
end
end)
backpackButton.MouseButton1Click:connect(function()
if not active or disabledByDeveloper then return end
toggleBackpack()
end)
if game.Players.LocalPlayer["Character"] then
activateBackpack()
end
game.Players.LocalPlayer.CharacterAdded:connect(activateBackpack)
-- search functions
searchBox.FocusLost:connect(function(enterPressed)
if enterPressed or searchBox.Text ~= "" then
doSearch()
elseif searchBox.Text == "" then
resetSearch()
end
end)
searchButton.MouseButton1Click:connect(doSearch)
resetButton.MouseButton1Click:connect(resetSearch)
if searchFrame and robloxGui.AbsoluteSize.Y <= 320 then
searchFrame.RobloxLocked = false
searchFrame:Destroy()
end

360
app/files/CoreGui/89449094 Normal file
View File

@ -0,0 +1,360 @@
-- This script manages context switches in the backpack (Gear to Wardrobe, etc.) and player state changes. Also manages global functions across different tabs (currently only search)
if game.CoreGui.Version < 7 then return end -- peace out if we aren't using the right client
-- basic functions
local function waitForChild(instance, name)
while not instance:FindFirstChild(name) do
instance.ChildAdded:wait()
end
return instance:FindFirstChild(name)
end
local function waitForProperty(instance, property)
while not instance[property] do
instance.Changed:wait()
end
end
-- don't do anything if we are in an empty game
waitForChild(game,"Players")
if #game.Players:GetChildren() < 1 then
game.Players.ChildAdded:wait()
end
-- make sure everything is loaded in before we do anything
-- get our local player
waitForProperty(game.Players,"LocalPlayer")
local player = game.Players.LocalPlayer
------------------------ Locals ------------------------------
local backpack = script.Parent
waitForChild(backpack,"Gear")
local screen = script.Parent.Parent
assert(screen:IsA("ScreenGui"))
waitForChild(backpack, "Tabs")
waitForChild(backpack.Tabs, "CloseButton")
local closeButton = backpack.Tabs.CloseButton
waitForChild(backpack.Tabs, "InventoryButton")
local inventoryButton = backpack.Tabs.InventoryButton
if game.CoreGui.Version >= 8 then
waitForChild(backpack.Tabs, "WardrobeButton")
local wardrobeButton = backpack.Tabs.WardrobeButton
end
waitForChild(backpack.Parent,"ControlFrame")
local backpackButton = waitForChild(backpack.Parent.ControlFrame,"BackpackButton")
local currentTab = "gear"
local searchFrame = waitForChild(backpack,"SearchFrame")
waitForChild(backpack.SearchFrame,"SearchBoxFrame")
local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame,"SearchBox")
local searchButton = waitForChild(backpack.SearchFrame,"SearchButton")
local resetButton = waitForChild(backpack.SearchFrame,"ResetButton")
local canToggle = true
local readyForNextEvent = true
local backpackIsOpen = false
local active = true
local humanoidDiedCon = nil
local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack
local searchDefaultText = "Search..."
local tilde = "~"
local backquote = "`"
------------------------ End Locals ---------------------------
---------------------------------------- Public Event Setup ----------------------------------------
function createPublicEvent(eventName)
assert(eventName, "eventName is nil")
assert(tostring(eventName),"eventName is not a string")
local newEvent = Instance.new("BindableEvent")
newEvent.Name = tostring(eventName)
newEvent.Parent = script
return newEvent
end
function createPublicFunction(funcName, invokeFunc)
assert(funcName, "funcName is nil")
assert(tostring(funcName), "funcName is not a string")
assert(invokeFunc, "invokeFunc is nil")
assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'")
local newFunction = Instance.new("BindableFunction")
newFunction.Name = tostring(funcName)
newFunction.OnInvoke = invokeFunc
newFunction.Parent = script
return newFunction
end
-- Events
local resizeEvent = createPublicEvent("ResizeEvent")
local backpackOpenEvent = createPublicEvent("BackpackOpenEvent")
local backpackCloseEvent = createPublicEvent("BackpackCloseEvent")
local tabClickedEvent = createPublicEvent("TabClickedEvent")
local searchRequestedEvent = createPublicEvent("SearchRequestedEvent")
---------------------------------------- End Public Event Setup ----------------------------------------
--------------------------- Internal Functions ----------------------------------------
function deactivateBackpack()
backpack.Visible = false
active = false
end
function activateBackpack()
initHumanoidDiedConnections()
active = true
backpack.Visible = backpackIsOpen
end
function initHumanoidDiedConnections()
if humanoidDiedCon then
humanoidDiedCon:disconnect()
end
waitForProperty(game.Players.LocalPlayer,"Character")
waitForChild(game.Players.LocalPlayer.Character,"Humanoid")
humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack)
end
local hideBackpack = function()
backpackIsOpen = false
readyForNextEvent = false
backpackButton.Selected = false
resetSearch()
backpackCloseEvent:Fire(currentTab)
backpack.Tabs.Visible = false
searchFrame.Visible = false
backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true,
function()
game.GuiService:RemoveCenterDialog(backpack)
backpack.Visible = false
backpackButton.Selected = false
end)
delay(guiTweenSpeed,function()
game.GuiService:RemoveCenterDialog(backpack)
backpack.Visible = false
backpackButton.Selected = false
canToggle = true
end)
end
function showBackpack()
game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
function()
backpack.Visible = true
backpackButton.Selected = true
end,
function()
backpack.Visible = false
backpackButton.Selected = false
end)
backpack.Visible = true
backpackButton.Selected = true
backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.76, 0),UDim2.new(0.225, 0, 0.09, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true)
delay(guiTweenSpeed,function()
backpack.Tabs.Visible = true
searchFrame.Visible = true
backpackOpenEvent:Fire(currentTab)
canToggle = true
end)
end
function toggleBackpack()
if not game.Players.LocalPlayer then return end
if not game.Players.LocalPlayer["Character"] then return end
if not canToggle then return end
if not readyForNextEvent then return end
readyForNextEvent = false
canToggle = false
backpackIsOpen = not backpackIsOpen
if backpackIsOpen then
showBackpack()
else
backpackButton.Selected = false
hideBackpack()
end
end
function closeBackpack()
if backpackIsOpen then
toggleBackpack()
end
end
function setSelected(tab)
assert(tab)
assert(tab:IsA("TextButton"))
tab.BackgroundColor3 = Color3.new(1,1,1)
tab.TextColor3 = Color3.new(0,0,0)
tab.Selected = true
tab.ZIndex = 3
end
function setUnselected(tab)
assert(tab)
assert(tab:IsA("TextButton"))
tab.BackgroundColor3 = Color3.new(0,0,0)
tab.TextColor3 = Color3.new(1,1,1)
tab.Selected = false
tab.ZIndex = 1
end
function updateTabGui(selectedTab)
assert(selectedTab)
if selectedTab == "gear" then
setSelected(inventoryButton)
setUnselected(wardrobeButton)
elseif selectedTab == "wardrobe" then
setSelected(wardrobeButton)
setUnselected(inventoryButton)
end
end
function mouseLeaveTab(button)
assert(button)
assert(button:IsA("TextButton"))
if button.Selected then return end
button.BackgroundColor3 = Color3.new(0,0,0)
end
function mouseOverTab(button)
assert(button)
assert(button:IsA("TextButton"))
if button.Selected then return end
button.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
end
function newTabClicked(tabName)
assert(tabName)
tabName = string.lower(tabName)
currentTab = tabName
updateTabGui(tabName)
tabClickedEvent:Fire(tabName)
resetSearch()
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
function splitByWhitespace(text)
if type(text) ~= "string" then return nil end
local terms = {}
for token in string.gmatch(text, "[^%s]+") do
if string.len(token) > 0 then
table.insert(terms,token)
end
end
return terms
end
function resetSearchBoxGui()
resetButton.Visible = false
searchBox.Text = searchDefaultText
end
function doSearch()
local searchText = searchBox.Text
if searchText == "" then
resetSearch()
return
end
searchText = trim(searchText)
resetButton.Visible = true
termTable = splitByWhitespace(searchText)
searchRequestedEvent:Fire(searchText) -- todo: replace this with termtable when table passing is possible
end
function resetSearch()
resetSearchBoxGui()
searchRequestedEvent:Fire()
end
local backpackReady = function()
readyForNextEvent = true
end
--------------------------- End Internal Functions -------------------------------------
------------------------------ Public Functions Setup -------------------------------------
createPublicFunction("CloseBackpack", hideBackpack)
createPublicFunction("BackpackReady", backpackReady)
------------------------------ End Public Functions Setup ---------------------------------
------------------------ Connections/Script Main -------------------------------------------
inventoryButton.MouseButton1Click:connect(function() newTabClicked("gear") end)
inventoryButton.MouseEnter:connect(function() mouseOverTab(inventoryButton) end)
inventoryButton.MouseLeave:connect(function() mouseLeaveTab(inventoryButton) end)
if game.CoreGui.Version >= 8 then
wardrobeButton.MouseButton1Click:connect(function() newTabClicked("wardrobe") end)
wardrobeButton.MouseEnter:connect(function() mouseOverTab(wardrobeButton) end)
wardrobeButton.MouseLeave:connect(function() mouseLeaveTab(wardrobeButton) end)
end
closeButton.MouseButton1Click:connect(closeBackpack)
screen.Changed:connect(function(prop)
if prop == "AbsoluteSize" then
resizeEvent:Fire(screen.AbsoluteSize)
end
end)
-- GuiService key setup
game:GetService("GuiService"):AddKey(tilde)
game:GetService("GuiService"):AddKey(backquote)
game:GetService("GuiService").KeyPressed:connect(function(key)
if not active then return end
if key == tilde or key == backquote then
toggleBackpack()
end
end)
backpackButton.MouseButton1Click:connect(function()
if not active then return end
toggleBackpack()
end)
if game.Players.LocalPlayer["Character"] then
activateBackpack()
end
game.Players.LocalPlayer.CharacterAdded:connect(activateBackpack)
-- search functions
searchBox.FocusLost:connect(function(enterPressed)
if enterPressed or searchBox.Text ~= "" then
doSearch()
elseif searchBox.Text == "" then
resetSearch()
end
end)
searchButton.MouseButton1Click:connect(doSearch)
resetButton.MouseButton1Click:connect(resetSearch)
backpackButton.Visible = true

1376
app/files/CoreGui/97188756 Normal file

File diff suppressed because it is too large Load Diff

1211
app/files/CoreGui/97188757 Normal file

File diff suppressed because it is too large Load Diff

BIN
app/files/LuaThumbnail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
app/files/NoRender.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

418
app/files/Old2014Join.lua Normal file
View File

@ -0,0 +1,418 @@
-- functions --------------------------
function onPlayerAdded(player)
-- override
end
-- MultiplayerSharedScript.lua inserted here ------ Prepended to GroupBuild.lua and Join.lua --
-- log app init time
pcall(function()
local t = ElapsedTime()
local platform = settings().Diagnostics.OsPlatform
game:HttpGet("http://www.syntax.eco/Game/JoinRate.ashx?st=0&i=0&p=-1&c=GameAppInit&r=Success&d=" .. (math.floor(t*1000)) .. "&ip=localhost&errorType=&platform=" .. platform, false)
end)
pcall(function() game:SetPlaceID(-1, false) end)
local startTime = tick()
local connectResolved = false
local loadResolved = false
local joinResolved = false
local playResolved = true
local playStartTime = 0
local cdnSuccess = 0
local cdnFailure = 0
settings()["Game Options"].CollisionSoundEnabled = true
pcall(function() settings().Rendering.EnableFRM = true end)
pcall(function() settings().Physics.Is30FpsThrottleEnabled = true end)
pcall(function() settings()["Task Scheduler"].PriorityMethod = Enum.PriorityMethod.AccumulatedError end)
pcall(function() settings().Physics.PhysicsEnvironmentalThrottle = Enum.EnviromentalPhysicsThrottle.DefaultAuto end)
function reportContentProvider(time, queueLength, blocking)
pcall(function()
game:HttpGet("http://www.syntax.eco/Analytics/ContentProvider.ashx?t=" .. time .. "&ql=" .. queueLength, blocking)
end)
end
function reportCdn(blocking)
pcall(function()
local newCdnSuccess = settings().Diagnostics.CdnSuccessCount
local newCdnFailure = settings().Diagnostics.CdnFailureCount
local successDelta = newCdnSuccess - cdnSuccess
local failureDelta = newCdnFailure - cdnFailure
cdnSuccess = newCdnSuccess
cdnFailure = newCdnFailure
if successDelta > 0 or failureDelta > 0 then
game:HttpGet("http://www.syntax.eco/Game/Cdn.ashx?source=client&success=" .. successDelta .. "&failure=" .. failureDelta, blocking)
end
end)
end
function reportDuration(category, result, duration, blocking,errorType)
if not errorType then
errorType = ''
end
local platform = settings().Diagnostics.OsPlatform
local bytesReceived = -1
if stats().Network:getChildren()[2] ~= nil then
bytesReceived = stats().Network:getChildren()[2].Stats.totalBytesReceived:GetValue()
end
pcall(function() game:HttpGet("http://www.syntax.eco/Game/JoinRate.ashx?st=0&i=0&p=-1&c=" .. category .. "&r=" .. result .. "&d=" .. (math.floor(duration*1000)) .. "&b=" .. bytesReceived .. "&ip=localhost&errorType=" .. errorType .. "&platform=" .. platform, blocking) end)
end
-- arguments ---------------------------------------
local threadSleepTime = ...
if threadSleepTime==nil then
threadSleepTime = 15
end
local test = true
print("! Joining game '' place -1 at localhost")
local closeConnection = game.Close:connect(function()
if 0 then
reportCdn(true)
if not connectResolved then
local duration = tick() - startTime;
reportDuration("GameConnect", "Failure", duration, true)
elseif (not loadResolved) or (not joinResolved) then
local duration = tick() - startTime;
if not loadResolved then
loadResolved = true
reportDuration("GameLoad","Cancel", duration, true)
end
if not joinResolved then
joinResolved = true
reportDuration("GameJoin","Cancel", duration, true)
end
elseif not playResolved then
local duration = tick() - playStartTime;
playResolved = true
reportDuration("GameDuration","Success", duration, true)
end
pcall(function() game:HttpGet("&disconnect=true", true) end)
if true then pcall(function() game:HttpPost("https://api.syntax.eco/auth/invalidate", "invalidate") end) end
end
end)
game:GetService("ChangeHistoryService"):SetEnabled(false)
game:GetService("ContentProvider"):SetThreadPool(16)
game:GetService("InsertService"):SetBaseSetsUrl("http://www.syntax.eco/Game/Tools/InsertAsset.ashx?nsets=10&type=base")
game:GetService("InsertService"):SetUserSetsUrl("http://www.syntax.eco/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d")
game:GetService("InsertService"):SetCollectionUrl("http://www.syntax.eco/Game/Tools/InsertAsset.ashx?sid=%d")
game:GetService("InsertService"):SetAssetUrl("http://www.syntax.eco/Asset/?id=%d")
game:GetService("InsertService"):SetAssetVersionUrl("http://www.syntax.eco/Asset/?assetversionid=%d")
pcall(function() game:GetService("SocialService"):SetFriendUrl("http://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=IsFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetBestFriendUrl("http://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=IsBestFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupUrl("http://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=IsInGroup&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRankUrl("http://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRank&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRoleUrl("http://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRole&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("GamePassService"):SetPlayerHasPassUrl("http://www.syntax.eco/Game/GamePass/GamePassHandler.ashx?Action=HasPass&UserID=%d&PassID=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetProductInfoUrl("https://api.syntax.eco/marketplace/productinfo?assetId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetPlayerOwnsAssetUrl("https://api.syntax.eco/ownership/hasasset?userId=%d&assetId=%d") end)
pcall(function() game:SetCreatorID(0, Enum.CreatorType.User) end)
-- Bubble chat. This is all-encapsulated to allow us to turn it off with a config setting
pcall(function() game:GetService("Players"):SetChatStyle(Enum.ChatStyle.Classic) end)
local waitingForCharacter = false
local waitingForCharacterGuid = "26c3de03-3381-4ab6-8e60-e415fa757eba";
pcall( function()
if settings().Network.MtuOverride == 0 then
settings().Network.MtuOverride = 1400
end
end)
-- globals -----------------------------------------
client = game:GetService("NetworkClient")
visit = game:GetService("Visit")
-- functions ---------------------------------------
function ifSeleniumThenSetCookie(key, value)
if false then
game:GetService("CookiesService"):SetCookieValue(key, value)
end
end
function setMessage(message)
-- todo: animated "..."
if not false then
game:SetMessage(message)
else
-- hack, good enought for now
game:SetMessage("Teleporting ...")
end
end
setMessage("Connecting to SYNTAX...")
function showErrorWindow(message, errorType, errorCategory)
if 0 then
if (not loadResolved) or (not joinResolved) then
local duration = tick() - startTime;
if not loadResolved then
loadResolved = true
reportDuration("GameLoad","Failure", duration, false,errorType)
end
if not joinResolved then
joinResolved = true
reportDuration("GameJoin",errorCategory, duration, false,errorType)
end
pcall(function() game:HttpGet("?FilterName=Type&FilterValue=" .. errorType .. "&Type=JoinFailure", false) end)
elseif not playResolved then
local duration = tick() - playStartTime;
playResolved = true
reportDuration("GameDuration",errorCategory, duration, false,errorType)
pcall(function() game:HttpGet("?FilterName=Type&FilterValue=" .. errorType .. "&Type=GameDisconnect", false) end)
end
end
game:SetMessage(message)
end
function registerPlay(key)
return
end
function analytics(name)
return
end
function analyticsGuid(name, guid)
return
end
function reportError(err, message)
print("***ERROR*** " .. err)
if not test then visit:SetUploadUrl("") end
client:Disconnect()
wait(4)
showErrorWindow("Error: " .. err, message, "Other")
end
-- called when the client connection closes
function onDisconnection(peer, lostConnection)
if lostConnection then
if waitingForCharacter then analyticsGuid("Waiting for Character Lost Connection",waitingForCharacterGuid) end
showErrorWindow("You have lost the connection to the game", "LostConnection", "LostConnection")
else
if waitingForCharacter then analyticsGuid("Waiting for Character Game Shutdown",waitingForCharacterGuid) end
showErrorWindow("This game has shut down", "Kick", "Kick")
end
pcall(function() game:HttpGet("&disconnect=true", true) end)
if true then pcall(function() game:HttpPost("https://api.syntax.eco/auth/invalidate", "invalidate") end) end
end
function requestCharacter(replicator)
-- prepare code for when the Character appears
local connection
connection = player.Changed:connect(function (property)
if property=="Character" then
game:ClearMessage()
waitingForCharacter = false
analyticsGuid("Waiting for Character Success", waitingForCharacterGuid)
connection:disconnect()
if 0 then
if not joinResolved then
local duration = tick() - startTime;
joinResolved = true
reportDuration("GameJoin","Success", duration, false)
playStartTime = tick()
playResolved = false
end
end
end
end)
setMessage("Requesting character")
if 0 and not loadResolved then
local duration = tick() - startTime;
loadResolved = true
reportDuration("GameLoad","Success", duration, false)
end
local success, err = pcall(function()
replicator:RequestCharacter()
setMessage("Waiting for character")
waitingForCharacter = true
analyticsGuid("Waiting for Character Begin",waitingForCharacterGuid);
end)
if not success then
reportError(err,"W4C")
return
end
end
-- called when the client connection is established
function onConnectionAccepted(url, replicator)
connectResolved = true
--reportDuration("GameConnect", "Success", tick() - startTime, false)
local waitingForMarker = true
local success, err = pcall(function()
if not test then
visit:SetPing("", 300)
end
if not false then
game:SetMessageBrickCount()
else
setMessage("Teleporting ...")
end
replicator.Disconnection:connect(onDisconnection)
-- Wait for a marker to return before creating the Player
local marker = replicator:SendMarker()
marker.Received:connect(function()
waitingForMarker = false
requestCharacter(replicator)
end)
end)
if not success then
reportError(err,"ConnectionAccepted")
return
end
-- TODO: report marker progress
while waitingForMarker do
workspace:ZoomToExtents()
wait(0.5)
end
end
-- called when the client connection fails
function onConnectionFailed(_, error)
showErrorWindow("Failed to connect to the Game. (ID=" .. error .. ")", "ID" .. error, "Other")
end
-- called when the client connection is rejected
function onConnectionRejected()
connectionFailed:disconnect()
showErrorWindow("This game is not available. Please try another", "WrongVersion", "WrongVersion")
end
idled = false
function onPlayerIdled(time)
if time > 20*60 then
showErrorWindow(string.format("You were disconnected for being idle %d minutes", time/60), "Idle", "Idle")
client:Disconnect()
if not idled then
idled = true
end
end
end
-- main ------------------------------------------------------------
--analytics("Start Join Script")
--ifSeleniumThenSetCookie("SeleniumTest1", "Started join script")
pcall(function() settings().Diagnostics:LegacyScriptMode() end)
local success, err = pcall(function()
game:SetRemoteBuildMode(true)
setMessage("Connecting to SYNTAX...")
client.ConnectionAccepted:connect(onConnectionAccepted)
client.ConnectionRejected:connect(onConnectionRejected)
connectionFailed = client.ConnectionFailed:connect(onConnectionFailed)
client.Ticket = ""
ifSeleniumThenSetCookie("SeleniumTest2", "Successfully connected to server")
playerConnectSucces, player = pcall(function() return client:PlayerConnect(0, "localhost", 53640, 0, threadSleepTime) end)
if not playerConnectSucces then
--Old player connection scheme
player = game:GetService("Players"):CreateLocalPlayer(0)
analytics("Created Player")
client:Connect("localhost", 53640, 0, threadSleepTime)
else
analytics("Created Player")
end
pcall(function()
registerPlay("rbx_evt_ftp")
delay(60*5, function() registerPlay("rbx_evt_fmp") end)
end)
-- negotiate an auth token
if true then
pcall(function() game:HttpPost("https://api.syntax.eco/auth/negotiate?ticket=", "negotiate") end)
delay(300, function()
while true do
pcall(function() game:HttpPost("https://api.syntax.eco/auth/renew", "renew") end)
wait(300)
end
end)
end
player:SetSuperSafeChat(false)
pcall(function() player:SetUnder13(false) end)
pcall(function() player:SetMembershipType(Enum.MembershipType.OutrageousBuildersClub) end)
pcall(function() player:SetAccountAge(365) end)
player.Idled:connect(onPlayerIdled)
-- Overriden
onPlayerAdded(player)
pcall(function() player.Name = [========[Player]========] end)
player.CharacterAppearance = "http://www.syntax.eco/Asset/CharacterFetch.ashx?userId=1"
if not test then visit:SetUploadUrl("")end
analytics("Connect Client")
end)
if not success then
reportError(err,"CreatePlayer")
end
--[[
ifSeleniumThenSetCookie("SeleniumTest3", "Successfully created player")
if not test then
-- TODO: Async get?
loadfile("")("", -1, 0)
end
if 0 then
delay(60*5, function()
while true do
reportCdn(false)
wait(60*5)
end
end)
local cpTime = 30
delay(cpTime, function()
while cpTime <= 480 do
reportContentProvider(cpTime, game:GetService("ContentProvider").RequestQueueSize, false)
wait(cpTime)
cpTime = cpTime * 2
end
end)
end
]]
pcall(function() game:SetScreenshotInfo("") end)
pcall(function() game:SetVideoInfo('<?xml version="1.0"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"><media:group><media:title type="plain"><![CDATA[ROBLOX Place]]></media:title><media:description type="plain"><![CDATA[ For more games visit http://www.syntax.eco]]></media:description><media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>') end)
-- use single quotes here because the video info string may have unescaped double quotes
--[[
analytics("Join Finished")
ifSeleniumThenSetCookie("SeleniumTest4", "Finished join")
]]

13
app/files/Pants.rbxmx Normal file
View File

@ -0,0 +1,13 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Pants" referent="RBX0">
<Properties>
<Content name="PantsTemplate">
<url>http://www.syntax.eco/asset/?id={PantsImageId}</url>
</Content>
<string name="Name">Pants</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>

13
app/files/Shirt.rbxmx Normal file
View File

@ -0,0 +1,13 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="Shirt" referent="RBX0">
<Properties>
<Content name="ShirtTemplate">
<url>http://www.syntax.eco/asset/?id={ShirtImageId}</url>
</Content>
<string name="Name">Shirt</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>

View File

@ -0,0 +1,37 @@
local AuthToken, PlaceId = ...
local Players = game:GetService("Players")
warn("Server shutdown requested by website")
local function ReportServerShutdown()
local success, message = pcall(function()
local MessagePayload = HttpService:JSONEncode({
["AuthToken"] = AuthToken,
["JobId"] = game.JobId,
["PlaceId"] = PlaceId,
["ServerAliveTime"] = workspace.DistributedGameTime
})
game:HttpPost(BaseURL.."/internal/gameserver/reportshutdown", MessagePayload, false, "application/json")
end)
end
Players.PlayerAdded:Connect(function(player)
coroutine.wrap(function()
local success, message = pcall(function()
player:Kick("This game has shut down.")
end)
end)()
end)
for _, Player in pairs(Players:GetPlayers()) do
coroutine.wrap(function()
local success, message = pcall(function()
Player:Kick("This game has shut down.")
end)
end)()
end
ReportServerShutdown()
ScriptContext.ScriptsDisabled = true
game:HttpPost("http://127.0.0.1:3000/CloseJob?RCCReturnAuth="..AuthToken, HttpService:JSONEncode({
["jobid"] = game.JobId
}), false, "application/json")

27
app/files/Studio.lua Normal file
View File

@ -0,0 +1,27 @@
-- Setup studio cmd bar & load core scripts
local baseUrl = "http://www.syntax.eco"
pcall(function() game:GetService("InsertService"):SetFreeModelUrl(baseUrl.."/Game/Tools/InsertAsset.ashx?type=fm&q=%s&pg=%d&rs=%d") end)
pcall(function() game:GetService("InsertService"):SetFreeDecalUrl(baseUrl.."/Game/Tools/InsertAsset.ashx?type=fd&q=%s&pg=%d&rs=%d") end)
game:GetService("ScriptInformationProvider"):SetAssetUrl(baseUrl.."/Asset/")
game:GetService("InsertService"):SetBaseSetsUrl(baseUrl.."/Game/Tools/InsertAsset.ashx?nsets=10&type=base")
game:GetService("InsertService"):SetUserSetsUrl(baseUrl.."/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d")
game:GetService("InsertService"):SetCollectionUrl(baseUrl.."/Game/Tools/InsertAsset.ashx?sid=%d")
game:GetService("InsertService"):SetAssetUrl(baseUrl.."/Asset/?id=%d")
game:GetService("InsertService"):SetAssetVersionUrl(baseUrl.."/Asset/?assetversionid=%d")
pcall(function() game:GetService("SocialService"):SetFriendUrl(baseUrl.."/Game/LuaWebService/HandleSocialRequest.ashx?method=IsFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetBestFriendUrl(baseUrl.."/Game/LuaWebService/HandleSocialRequest.ashx?method=IsBestFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupUrl(baseUrl.."/Game/LuaWebService/HandleSocialRequest.ashx?method=IsInGroup&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRankUrl(baseUrl.."/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRank&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRoleUrl(baseUrl.."/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRole&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("GamePassService"):SetPlayerHasPassUrl(baseUrl.."/Game/GamePass/GamePassHandler.ashx?Action=HasPass&UserID=%d&PassID=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetProductInfoUrl(baseUrl.."/marketplace/productinfo?assetId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetDevProductInfoUrl(baseUrl.."/marketplace/productDetails?productId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetPlayerOwnsAssetUrl(baseUrl.."/ownership/hasasset?userId=%d&assetId=%d") end)
local result = pcall(function() game:GetService("ScriptContext"):AddStarterScript(37801172) end)
if not result then
pcall(function() game:GetService("ScriptContext"):AddCoreScript(37801172,game:GetService("ScriptContext"),"StarterScript") end)
end

13
app/files/TShirt.rbxmx Normal file
View File

@ -0,0 +1,13 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<External>null</External>
<External>nil</External>
<Item class="ShirtGraphic" referent="RBX0">
<Properties>
<Content name="Graphic">
<url>http://www.syntax.eco/asset/?id={TShirtImageId}</url>
</Content>
<string name="Name">Shirt Graphic</string>
<bool name="archivable">true</bool>
</Properties>
</Item>
</roblox>

132
app/files/Visit.lua Normal file
View File

@ -0,0 +1,132 @@
function ifSeleniumThenSetCookie(key, value)
if false then
game:GetService("CookiesService"):SetCookieValue(key, value)
end
end
ifSeleniumThenSetCookie("SeleniumTest1", "Inside the visit lua script")
pcall(function() game:SetPlaceID({PlaceId}) end)
pcall(function() game:SetUniverseId({UniverseId}) end)
visit = game:GetService("Visit")
local message = Instance.new("Message")
message.Parent = workspace
message.archivable = false
game:GetService("ScriptInformationProvider"):SetAssetUrl("https://www.syntax.eco/Asset/")
game:GetService("ContentProvider"):SetThreadPool(16)
pcall(function() game:GetService("InsertService"):SetFreeModelUrl("https://www.syntax.eco/Game/Tools/InsertAsset.ashx?type=fm&q=%s&pg=%d&rs=%d") end) -- Used for free model search (insert tool)
pcall(function() game:GetService("InsertService"):SetFreeDecalUrl("https://www.syntax.eco/Game/Tools/InsertAsset.ashx?type=fd&q=%s&pg=%d&rs=%d") end) -- Used for free decal search (insert tool)
ifSeleniumThenSetCookie("SeleniumTest2", "Set URL service")
settings().Diagnostics:LegacyScriptMode()
game:GetService("InsertService"):SetBaseSetsUrl("https://www.syntax.eco/Game/Tools/InsertAsset.ashx?nsets=10&type=base")
game:GetService("InsertService"):SetUserSetsUrl("https://www.syntax.eco/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d")
game:GetService("InsertService"):SetCollectionUrl("https://www.syntax.eco/Game/Tools/InsertAsset.ashx?sid=%d")
game:GetService("InsertService"):SetAssetUrl("https://www.syntax.eco/Asset/?id=%d")
game:GetService("InsertService"):SetAssetVersionUrl("https://www.syntax.eco/Asset/?assetversionid=%d")
pcall(function() game:GetService("SocialService"):SetFriendUrl("https://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=IsFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetBestFriendUrl("https://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=IsBestFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupUrl("https://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=IsInGroup&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRankUrl("https://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRank&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRoleUrl("https://www.syntax.eco/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRole&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("GamePassService"):SetPlayerHasPassUrl("https://www.syntax.eco/Game/GamePass/GamePassHandler.ashx?Action=HasPass&UserID=%d&PassID=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetProductInfoUrl("https://www.syntax.eco/marketplace/productinfo?assetId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetDevProductInfoUrl("https://www.syntax.eco/marketplace/productDetails?productId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetPlayerOwnsAssetUrl("https://www.syntax.eco/ownership/hasasset?userId=%d&assetId=%d") end)
pcall(function() game:SetCreatorID(0, Enum.CreatorType.User) end)
ifSeleniumThenSetCookie("SeleniumTest3", "Set creator ID")
pcall(function() game:SetScreenshotInfo("") end)
pcall(function() game:SetVideoInfo("") end)
ifSeleniumThenSetCookie("SeleniumTest4", "Exiting SingleplayerSharedScript")-- SingleplayerSharedScript.lua inserted here --
pcall(function() settings().Rendering.EnableFRM = true end)
pcall(function() settings()["Task Scheduler"].PriorityMethod = Enum.PriorityMethod.AccumulatedError end)
game:GetService("ChangeHistoryService"):SetEnabled(false)
pcall(function() game:GetService("Players"):SetBuildUserPermissionsUrl("https://www.syntax.eco/Game/BuildActionPermissionCheck.ashx?assetId=0&userId=%d&isSolo=true") end)
workspace:SetPhysicsThrottleEnabled(true)
local addedBuildTools = false
local screenGui = game:GetService("CoreGui"):FindFirstChild("RobloxGui")
local inStudio = true
function doVisit()
message.Text = "Loading Game"
if false then
if false then
success, err = pcall(function() game:Load("") end)
if not success then
message.Text = "Could not teleport"
return
end
end
else
if false then
game:Load("")
pcall(function() visit:SetUploadUrl("") end)
else
pcall(function() visit:SetUploadUrl("") end)
end
end
message.Text = "Running"
game:GetService("RunService"):Run()
message.Text = "Creating Player"
player = game:GetService("Players"):CreateLocalPlayer(0)
player.CharacterAppearance = "https://www.syntax.eco/Asset/CharacterFetch.ashx?userId={UserId}&placeId={PlaceId}"
local propExists, canAutoLoadChar = false
propExists = pcall(function() canAutoLoadChar = game.Players.CharacterAutoLoads end)
if (propExists and canAutoLoadChar) or (not propExists) then
player:LoadCharacter()
end
message.Text = "Setting GUI"
player:SetSuperSafeChat(false)
pcall(function() player:SetUnder13(false) end)
pcall(function() player:SetMembershipType(None) end)
pcall(function() player:SetAccountAge(0) end)
end
success, err = pcall(doVisit)
if not inStudio and not addedBuildTools then
local playerName = Instance.new("StringValue")
playerName.Name = "PlayerName"
playerName.Value = player.Name
playerName.RobloxLocked = true
playerName.Parent = screenGui
pcall(function() game:GetService("ScriptContext"):AddCoreScript(59431535,screenGui,"BuildToolsScript") end)
addedBuildTools = true
end
if success then
message.Parent = nil
else
print(err)
if not inStudio then
if false then
pcall(function() visit:SetUploadUrl("") end)
end
end
wait(5)
message.Text = "Error on visit: " .. err
if not inStudio then
if false then
game:HttpPost("https://www.syntax.eco/Error/Lua.ashx", "Visit.lua: " .. err)
end
end
end

View File

@ -0,0 +1,16 @@
from app.extensions import db
class AdminPermissions(db.Model):
id = db.Column(db.BigInteger, primary_key=True, nullable=False, unique=True, autoincrement=True)
userid = db.Column(db.BigInteger, nullable=False, index=True)
permission = db.Column(db.String(128), nullable=False, index=True)
def __init__(self, userid, permission):
self.userid = userid
self.permission = permission
def __repr__(self):
return "<AdminPermissions userid={userid}, permission={permission}>".format(
userid=self.userid,
permission=self.permission
)

83
app/models/asset.py Normal file
View File

@ -0,0 +1,83 @@
from app.extensions import db
from app.enums.AssetType import AssetType
from sqlalchemy import Enum
from datetime import datetime
class Asset(db.Model):
id = db.Column(db.BigInteger, primary_key=True, unique=True, nullable=False, autoincrement=True)
roblox_asset_id = db.Column(db.BigInteger, nullable=True, default=None, index=True) # Roblox asset ID
name = db.Column(db.Text, nullable=False) # Asset name
description = db.Column(db.String(4096), nullable=False) # Asset description
created_at = db.Column(db.DateTime, nullable=False) # Asset creation date
updated_at = db.Column(db.DateTime, nullable=False) # Asset last update date
asset_type = db.Column(Enum(AssetType), nullable=False, index=True) # Asset type (e.g. shirt, pants, etc.)
asset_genre = db.Column(db.SmallInteger, nullable=False) # Asset genre (e.g. all, town and city, etc.)
creator_type = db.Column(db.SmallInteger, nullable=False) # Asset creator type (e.g. user, group, etc.)
creator_id = db.Column(db.BigInteger, nullable=False, index=True) # Asset creator ID
moderation_status = db.Column(db.SmallInteger, nullable=False, index=True) # Asset moderation status ( 0 = Approved, 1 = Pending, 2 = Declined )
# Economy
is_for_sale = db.Column(db.Boolean, nullable=False, default=False, index=True) # Is the asset for sale?
price_robux = db.Column(db.BigInteger, nullable=False, default=0) # Asset price in Robux
price_tix = db.Column(db.BigInteger, nullable=False, default=0) # Asset price in Tix
is_limited = db.Column(db.Boolean, nullable=False, default=False, index=True) # Is the asset limited?
is_limited_unique = db.Column(db.Boolean, nullable=False, default=False) # Is the asset limited unique?
serial_count = db.Column(db.BigInteger, nullable=False, default=0) # Asset serial count
sale_count = db.Column(db.BigInteger, nullable=False, default=0) # Asset sale count
offsale_at = db.Column(db.DateTime, nullable=True, default=None) # Asset offsale date
def __init__(
self,
roblox_asset_id=None,
name="Asset",
description="",
created_at=None,
updated_at=None,
asset_type=AssetType.Image,
asset_genre=0,
creator_type=0,
creator_id=1,
moderation_status=1,
is_for_sale=False,
price_robux=0,
price_tix=0,
is_limited=False,
is_limited_unique=False,
serial_count=0,
sale_count=0,
offsale_at=None,
force_asset_id=None
):
if created_at is None:
created_at = datetime.utcnow()
if updated_at is None:
updated_at = datetime.utcnow()
self.roblox_asset_id = roblox_asset_id
self.name = name
self.description = description
self.created_at = created_at
self.updated_at = updated_at
self.asset_type = asset_type
self.asset_genre = asset_genre
self.creator_type = creator_type
self.creator_id = creator_id
self.moderation_status = moderation_status
self.is_for_sale = is_for_sale
self.price_robux = price_robux
self.price_tix = price_tix
self.is_limited = is_limited
self.is_limited_unique = is_limited_unique
self.serial_count = serial_count
self.sale_count = sale_count
self.offsale_at = offsale_at
if force_asset_id is not None:
self.id = force_asset_id
def __repr__(self):
return f"<Asset {self.id}>"

View File

@ -0,0 +1,13 @@
from app.extensions import db
class AssetFavorite( db.Model ):
id = db.Column( db.BigInteger, primary_key=True, autoincrement=True )
assetid = db.Column( db.BigInteger, nullable=False, index=True )
userid = db.Column( db.BigInteger, nullable=False, index=True )
def __init__(self, assetid : int, userid : int):
self.assetid = assetid
self.userid = userid
def __repr__(self):
return f"<AssetFavorite {self.id} {self.assetid} {self.userid}>"

View File

@ -0,0 +1,27 @@
from app.extensions import db
# This is used for the asset moderation system to link two assets together, eg. a Image and Shirt
# So the moderator does not need to approve both assets
class AssetModerationLink(db.Model):
id = db.Column(db.BigInteger, primary_key=True, unique=True, nullable=False, autoincrement=True)
ParentAssetId = db.Column(db.BigInteger, db.ForeignKey('asset.id'), nullable=False, index=True) # Parent asset ID, eg. Shirt
ChildAssetId = db.Column(db.BigInteger, db.ForeignKey('asset.id'), nullable=False, index=True) # Child asset ID eg. Image
ParentAsset = db.relationship("Asset", foreign_keys=[ParentAssetId], uselist=False, lazy="joined")
ChildAsset = db.relationship("Asset", foreign_keys=[ChildAssetId], uselist=False, lazy="joined")
def __init__(
self,
ParentAssetId,
ChildAssetId
):
self.ParentAssetId = ParentAssetId
self.ChildAssetId = ChildAssetId
def __repr__(self):
return "<AssetModerationLink id={id} ParentAssetId={ParentAssetId} ChildAssetId={ChildAssetId}>".format(
id=self.id,
ParentAssetId=self.ParentAssetId,
ChildAssetId=self.ChildAssetId
)

23
app/models/asset_rap.py Normal file
View File

@ -0,0 +1,23 @@
from app.extensions import db
from datetime import datetime
class AssetRap(db.Model):
assetid = db.Column(db.BigInteger, primary_key=True, nullable=False, unique=True)
rap = db.Column(db.BigInteger, nullable=False, default=0)
updated = db.Column(db.DateTime, nullable=False)
def __init__(
self,
assetid,
rap=0
):
self.assetid = assetid
self.rap = rap
self.updated = datetime.utcnow()
def __repr__(self):
return "<AssetRap assetid={assetid}, rap={rap}, updated={updated}>".format(
assetid=self.assetid,
rap=self.rap,
updated=self.updated
)

View File

@ -0,0 +1,36 @@
from app.extensions import db
class AssetThumbnail(db.Model):
id = db.Column(db.BigInteger, primary_key=True, unique=True, nullable=False, autoincrement=True)
asset_id = db.Column(db.BigInteger, db.ForeignKey('asset.id'), nullable=False, index=True) # Asset ID
asset_version_id = db.Column(db.BigInteger, nullable=False) # Asset version ID
content_hash = db.Column(db.String(512), nullable=False) # Asset thumbnail content hash
created_at = db.Column(db.DateTime, nullable=False) # Asset thumbnail creation date
updated_at = db.Column(db.DateTime, nullable=False) # Asset thumbnail last update date
moderation_status = db.Column(db.SmallInteger, nullable=False) # Asset thumbnail moderation status ( 0 = Approved, 1 = Pending, 2 = Declined )
asset = db.relationship('Asset', backref=db.backref('thumbnails', lazy=True, uselist=True), uselist=False)
def __init__(
self,
asset_id,
asset_version_id,
content_hash,
created_at,
moderation_status
):
self.asset_id = asset_id
self.asset_version_id = asset_version_id
self.content_hash = content_hash
self.created_at = created_at
self.updated_at = created_at
self.moderation_status = moderation_status
def __repr__(self):
return "<AssetThumbnail asset_id={asset_id} asset_version_id={asset_version_id} content_hash={content_hash} created_at={created_at} updated_at={updated_at} moderation_status={moderation_status}>".format(
asset_id=self.asset_id,
asset_version_id=self.asset_version_id,
content_hash=self.content_hash,
created_at=self.created_at,
updated_at=self.updated_at,
moderation_status=self.moderation_status
)

View File

@ -0,0 +1,35 @@
from app.extensions import db
class AssetVersion(db.Model):
id = db.Column(db.BigInteger, primary_key=True, unique=True, nullable=False, autoincrement=True)
asset_id = db.Column(db.BigInteger, nullable=False, index=True)
version = db.Column(db.BigInteger, nullable=False)
content_hash = db.Column(db.String(512), nullable=False)
created_at = db.Column(db.DateTime, nullable=False)
updated_at = db.Column(db.DateTime, nullable=False)
uploaded_by = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=True, index=True)
def __init__(
self,
asset_id,
version,
content_hash,
created_at,
uploaded_by=None
):
self.asset_id = asset_id
self.version = version
self.content_hash = content_hash
self.created_at = created_at
self.updated_at = created_at
self.uploaded_by = uploaded_by
def __repr__(self):
return "<AssetVersion id={id} asset_id={asset_id} version={version} content_hash={content_hash} created_at={created_at} updated_at={updated_at}>".format(
id=self.id,
asset_id=self.asset_id,
version=self.version,
content_hash=self.content_hash,
created_at=self.created_at,
updated_at=self.updated_at
)

15
app/models/asset_votes.py Normal file
View File

@ -0,0 +1,15 @@
from app.extensions import db
class AssetVote( db.Model ):
id = db.Column( db.BigInteger, primary_key=True )
assetid = db.Column( db.BigInteger, nullable=False, index=True )
userid = db.Column( db.BigInteger, nullable=False, index=True )
vote = db.Column( db.Boolean, nullable=False, default=True )
def __init__(self, assetid : int, userid : int, vote : bool):
self.assetid = assetid
self.userid = userid
self.vote = vote
def __repr__(self):
return f"<AssetVote {self.id} {self.assetid} {self.userid} {self.vote}>"

View File

@ -0,0 +1,52 @@
from app.extensions import db
from datetime import datetime
from app.enums.CryptomusPaymentStatus import CryptomusPaymentStatus
class CryptomusInvoice(db.Model):
id = db.Column( db.Text, primary_key=True, unique=True, nullable=False, index = True )
cryptomus_invoice_id = db.Column( db.Text, nullable=False, index = True )
initiator_id = db.Column( db.Integer, db.ForeignKey('user.id'), nullable=False, index = True )
required_amount = db.Column( db.Float, nullable=False )
paid_amount_usd = db.Column( db.Float, nullable=False, default=0 )
currency = db.Column( db.Text, nullable=False )
status = db.Column( db.Enum(CryptomusPaymentStatus), nullable=False )
is_final = db.Column( db.Boolean, nullable=False, default=False )
extra_data = db.Column( db.Text, nullable=True )
created_at = db.Column( db.DateTime, nullable=False )
updated_at = db.Column( db.DateTime, nullable=False )
expires_at = db.Column( db.DateTime, nullable=False )
assigned_key = db.Column( db.Text, nullable=True )
def __init__(
self,
id : str,
cryptomus_invoice_id : str,
initiator_id : int,
required_amount : float,
currency : str,
status : CryptomusPaymentStatus,
expires_at : datetime,
created_at : datetime = None,
updated_at : datetime = None,
paid_amount_usd : float = 0,
extra_data : str = None
):
self.id = id
self.cryptomus_invoice_id = cryptomus_invoice_id
self.initiator_id = initiator_id
self.required_amount = required_amount
self.currency = currency
self.status = status
self.expires_at = expires_at
self.created_at = created_at if created_at is not None else datetime.utcnow()
self.updated_at = updated_at if updated_at is not None else datetime.utcnow()
self.paid_amount_usd = paid_amount_usd
self.extra_data = extra_data

View File

@ -0,0 +1,54 @@
from app.extensions import db
from datetime import datetime, timedelta
class ExchangeOffer(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
creator_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=False, index=True)
creator = db.relationship('User', backref=db.backref('exchange_offers', lazy=True), foreign_keys=[creator_id], uselist=False)
offer_value = db.Column(db.BigInteger, nullable=False) # Amount of currency the creator is sending
receive_value = db.Column(db.BigInteger, nullable=False) # Amount of currency the creator is receiving
offer_currency_type = db.Column(db.SmallInteger, nullable=False) # Currency type of the offer value, 0 = Robux, 1 = Tix
# Recieve currency type is the opposite of the offer currency type
reciever_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=True, index=True) # If the offer is accepted by someone, this will be set to the user's id
reciever = db.relationship('User', backref=db.backref('exchange_offers_recieved', lazy=True), foreign_keys=[reciever_id], uselist=False)
created_at = db.Column(db.DateTime, nullable=False)
expires_at = db.Column(db.DateTime, nullable=False)
ratio = db.Column(db.Float, nullable=False, default=0) # The ratio of the offer value to the receive value
worth = db.Column(db.Float, nullable=False, default=0, index = True)
def __init___(
self,
creator_id,
offer_value,
receive_value,
offer_currency_type=0, # Robux
reciever_id=None,
ratio = None,
created_at=None,
expires_at=None
):
if created_at is None:
created_at = datetime.utcnow()
if expires_at is None:
expires_at = datetime.utcnow() + timedelta(days=31)
self.creator_id = creator_id
self.offer_value = offer_value
self.receive_value = receive_value
self.offer_currency_type = offer_currency_type
self.reciever_id = reciever_id
self.created_at = created_at
self.expires_at = expires_at
if ratio is None:
self.ratio = (offer_value / receive_value) if offer_currency_type == 0 else (receive_value / offer_value)
else:
self.ratio = ratio
def __repr__(self):
return '<ExchangeOffer %r>' % self.id

35
app/models/fflag_group.py Normal file
View File

@ -0,0 +1,35 @@
from app.extensions import db
class FflagGroup(db.Model):
group_id = db.Column(db.BigInteger, primary_key=True, nullable=False, index=True) # Group ID
name = db.Column(db.String(128), nullable=False) # Group name
description = db.Column(db.String(512), nullable=False) # Group description
created_at = db.Column(db.DateTime, nullable=False) # Group creation date
updated_at = db.Column(db.DateTime, nullable=False) # Group last update date
enabled = db.Column(db.Boolean, nullable=False) # Group enabled
apikey = db.Column(db.String(128), nullable=True) # Group API key ( optional )
gameserver_only = db.Column(db.Boolean, nullable=False) # Group is for gameserver only
def __init__(
self,
group_id,
name,
description,
created_at,
enabled,
apikey
):
self.group_id = group_id
self.name = name
self.description = description
self.created_at = created_at
self.updated_at = created_at
self.enabled = enabled
self.apikey = apikey
def __repr__(self):
return "<FflagGroup group_id={group_id}, name={name}, enabled={enabled}>".format(
group_id=self.group_id,
name=self.name,
enabled=self.enabled
)

29
app/models/fflag_value.py Normal file
View File

@ -0,0 +1,29 @@
from app.extensions import db
class FflagValue(db.Model):
flag_id = db.Column(db.BigInteger, primary_key=True, nullable=False, autoincrement=True) # Flag ID
group_id = db.Column(db.BigInteger, nullable=False, index=True) # Group ID
name = db.Column(db.String(128), nullable=False) # Flag name
flag_type = db.Column(db.Integer, nullable=False, default=1) # Flag type ( 1 = bool, 2 = number, 3 = string)
flag_value = db.Column(db.Text, nullable=False) # Flag value ( base64 )
def __init__(
self,
group_id,
name,
flag_type,
flag_value
):
self.group_id = group_id
self.name = name
self.flag_type = flag_type
self.flag_value = flag_value
def __repr__(self):
return "<FflagValue flag_id={flag_id}, group_id={group_id}, name={name}, flag_type={flag_type}>".format(
flag_id=self.flag_id,
group_id=self.group_id,
name=self.name,
flag_type=self.flag_type
)

View File

@ -0,0 +1,20 @@
from app.extensions import db
from datetime import datetime
class FollowRelationship(db.Model):
id = db.Column(db.BigInteger, primary_key=True, nullable=False, unique=True, autoincrement=True)
followerUserId = db.Column(db.BigInteger, nullable=False, index=True)
followeeUserId = db.Column(db.BigInteger, nullable=False, index=True)
created = db.Column(db.DateTime, nullable=False)
def __init__(self, followerUserId, followeeUserId):
self.followerUserId = followerUserId
self.followeeUserId = followeeUserId
self.created = datetime.utcnow()
def __repr__(self):
return "<FollowRelationship followerUserId={followerUserId}, followeeUserId={followeeUserId}, created={created}>".format(
followerUserId=self.followerUserId,
followeeUserId=self.followeeUserId,
created=self.created
)

View File

@ -0,0 +1,16 @@
from app.extensions import db
from datetime import datetime
class FriendRelationship(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True, nullable=False)
user_id = db.Column(db.BigInteger, nullable=False, index=True)
friend_id = db.Column(db.BigInteger, nullable=False, index=True)
created_at = db.Column(db.DateTime, nullable=False)
def __init__(self, user_id, friend_id):
self.user_id = user_id
self.friend_id = friend_id
self.created_at = datetime.utcnow()
def __repr__(self):
return '<FriendRelationship %r>' % self.id

View File

@ -0,0 +1,17 @@
from app.extensions import db
from datetime import datetime
class FriendRequest(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True, nullable=False)
requester_id = db.Column(db.BigInteger, db.ForeignKey("user.id") ,nullable=False, index=True) # The person who sent the friend request
requestee_id = db.Column(db.BigInteger, nullable=False, index=True) # The person who received the friend request
created_at = db.Column(db.DateTime, nullable=False)
requester = db.relationship("User", foreign_keys=[requester_id], backref="friend_requests_sent", uselist=False)
def __init__(self, requester_id, requestee_id):
self.requester_id = requester_id
self.requestee_id = requestee_id
self.created_at = datetime.utcnow()
def __repr__(self):
return '<FriendRequest %r>' % self.id

View File

@ -0,0 +1,36 @@
from app.extensions import db
from sqlalchemy.dialects.postgresql import UUID
from datetime import datetime, timedelta
class GameSessionLog( db.Model ):
id = db.Column( db.BigInteger, primary_key = True, autoincrement = True, nullable = False )
user_id = db.Column( db.BigInteger, db.ForeignKey( "user.id" ), nullable = False, index=True)
serveruuid = db.Column( UUID(as_uuid=True), nullable=False, index=True )
joined_at = db.Column( db.DateTime, nullable = False, index = True )
left_at = db.Column( db.DateTime, nullable = True )
place_id = db.Column( db.BigInteger, nullable = False, index=True )
def __init__(
self,
user_id,
serveruuid,
place_id,
joined_at = None,
left_at = None
):
self.user_id = user_id
self.serveruuid = serveruuid
self.place_id = place_id
self.joined_at = joined_at or datetime.utcnow()
self.left_at = left_at
def __repr__(self):
return "<GameSessionLog user_id={user_id}, serveruuid={serveruuid}, place_id={place_id}, joined_at={joined_at}, left_at={left_at}>".format(
user_id=self.user_id,
serveruuid=self.serveruuid,
place_id=self.place_id,
joined_at=self.joined_at,
left_at=self.left_at
)

View File

@ -0,0 +1,24 @@
from app.extensions import db
import datetime
class GamepassLink(db.Model):
gamepass_id = db.Column(db.BigInteger, db.ForeignKey("asset.id"), primary_key=True, nullable=False)
place_id = db.Column(db.BigInteger, db.ForeignKey("asset.id"), primary_key=True, nullable=False, index=True) # DEPRECATED
creator_id = db.Column(db.BigInteger, db.ForeignKey("user.id"), nullable=False, index=True)
created_at = db.Column(db.DateTime, nullable=False)
gamepass = db.relationship("Asset", foreign_keys=[gamepass_id], uselist=False, lazy="joined")
place = db.relationship("Asset", foreign_keys=[place_id], uselist=False, lazy="joined")
creator = db.relationship("User", foreign_keys=[creator_id], uselist=False, lazy="joined")
universe_id = db.Column(db.BigInteger, db.ForeignKey("universe.id"), nullable=True, index=True)
def __init__(self, place_id, gamepass_id, universe_id, creator_id):
self.place_id = place_id
self.gamepass_id = gamepass_id
self.universe_id = universe_id
self.creator_id = creator_id
self.created_at = datetime.datetime.utcnow()
def __repr__(self):
return '<GamepassLink %r>' % self.id

45
app/models/gameservers.py Normal file
View File

@ -0,0 +1,45 @@
from app.extensions import db
from sqlalchemy.dialects.postgresql import UUID
import uuid
class GameServer(db.Model):
serverId = db.Column(UUID(as_uuid=True), primary_key=True, nullable=False, unique=True, default=uuid.uuid4)
serverName = db.Column(db.String(128), nullable=False)
serverIP = db.Column(db.String(128), nullable=False)
serverPort = db.Column(db.Integer, nullable=False)
accessKey = db.Column(db.String(128), nullable=False)
lastHeartbeat = db.Column(db.DateTime, nullable=True, default=None)
heartbeatResponseTime = db.Column(db.Float, nullable=True, default=0)
isRCCOnline = db.Column(db.Boolean, nullable=False, default=False)
thumbnailQueueSize = db.Column(db.Integer, nullable=False, default=0)
RCCmemoryUsage = db.Column(db.BigInteger, nullable=False, default=0)
allowThumbnailGen = db.Column(db.Boolean, nullable=False, default=True) # If false, the server will not be able to generate thumbnails
allowGameServerHost = db.Column(db.Boolean, nullable=False, default=True) # If false, the server will not be able to host game servers
def __init__(
self,
serverId,
serverName,
serverIP,
serverPort,
accessKey,
allowThumbnailGen=True,
allowGameServerHost=True
):
self.serverId = serverId
self.serverName = serverName
self.serverIP = serverIP
self.serverPort = serverPort
self.accessKey = accessKey
self.allowThumbnailGen = allowThumbnailGen
self.allowGameServerHost = allowGameServerHost
def __repr__(self):
return "<GameServers serverId={serverId}, serverName={serverName}, serverIP={serverIP}, serverPort={serverPort}>".format(
serverId=self.serverId,
serverName=self.serverName,
serverIP=self.serverIP,
serverPort=self.serverPort
)

View File

@ -0,0 +1,31 @@
from app.extensions import db
from app.enums.GiftcardType import GiftcardType
from datetime import datetime
class GiftcardKey(db.Model):
id = db.Column(db.BigInteger, primary_key=True)
key = db.Column(db.String(255), nullable=False)
type = db.Column(db.Enum(GiftcardType), nullable=False)
value = db.Column(db.BigInteger, nullable=True)
created_at = db.Column(db.DateTime, nullable=False)
redeemed_at = db.Column(db.DateTime, nullable=True)
redeemed_by = db.Column(db.BigInteger, nullable=True)
def __init__(
self,
key: str,
type: GiftcardType,
value: int = None,
created_at: datetime = None,
):
if created_at is None:
created_at = datetime.utcnow()
self.key = key
self.type = type
self.value = value
self.created_at = created_at
def __repr__(self):
return f'<GiftcardKey {self.id}>'

296
app/models/groups.py Normal file
View File

@ -0,0 +1,296 @@
from app.extensions import db
from datetime import datetime
class Group(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
owner_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=True, index=True) # Can be nullable since owners can leave groups
name = db.Column(db.String(255), nullable=False, index=True)
description = db.Column(db.String(1024), nullable=False)
created_at = db.Column(db.DateTime, nullable=False)
updated_at = db.Column(db.DateTime, nullable=False)
locked = db.Column(db.Boolean, nullable=False, default=False)
owner = db.relationship('User', backref=db.backref('groups', lazy=True))
def __init__(
self,
owner_id,
name,
description,
created_at=None,
updated_at=None,
):
if created_at is None:
created_at = datetime.utcnow()
if updated_at is None:
updated_at = datetime.utcnow()
self.owner_id = owner_id
self.name = name
self.description = description
self.created_at = created_at
self.updated_at = updated_at
def __repr__(self):
return '<Group %r>' % self.name
class GroupIcon(db.Model):
group_id = db.Column(db.BigInteger, db.ForeignKey('group.id'), primary_key=True)
content_hash = db.Column(db.String(512), nullable=False, index=True)
moderation_status = db.Column(db.Integer, nullable=False, default=1)
creator_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=False, index=True)
created_at = db.Column(db.DateTime, nullable=False)
group = db.relationship('Group', backref=db.backref('icon', lazy=True, uselist=False), uselist=False)
creator = db.relationship('User', backref=db.backref('group_icons', lazy=True))
def __init__(
self,
group_id,
content_hash,
moderation_status,
creator_id,
created_at=None
):
if created_at is None:
created_at = datetime.utcnow()
self.group_id = group_id
self.content_hash = content_hash
self.moderation_status = moderation_status
self.creator_id = creator_id
self.created_at = created_at
def __repr__(self):
return '<GroupIcon %r>' % self.group_id
class GroupSettings(db.Model):
group_id = db.Column(db.BigInteger, db.ForeignKey('group.id'), primary_key=True)
approval_required = db.Column(db.Boolean, nullable=False, default=False)
enemies_allowed = db.Column(db.Boolean, nullable=False, default=False)
funds_visible = db.Column(db.Boolean, nullable=False, default=False)
games_visible = db.Column(db.Boolean, nullable=False, default=False)
membership_required = db.Column(db.Boolean, nullable=False, default=False)
last_updated = db.Column(db.DateTime, nullable=False)
group = db.relationship('Group', backref=db.backref('settings', lazy=True, uselist=False), uselist=False)
def __init__(
self,
group_id,
approval_required = False,
enemies_allowed = False,
funds_visible = False,
games_visible = False,
membership_required = False,
last_updated=None
):
if last_updated is None:
last_updated = datetime.utcnow()
self.group_id = group_id
self.approval_required = approval_required
self.enemies_allowed = enemies_allowed
self.funds_visible = funds_visible
self.games_visible = games_visible
self.membership_required = membership_required
self.last_updated = last_updated
def __repr__(self):
return '<GroupSettings %r>' % self.group_id
class GroupRole(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
group_id = db.Column(db.BigInteger, db.ForeignKey('group.id'), nullable=False, index=True)
name = db.Column(db.String(255), nullable=False)
description = db.Column(db.String(255), nullable=False)
rank = db.Column(db.Integer, nullable=False, default=1)
member_count = db.Column(db.Integer, nullable=False, default=0)
created_at = db.Column(db.DateTime, nullable=False)
updated_at = db.Column(db.DateTime, nullable=False)
group = db.relationship('Group', backref=db.backref('roles', lazy=True))
def __init__(
self,
group_id,
name,
description,
rank,
member_count,
created_at=None,
updated_at=None
):
if created_at is None:
created_at = datetime.utcnow()
if updated_at is None:
updated_at = datetime.utcnow()
self.group_id = group_id
self.name = name
self.description = description
self.rank = rank
self.member_count = member_count
self.created_at = created_at
self.updated_at = updated_at
def __repr__(self):
return '<GroupRole %r>' % self.name
class GroupRolePermission(db.Model):
group_role_id = db.Column(db.BigInteger, db.ForeignKey('group_role.id'), primary_key=True)
# One to one relationship
group_roleset = db.relationship('GroupRole', backref=db.backref('permissions', uselist=False, lazy=True), lazy=True, uselist=False)
delete_from_wall = db.Column(db.Boolean, nullable=False, default=False)
post_to_wall = db.Column(db.Boolean, nullable=False, default=False)
invite_members = db.Column(db.Boolean, nullable=False, default=False)
post_to_status = db.Column(db.Boolean, nullable=False, default=False)
remove_members = db.Column(db.Boolean, nullable=False, default=False)
view_status = db.Column(db.Boolean, nullable=False, default=False)
view_wall = db.Column(db.Boolean, nullable=False, default=False)
change_rank = db.Column(db.Boolean, nullable=False, default=False)
advertise_group = db.Column(db.Boolean, nullable=False, default=False)
manage_relationships = db.Column(db.Boolean, nullable=False, default=False)
add_group_places = db.Column(db.Boolean, nullable=False, default=False)
view_audit_logs = db.Column(db.Boolean, nullable=False, default=False)
create_items = db.Column(db.Boolean, nullable=False, default=False)
manage_items = db.Column(db.Boolean, nullable=False, default=False)
spend_group_funds = db.Column(db.Boolean, nullable=False, default=False)
manage_clan = db.Column(db.Boolean, nullable=False, default=False)
manage_group_games = db.Column(db.Boolean, nullable=False, default=False)
def __init__(
self,
group_role_id
):
self.group_role_id = group_role_id
def __repr__(self):
return '<GroupRolePermission %r>' % self.group_role_id
class GroupMember(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
group_id = db.Column(db.BigInteger, db.ForeignKey('group.id'), nullable=False, index=True)
user_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=False, index=True)
group_role_id = db.Column(db.BigInteger, db.ForeignKey('group_role.id'), nullable=False, index=True)
created_at = db.Column(db.DateTime, nullable=False)
group = db.relationship('Group', backref=db.backref('members', lazy=True))
user = db.relationship('User', backref=db.backref('group_members', lazy=True))
group_role = db.relationship('GroupRole', backref=db.backref('members', lazy=True))
def __init__(
self,
group_id,
user_id,
group_role_id,
created_at=None
):
if created_at is None:
created_at = datetime.utcnow()
self.created_at = created_at
self.group_id = group_id
self.user_id = user_id
self.group_role_id = group_role_id
def __repr__(self):
return '<GroupMember %r>' % self.id
class GroupEconomy(db.Model):
group_id = db.Column(db.BigInteger, db.ForeignKey('group.id'), primary_key=True)
robux_balance = db.Column(db.BigInteger, nullable=False, default=0)
tix_balance = db.Column(db.BigInteger, nullable=False, default=0)
group = db.relationship('Group', backref=db.backref('economy', lazy=True, uselist=False), uselist=False)
def __init__(
self,
group_id
):
self.group_id = group_id
def __repr__(self):
return '<GroupEconomy %r>' % self.group_id
class GroupJoinRequest(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
group_id = db.Column(db.BigInteger, db.ForeignKey('group.id'), nullable=False, index=True)
user_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=False, index=True)
created_at = db.Column(db.DateTime, nullable=False)
group = db.relationship('Group', backref=db.backref('join_requests', lazy=True))
user = db.relationship('User', backref=db.backref('group_join_requests', lazy=True))
def __init__(
self,
group_id,
user_id,
created_at=None
):
if created_at is None:
created_at = datetime.utcnow()
self.group_id = group_id
self.user_id = user_id
self.created_at = created_at
def __repr__(self):
return '<GroupJoinRequest %r>' % self.id
class GroupStatus(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
group_id = db.Column(db.BigInteger, db.ForeignKey('group.id'), nullable=False, index=True)
poster_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=False, index=True)
content = db.Column(db.String(1024), nullable=False)
created_at = db.Column(db.DateTime, nullable=False)
group = db.relationship('Group', backref=db.backref('statuses', lazy=True))
poster = db.relationship('User', backref=db.backref('group_statuses', lazy=True))
def __init__(
self,
group_id,
poster_id,
content,
created_at=None
):
self.group_id = group_id
self.poster_id = poster_id
self.content = content
if created_at is None:
created_at = datetime.utcnow()
self.created_at = created_at
def __repr__(self):
return '<GroupStatus %r>' % self.id
class GroupWallPost(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
group_id = db.Column(db.BigInteger, db.ForeignKey('group.id'), nullable=False, index=True)
poster_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=False, index=True)
content = db.Column(db.String(1024), nullable=False)
created_at = db.Column(db.DateTime, nullable=False)
group = db.relationship('Group', backref=db.backref('wall_posts', lazy=True))
poster = db.relationship('User', backref=db.backref('group_wall_posts', lazy=True, uselist=False), uselist=False)
def __init__(
self,
group_id,
poster_id,
content,
created_at=None
):
self.group_id = group_id
self.poster_id = poster_id
self.content = content
if created_at is None:
created_at = datetime.utcnow()
self.created_at = created_at
def __repr__(self):
return '<GroupWallPost %r>' % self.id

25
app/models/invite_key.py Normal file
View File

@ -0,0 +1,25 @@
from app.extensions import db
from datetime import datetime
class InviteKey(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True, nullable=False)
key = db.Column(db.String(255), nullable=False) # syntax-randomstring
created_at = db.Column(db.DateTime, nullable=False)
created_by = db.Column(db.BigInteger, db.ForeignKey('user.id') ,nullable=True, index=True)
used_by = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=True)
used_on = db.Column(db.DateTime, nullable=True)
creator = db.relationship('User', backref=db.backref('invite_keys', lazy=True), foreign_keys=[created_by], uselist=False)
user = db.relationship('User', backref=db.backref('used_invite_keys', lazy=True), foreign_keys=[used_by], uselist=False)
def __init__(
self,
key,
created_by
):
self.key = key
self.created_by = created_by
self.created_at = datetime.utcnow()
def __repr__(self):
return '<InviteKey %r>' % self.id

View File

@ -0,0 +1,41 @@
from app.extensions import db
class KofiTransaction(db.Model):
kofi_transaction_id = db.Column(db.Text, primary_key=True)
timestamp = db.Column(db.DateTime, nullable=False)
donation_type = db.Column(db.Text, nullable=False)
amount = db.Column(db.Float, nullable=False)
currency = db.Column(db.Text, nullable=False)
is_subscription_payment = db.Column(db.Boolean, nullable=False)
message = db.Column(db.Text, nullable=False)
from_name = db.Column(db.Text, nullable=False)
from_email = db.Column(db.Text, nullable=False)
assigned_key = db.Column(db.Text ,nullable=True)
def __init__(
self,
kofi_transaction_id,
timestamp,
donation_type,
amount,
currency,
is_subscription_payment,
message,
from_name,
from_email,
assigned_key=None
):
self.kofi_transaction_id = kofi_transaction_id
self.timestamp = timestamp
self.donation_type = donation_type
self.amount = amount
self.currency = currency
self.is_subscription_payment = is_subscription_payment
self.message = message
self.from_name = from_name
self.from_email = from_email
self.assigned_key = assigned_key
def __repr__(self):
return f"<KofiTransaction {self.kofi_transaction_id}>"

View File

@ -0,0 +1,31 @@
from app.extensions import db
from datetime import datetime
class LegacyDataPersistence( db.Model ):
id = db.Column( db.BigInteger, primary_key=True, nullable=False, unique=True, autoincrement=True )
userid = db.Column( db.BigInteger, nullable=False, index=True )
placeid = db.Column( db.BigInteger, nullable=False, index=True ) # DEPRECATED
data = db.Column( db.LargeBinary, nullable=False )
last_updated = db.Column( db.DateTime, nullable=False )
universe_id = db.Column( db.BigInteger, db.ForeignKey('universe.id'), nullable=True, index=True )
def __init__(
self,
userid,
placeid,
universe_id
):
self.userid = userid
self.placeid = placeid
self.last_updated = datetime.utcnow()
self.universe_id = universe_id
def __repr__(self):
return "<LegacyDataPersistence id={id}, userid={userid}, placeid={placeid}>".format(
id=self.id,
userid=self.userid,
placeid=self.placeid
)

View File

@ -0,0 +1,33 @@
from app.extensions import db
from app.enums.LimitedItemTransferMethod import LimitedItemTransferMethod
from datetime import datetime
class LimitedItemTransfer(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
original_owner_id = db.Column(db.BigInteger, nullable=False, index=True)
new_owner_id = db.Column(db.BigInteger, nullable=False, index=True)
asset_id = db.Column(db.BigInteger, nullable=False, index=True)
user_asset_id = db.Column(db.BigInteger, nullable=False, index=True)
transferred_at = db.Column(db.DateTime, nullable=False)
transfer_method = db.Column(db.Enum(LimitedItemTransferMethod), nullable=False, index=True)
purchased_price = db.Column(db.BigInteger, nullable=True, default=None)
associated_trade_id = db.Column(db.BigInteger, nullable=True, default=None)
def __init__(self, original_owner_id, new_owner_id, asset_id, user_asset_id, transfer_method=LimitedItemTransferMethod.Purchase, transferred_at=None, purchased_price=None, associated_trade_id = None):
self.original_owner_id = original_owner_id
self.new_owner_id = new_owner_id
self.asset_id = asset_id
self.user_asset_id = user_asset_id
self.transfer_method = transfer_method
if transferred_at is None:
self.transferred_at = datetime.utcnow()
else:
self.transferred_at = transferred_at
self.purchased_price = purchased_price
self.associated_trade_id = associated_trade_id

View File

@ -0,0 +1,49 @@
from app.extensions import db
from datetime import datetime
class LinkedDiscord(db.Model):
user_id = db.Column(db.BigInteger, db.ForeignKey('user.id'), primary_key=True)
discord_id = db.Column(db.BigInteger, nullable=False)
discord_username = db.Column(db.String(255), nullable=False)
discord_discriminator = db.Column(db.String(255), nullable=True)
discord_avatar = db.Column(db.Text, nullable=True)
discord_access_token = db.Column(db.String(512), nullable=True)
discord_refresh_token = db.Column(db.String(512), nullable=True)
discord_expiry = db.Column(db.DateTime, nullable=True)
last_updated = db.Column(db.DateTime, nullable=False)
linked_on = db.Column(db.DateTime, nullable=False)
user = db.relationship('User', backref=db.backref('discord', lazy=True))
def __init__(self,
user_id,
discord_id,
discord_username,
discord_discriminator,
discord_avatar,
discord_access_token,
discord_refresh_token,
discord_expiry,
last_updated=None,
linked_on=None
):
self.user_id = user_id
self.discord_id = discord_id
self.discord_username = discord_username
self.discord_discriminator = discord_discriminator
self.discord_avatar = discord_avatar
self.discord_access_token = discord_access_token
self.discord_refresh_token = discord_refresh_token,
self.discord_expiry = discord_expiry
if last_updated is None:
self.last_updated = datetime.utcnow()
else:
self.last_updated = last_updated
if linked_on is None:
self.linked_on = datetime.utcnow()
else:
self.linked_on = linked_on
def __repr__(self):
return '<LinkedDiscord %r>' % self.user_id

View File

@ -0,0 +1,21 @@
from app.extensions import db
class LoginRecord(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True, nullable=False)
userid = db.Column(db.BigInteger, db.ForeignKey('user.id'), nullable=False, index=True)
ip = db.Column(db.Text, nullable=False, index=True)
useragent = db.Column(db.Text, nullable=False)
timestamp = db.Column(db.DateTime, nullable=False)
session_token = db.Column(db.Text, nullable=True, index=True)
User = db.relationship('User', backref=db.backref('login_records', lazy=True), uselist=False)
def __init__(self, userid, ip, useragent, timestamp, session_token = None):
self.userid = userid
self.ip = ip
self.useragent = useragent
self.timestamp = timestamp
self.session_token = session_token
def __repr__(self):
return '<LoginRecord {} ({} - {})>'.format(self.id, self.userid, self.ip)

33
app/models/messages.py Normal file
View File

@ -0,0 +1,33 @@
from app.extensions import db
from datetime import datetime
class Message( db.Model ):
id = db.Column( db.BigInteger, primary_key=True, autoincrement=True, nullable=False )
sender_id = db.Column( db.BigInteger, db.ForeignKey("user.id"), nullable=False, index=True )
recipient_id = db.Column( db.BigInteger, db.ForeignKey("user.id"), nullable=False, index=True )
created = db.Column( db.DateTime, nullable=False )
read = db.Column( db.Boolean, nullable=False )
subject = db.Column( db.String( 128 ), nullable=False )
content = db.Column( db.Text, nullable=False )
sender = db.relationship( "User", foreign_keys=[sender_id], uselist=False)
recipient = db.relationship( "User", foreign_keys=[recipient_id], uselist=False)
def __init__(
self,
sender_id,
recipient_id,
content,
subject,
read=False
):
self.sender_id = sender_id
self.recipient_id = recipient_id
self.content = content
self.read = read
self.subject = subject
self.created = datetime.utcnow()
def __repr__(self):
return '<Message %r>' % self.id

Some files were not shown because too many files have changed in this diff Show More