Merge branch 'master' into production

This commit is contained in:
Michael Schmatz 2014-11-28 11:09:07 -05:00
commit 3475770f13
28 changed files with 965 additions and 730 deletions

View file

@ -15,8 +15,7 @@ module.exports = class CocoRouter extends Backbone.Router
@initializeSocialMediaServices = _.once @initializeSocialMediaServices
routes:
'': go('HomeView') # This will go somewhere deprecated when FrontView is done.
'front': go('FrontView') # This will become '' when it is done.
'': go('HomeView')
'about': go('AboutView')
@ -85,7 +84,6 @@ module.exports = class CocoRouter extends Backbone.Router
'play-old': go('play/MainPlayView') # This used to be 'play'.
'play': go('play/WorldMapView')
'play-hero': go('play/WorldMapView') # Legacy URL for /play; leave up until start of 2015, I guess.
'play/ladder/:levelID': go('play/ladder/LadderView')
'play/ladder': go('play/ladder/MainLadderView')
'play/level/:levelID': go('play/level/PlayLevelView')

View file

@ -141,6 +141,7 @@ module.exports = LevelOptions =
hidesRealTimePlayback: true
requiredGear: {'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i', torso: 'tarnished-bronze-breastplate'}
restrictedGear: {feet: 'leather-boots'}
suspectCode: [{name: 'enemy-in-quotes', pattern: /['"]enemy/m}] # '
'master-of-names':
hidesHUD: true
hidesSay: true

View file

@ -12,7 +12,7 @@ module.exports = class Tracker
identify: (traits) ->
console.log 'Would identify', traits if debugAnalytics
return unless me and @isProduction and analytics?
return unless me and @isProduction and analytics? and not me.isAdmin()
# https://segment.io/docs/methods/identify
traits ?= {}
for userTrait in ['email', 'anonymous', 'dateCreated', 'name', 'wizardColor1', 'testGroupNumber', 'gender']
@ -20,14 +20,14 @@ module.exports = class Tracker
analytics.identify me.id, traits
trackPageView: ->
return unless @isProduction and analytics?
return unless @isProduction and analytics? and not me.isAdmin()
url = Backbone.history.getFragment()
console.log 'Going to track visit for', "/#{url}" if debugAnalytics
analytics.pageview "/#{url}"
trackEvent: (event, properties, includeProviders=null) =>
console.log 'Would track analytics event:', event, properties if debugAnalytics
return unless me and @isProduction and analytics?
return unless me and @isProduction and analytics? and not me.isAdmin()
console.log 'Going to track analytics event:', event, properties if debugAnalytics
properties = properties or {}
context = {}

View file

@ -1,42 +1,42 @@
module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Indonesian", translation:
# home:
home:
# slogan: "Learn to Code by Playing a Game"
# no_ie: "CodeCombat does not run in Internet Explorer 8 or older. Sorry!" # Warning that only shows up in IE8 and older
# no_mobile: "CodeCombat wasn't designed for mobile devices and may not work!" # Warning that shows up on mobile devices
# play: "Play" # The big play button that just starts playing a level
# old_browser: "Uh oh, your browser is too old to run CodeCombat. Sorry!" # Warning that shows up on really old Firefox/Chrome/Safari
# old_browser_suffix: "You can try anyway, but it probably won't work."
# campaign: "Campaign"
# for_beginners: "For Beginners"
# multiplayer: "Multiplayer" # Not currently shown on home page
# for_developers: "For Developers" # Not currently shown on home page.
# or_ipad: "Or download for iPad"
no_ie: "Maaf, CodeCombat tidak bisa dijalankan pada Internet Explorer 8 dan sebelumnya" # Warning that only shows up in IE8 and older
no_mobile: "Maaf. CodeCombat tidak dibuat untuk perangkat mobile" # Warning that shows up on mobile devices
play: "Play" # The big play button that just starts playing a level
old_browser: "Uh oh, Maaf. Versi broser anda terlalu lama " # Warning that shows up on really old Firefox/Chrome/Safari
old_browser_suffix: "Anda bisa mencoba, tapi mungkin tidak akan berjalan."
campaign: "Campaign"
for_beginners: "Pemula"
multiplayer: "Multiplayer" # Not currently shown on home page
for_developers: "Developers" # Not currently shown on home page.
or_ipad: "atau download untuk iPad"
# nav:
# play: "Levels" # The top nav bar entry where players choose which levels to play
# community: "Community"
# editor: "Editor"
# blog: "Blog"
# forum: "Forum"
# account: "Account"
# profile: "Profile"
# stats: "Stats"
# code: "Code"
# admin: "Admin" # Only shows up when you are an admin
# home: "Home"
nav:
play: "Levels" # The top nav bar entry where players choose which levels to play
community: "Community"
editor: "Editor"
blog: "Blog"
forum: "Forum"
account: "Akun"
profile: "Profile"
stats: "Mulai"
code: "Code"
admin: "Admin" # Only shows up when you are an admin
home: "Home"
# contribute: "Contribute"
# legal: "Legal"
legal: "Legal"
# about: "About"
# contact: "Contact"
# twitter_follow: "Follow"
contact: "Kontak"
twitter_follow: "Follow"
# teachers: "Teachers"
# modal:
# close: "Close"
# okay: "Okay"
modal:
close: "Close"
okay: "Okay"
# not_found:
# page_not_found: "Page not found"
not_found:
page_not_found: "Alamat tidak ditemukan"
diplomat_suggestion:
# title: "Help translate CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
@ -46,22 +46,22 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# learn_more: "Learn more about being a Diplomat"
# subscribe_as_diplomat: "Subscribe as a Diplomat"
# play:
play:
# play_as: "Play As" # Ladder page
# spectate: "Spectate" # Ladder page
# players: "players" # Hover over a level on /play
# hours_played: "hours played" # Hover over a level on /play
# items: "Items" # Tooltip on item shop button from /play
# unlock: "Unlock" # For purchasing items and heroes
# confirm: "Confirm"
confirm: "Konfirmasi"
# owned: "Owned" # For items you own
# locked: "Locked"
# available: "Available"
locked: "Terkunci"
available: "Trsedia"
# skills_granted: "Skills Granted" # Property documentation details
# heroes: "Heroes" # Tooltip on hero shop button from /play
heroes: "Heroes" # Tooltip on hero shop button from /play
# achievements: "Achievements" # Tooltip on achievement list button from /play
# account: "Account" # Tooltip on account button from /play
# settings: "Settings" # Tooltip on settings button from /play
account: "Akun" # Tooltip on account button from /play
settings: "Settings" # Tooltip on settings button from /play
# next: "Next" # Go from choose hero to choose inventory before playing a level
# change_hero: "Change Hero" # Go back from choose inventory to choose hero
# choose_inventory: "Equip Items"
@ -70,10 +70,10 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# anonymous: "Anonymous Player"
# level_difficulty: "Difficulty: "
# campaign_beginner: "Beginner Campaign"
# awaiting_levels_adventurer_prefix: "We release five levels per week."
awaiting_levels_adventurer_prefix:"Kami meliris lima level per minggu"
# awaiting_levels_adventurer: "Sign up as an Adventurer"
# awaiting_levels_adventurer_suffix: "to be the first to play new levels."
# choose_your_level: "Choose Your Level" # The rest of this section is the old play view at /play-old and isn't very important.
choose_your_level: "Pilih Level Anda" # The rest of this section is the old play view at /play-old and isn't very important.
# adventurer_prefix: "You can jump to any level below, or discuss the levels on "
# adventurer_forum: "the Adventurer forum"
# adventurer_suffix: "."
@ -81,7 +81,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# campaign_old_beginner_description: "... in which you learn the wizardry of programming."
# campaign_dev: "Random Harder Levels"
# campaign_dev_description: "... in which you learn the interface while doing something a little harder."
# campaign_multiplayer: "Multiplayer Arenas"
campaign_multiplayer: "Arena Multiplayer"
# campaign_multiplayer_description: "... in which you code head-to-head against other players."
# campaign_player_created: "Player-Created"
# campaign_player_created_description: "... in which you battle against the creativity of your fellow <a href=\"/contribute#artisan\">Artisan Wizards</a>."
@ -90,11 +90,11 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# campaign_forest: "Forest Campaign"
# campaign_dungeon: "Dungeon Campaign"
# login:
# sign_up: "Create Account"
# log_in: "Log In"
# logging_in: "Logging In"
# log_out: "Log Out"
login:
sign_up: "Buat Akun"
log_in: "Masuk"
logging_in: "Logging In"
log_out: "Keluar"
# recover: "recover account"
# authenticate_gplus: "Authenticate G+"
# load_profile: "Load G+ Profile"
@ -106,7 +106,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# description: "It's free. Just need a couple things and you'll be good to go:"
# email_announcements: "Receive announcements by email"
# coppa: "13+ or non-USA "
# coppa_why: "(Why?)"
# coppa_why: "(Kenapa?)"
# creating: "Creating Account..."
# sign_up: "Sign Up"
# log_in: "log in with password"

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
for_beginners: "Yeni Başlayanlar için"
multiplayer: "Çoklu-oyuncu Kipi" # Not currently shown on home page
for_developers: "Geliştiriciler için" # Not currently shown on home page.
# or_ipad: "Or download for iPad"
or_ipad: "Ya da iPad için indir"
nav:
play: "Oyna" # The top nav bar entry where players choose which levels to play
@ -52,11 +52,11 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
players: "oyuncu" # Hover over a level on /play
hours_played: "saat oynandı" # Hover over a level on /play
items: "Ögeler" # Tooltip on item shop button from /play
# unlock: "Unlock" # For purchasing items and heroes
# confirm: "Confirm"
# owned: "Owned" # For items you own
# locked: "Locked"
# available: "Available"
unlock: "Kilidi aç" # For purchasing items and heroes
confirm: "Devam et"
owned: "Sahipsin" # For items you own
locked: "Kilitli"
available: "ık"
# skills_granted: "Skills Granted" # Property documentation details
heroes: "Kahramanlar" # Tooltip on hero shop button from /play
achievements: "Başarımlar" # Tooltip on achievement list button from /play
@ -65,13 +65,13 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
next: "İleri" # Go from choose hero to choose inventory before playing a level
change_hero: "Kahramanı Değiştir" # Go back from choose inventory to choose hero
choose_inventory: "Ögeleri Giy"
# buy_gems: "Buy Gems"
buy_gems: "Taş satın a"
older_campaigns: "Daha Eski Görevler"
anonymous: "Anonim Oyuncu"
level_difficulty: "Zorluk: "
campaign_beginner: "Acemi Seferi"
# awaiting_levels_adventurer_prefix: "We release five levels per week."
# awaiting_levels_adventurer: "Sign up as an Adventurer"
awaiting_levels_adventurer: "Maceracı olmak için kayıt ol"
# awaiting_levels_adventurer_suffix: "to be the first to play new levels."
choose_your_level: "Seviye Seçimi" # The rest of this section is the old play view at /play-old and isn't very important.
adventurer_prefix: "Aşağıdaki seviyelerden birini doğrudan oynayabilirsiniz, veya seviye ile ilgili "
@ -87,8 +87,8 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
campaign_player_created_description: "<a href=\"/contribute#artisan\">Zanaatkâr Büyücüler</a>in yaratıcılıklarına karşı mücadele etmek için..."
campaign_classic_algorithms: "Klasik Algoritmalar"
campaign_classic_algorithms_description: "... Bilgisayar Bilimleri'nde öğrendiğiniz en yaygın algoritmalar."
# campaign_forest: "Forest Campaign"
# campaign_dungeon: "Dungeon Campaign"
campaign_forest: "Orman Senaryosu"
campaign_dungeon: "Zindan Senaryosu"
login:
sign_up: "Hesap Oluştur"
@ -119,12 +119,12 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
recovery_sent: "Kurtarma e-postası gönderildi."
items:
# primary: "Primary"
# secondary: "Secondary"
primary: "Birincil"
secondary: "İkincil"
armor: "Zırh"
accessories: "Aksesuarlar"
misc: "Çeşitli"
# books: "Books"
books: "Kitaplar"
common:
loading: "Yükleniyor..."
@ -137,7 +137,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
create: "Oluştur"
manual: "El ile"
fork: "Çatalla"
play: "Oyna" # When used as an action verb, like "Play next level"
play: "Oyna" # When used as an action verb, like "Sonraki Seviyeyi Oyna"
retry: "Yeniden Dene"
watch: "İzle"
unwatch: "İzlemeyi Bırak"
@ -201,16 +201,16 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
restart: "Yeniden başlat"
goals: "Hedefler"
goal: "Amaç"
# running: "Running..."
running: "Çalıştırılıyor..."
success: "Başarılı!"
incomplete: "Tamamlanmamış"
timed_out: "Süre bitti"
failing: "Başarısız"
action_timeline: "Eylem Çizelgesi"
click_to_select: "Birimi seçmek için üzerine tıklayın."
# control_bar_multiplayer: "Multiplayer"
# control_bar_join_game: "Join Game"
# reload: "Reload"
control_bar_multiplayer: "Çoklu Oyuncu"
control_bar_join_game: "Oyuna Katıl"
reload: "Yeniden Yükle"
reload_title: "Tüm kod yeniden yüklensin mi?"
reload_really: "Bu seviyeyi en baştan yüklemek istediğinizden emin misiniz?"
reload_confirm: "Tümünü Yeniden Yükle"
@ -247,13 +247,13 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
tome_available_spells: "Kullanılabilir Büyüler"
tome_your_skills: "Yetenekleriniz"
# tome_current_method: "Current Method"
# hud_continue_short: "Continue"
hud_continue_short: "Devam"
code_saved: "Kod Kaydedildi"
skip_tutorial: "Atla (ESC)"
keyboard_shortcuts: "Klavye Kısayolları"
loading_ready: "Hazır!"
loading_start: "Seviyeyi Başlat"
# problem_alert_title: "Fix Your Code"
problem_alert_title: "Kodunu Düzelt"
time_current: "Şimdi:"
time_total: "Max:"
time_goto: "Git:"
@ -308,20 +308,20 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
inventory:
choose_inventory: "Ögeleri Donan"
# equipped_item: "Equipped"
# available_item: "Available"
equipped_item: "Giyilmiş"
available_item: "ık"
# restricted_title: "Restricted"
# should_equip: "(double-click to equip)"
# equipped: "(equipped)"
# locked: "(locked)"
should_equip: "(iki kere tıklayarak giy)"
equipped: "(giyildi)"
locked: "(kitli)"
# restricted: "(restricted in this level)"
# equip: "Equip"
# unequip: "Unequip"
equip: "Giy"
unequip: "Çıkar"
# buy_gems:
# few_gems: "A few gems"
# pile_gems: "Pile of gems"
# chest_gems: "Chest of gems"
buy_gems:
few_gems: "Bir avuç taş"
pile_gems: "Bir Torba"
chest_gems: "Sandık dolusu taş"
# purchasing: "Purchasing..."
# declined: "Your card was declined"
# retrying: "Server error, retrying."
@ -330,7 +330,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
choose_hero: "Kahramanınızı Seçin"
programming_language: "Programlama Dili"
programming_language_description: "Hangi programlama dilini kullanmak istiyorsunuz?"
# default: "Default"
# default: "Normal"
# experimental: "Experimental"
python_blurb: "Basit ancak güçlü. Python mükemmel bir genel amaçlı dildir."
javascript_blurb: "Web'in dili."
@ -347,8 +347,8 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
health: "Sağlık"
speed: "Hız"
# regeneration: "Regeneration"
# range: "Range" # As in "attack or visual range"
# blocks: "Blocks" # As in "this shield blocks this much damage"
range: "Menzil" # As in "attack or visual range"
blocks: "Blok" # As in "this shield blocks this much damage"
skills: "Yetenekler"
# skill_docs:

View file

@ -10,7 +10,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
for_beginners: "适合初学者"
multiplayer: "多人游戏" # Not currently shown on home page
for_developers: "适合开发者" # Not currently shown on home page.
# or_ipad: "Or download for iPad"
or_ipad: "或者下载iPad版本" # Or download for iPad
nav:
play: "关卡选择" # The top nav bar entry where players choose which levels to play
@ -208,8 +208,8 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
failing: "失败"
action_timeline: "行动时间轴"
click_to_select: "点击选择一个单元。"
# control_bar_multiplayer: "Multiplayer"
# control_bar_join_game: "Join Game"
control_bar_multiplayer: "多人游戏"
control_bar_join_game: "加入游戏"
reload: "重载"
reload_title: "重载所有代码?"
reload_really: "确定重载这一关,返回开始处吗?"

View file

@ -133,6 +133,17 @@ _.extend ThangTypeSchema.properties,
rasterIcon: { type: 'string', format: 'image-file', title: 'Raster Image Icon' }
containerIcon: { type: 'string' }
featureImage: { type: 'string', format: 'image-file', title: 'Feature Image' }
featureImageHair: { type: 'string', format: 'image-file', title: 'Feature Image Hair' }
featureImageThumb: { type: 'string', format: 'image-file', title: 'Feature Image Thumb' }
dollImages: c.object { title: 'Paper Doll Images' },
male: { type: 'string', format: 'image-file', title: ' Male' }
female: { type: 'string', format: 'image-file', title: ' Female' }
maleThumb: { type: 'string', format: 'image-file', title: 'Thumb (Male)' }
femaleThumb: { type: 'string', format: 'image-file', title: 'Thumb (Female)' }
maleRanger: { type: 'string', format: 'image-file', title: 'Glove (Male Ranger)' }
maleRangerThumb: { type: 'string', format: 'image-file', title: 'Thumb (Male Ranger)' }
femaleRanger: { type: 'string', format: 'image-file', title: 'Glove (Female Ranger)' }
femaleRangeThumbr: { type: 'string', format: 'image-file', title: 'Thumb (Female Ranger)' }
colorGroups: c.object
title: 'Color Groups'
additionalProperties:

View file

@ -1,8 +1,9 @@
@import "app/styles/mixins"
$itemSlotSize: 55px
$itemSlotSize: 48px
$itemSlotInnerWidth: $itemSlotSize - 4
$itemSlotGridHeight: 70px
$itemSlotGridWidth: 51px
$itemSlotGridHeight: 51px
.ui-effects-transfer
outline: 2px solid #28f
@ -83,15 +84,6 @@ $itemSlotGridHeight: 70px
height: 450px
overflow: hidden
#hero-image
@include filter(contrast(0%) brightness(0%))
opacity: 0.4
width: 225px
height: 410px
position: absolute
left: 10px
top: 20px
.item-slot
width: $itemSlotSize
height: $itemSlotSize
@ -101,6 +93,7 @@ $itemSlotGridHeight: 70px
position: relative
cursor: pointer
@include transition(0.5s ease)
z-index: 20
//&.disabled
// opacity: 0.5
@ -134,36 +127,36 @@ $itemSlotGridHeight: 70px
background-image: url(/images/pages/game-menu/slot-icons.png)
// A terrible awful bit of styling, but will be gone or messed around with soon anyway
// Positioning the slots manually
&[data-slot]
position: absolute
top: 10px
left: 10px
&[data-slot="misc-1"]
display: none // hiding for now
position: absolute
left: 250px
top: 20px + ($itemSlotGridHeight * 3)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 3)
.placeholder
background-position: (-0 * $itemSlotInnerWidth) 0px
&[data-slot="misc-0"]
display: none // hiding for now
position: absolute
left: 250px
top: 20px + ($itemSlotGridHeight * 2)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 2)
.placeholder
background-position: (-4 * $itemSlotInnerWidth) 0px
&[data-slot="minion"]
position: absolute
left: 250px
top: 20px + ($itemSlotGridHeight * 1)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 0)
.placeholder
background-position: (-1 * $itemSlotInnerWidth) 0px
&[data-slot="programming-book"]
position: absolute
left: 250px
top: 20px + ($itemSlotGridHeight * 4)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 0)
.placeholder
background-position: (-3 * $itemSlotInnerWidth) 0px
@ -172,100 +165,86 @@ $itemSlotGridHeight: 70px
// background-position: (-2 * $itemSlotInnerWidth) 0px
&[data-slot="wrists"]
position: absolute
left: 20px
top: 20px + ($itemSlotGridHeight * 2.5)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 0)
.placeholder
background-position: (-5 * $itemSlotInnerWidth) 0px
&[data-slot="left-ring"]
position: absolute
left: 250px
top: 20px + ($itemSlotGridHeight * 2)
left: 10px + ($itemSlotGridWidth * 4)
top: 15px + ($itemSlotGridHeight * 0)
.placeholder
background-position: (-6 * $itemSlotInnerWidth) 0px
&[data-slot="right-ring"]
position: absolute
left: 250px
top: 20px + ($itemSlotGridHeight * 3)
left: 10px + ($itemSlotGridWidth * 1)
top: 15px + ($itemSlotGridHeight * 0)
.placeholder
background-position: (-7 * $itemSlotInnerWidth) 0px
&[data-slot="torso"]
position: absolute
left: 90px
top: 20px + ($itemSlotGridHeight * 3)
left: 10px + ($itemSlotGridWidth * 5)
top: 15px + ($itemSlotGridHeight * 2)
.placeholder
background-position: (-8 * $itemSlotInnerWidth) 0px
&[data-slot="feet"]
position: absolute
left: 90px
top: 20px + ($itemSlotGridHeight * 5)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 7.2)
.placeholder
background-position: (-9 * $itemSlotInnerWidth) 0px
&[data-slot="neck"]
position: absolute
left: 90px
top: 20px + ($itemSlotGridHeight * 2)
left: 10px + ($itemSlotGridWidth * 3)
top: 15px + ($itemSlotGridHeight * 0)
.placeholder
background-position: (-10 * $itemSlotInnerWidth) 0px
&[data-slot="waist"]
position: absolute
left: 90px
top: 20px + ($itemSlotGridHeight * 4)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 1)
.placeholder
background-position: (-11 * $itemSlotInnerWidth) 0px
&[data-slot="eyes"]
position: absolute
left: 90px
top: 20px + $itemSlotGridHeight
left: 10px + ($itemSlotGridWidth * 2)
top: 15px + ($itemSlotGridHeight * 0)
.placeholder
background-position: (-12 * $itemSlotInnerWidth) 0px
&[data-slot="head"]
position: absolute
left: 90px
top: 20px
left: 10px + ($itemSlotGridWidth * 5)
top: 15px + ($itemSlotGridHeight * 1)
.placeholder
background-position: (-13 * $itemSlotInnerWidth) 0px
&[data-slot="pet"]
position: absolute
left: 250px
top: 20px
left: 10px + ($itemSlotGridWidth * 5)
top: 15px + ($itemSlotGridHeight * 7.2)
.placeholder
background-position: (-14 * $itemSlotInnerWidth) 0px
&[data-slot="gloves"]
position: absolute
left: 160px
top: 20px + ($itemSlotGridHeight * 2.5)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 2)
.placeholder
background-position: (-15 * $itemSlotInnerWidth) 0px
&[data-slot="left-hand"]
position: absolute
left: 160px
top: 20px + ($itemSlotGridHeight * 3.5)
left: 10px + ($itemSlotGridWidth * 5)
top: 15px + ($itemSlotGridHeight * 3)
.placeholder
background-position: (-16 * $itemSlotInnerWidth) 0px
&[data-slot="right-hand"]
position: absolute
left: 20px
top: 20px + ($itemSlotGridHeight * 3.5)
left: 10px + ($itemSlotGridWidth * 0)
top: 15px + ($itemSlotGridHeight * 3)
.placeholder
background-position: (-17 * $itemSlotInnerWidth) 0px
&[data-slot="flag"]
position: absolute
left: 250px
top: 20px + ($itemSlotGridHeight * 5)
left: 10px + ($itemSlotGridWidth * 5)
top: 15px + ($itemSlotGridHeight * 0)
.placeholder
background-position: (-2 * $itemSlotInnerWidth) 0px
@ -498,3 +477,130 @@ $itemSlotGridHeight: 70px
#equip-item-viewed
background: rgb(84,128,44)
color: white
//- Paper doll positioning
#hero-image
//@include filter(contrast(0%) brightness(0%))
//opacity: 0.4
//width: 225px
display: block
position: absolute
z-index: 12
&.male
left: 65px
bottom: 31px
&.female
left: 80px
bottom: 31px
#hero-image-hair
position: absolute
z-index: 16
&.female
left: 103px
bottom: 218px
&.male
left: 124px
bottom: 228px
#hero-image-thumb
position: absolute
z-index: 16
&.female
left: 81px
bottom: 150px
@include rotate(-15deg)
&.male
left: 68px
bottom: 121px
@include rotate(-15deg)
.doll-image
position: absolute
z-index: 15
&.feet
z-index: 13
&.female
left: 101px
bottom: 37px
&.male
left: 98px
bottom: 37px
&.right-hand
&.female
left: 48px
bottom: 132px
@include rotate(-15deg)
&.male
left: 40px
bottom: 111px
@include rotate(-15deg)
&.left-hand
z-index: 17
&.female
left: 193px
bottom: 72px
&.male
left: 193px
bottom: 72px
&.torso
z-index: 14
&.female
left: 72px
bottom: 105px
&.male
left: 55px
bottom: 69px
&.gloves
z-index: 15
&.female
left: 78px
bottom: 133px
&.female-thumb
z-index: 16
left: 81px
bottom: 150px
@include rotate(-15deg)
&.male
left: 65px
bottom: 109px
&.male-thumb
z-index: 16
left: 68px
bottom: 121px
@include rotate(-15deg)
&.head
z-index: 16
&.female
left: 72px
bottom: 105px
&.male
left: 119px
bottom: 180px

