Path: blob/master/Sonic 1/Scripts/GHZ/Eggman.txt
1480 views
// ----------------------------------1// RSDK Project: Sonic 12// Script Description: GHZ Eggman Object3// Script Author: Christian Whitehead/Simon Thomley4// Unpacked by Rubberduckycooly's script unpacker5// ----------------------------------67// Using GHZEggman as a prefix here because there's like 6 "Eggman" objects in the game so its less confusing this way89// ========================10// Aliases11// ========================1213private alias object.value0 : object.timer14private alias object.value1 : object.health15private alias object.value2 : object.arenaBorder16private alias object.value3 : object.oscillatePos17private alias object.value4 : object.originY18private alias object.value5 : object.arenaOffset19private alias object.value6 : object.ballPos20private alias object.value7 : object.lightPos2122// object[-1] (WreckingBall) Aliases,23// this object is structured like a v3 one so these are all used here instead of in WreckingBall24private alias object.value1 : object.initialMoveVel25private alias object.value2 : object.moveVelocity26private alias object.value3 : object.arenaSize27private alias object.value4 : object.invincibilityTimer28private alias object.value5 : object.gravityStrength29private alias object.value6 : object.flameAnim30private alias object.value7 : object.flameAnimTimer3132// Player Aliases33private alias object.value40 : player.hitboxLeft34private alias object.value38 : player.hitboxTop35private alias object.value41 : player.hitboxRight36private alias object.value39 : player.hitboxBottom3738// Eggman States39private alias 0 : GHZEGGMAN_AWAITPLAYER40private alias 1 : GHZEGGMAN_ENTEREGGMAN41private alias 2 : GHZEGGMAN_MOVEINTOPLACE42private alias 3 : GHZEGGMAN_LOWERBALL43private alias 4 : GHZEGGMAN_INITIALSWING44private alias 5 : GHZEGGMAN_MOVERIGHT45private alias 6 : GHZEGGMAN_MOVELEFT46private alias 7 : GHZEGGMAN_EXPLODE47private alias 8 : GHZEGGMAN_DEFEATFALL48private alias 9 : GHZEGGMAN_DEFEATRISE49private alias 10 : GHZEGGMAN_FLEE50private alias 11 : GHZEGGMAN_ESCAPE5152// Wrecking Ball States53private alias 0 : WRECKINGBALL_INACTIVE54private alias 1 : WRECKINGBALL_ACTIVE55private alias 2 : WRECKINGBALL_EXPLODE5657// Eggman Animations58private alias 0 : GHZEGGANI_INVISIBLE59private alias 1 : GHZEGGANI_IDLE60private alias 2 : GHZEGGANI_LAUGH61private alias 3 : GHZEGGANI_HIT62private alias 4 : GHZEGGANI_DEFEATED63private alias 5 : GHZEGGANI_TOASTED64private alias 6 : GHZEGGANI_PANIC6566// Flame Animations67private alias 0 : FLAME_INACTIVE68private alias 1 : FLAME_ACTIVE69private alias 2 : FLAME_EXPLODE7071// Player Aliases72private alias object.xpos : player.xpos73private alias object.xvel : player.xvel74private alias object.speed: player.speed75private alias object.animation : player.animation76private alias object.collisionRight : player.collisionRight7778// Music Events79private alias 26 : SLOT_MUSICEVENT_BOSS8081private alias 0 : MUSICEVENT_FADETOBOSS82private alias 1 : MUSICEVENT_FADETOSTAGE83private alias 2 : MUSICEVENT_TRANSITION848586// ========================87// Function Declarations88// ========================8990reserve function GHZEggman_Oscillate91reserve function GHZEggman_FlyAway92reserve function GHZEggman_SwingBall939495// ========================96// Function Definitions97// ========================9899private function GHZEggman_Oscillate100object.rotation += 2101object.rotation &= 511102temp0 = object.rotation103temp0 <<= 1104temp0 += 128105Sin(object.ypos, temp0)106object.ypos <<= 9107object.ypos += object.originY108end function109110111private function GHZEggman_FlyAway112object.rotation += 4113object.rotation &= 511114Sin(object.ypos, object.rotation)115object.ypos <<= 9116object.ypos += object.oscillatePos117end function118119120private function GHZEggman_SwingBall121// Lights122object[-6].xpos = object.xpos123object[-6].ypos = object.ypos124object[-6].ypos += object.lightPos125Sin(temp1, object.rotation)126temp1 >>= 2127temp1 += 128128129// Chain 1130temp0 = 16131Cos(object[-5].xpos, temp1)132object[-5].xpos *= temp0133object[-5].xpos <<= 7134object[-5].xpos += object[-6].xpos135Sin(object[-5].ypos, temp1)136object[-5].ypos *= temp0137object[-5].ypos <<= 7138object[-5].ypos += object[-6].ypos139140// Chain 2141temp0 += 16142Cos(object[-4].xpos, temp1)143object[-4].xpos *= temp0144object[-4].xpos <<= 7145object[-4].xpos += object[-6].xpos146Sin(object[-4].ypos, temp1)147object[-4].ypos *= temp0148object[-4].ypos <<= 7149object[-4].ypos += object[-6].ypos150151// Chain 3152temp0 += 16153Cos(object[-3].xpos, temp1)154object[-3].xpos *= temp0155object[-3].xpos <<= 7156object[-3].xpos += object[-6].xpos157Sin(object[-3].ypos, temp1)158object[-3].ypos *= temp0159object[-3].ypos <<= 7160object[-3].ypos += object[-6].ypos161162// Chain 4163temp0 += 16164Cos(object[-2].xpos, temp1)165object[-2].xpos *= temp0166object[-2].xpos <<= 7167object[-2].xpos += object[-6].xpos168Sin(object[-2].ypos, temp1)169object[-2].ypos *= temp0170object[-2].ypos <<= 7171object[-2].ypos += object[-6].ypos172173// Ball174temp0 += 32175Cos(object[-1].xpos, temp1)176object[-1].xpos *= temp0177object[-1].xpos <<= 7178object[-1].xpos += object[-6].xpos179Sin(object[-1].ypos, temp1)180object[-1].ypos *= temp0181object[-1].ypos <<= 7182object[-1].ypos += object[-6].ypos183object[-1].rotation = temp1184185if object.rotation >= 0x100186object.direction = FLIP_NONE187else188object.direction = FLIP_X189end if190end function191192193// ========================194// Events195// ========================196197event ObjectUpdate198switch object.state199case GHZEGGMAN_AWAITPLAYER200temp0 = object[-1].ixpos201temp0 -= screen.xcenter202stage.newXBoundary1 = temp0203204temp0 = object[-1].ixpos205temp0 += screen.xcenter206stage.newXBoundary2 = temp0207208temp0 = object.iypos209temp0 += 64210if screen.yoffset > temp0211if player[0].xpos > object[-1].xpos212object.animation = GHZEGGANI_IDLE213#platform: USE_ORIGINS214if game.bossOneLife == false215object.health = 8216else217object.health = 1218end if219#endplatform220#platform: USE_STANDALONE221object.health = 8222#endplatform223ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOBOSS, 0, 0)224object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE225object.state++226end if227end if228break229230case GHZEGGMAN_ENTEREGGMAN231object.ypos += 0x10000232if object.ypos >= object.oscillatePos233object.ypos = object.oscillatePos234object.timer = 96235object[-1].flameAnim = FLAME_ACTIVE236object.state++237end if238break239240case GHZEGGMAN_MOVEINTOPLACE241if object.timer > 0242object.timer--243object.xpos = object.timer244object.xpos <<= 16245object.xpos += object[-1].xpos246temp0 = object.timer247temp0 <<= 7248temp0 /= 96249Cos(object.ypos, temp0)250object.ypos *= -0xB00251object.ypos += object.oscillatePos252else253object.xpos = object[-1].xpos254object.arenaBorder = object[-1].xpos255object.ypos = object.originY256object.originY -= 0x40000257object.state++258object[-1].type = TypeName[Wrecking Ball]259object[-1].ypos = object.ypos260object[-6].type = TypeName[Boss Lights]261object[-6].ypos = object.ypos262object.animation = GHZEGGANI_LAUGH263object[-1].flameAnim = FLAME_INACTIVE264end if265break266267case GHZEGGMAN_LOWERBALL268if object.ballPos < 0x7C0000269CallFunction(GHZEggman_Oscillate)270271object.ballPos += 0x10000272if object.lightPos < 0x1C0000273object.lightPos += 0x8000274end if275276if object.ballPos > 0x2C0000277object[-5].type = TypeName[Boss Chain]278end if279280if object.ballPos > 0x3C0000281object[-4].type = TypeName[Boss Chain]282end if283284if object.ballPos > 0x4C0000285object[-3].type = TypeName[Boss Chain]286end if287288if object.ballPos > 0x5C0000289object[-2].type = TypeName[Boss Chain]290end if291292// Ball293object[-1].ypos = object.ypos294object[-1].ypos += object.ballPos295296// Lights297object[-6].ypos = object.ypos298object[-6].ypos += object.lightPos299300// Chain 1301object[-5].ypos = object[-6].ypos302object[-5].ypos += 0x100000303304// Chain 2305object[-4].ypos = object[-5].ypos306object[-4].ypos += 0x100000307308// Chain 3309object[-3].ypos = object[-4].ypos310object[-3].ypos += 0x100000311312// Chain 4313object[-2].ypos = object[-3].ypos314object[-2].ypos += 0x100000315316object.animationTimer %= 10317else318object.rotation = 256319CallFunction(GHZEggman_Oscillate)320CallFunction(GHZEggman_SwingBall)321object[-1].initialMoveVel = object.arenaOffset322object[-1].initialMoveVel >>= 2323object[-1].moveVelocity = object.arenaOffset324object[-1].arenaSize = object.arenaOffset325object[-1].arenaSize *= 64326temp0 = object[-1].arenaSize327temp0 >>= 1328object.arenaBorder -= temp0329object.state++330object.animation = GHZEGGANI_IDLE331object[-1].flameAnim = FLAME_ACTIVE332object[-1].state = WRECKINGBALL_ACTIVE333end if334break335336case GHZEGGMAN_INITIALSWING337CallFunction(GHZEggman_Oscillate)338CallFunction(GHZEggman_SwingBall)339if object.xpos > object.arenaBorder340object.xpos -= object[-1].initialMoveVel341if object.xpos < object.arenaBorder342object.xpos = object.arenaBorder343end if344else345object[-1].flameAnim = FLAME_INACTIVE346object.arenaBorder += object[-1].arenaSize347object.state++348end if349break350351case GHZEGGMAN_MOVERIGHT352CallFunction(GHZEggman_Oscillate)353CallFunction(GHZEggman_SwingBall)354if object.xpos < object.arenaBorder355if object.rotation >= 128356object[-1].flameAnim = FLAME_ACTIVE357object.xpos += object[-1].moveVelocity358if object.xpos > object.arenaBorder359object.xpos = object.arenaBorder360end if361end if362else363object[-1].flameAnim = FLAME_INACTIVE364object.arenaBorder -= object[-1].arenaSize365object.state++366end if367break368369case GHZEGGMAN_MOVELEFT370CallFunction(GHZEggman_Oscillate)371CallFunction(GHZEggman_SwingBall)372if object.xpos > object.arenaBorder373if object.rotation >= 384374object[-1].flameAnim = FLAME_ACTIVE375object.xpos -= object[-1].moveVelocity376if object.xpos < object.arenaBorder377object.xpos = object.arenaBorder378end if379end if380else381object[-1].flameAnim = FLAME_INACTIVE382object.arenaBorder += object[-1].arenaSize383object.state--384end if385break386387case GHZEGGMAN_EXPLODE388object.timer++389temp0 = object.timer390temp0 &= 7391if temp0 == 4392Rand(temp0, 96)393temp0 -= 48394temp0 <<= 16395temp0 += object.xpos396Rand(temp1, 48)397temp1 -= 24398temp1 <<= 16399temp1 += object.ypos400CreateTempObject(TypeName[Explosion], 0, temp0, temp1)401PlaySfx(SfxName[Explosion], false)402end if403404if object.timer == 180405object.animation = GHZEGGANI_TOASTED406object.animationTimer = 0407object.timer = 0408object.direction = FLIP_X409ResetObjectEntity(SLOT_MUSICEVENT_BOSS, TypeName[Music Event], MUSICEVENT_FADETOSTAGE, 0, 0)410object[SLOT_MUSICEVENT_BOSS].priority = PRIORITY_ACTIVE411object.state++412end if413break414415case GHZEGGMAN_DEFEATFALL416object.ypos += object[-1].gravityStrength417object[-1].gravityStrength += 0x1800418419object.timer++420if object.timer == 38421object[-1].gravityStrength = 0422object.timer = 0423object.animationTimer = 0424object.state++425end if426break427428case GHZEGGMAN_DEFEATRISE429if object.timer < 48430object.ypos += object[-1].gravityStrength431object[-1].gravityStrength -= 0x800432object.timer++433else434object.timer = 0435object[-1].gravityStrength = 0436object.rotation = 0437object.oscillatePos = object.ypos438object.state++439end if440break441442case GHZEGGMAN_FLEE443CallFunction(GHZEggman_FlyAway)444445if object.timer < 8446object.timer++447else448object.timer = 0449object.animation = GHZEGGANI_PANIC450object.animationTimer = 0451object[-1].flameAnim = FLAME_EXPLODE452object[-1].flameAnimTimer = 0453object.priority = PRIORITY_ACTIVE454temp0 = tileLayer[0].xsize455temp0 <<= 7456stage.newXBoundary2 = temp0457object.state++458end if459break460461case GHZEGGMAN_ESCAPE462CallFunction(GHZEggman_FlyAway)463object.xpos += 0x40000464object.oscillatePos -= 0x4000465if object.outOfBounds == true466object.type = TypeName[Blank Object]467object.priority = PRIORITY_BOUNDS468end if469break470471end switch472473if object[-1].invincibilityTimer > 0474object[-1].invincibilityTimer--475end if476477foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)478if object[-1].invincibilityTimer == 0479CheckEqual(player[currentPlayer].animation, ANI_HURT)480temp0 = checkResult481CheckEqual(player[currentPlayer].animation, ANI_DYING)482temp0 |= checkResult483CheckEqual(player[currentPlayer].animation, ANI_DROWNING)484temp0 |= checkResult485if temp0 != 0486if object.animation != GHZEGGANI_LAUGH487object.animation = GHZEGGANI_LAUGH488object.animationTimer = 0489end if490end if491492switch object.state493default494break495496case GHZEGGMAN_INITIALSWING497case GHZEGGMAN_MOVERIGHT498case GHZEGGMAN_MOVELEFT499#platform: USE_STANDALONE500BoxCollisionTest(C_TOUCH, object.entityPos, -20, -16, 20, 16, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)501#endplatform502#platform: USE_ORIGINS503BoxCollisionTest(C_TOUCH, object.entityPos, -20, -16, 20, 16, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)504#endplatform505506if checkResult == true507CallFunction(Player_CheckHit)508if checkResult == true509object.health--510if object.health == 0511#platform: USE_ORIGINS512CallNativeFunction2(NotifyCallback, NOTIFY_KILL_BOSS, 0)513CallNativeFunction2(NotifyCallback, NOTIFY_BOSS_END, true)514#endplatform515player.score += 1000516object.animationTimer = 0517object.animation = GHZEGGANI_DEFEATED518temp0 = object.entityPos519temp0 -= 2520ResetObjectEntity(temp0, TypeName[Explosion], 0, object[-2].xpos, object[-2].ypos)521temp0--522ResetObjectEntity(temp0, TypeName[Explosion], 0, object[-3].xpos, object[-3].ypos)523temp0--524ResetObjectEntity(temp0, TypeName[Explosion], 0, object[-4].xpos, object[-4].ypos)525temp0--526ResetObjectEntity(temp0, TypeName[Explosion], 0, object[-5].xpos, object[-5].ypos)527temp0--528ResetObjectEntity(temp0, TypeName[Explosion], 0, object[-6].xpos, object[-6].ypos)529object[-1].state = WRECKINGBALL_EXPLODE530object[-1].flameAnim = FLAME_INACTIVE531object.timer = 0532object.state = GHZEGGMAN_EXPLODE533else534object.animationTimer = 0535object.animation = GHZEGGANI_HIT536object[-1].invincibilityTimer = 32537PlaySfx(SfxName[Boss Hit], false)538end if539end if540end if541end switch542543// Arena Boundaries544// They're only enforced when Eggman is vulnerable for some reason??545// (With how the rest of this script is like, maybe this was originally just part of sub ObjectPlayerInteraction,546// and only during the updating process these bounds were accidentally moved to only be enforced while vulnerable?547// Don't know if what I'm saying even makes any sense, hopefully it does...)548if object.state < GHZEGGMAN_ESCAPE549temp0 = player[currentPlayer].collisionRight550temp0 <<= 16551temp0 += player[currentPlayer].xpos552temp1 = stage.curXBoundary2553temp1 <<= 16554if temp0 > temp1555player[currentPlayer].xvel = 0556player[currentPlayer].speed = 0557player[currentPlayer].xpos = temp1558temp0 = player[currentPlayer].collisionRight559temp0 <<= 16560player[currentPlayer].xpos -= temp0561end if562end if563end if564next565end event566567568event ObjectDraw569switch object.animation570default571case GHZEGGANI_INVISIBLE572break573574case GHZEGGANI_IDLE575temp0 = object.animationTimer576temp0 /= 6577object.animationTimer++578object.animationTimer %= 12579DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)580break581582case GHZEGGANI_LAUGH583temp0 = object.animationTimer584temp0 %= 10585temp0 /= 5586temp0 += 9587object.animationTimer++588if object.animationTimer == 50589object.animationTimer = 0590if player[0].animation != ANI_DYING591object.animation = GHZEGGANI_IDLE592end if593end if594DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)595break596597case GHZEGGANI_HIT598temp0 = object.animationTimer599temp0 &= 1600temp0 += 2601object.animationTimer++602if object.animationTimer == 30603object.animationTimer = 0604object.animation = GHZEGGANI_IDLE605end if606DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)607break608609case GHZEGGANI_DEFEATED610temp0 = object.animationTimer611temp0 >>= 5612temp0 += 4613object.animationTimer++614object.animationTimer &= 63615DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)616break617618case GHZEGGANI_TOASTED619DrawSpriteFX(6, FX_FLIP, object.xpos, object.ypos)620break621622case GHZEGGANI_PANIC623temp0 = object.animationTimer624temp0 >>= 2625temp0 += 7626object.animationTimer++627object.animationTimer %= 7628DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)629break630631end switch632633switch object[-1].flameAnim634case FLAME_INACTIVE635default636break637638case FLAME_ACTIVE639temp0 = object[-1].flameAnimTimer640temp0 >>= 2641temp0 += 11642object[-1].flameAnimTimer++643object[-1].flameAnimTimer &= 7644DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)645break646647case FLAME_EXPLODE648temp0 = object[-1].flameAnimTimer649temp0 /= 3650temp0 += 11651object[-1].flameAnimTimer++652if object[-1].flameAnimTimer > 21653object[-1].flameAnimTimer = 18654end if655DrawSpriteFX(temp0, FX_FLIP, object.xpos, object.ypos)656break657658end switch659end event660661662event ObjectStartup663LoadSpriteSheet("Global/Eggman.gif")664SpriteFrame(-28, -32, 64, 56, 1, 1) // ? - #0665SpriteFrame(-28, -32, 64, 56, 66, 1) // ? - #1666SpriteFrame(-28, -32, 64, 56, 131, 1) // ? - #2667SpriteFrame(-28, -32, 64, 56, 1, 58) // ? - #3668SpriteFrame(-28, -32, 64, 56, 1, 1) // ? - #4669SpriteFrame(-28, -32, 64, 56, 1, 58) // ? - #5670SpriteFrame(-28, -32, 64, 56, 66, 58) // ? - #6671SpriteFrame(-28, -32, 64, 56, 131, 58) // ? - #7672SpriteFrame(-28, -32, 64, 56, 66, 1) // ? - #8673SpriteFrame(-28, -32, 64, 56, 1, 115) // ? - #9674SpriteFrame(-28, -32, 64, 56, 66, 115) // ? - #10675SpriteFrame(34, 1, 10, 9, 196, 2) // ? - #11676SpriteFrame(33, 0, 15, 11, 196, 12) // ? - #12677SpriteFrame(34, -1, 22, 14, 213, 1) // ? - #13678SpriteFrame(34, -8, 32, 26, 213, 16) // ? - #14679SpriteFrame(34, -1, 22, 14, 213, 1) // ? - #15680SpriteFrame(34, -8, 32, 26, 213, 16) // ? - #16681SpriteFrame(34, 1, 10, 9, 196, 2) // ? - #17682SpriteFrame(33, 0, 15, 11, 196, 12) // ? - #18683684foreach (TypeName[Eggman], arrayPos0, ALL_ENTITIES)685// Prolly a leftover from this script being much more v3-like, this foreach may have originally been a while loop of all objects686if object[arrayPos0].type == TypeName[Eggman]687object[arrayPos0].priority = PRIORITY_XBOUNDS688689// Screen Offset690temp0 = screen.xcenter691temp0 -= 160 //xcenter if screen width was 320 like OG games692temp0 -= 8693694if temp0 < 0695temp0 = 0696end if697698if temp0 > 24699temp0 = 24700end if701702object[arrayPos0].arenaOffset = temp0703object[arrayPos0].arenaOffset += 32704object[arrayPos0].arenaOffset *= 0x800705temp0 <<= 16706707// Align the left Boss platform708arrayPos1 = arrayPos0709arrayPos1++710object[arrayPos1].xpos -= temp0711712// And then align the right Boss platform713arrayPos1++714object[arrayPos1].xpos += temp0715716// Still looking at the right Boss platform, make the Boss's base oscillation position be 68 pixels above that717object[arrayPos0].oscillatePos = object[arrayPos1].ypos718object[arrayPos0].oscillatePos -= 0x440000719720// And then, make the base normal position be 90 pixels above the platform721object[arrayPos0].originY = object[arrayPos1].ypos722object[arrayPos0].originY -= 0x5A0000723724arrayPos1 = arrayPos0725arrayPos1--726object[arrayPos0].arenaBorder = object[arrayPos1].xpos727object[arrayPos0].arenaBorder += 0x600000728729object[arrayPos0].xpos = object[arrayPos0].arenaBorder730object[arrayPos0].ypos = object[arrayPos0].originY731object[arrayPos0].ypos -= 0xC00000732end if733next734end event735736737// ========================738// Editor Events739// ========================740741event RSDKDraw742DrawSprite(0)743744if editor.showGizmos == true745editor.drawingOverlay = true746747DrawArrow(object.xpos, object.ypos, object[-6].xpos, object[-6].ypos, 255, 255, 0) // Lights748DrawArrow(object.xpos, object.ypos, object[-5].xpos, object[-5].ypos, 255, 255, 0) // Chain 1749DrawArrow(object.xpos, object.ypos, object[-4].xpos, object[-4].ypos, 255, 255, 0) // Chain 2750DrawArrow(object.xpos, object.ypos, object[-3].xpos, object[-3].ypos, 255, 255, 0) // Chain 3751DrawArrow(object.xpos, object.ypos, object[-2].xpos, object[-2].ypos, 255, 255, 0) // Chain 4752DrawArrow(object.xpos, object.ypos, object[-1].xpos, object[-1].ypos, 255, 255, 0) // Ball753754DrawArrow(object.xpos, object.ypos, object[+1].xpos, object[+1].ypos, 255, 255, 0) // Platform L755DrawArrow(object.xpos, object.ypos, object[+2].xpos, object[+2].ypos, 255, 255, 0) // Platform R756757editor.drawingOverlay = false758end if759end event760761762event RSDKLoad763LoadSpriteSheet("Global/Eggman.gif")764SpriteFrame(-28, -32, 64, 56, 1, 1)765766SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")767end event768769770