View file

@ -70,3 +70,15 @@
.alert
top: 213px
border: 5px solid darkred
&.hour-of-code
#site-footer
background-color: rgb(70, 58, 44)
height: 185px
.hour-of-code-explanation
color: #9e8777
text-align: center
a
color: lighten(#0b63bc, 10%)

View file

@ -231,6 +231,23 @@
width: calc(33.333333% - 10px)
margin: 5px
.hour-of-code-done
clear: both
padding-top: 10px
strong
color: white
display: block
margin-bottom: 10px
font-weight: normal
.image-link
float: right
margin-left: 10px
.text-link
color: lighten(#0b63bc, 10%)
html.no-borderimage
#hero-victory-modal

View file

@ -86,3 +86,5 @@ block footer
a(href="http://www.fullyillustrated.com/") Fully Illustrated
a.firebase-bade(href="https://www.firebase.com/")
img(src="/images/pages/base/firebase.png", alt="Powered by Firebase")
block extra_footer_content

View file

@ -26,7 +26,7 @@ block content
p
span(data-i18n="community.thang_editor_prefix") We call units within the game 'thangs'. Use the
a.spl.spr(href="/editor/thang", data-i18n="editor.thang_title")
span(data-i18n="community.level_editor_suffix") to modify the CodeCombat source artwork. Allow units to throw projectiles, alter the direction of an animation, change a unit's hit points, or upload your own vector sprites.
span(data-i18n="community.thang_editor_suffix") to modify the CodeCombat source artwork. Allow units to throw projectiles, alter the direction of an animation, change a unit's hit points, or upload your own vector sprites.
.community-columns
a(href="/editor/article")

View file

@ -10,7 +10,11 @@
#equipped
if selectedHero && selectedHero.get('featureImage')
img(src="/file/"+selectedHero.get('featureImage'))#hero-image
img(src="/file/"+selectedHero.get('featureImage'), draggable="false")#hero-image
if selectedHero.get('featureImageHair')
img(src="/file/"+selectedHero.get('featureImageHair'), draggable="false")#hero-image-hair
if selectedHero.get('featureImageThumb')
img(src="/file/"+selectedHero.get('featureImageThumb'), draggable="false")#hero-image-thumb
for slot in ['head', 'eyes', 'neck', 'torso', 'gloves', 'wrists', 'left-hand', 'right-hand', 'waist', 'feet', 'left-ring', 'right-ring', 'minion', 'flag', 'pet', 'programming-book', 'misc-0', 'misc-1']
.item-slot(data-slot=slot)

View file

@ -22,4 +22,13 @@ block outer_content
strong(data-i18n="home.old_browser") Uh oh, your browser is too old to run CodeCombat. Sorry!
br
span(data-i18n="home.old_browser_suffix") You can try anyway, but it probably won't work.
block extra_footer_content
if true || explainHourOfCode
// Does not show up unless lang is en-US.
div.hour-of-code-explanation
| The 'Hour of Code' is a nationwide initiative by
a(href="http://csedweek.org") Computer Science Education Week
| and
a(href="http://code.org") Code.org
| to introduce millions of students to one hour of computer science and computer programming.

View file

@ -37,11 +37,3 @@
#play-footer
p(class='footer-link-text')
a(title='Send CodeCombat a message', tabindex=-1, data-toggle="coco-modal", data-target="modal/ContactModal", data-i18n="nav.contact") Contact
if explainHourOfCode
// Does not show up unless lang is en-US.
div.hour-of-code-explanation
| The 'Hour of Code' is a nationwide initiative by
a(href="http://csedweek.org") Computer Science Education Week
| and
a(href="http://code.org") Code.org
| to introduce millions of students to one hour of computer science and computer programming.

View file

@ -69,3 +69,12 @@ block modal-footer-content
button.btn.btn-primary.return-to-ladder-button(data-href="/play/ladder/#{level.get('slug')}#my-matches", data-dismiss="modal", data-i18n="play_level.victory_return_to_ladder") Return to Ladder
else
button.btn.btn-success.world-map-button.next-level-button.hide#continue-button(data-i18n="play_level.victory_play_continue") Continue
if showHourOfCodeDoneButton
.hour-of-code-done
hr
a.image-link(href="http://code.org/api/hour/finish")
img(src="/images/level/csedweek-logo-final-small.jpg", alt="CS Ed Week Hour of Code", title="I'm finished with my Hour of Code", width=80)
strong(data-i18n="play_level.victory_hour_of_code_done") Are You Done?
a.text-link(href="http://code.org/api/hour/finish")
span(data-i18n="play_level.victory_hour_of_code_done_yes") Yes, I'm finished with my Hour of Code!

View file

@ -1,34 +0,0 @@
RootView = require 'views/kinds/RootView'
template = require 'templates/front-view'
{me} = require '/lib/auth'
ModalView = require 'views/kinds/ModalView'
module.exports = class FrontView extends RootView
id: 'front-view'
template: template
events:
'click .platform-ios a': 'onIOSClicked'
getRenderData: ->
c = super()
if $.browser
majorVersion = $.browser.versionNumber
c.isOldBrowser = true if $.browser.mozilla && majorVersion < 21
c.isOldBrowser = true if $.browser.chrome && majorVersion < 17
c.isOldBrowser = true if $.browser.safari && majorVersion < 6
else
console.warn 'no more jquery browser version...'
c
afterRender: ->
super()
onIOSClicked: (e) ->
header = 'Sorry, the iPad app isn\'t ready yet'
body = '''
<p class="lead">We are working on it!</p>
<p>For now, try playing on the web, and totally sign up (with emails enabled) so you can be the first to hear when it is ready.</p>
'''
notImplementedModal = new ModalView headerContent: header, bodyContent: body
@openModalView notImplementedModal

View file

@ -16,6 +16,12 @@ module.exports = class HomeView extends RootView
constructor: ->
super()
window.tracker?.trackEvent 'Homepage', Action: 'Loaded'
if not me.get('hourOfCode') and @getQueryVariable 'hour_of_code'
@setUpHourOfCode()
elapsed = (new Date() - new Date(me.get('dateCreated')))
if me.get('hourOfCode') and elapsed < 86400 * 1000 and me.get('preferredLanguage', true) is 'en-US'
# Show the Hour of Code footer explanation in English until it's been more than a day
@explainsHourOfCode = true
getRenderData: ->
c = super()
@ -28,6 +34,7 @@ module.exports = class HomeView extends RootView
console.warn 'no more jquery browser version...'
c.isEnglish = (me.get('preferredLanguage') or 'en').startsWith 'en'
c.languageName = me.get('preferredLanguage')
c.explainsHourOfCode = @explainsHourOfCode
c
onClickBeginnerCampaign: (e) ->
@ -39,3 +46,17 @@ module.exports = class HomeView extends RootView
afterInsert: ->
super(arguments...)
@$el.addClass 'hour-of-code' if @explainsHourOfCode
if me.isAdmin() and me.get('slug') is 'nick'
LevelSetupManager = require 'lib/LevelSetupManager'
setupManager = new LevelSetupManager levelID: 'dungeons-of-kithgard', hadEverChosenHero: true, parent: @
setupManager.open()
setUpHourOfCode: ->
elapsed = (new Date() - new Date(me.get('dateCreated')))
if elapsed < 5 * 60 * 1000
me.set 'hourOfCode', true
me.patch()
# We may also insert the tracking pixel for everyone on the WorldMapView so as to count directly-linked visitors.
$('body').append($('<img src="http://code.org/api/hour/begin_codecombat.png" style="visibility: hidden;">'))
application.tracker?.trackEvent 'Hour of Code Begin', {}

View file

@ -76,7 +76,7 @@ module.exports = class DiplomatView extends ContributeClassView
bg: [] # български език, Bulgarian
no: ['bardeh', 'torehaug'] # Norsk, Norwegian
nn: [] # Norwegian (Nynorsk), Norwegian Nynorsk
nb: ['mcclane654'] # Norsk Bokmål, Norwegian (Bokmål)
nb: ['ebirkenes','mcclane654'] # Norsk Bokmål, Norwegian (Bokmål)
he: ['OverProgram', 'monetita'] # עברית, Hebrew
lt: [] # lietuvių kalba, Lithuanian
sr: [] # српски, Serbian

View file

@ -54,6 +54,7 @@ module.exports = class InventoryModal extends ModalView
'components'
'original'
'rasterIcon'
'dollImages'
'gems'
'tier'
'description'
@ -144,6 +145,7 @@ module.exports = class InventoryModal extends ModalView
@canvasHeight = @$el.find('canvas').innerHeight()
@inserted = true
@requireLevelEquipment()
@onEquipmentChanged()
#- Draggable logic
@ -269,6 +271,7 @@ module.exports = class InventoryModal extends ModalView
@makeEquippedSlotDraggable slotEl
@requireLevelEquipment()
@onSelectionChanged()
@onEquipmentChanged()
unequipSelectedItem: ->
slotEl = @getSelectedSlot()
@ -283,7 +286,7 @@ module.exports = class InventoryModal extends ModalView
@showItemDetails(item, 'equip')
@requireLevelEquipment()
@onSelectionChanged()
@onEquipmentChanged()
#- Select/equip helpers
@ -399,6 +402,7 @@ module.exports = class InventoryModal extends ModalView
@$el.removeClass('Warrior Ranger Wizard').addClass(@selectedHero.get('heroClass'))
@requireLevelEquipment()
@render()
@onEquipmentChanged()
onShown: ->
# Called when we switch tabs to this within the modal
@ -515,13 +519,56 @@ module.exports = class InventoryModal extends ModalView
return if @destroyed
@$el.find('.unlock-button').popover 'destroy'
#- Paper doll equipment updating
onEquipmentChanged: ->
@removeDollImages()
heroClass = @selectedHero?.get('heroClass') ? 'Warrior'
gender = if @selectedHero?.get('slug') in heroGenders.male then 'male' else 'female'
equipment = @getCurrentEquipmentConfig()
slotsWithImages = []
for slot, original of equipment
item = _.find @items.models, (item) -> item.get('original') is original
continue unless dollImages = item?.get('dollImages')
didAdd = @addDollImage slot, dollImages, heroClass, gender
slotsWithImages.push slot if didAdd
@$el.find('#hero-image, #hero-image-hair, #hero-image-thumb').removeClass().addClass "#{gender} #{heroClass}"
@$el.find('#hero-image-hair').toggle not ('head' in slotsWithImages)
@$el.find('#hero-image-thumb').toggle not ('gloves' in slotsWithImages)
removeDollImages: ->
@$el.find('.doll-image').remove()
addDollImage: (slot, dollImages, heroClass, gender) ->
heroClass = @selectedHero?.get('heroClass') ? 'Warrior'
gender = if @selectedHero?.get('slug') in heroGenders.male then 'male' else 'female'
didAdd = false
if slot is 'gloves'
if heroClass is 'Ranger'
imageKeys = ["#{gender}#{heroClass}", "#{gender}#{heroClass}Thumb"]
else
imageKeys = ["#{gender}", "#{gender}Thumb"]
else
imageKeys = [gender]
for imageKey in imageKeys
imageURL = dollImages[imageKey]
if not imageURL
console.log "Hmm, should have #{slot} #{imageKey} paper doll image, but don't have it."
else
imageEl = $('<img>').attr('src', "/file/#{imageURL}").addClass("doll-image #{slot} #{heroClass} #{gender} #{_.string.underscored(imageKey).replace(/_/g, '-')}").attr('draggable', false)
@$el.find('#equipped').append imageEl
didAdd = true
didAdd
destroy: ->
@$el.find('.unlock-button').popover 'destroy'
@stage?.removeAllChildren()
super()
heroGenders =
male: ['knight', 'samurai', 'trapper', 'potion-master']
female: ['captain', 'ninja', 'forest-archer', 'librarian', 'sorcerer']
gear =
'simple-boots': '53e237bf53457600003e3f05'

View file

@ -319,6 +319,13 @@ playerCreated = [
image: '/file/db/level/526711d9add4f8965f000002/hunter_triplets_icon.png'
description: 'There is a horde of ogres marching on your village. Stay out of reach and use your bow to take them out! - by Danny Whittaker'
}
{
name: "IFC - Videira"
difficulty: 3
id: 'ifc-videira'
image: '/file/db/level/52602ecb026e8481e7000001/generic_1.png'
description: 'A level inspired by IFC Videira. - by Leonardo Meneguzzi.'
}
]
campaigns = [

View file

@ -10,6 +10,8 @@ MusicPlayer = require 'lib/surface/MusicPlayer'
storage = require 'lib/storage'
AuthModal = require 'views/modal/AuthModal'
trackedHourOfCode = false
class LevelSessionsCollection extends CocoCollection
url: ''
model: LevelSession
@ -70,6 +72,12 @@ module.exports = class WorldMapView extends RootView
@listenTo me, 'change:spent', -> @renderSelectors('#gems-count')
window.tracker?.trackEvent 'World Map', Action: 'Loaded', ['Google Analytics']
# If it's a new player who didn't appear to come from Hour of Code, we register her here without setting the hourOfCode property.
elapsed = (new Date() - new Date(me.get('dateCreated')))
if not trackedHourOfCode and not me.get('hourOfCode') and elapsed < 5 * 60 * 1000
$('body').append($('<img src="http://code.org/api/hour/begin_codecombat.png" style="visibility: hidden;">'))
trackedHourOfCode = true
destroy: ->
@setupManager?.destroy()
$(window).off 'resize', @onWindowResize

View file

@ -93,8 +93,6 @@ module.exports = class PlayLevelView extends RootView
constructor: (options, @levelID) ->
console.profile?() if PROFILE_ME
super options
if not me.get('hourOfCode') and @getQueryVariable 'hour_of_code'
@setUpHourOfCode()
@isEditorPreview = @getQueryVariable 'dev'
@sessionID = @getQueryVariable 'session'
@ -114,12 +112,6 @@ module.exports = class PlayLevelView extends RootView
@load()
application.tracker?.trackEvent 'Started Level Load', level: @levelID, label: @levelID, ['Google Analytics']
setUpHourOfCode: ->
me.set 'hourOfCode', true
me.patch()
$('body').append($('<img src="http://code.org/api/hour/begin_codecombat.png" style="visibility: hidden;">'))
application.tracker?.trackEvent 'Hour of Code Begin', {}
setLevel: (@level, givenSupermodel) ->
@supermodel.models = givenSupermodel.models
@supermodel.collections = givenSupermodel.collections
@ -152,10 +144,6 @@ module.exports = class PlayLevelView extends RootView
getRenderData: ->
c = super()
c.world = @world
if me.get('hourOfCode') and me.get('preferredLanguage', true) is 'en-US'
# Show the Hour of Code footer explanation until it's been more than a day
elapsed = (new Date() - new Date(me.get('dateCreated')))
c.explainHourOfCode = elapsed < 86400 * 1000
c
afterRender: ->
@ -606,7 +594,7 @@ module.exports = class PlayLevelView extends RootView
# Current real-time multiplayer session
# Internal multiplayer create/joined/left events
#
# Real-time state variables.
# Real-time state variables.
# Each Ref is Firebase reference, and may have a matching Data suffixed variable with the latest data received.
# @realTimePlayerRef - User's real-time multiplayer player for this level
# @realTimePlayerGameRef - User's current real-time multiplayer player game session
@ -727,7 +715,7 @@ module.exports = class PlayLevelView extends RootView
@realTimeSessionRef = new Firebase "#{@multiplayerFireHost}multiplayer_level_sessions/#{@levelID}/#{e.realTimeSessionID}"
@realTimePlayersRef = @realTimeSessionRef.child 'players'
# Look for opponent
@realTimeSessionRef.once 'value', (multiplayerSessionSnapshot) =>
if @realTimeSessionData = multiplayerSessionSnapshot.val()
@ -751,7 +739,7 @@ module.exports = class PlayLevelView extends RootView
console.error 'Could not lookup multiplayer session data.'
@realTimeSessionRef.on 'value', @onRealTimeSessionChanged
@realTimePlayerGameRef = @realTimeSessionRef.child "players/#{me.id}"
@realTimePlayerGameRef = @realTimeSessionRef.child "players/#{me.id}"
# TODO: Follow up in MultiplayerView to see if double joins can be avoided
# else
@ -817,7 +805,7 @@ module.exports = class PlayLevelView extends RootView
unless @realTimeSessionRef?
console.error 'Real-time multiplayer cast without multiplayer session.'
return
unless @realTimeSessionData?
unless @realTimeSessionData?
console.error 'Real-time multiplayer cast without multiplayer data.'
return
unless @realTimePlayersData?

View file

@ -80,7 +80,7 @@ module.exports = class HeroVictoryModal extends ModalView
@readyToContinue = true
@updateSavingProgressStatus()
me.fetch() unless me.loading
@readyToContinue = true if not @achievements.models.length
getRenderData: ->
@ -117,6 +117,23 @@ module.exports = class HeroVictoryModal extends ModalView
{key: 'continue', link: @continueLevelLink, 'choice-explicit': 'next_level', 'choice-implicit': 'just_right'}
{key: 'more_practice', link: @morePracticeLevelLink, 'choice-explicit': 'more_practice', 'choice-implicit': 'too_hard'}
]
elapsed = (new Date() - new Date(me.get('dateCreated')))
isHourOfCode = me.get('hourOfCode') or elapsed < 120 * 60 * 1000
# Later we should only check me.get('hourOfCode'), but for now so much traffic comes in that we just assume it.
if isHourOfCode
# Show the Hour of Code "I'm Done" tracking pixel after they played for 20 minutes
enough = elapsed >= 20 * 60 * 1000
tooMuch = elapsed > 120 * 60 * 1000
showDone = elapsed >= 30 * 60 * 1000 and not tooMuch
if enough and not tooMuch and not me.get('hourOfCodeComplete')
$('body').append($('<img src="http://code.org/api/hour/finish_codecombat.png" style="visibility: hidden;">'))
me.set 'hourOfCodeComplete', true # Note that this will track even for players who don't have hourOfCode set.
me.patch()
window.tracker?.trackEvent 'Hour of Code Finish', {}
# Show the "I'm done" button between 30 - 120 minutes if they definitely came from Hour of Code
c.showHourOfCodeDoneButton = me.get('hourOfCode') and showDone
return c
afterRender: ->

View file

@ -35,7 +35,7 @@ module.exports = class PlayHeroesModal extends ModalView
@confirmButtonI18N = options.confirmButtonI18N ? "common.save"
@heroes = new CocoCollection([], {model: ThangType})
@heroes.url = '/db/thang.type?view=heroes'
@heroes.setProjection ['original','name','slug','soundTriggers','featureImage','gems','heroClass','description','components','extendedName','unlockLevelName','i18n']
@heroes.setProjection ['original','name','slug','soundTriggers','featureImage','featureImageHair','featureImageThumb','gems','heroClass','description','components','extendedName','unlockLevelName','i18n']
@heroes.comparator = 'gems'
@listenToOnce @heroes, 'sync', @onHeroesLoaded
@supermodel.loadCollection(@heroes, 'heroes')

View file

@ -23,6 +23,9 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
'raster'
'rasterIcon'
'featureImage'
'featureImageHair'
'featureImageThumb'
'dollImages'
'spriteType'
'i18nCoverage'
'i18n'

View file

@ -271,7 +271,7 @@ PaymentHandler = class PaymentHandler extends Handler
sendPaymentHipChatMessage: (options) ->
try
message = "#{options.user?.get('name')} bought #{options.payment?.get('amount')} via #{options.payment?.get('service'}."
message = "#{options.user?.get('name')} bought #{options.payment?.get('amount')} via #{options.payment?.get('service')}."
hipchat.sendHipChatMessage message
catch e
log.error "Couldn't send HipChat message on payment because of error: #{e}"